@promptctl/cc-candybar 1.39.0 → 1.41.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.
- package/dist/index.mjs +106 -104
- package/package.json +5 -5
- package/schema/cc-candybar.schema.json +61 -1
- package/src/check.ts +14 -31
- package/src/config/default-dsl-config.ts +18 -0
- package/src/config/disclosure.ts +61 -0
- package/src/config/dsl-loader.ts +8 -1
- package/src/config/dsl-types.ts +23 -0
- package/src/config/edit-chrome.ts +114 -21
- package/src/config/help.ts +151 -0
- package/src/config/loader/edit-mode.ts +15 -3
- package/src/config/loader/emit-schema.ts +2 -1
- package/src/config/loader/globals.ts +66 -32
- package/src/config/loader/layout.ts +8 -10
- package/src/config/loader/merge.ts +6 -0
- package/src/config/presets.ts +20 -1
- package/src/config/settings-menu.ts +107 -28
- package/src/daemon/render-payload.ts +98 -1
- package/src/daemon/server.ts +29 -88
- package/src/demo/dsl.ts +21 -37
- package/src/help-text.ts +28 -2
- package/src/themes/policy.ts +44 -4
package/src/themes/policy.ts
CHANGED
|
@@ -52,14 +52,30 @@ export function resolvePaletteName(name: string): string {
|
|
|
52
52
|
// default rather than throw or render something the label disagrees with
|
|
53
53
|
// [LAW:no-silent-failure] — the caller publishes what this returns as
|
|
54
54
|
// `<field>.effective`, so bar and label always trace to one value.
|
|
55
|
+
//
|
|
56
|
+
// [LAW:one-source-of-truth] `staged` is the RIGHTMOST rung of the precedence
|
|
57
|
+
// chain documented in src/config/presets.ts — a fragment some transient MODE of
|
|
58
|
+
// the bar puts on top while it is on (today: edit mode's `editGlobals`). It
|
|
59
|
+
// outranks even the session pick because it is decided LATER: a user picks a
|
|
60
|
+
// style, then afterwards enters edit mode. That is the same lifetime rule that
|
|
61
|
+
// forced the preset's own position, applied one rung further along, which is
|
|
62
|
+
// why it is a parameter of THIS function rather than a check at any call site —
|
|
63
|
+
// a chain with a rung missing from one field is exactly the drift a single
|
|
64
|
+
// resolver exists to prevent.
|
|
65
|
+
//
|
|
66
|
+
// [LAW:dataflow-not-control-flow] Absent ⇒ `undefined`, which the `??` chain
|
|
67
|
+
// skips by the same code path a session that never clicked skips its own rung.
|
|
68
|
+
// There is no "is edit mode on" branch anywhere below this line; the mode is
|
|
69
|
+
// carried entirely by whether this argument has a value.
|
|
55
70
|
export function effectiveGlobal<T>(
|
|
71
|
+
staged: T | null | undefined,
|
|
56
72
|
sessionPick: string | null,
|
|
57
73
|
configDefault: T | null | undefined,
|
|
58
74
|
floor: T,
|
|
59
75
|
parseSession: (raw: string) => T | null,
|
|
60
76
|
): T {
|
|
61
77
|
const picked = sessionPick === null ? null : parseSession(sessionPick);
|
|
62
|
-
return picked ?? configDefault ?? floor;
|
|
78
|
+
return staged ?? picked ?? configDefault ?? floor;
|
|
63
79
|
}
|
|
64
80
|
|
|
65
81
|
// The theme name a render should use, as data.
|
|
@@ -70,10 +86,12 @@ export function effectiveGlobal<T>(
|
|
|
70
86
|
// parse is identity: there is no membership to check here, and pretending
|
|
71
87
|
// otherwise would collapse names `paletteForThemeName` handles fine.
|
|
72
88
|
export function effectiveThemeName(
|
|
89
|
+
stagedPalette: string | undefined,
|
|
73
90
|
sessionTheme: string | null,
|
|
74
91
|
globalsPalette: string | undefined,
|
|
75
92
|
): string {
|
|
76
93
|
return effectiveGlobal(
|
|
94
|
+
stagedPalette,
|
|
77
95
|
sessionTheme,
|
|
78
96
|
globalsPalette,
|
|
79
97
|
"textual-dark",
|
|
@@ -110,7 +128,12 @@ export function listResolvablePaletteNames(): readonly string[] {
|
|
|
110
128
|
//
|
|
111
129
|
// The floor's membership is a load-time guarantee, not a runtime hope: the
|
|
112
130
|
// bundled stdlib ships it and merge-by-name cannot remove it.
|
|
131
|
+
//
|
|
132
|
+
// The staged rung runs through the SAME membership parse the other two do: a
|
|
133
|
+
// fragment naming a member the config does not declare is no more a pick than a
|
|
134
|
+
// stale session entry is, and collapses one rung onward rather than throwing.
|
|
113
135
|
export function effectiveMemberName(
|
|
136
|
+
stagedName: string | undefined,
|
|
114
137
|
sessionPick: string | null,
|
|
115
138
|
configDefault: string | undefined,
|
|
116
139
|
floor: string,
|
|
@@ -119,6 +142,7 @@ export function effectiveMemberName(
|
|
|
119
142
|
const member = (raw: string): string | null =>
|
|
120
143
|
Object.prototype.hasOwnProperty.call(declared, raw) ? raw : null;
|
|
121
144
|
return effectiveGlobal(
|
|
145
|
+
stagedName === undefined ? null : member(stagedName),
|
|
122
146
|
sessionPick,
|
|
123
147
|
member(configDefault ?? floor),
|
|
124
148
|
floor,
|
|
@@ -133,11 +157,18 @@ export function effectiveMemberName(
|
|
|
133
157
|
// carries. A named wrapper (not a bare call at each site) so the floor is
|
|
134
158
|
// spelled once and the three call sites cannot disagree about it.
|
|
135
159
|
export function effectiveLookName(
|
|
160
|
+
stagedLook: string | undefined,
|
|
136
161
|
sessionLook: string | null,
|
|
137
162
|
globalsLook: string | undefined,
|
|
138
163
|
declaredLooks: Readonly<Record<string, ThemeKey>>,
|
|
139
164
|
): string {
|
|
140
|
-
return effectiveMemberName(
|
|
165
|
+
return effectiveMemberName(
|
|
166
|
+
stagedLook,
|
|
167
|
+
sessionLook,
|
|
168
|
+
globalsLook,
|
|
169
|
+
"none",
|
|
170
|
+
declaredLooks,
|
|
171
|
+
);
|
|
141
172
|
}
|
|
142
173
|
|
|
143
174
|
// [LAW:single-enforcer] The one place an effective look NAME becomes the
|
|
@@ -196,11 +227,16 @@ export function isStripStyle(value: string): value is StripStyle {
|
|
|
196
227
|
// [LAW:one-source-of-truth]; test/session-globals.test.ts pins it with a stale
|
|
197
228
|
// pick over a valid non-floor default, the case the old tests never exercised.
|
|
198
229
|
export function effectiveStripStyle(
|
|
230
|
+
stagedStyle: StripStyle | undefined,
|
|
199
231
|
sessionStyle: string | null,
|
|
200
232
|
globalsStyle: StripStyle | undefined,
|
|
201
233
|
): StripStyle {
|
|
202
|
-
return effectiveGlobal(
|
|
203
|
-
|
|
234
|
+
return effectiveGlobal(
|
|
235
|
+
stagedStyle,
|
|
236
|
+
sessionStyle,
|
|
237
|
+
globalsStyle,
|
|
238
|
+
"powerline",
|
|
239
|
+
(raw) => (isStripStyle(raw) ? raw : null),
|
|
204
240
|
);
|
|
205
241
|
}
|
|
206
242
|
|
|
@@ -323,10 +359,12 @@ function parsePadding(raw: string): number | null {
|
|
|
323
359
|
// Whether a render wraps over-wide rows, as data. The session's pick over the
|
|
324
360
|
// config default over the on floor — `effectiveGlobal` with a boolean domain.
|
|
325
361
|
export function effectiveAutoWrap(
|
|
362
|
+
stagedAutoWrap: boolean | undefined,
|
|
326
363
|
sessionAutoWrap: string | null,
|
|
327
364
|
globalsAutoWrap: boolean | undefined,
|
|
328
365
|
): boolean {
|
|
329
366
|
return effectiveGlobal(
|
|
367
|
+
stagedAutoWrap,
|
|
330
368
|
sessionAutoWrap,
|
|
331
369
|
globalsAutoWrap,
|
|
332
370
|
DEFAULT_WRAP,
|
|
@@ -341,10 +379,12 @@ export function effectiveAutoWrap(
|
|
|
341
379
|
// own default is the honest answer rather than a render at a width nobody
|
|
342
380
|
// chose.
|
|
343
381
|
export function effectivePadding(
|
|
382
|
+
stagedPadding: number | undefined,
|
|
344
383
|
sessionPadding: string | null,
|
|
345
384
|
globalsPadding: number | undefined,
|
|
346
385
|
): number {
|
|
347
386
|
return effectiveGlobal(
|
|
387
|
+
stagedPadding,
|
|
348
388
|
sessionPadding,
|
|
349
389
|
globalsPadding,
|
|
350
390
|
DEFAULT_PADDING,
|