paneltir 0.7.0 → 0.9.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.
@@ -39,11 +39,26 @@ library shared with other projects. Rules:
39
39
  The password, the GitHub token and the target repository are environment
40
40
  variables where this project is hosted — never in this repository.
41
41
  - **The panel explains itself once.** New readers get a short guided tour the
42
- first time they open the board; each note is dismissed and stays dismissed,
43
- per browser. **Help** in the header reports what the panel needs — the
44
- password, the GitHub token, the target repository — with what is missing and
45
- the steps to fix it, asked from the server so it reports the truth rather
46
- than a guess. "Show the guide again" in there brings the tour back.
42
+ first time they open the board; each note is dismissed and stays dismissed.
43
+ **Help** in the header reports what the panel needs — the password, the
44
+ GitHub token, the target repository — with what is missing and the steps to
45
+ fix it, asked from the server so it reports the truth rather than a guess.
46
+ "Show the guide again" in there brings the tour back.
47
+ - **A panel nobody has used yet walks its own setup.** On a board with no
48
+ cards and no runs, the panel asks the server what is configured and, if
49
+ something is missing, opens a walkthrough that does one variable at a time
50
+ and checks each rather than asking anyone to tick it. Closing it is
51
+ remembered in this browser, because the board it would otherwise be written
52
+ to is the very thing that cannot be saved yet. On a board already in use it
53
+ is a banner instead — said before a save fails rather than after — and the
54
+ walkthrough waits behind **Help**. Its last screen carries the one thing no
55
+ screen can check for you: `/admin` and its bundle must both refuse a signed
56
+ out visitor.
57
+ - **And it can hand the problem to Claude.** The walkthrough carries a line to
58
+ paste into a session in this repository. It names
59
+ `.claude/skills/panel/SKILL.md`, which `paneltir init` wrote, and that file
60
+ covers every variable the panel checks for — held together by a test, so the
61
+ prompt cannot come to point at a document that no longer answers it.
47
62
  - **Say which version the dashboard runs on.** `paneltirBuild.short` from
48
63
  `paneltir` renders as `vX.Y.Z · <first 12 of the fingerprint>`; keep it visible somewhere in
49
64
  the panel. `npx paneltir version` answers the same question from a terminal,
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.7.0
22
+ # npm install github:daifukus/paneltir#v0.9.0
23
23
  ```
24
24
 
25
25
  (Use the tag you were given; never install without pinning a version.)
@@ -39,10 +39,11 @@ identity** — never another project's.
39
39
  not another project's theme.
40
40
 
41
41
  3. **If no palette is defined yet**, do not make up values: `paneltir` ships
42
- base themes that are already designed and tested (`cyberpunkTheme`,
43
- `midnightTheme`, `oldMoneyTheme`, all exported in `THEME_PRESETS`). Ask
44
- which one fits the project best and if the answer is not available right
45
- now, use `midnightTheme`, the most neutral one, and say so explicitly.
42
+ base themes that are already designed and tested `midnightTheme`,
43
+ `oldMoneyTheme`, `cyberpunkTheme` and `claudeTheme`, the only light one, all
44
+ exported in `THEME_PRESETS`. Ask which one fits the project best, and if the
45
+ answer is not available right now use `midnightTheme`, the most neutral one,
46
+ and say so explicitly.
46
47
  Store the decision in a new file (for example `src/dashboard-theme.ts`),
47
48
  re-exporting the chosen preset, or copying its values if they are expected
48
49
  to diverge:
@@ -138,18 +139,32 @@ identity** — never another project's.
138
139
  import 'paneltir/style.css'
139
140
  import { PanelApp } from 'paneltir'
140
141
  import board from './data/panel-state.json'
141
-
142
- <PanelApp state={board} saveEndpoint="/admin/api/panel-state" showHistory />
142
+ import { dashboardTheme } from './dashboard-theme'
143
+
144
+ <PanelApp
145
+ state={board}
146
+ saveEndpoint="/admin/api/panel-state"
147
+ showHistory
148
+ // This project's identity, offered *alongside* the kit's presets. Use
149
+ // `extraThemes` and never `themes`: `themes` is the exact set, so passing
150
+ // one theme there deletes all four presets and the settings sheet ends up
151
+ // with a single row. That happened to two real projects.
152
+ extraThemes={{
153
+ thisProject: { label: 'This Project', tokens: dashboardTheme, note: 'derived from this repository' },
154
+ }}
155
+ />
143
156
  ```
144
157
 
145
158
  That is the whole page. `PanelApp` draws the board, the analysis, the card
146
- sheet, the settings, the guide and the notifications, and it offers the
147
- kit's themes with no further configuration. Everything a project wants
159
+ sheet, the settings, the guide and the notifications, and with no themes
160
+ passed at all it offers the kit's four. Everything a project wants
148
161
  differently is a prop rather than a fork:
149
162
 
150
163
  | Prop | What it changes |
151
164
  | --- | --- |
152
- | `themes`, `defaultTheme` | The identities the settings sheet offers. Defaults to the kit's presets. |
165
+ | `extraThemes` | This project's own identities, offered **as well as** the kit's presets. Theirs come first, so the panel opens in one of them. This is the one you want. |
166
+ | `themes` | The exact set: these and nothing else, presets included. Only for a caller deliberately curating the list — it replaces rather than adds. |
167
+ | `defaultTheme` | Which one to draw before the board has said. Defaults to the first key. |
153
168
  | `brand` | What sits where a name goes in the header. Defaults to the board's `project`. |
154
169
  | `capabilities`, `extras` | Sections of the caller's own. Not drawn when absent. |
155
170
  | `links`, `footer`, `decoration`, `className` | Where else to go, what sits under the panel, and anything the caller draws behind it. |
@@ -169,19 +184,27 @@ identity** — never another project's.
169
184
  | `PANEL_FILE` | Where the board lives in it, if not `src/data/panel-state.json`. |
170
185
  | `SESSION_SECRET` | Optional. Defaults to `ADMIN_PASSWORD`, so changing the password ends every session already issued. |
171
186
 
187
+ None of that has to be done from a table. Open the panel on a board nobody
188
+ has worked yet and it walks the variables one at a time, checking each
189
+ against the server rather than asking anyone to tick it off — and if a step
190
+ does not land, it carries a line to paste into a Claude session in this
191
+ repository, which reads the skill `init` just wrote and takes it from
192
+ there. On a board already in use the same walkthrough is behind **Help**,
193
+ offered only while something is actually missing.
194
+
172
195
  Two things to check before trusting it: `/admin` signed out must land on
173
196
  `/login`, and **the panel's own JavaScript bundle must answer 401 signed
174
197
  out**. If it does not, point the last entry of the matcher in
175
198
  `middleware.ts` at wherever this project's build emits it — protecting the
176
199
  page but not the bundle leaves the board readable by anyone who opens the
177
- HTML.
200
+ HTML. The walkthrough's last screen says both, for the same reason.
178
201
 
179
202
  9. **Record the kit fingerprint.** The kit reports itself, so no one has to
180
203
  read `node_modules` to find out what is installed:
181
204
 
182
205
  ```bash
183
206
  npx paneltir version # version, fingerprint, where it came from
184
- npx paneltir check 0.7.0 # exits non-zero if that is not what is installed
207
+ npx paneltir check 0.9.0 # exits non-zero if that is not what is installed
185
208
  npx paneltir board # read the board and say what is wrong with it
186
209
  ```
187
210
 
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.7.0
57
+ # npm install github:daifukus/paneltir#v0.9.0
58
58
  ```
59
59
 
60
60
  Installing from Git runs the `prepare` script, which builds `dist/`, so the
package/bin/paneltir.mjs CHANGED
@@ -197,8 +197,20 @@ function init(args) {
197
197
  for (const file of kept) console.log(` = ${file}`)
198
198
  }
199
199
 
200
+ // Written the gate versus found it already there is the honest first-install
201
+ // signal on this side, and it changes what is worth saying: somebody
202
+ // re-running this has read the rest once already.
200
203
  if (!written.length) {
201
204
  console.log('\nNothing to do — every file is already in place.')
205
+ console.log(`
206
+ If the panel still will not save, open it and press Help: it asks the server
207
+ what is actually set and reports whether, never the value. Or ask this
208
+ project's own Claude:
209
+
210
+ Read .claude/skills/panel/SKILL.md and set up the Paneltir panel with me:
211
+ tell me each environment variable it needs, what it is for, where in this
212
+ project to put it, and check the ones already set.
213
+ `)
202
214
  return
203
215
  }
204
216
 
@@ -232,6 +244,17 @@ Then check two things before trusting it:
232
244
  not, adjust the last entry of the matcher in middleware.ts to wherever
233
245
  this project's build emits it — protecting the page but not the bundle
234
246
  leaves the board readable by anyone who opens the HTML.
247
+
248
+ None of that has to be done from here. Open the panel and it walks the
249
+ variables one at a time, checking each against the server rather than asking
250
+ you to tick it. And if a step does not land, the walkthrough carries a line to
251
+ paste into a session in this repository:
252
+
253
+ Read .claude/skills/panel/SKILL.md and set up the Paneltir panel with me:
254
+ tell me each environment variable it needs, what it is for, where in this
255
+ project to put it, and check the ones already set.
256
+
257
+ That skill was just written into this project, and it covers exactly this.
235
258
  `)
236
259
  }
237
260
 
package/dist/index.d.ts CHANGED
@@ -388,7 +388,9 @@ interface GuideTourProps {
388
388
  * durable. Leave it out and each reader's browser remembers, which is the
389
389
  * right home for a fact about one browser — and the wrong one for a panel
390
390
  * with a single owner, who would be told the same tour again on a new
391
- * machine.
391
+ * machine. Passing it does not switch the browser off: a note dismissed
392
+ * here is written to both, because a caller whose store needs saving would
393
+ * otherwise lose the dismissal on reload.
392
394
  */
393
395
  dismissed?: string[];
394
396
  /** Told when a note is dismissed. Required for `dismissed` to mean anything. */
@@ -442,7 +444,11 @@ interface NotificationBellProps {
442
444
  * make, not the component's, which is why both work.
443
445
  */
444
446
  seen?: string[];
445
- /** Told which ids were just seen. Required for `seen` to mean anything. */
447
+ /**
448
+ * Told which ids were just seen. Required for `seen` to mean anything —
449
+ * though the bell also remembers in localStorage either way, so a caller
450
+ * that has not saved yet does not show the same notifications again.
451
+ */
446
452
  onSeen?: (ids: string[]) => void;
447
453
  }
448
454
  declare function NotificationBell({ notifications, labels, seen: given, onSeen }: NotificationBellProps): React.JSX.Element | null;
@@ -517,6 +523,121 @@ interface SetupGuideProps {
517
523
  }
518
524
  declare function SetupGuide({ requirements, readyMessage, labels }: SetupGuideProps): React.JSX.Element;
519
525
 
526
+ /**
527
+ * The setup, walked one step at a time.
528
+ *
529
+ * `SetupGuide` is the list: the right shape for somebody auditing a panel that
530
+ * already works. This is the other reader — the one who installed it twenty
531
+ * minutes ago, has four things missing and no idea which to do first. A wall
532
+ * of four is not four times as useful as one; it is the thing people close.
533
+ *
534
+ * Two rules hold it honest. It **checks rather than asks**: every step ends in
535
+ * a button that re-reads the environment from the server, so the reader is
536
+ * told whether it worked instead of ticking a box themselves. And it **never
537
+ * claims what it cannot see**: a panel that could not reach its own endpoint
538
+ * says the check failed, never that a variable is missing, because telling
539
+ * somebody to add a token they already added is the worse of the two wrong
540
+ * answers.
541
+ *
542
+ * There is no copy of the values here and nothing is written: the panel cannot
543
+ * set an environment variable, and a button that appeared to would be the same
544
+ * fault as one that appeared to install an update.
545
+ */
546
+ interface SetupWizardLabels {
547
+ title: string;
548
+ /** `(index, total)` — "Step 2 of 5". */
549
+ progress: (index: number, total: number) => string;
550
+ /** Shown above the one step in hand. */
551
+ nowDo: string;
552
+ /** The button that re-reads the environment. */
553
+ check: string;
554
+ checking: string;
555
+ /** Said when a check ran and the step is still not in place. */
556
+ stillMissing: string;
557
+ /** Said when the panel could not ask its own server. */
558
+ cannotTell: string;
559
+ /** The heading over the finished steps. */
560
+ doneTitle: string;
561
+ /** Shown in place of a step when every requirement is in place. */
562
+ readyTitle: string;
563
+ readyBody: string;
564
+ /** The two things to try before trusting the gate, as list items. */
565
+ verify: string[];
566
+ /** Closes the wizard. */
567
+ close: string;
568
+ /** The escape hatch: heading, explanation, and the prompt to copy. */
569
+ stuckTitle: string;
570
+ stuckBody: string;
571
+ stuckPrompt: string;
572
+ copy: string;
573
+ copied: string;
574
+ }
575
+ interface SetupWizardProps {
576
+ /** In the order they are to be done. The caller owns that order. */
577
+ requirements: SetupRequirement[];
578
+ labels: SetupWizardLabels;
579
+ /** Re-reads the environment. Resolves when the answer has been applied. */
580
+ onCheck: () => Promise<void> | void;
581
+ /** Told when the reader closes it. */
582
+ onClose?: () => void;
583
+ }
584
+ declare function SetupWizard({ requirements, labels, onCheck, onClose }: SetupWizardProps): React.JSX.Element;
585
+
586
+ /**
587
+ * Where a reader is in the setup, as one answer instead of a list to read.
588
+ *
589
+ * `SetupGuide` draws every requirement at once, which is the right shape for
590
+ * somebody checking a panel that already works. It is the wrong shape for
591
+ * somebody who has just installed one: five things at once, four of them
592
+ * missing, and no order to do them in reads as a wall rather than as a first
593
+ * step. So the same requirements are walked one at a time, and this is the
594
+ * function that decides which one.
595
+ *
596
+ * The order the caller gives is the order they are done in — a token that
597
+ * cannot be scoped before the repository is named is a step in the wrong
598
+ * place, and that is the caller's knowledge, not this function's.
599
+ */
600
+ interface WizardStep {
601
+ /** The requirement to show, or null when nothing is left to do. */
602
+ current: SetupRequirement | null;
603
+ /** 1-based, for "step 2 of 5". Zero when there is nothing left. */
604
+ index: number;
605
+ /** How many steps this setup has in total. */
606
+ total: number;
607
+ /** Every requirement that is in place, in the caller's order. */
608
+ done: SetupRequirement[];
609
+ /** True when every requirement is `ok`. */
610
+ ready: boolean;
611
+ /**
612
+ * True when the panel could not ask the server, so nothing is claimed.
613
+ *
614
+ * This is not "not ready": a panel that cannot reach its own endpoint knows
615
+ * nothing about the environment, and telling somebody to add a token they
616
+ * already added is worse than saying the check itself failed.
617
+ */
618
+ unknown: boolean;
619
+ }
620
+ declare function wizardStep(requirements: SetupRequirement[]): WizardStep;
621
+ /**
622
+ * Whether this panel has never been worked, which is what "first install"
623
+ * means here.
624
+ *
625
+ * `paneltir init` writes a board with the columns already there and nothing
626
+ * on them, so a board carrying no cards and no runs is one nobody has used
627
+ * yet. That is a better signal than a version on disk: a project can install
628
+ * the package, never open the panel, and update three times before anyone
629
+ * sees it — and it is still that reader's first run.
630
+ *
631
+ * A panel that has been worked and then loses a variable is deliberately not
632
+ * this. It needs the same instructions and gets them from the same wizard,
633
+ * but it is told rather than taken over: somebody mid-sentence on a board
634
+ * they know does not want a walkthrough opening on top of it.
635
+ */
636
+ declare function isFirstRun(board: {
637
+ cards?: unknown[];
638
+ runs?: unknown[];
639
+ }): boolean;
640
+
520
641
  type Handler = (payload: Record<string, string>, event: MouseEvent) => void;
521
642
  /**
522
643
  * A single click listener on document that dispatches by data-* attributes,
@@ -872,6 +993,14 @@ interface Preferences {
872
993
  seen?: string[];
873
994
  /** Ids of guide notes already dismissed. */
874
995
  guideDismissed?: string[];
996
+ /**
997
+ * Whether an update card is written as an order rather than a suggestion.
998
+ *
999
+ * It does not make anything automatic — the panel cannot run npm, and this
1000
+ * changes `order` on the card it offers to write, nothing else. Off means
1001
+ * the card asks; on means it tells.
1002
+ */
1003
+ updateAsOrder?: boolean;
875
1004
  }
876
1005
  interface PanelState {
877
1006
  v: 2;
@@ -1027,6 +1156,27 @@ interface PanelTheme {
1027
1156
  type PanelThemes = Record<string, PanelTheme>;
1028
1157
  /** Every preset the kit ships, as a panel would offer them. */
1029
1158
  declare const PRESET_PANEL_THEMES: PanelThemes;
1159
+ /**
1160
+ * The identities a panel actually offers, given what its caller asked for.
1161
+ *
1162
+ * `themes` is the exact set: these and nothing else. `extraThemes` adds to the
1163
+ * presets, which is what a project installing the panel nearly always means —
1164
+ * it has one identity of its own and no reason to lose the four the kit ships.
1165
+ *
1166
+ * The distinction exists because the absence of it cost two real installs. A
1167
+ * default parameter is replaced, not merged, so a project passing its own
1168
+ * theme as `themes` silently deleted every preset and its settings sheet
1169
+ * offered exactly one row. `INSTALL.md` led there — it said to derive the
1170
+ * project's palette and then listed `themes` as the prop for identities — so
1171
+ * the reader followed the instructions and the API was the thing that was
1172
+ * wrong.
1173
+ *
1174
+ * Extras come first, because `defaultTheme` falls back to the first key: a
1175
+ * panel should open in the project's own identity, not in a preset that
1176
+ * happens to sort ahead of it. A key that collides with a preset belongs to
1177
+ * the caller — they named it, so they meant it.
1178
+ */
1179
+ declare function offeredThemes(themes?: PanelThemes, extraThemes?: PanelThemes): PanelThemes;
1030
1180
 
1031
1181
  /**
1032
1182
  * What the panel shows for the dfklabs catalogue, and the three ways to
@@ -1117,6 +1267,25 @@ interface UiStrings {
1117
1267
  analysis: string;
1118
1268
  /** The Revisions tab. Short, because it sits beside Board and Analysis. */
1119
1269
  history: string;
1270
+ updateTitle: string;
1271
+ updateSubtitle: string;
1272
+ updateCurrent: (version: string) => string;
1273
+ updateAvailable: (version: string) => string;
1274
+ updateUpToDate: string;
1275
+ updateUnknown: string;
1276
+ updateCreateCard: string;
1277
+ updateCardExists: string;
1278
+ updateAsOrder: string;
1279
+ updateAsOrderHow: string;
1280
+ notifUpdate: string;
1281
+ releaseTitle: (version: string) => string;
1282
+ releaseDate: (date: string) => string;
1283
+ releaseShape: Record<'breaking' | 'feature' | 'fix' | 'chore', string>;
1284
+ releaseKind: Record<'breaking' | 'feature' | 'fix' | 'chore', string>;
1285
+ releaseClose: string;
1286
+ releaseNone: string;
1287
+ updateCardTitle: (version: string) => string;
1288
+ updateCardBody: (version: string) => string;
1120
1289
  cardDetail: string;
1121
1290
  panelSettings: string;
1122
1291
  title: string;
@@ -1197,6 +1366,25 @@ interface UiStrings {
1197
1366
  fixTokenPaste: string;
1198
1367
  fixTokenRedeploy: string;
1199
1368
  fixRepo: string;
1369
+ wizardTitle: string;
1370
+ wizardProgress: (index: number, total: number) => string;
1371
+ wizardNowDo: string;
1372
+ wizardCheck: string;
1373
+ wizardChecking: string;
1374
+ wizardStillMissing: string;
1375
+ wizardCannotTell: string;
1376
+ wizardDoneTitle: string;
1377
+ wizardReadyTitle: string;
1378
+ wizardReadyBody: string;
1379
+ wizardVerify: string[];
1380
+ wizardClose: string;
1381
+ wizardStuckTitle: string;
1382
+ wizardStuckBody: string;
1383
+ wizardStuckPrompt: string;
1384
+ wizardCopy: string;
1385
+ wizardCopied: string;
1386
+ wizardOpen: string;
1387
+ wizardBanner: string;
1200
1388
  demoTourWelcomeTitle: string;
1201
1389
  demoTourWelcomeBody: string;
1202
1390
  demoTourBoardTitle: string;
@@ -1271,6 +1459,10 @@ interface UiStrings {
1271
1459
  suggestionStatuses: Record<'new' | 'doing' | 'done' | 'dismissed', string>;
1272
1460
  analysisSections: Record<AnalysisSection, string>;
1273
1461
  analysisSectionHints: Record<AnalysisSection, string>;
1462
+ analysisRedo: string;
1463
+ analysisRedoAsked: string;
1464
+ analysisRedoTitle: Record<AnalysisSection, string>;
1465
+ analysisRedoBody: Record<AnalysisSection, string>;
1274
1466
  analysisAnswered: (answered: number, total: number) => string;
1275
1467
  analysisAllDecided: string;
1276
1468
  choicesTitle: string;
@@ -1379,13 +1571,26 @@ interface Capability {
1379
1571
  }
1380
1572
  declare const CAPABILITIES: Capability[];
1381
1573
 
1574
+ type ThemeChoice = string;
1382
1575
  interface PanelAppProps {
1383
1576
  state: PanelState;
1384
1577
  /**
1385
- * The identities the settings sheet offers. Defaults to the kit's presets,
1386
- * so a panel has something to switch between on its first session.
1578
+ * The exact identities the settings sheet offers: these and nothing else.
1579
+ *
1580
+ * Almost nobody wants this. A project with one identity of its own wants
1581
+ * `extraThemes`, which adds to the presets instead of replacing them — this
1582
+ * prop silently deleted all four for two real installs, whose settings sheet
1583
+ * then offered a single row.
1387
1584
  */
1388
1585
  themes?: PanelThemes;
1586
+ /**
1587
+ * Identities of the caller's own, offered *alongside* the kit's presets.
1588
+ *
1589
+ * This is what a project installing the panel means. They come first, so the
1590
+ * panel opens in the project's identity rather than in a preset; a key that
1591
+ * collides with a preset replaces it, because the caller named it.
1592
+ */
1593
+ extraThemes?: PanelThemes;
1389
1594
  /** Which one to draw before the board has said. Defaults to the first. */
1390
1595
  defaultTheme?: string;
1391
1596
  /**
@@ -1396,8 +1601,16 @@ interface PanelAppProps {
1396
1601
  * business drawing anybody's mark, including its own.
1397
1602
  */
1398
1603
  brand?: React.ReactNode;
1399
- /** Rendered inside the theme provider, behind everything: a caller's screen effects. */
1400
- decoration?: React.ReactNode;
1604
+ /**
1605
+ * Rendered inside the theme provider, behind everything: a caller's screen
1606
+ * effects.
1607
+ *
1608
+ * It may be a function of the theme in force, because a decoration usually
1609
+ * belongs to one theme rather than to the panel. This project's scanlines
1610
+ * are Night City's and were drawn over every other theme until this existed
1611
+ * — a palette swapped underneath an effect that did not move with it.
1612
+ */
1613
+ decoration?: React.ReactNode | ((theme: ThemeChoice) => React.ReactNode);
1401
1614
  /** Put on the theme root, so a caller's stylesheet has something to hang on. */
1402
1615
  className?: string;
1403
1616
  /** Rendered under the panel. A caller's footer, or nothing. */
@@ -1419,6 +1632,14 @@ interface PanelAppProps {
1419
1632
  showLanguage?: boolean;
1420
1633
  /** The revision log: one entry per session, newest first. */
1421
1634
  showHistory?: boolean;
1635
+ /**
1636
+ * Ask the public npm registry whether a newer kit has been published.
1637
+ *
1638
+ * Opt-in, because it is a request leaving the reader's browser and that is
1639
+ * the caller's decision rather than the kit's. Nothing is installed either
1640
+ * way: the panel offers to write a card, and a session acts on it.
1641
+ */
1642
+ checkForUpdates?: boolean;
1422
1643
  /** Endpoint that commits the board back to the repository, when there is one. */
1423
1644
  saveEndpoint?: string;
1424
1645
  /**
@@ -1436,7 +1657,7 @@ interface PanelAppProps {
1436
1657
  fileCount: number;
1437
1658
  };
1438
1659
  }
1439
- declare function PanelApp({ state: initialState, themes, defaultTheme, brand, decoration, className, footer, links, capabilities, extras, showLanguage, showHistory, saveEndpoint, marketplaceEndpoint, marketplaceReport, fingerprint, }: PanelAppProps): React.JSX.Element;
1660
+ declare function PanelApp({ state: initialState, themes: exactThemes, extraThemes, defaultTheme, brand, decoration, className, footer, links, capabilities, extras, showLanguage, showHistory, checkForUpdates, saveEndpoint, marketplaceEndpoint, marketplaceReport, fingerprint, }: PanelAppProps): React.JSX.Element;
1440
1661
 
1441
1662
  /**
1442
1663
  * Applies a board move to the flat card list.
@@ -1461,8 +1682,16 @@ interface AnalysisViewProps {
1461
1682
  onDecide: (section: AnalysisSection, choiceId: string, optionId: string | null) => void;
1462
1683
  /** Opening the card a fact is about, so a number is never a dead end. */
1463
1684
  onOpenCard?: (id: string) => void;
1685
+ /**
1686
+ * Asks for this screen's analysis to be worked again.
1687
+ *
1688
+ * The panel cannot run Claude, so it writes a card and says so. A button
1689
+ * that appeared to fetch a report and did not would be the exact fault the
1690
+ * derived theme's refresh already avoids. Omit it and no button is drawn.
1691
+ */
1692
+ onRequestReport?: (section: AnalysisSection) => void;
1464
1693
  }
1465
- declare function AnalysisView({ analysis, cards, columns, today, lang, ui, onChooseStrategy, onSuggestionStatus, onDecide, onOpenCard, }: AnalysisViewProps): React.JSX.Element;
1694
+ declare function AnalysisView({ analysis, cards, columns, today, lang, ui, onChooseStrategy, onSuggestionStatus, onDecide, onOpenCard, onRequestReport, }: AnalysisViewProps): React.JSX.Element;
1466
1695
 
1467
1696
  interface MarketplaceViewProps {
1468
1697
  /** Null while the catalogue is still being asked for. */
@@ -1488,4 +1717,4 @@ interface CardSheetProps {
1488
1717
  }
1489
1718
  declare function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }: CardSheetProps): React.JSX.Element | null;
1490
1719
 
1491
- 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 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_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, 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, applyMove, boardFacts, checkProgress, claimedWithoutStarting, claudeTheme, commandSnippet, countCards, cyberpunkTheme, decided, emptyCard, explainBoard, isCard, ledgerForm, midnightTheme, moveCardInColumns, newId, oldMoneyTheme, panelForm, paneltirBuild, paperForm, readBoard, readStoredLang, repositorySnippet, resetGuide, sparkPoints, stampForColumn, storeLang, text, today, trendOf, undecided, untranslated, useDashboardForm, useDashboardTheme, useDelegatedClick, useGuideNote, useMediaQuery, validateBoard, writeText };
1720
+ 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 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_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, 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 };