@promptctl/cc-candybar 1.42.1 → 1.43.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.
Files changed (126) hide show
  1. package/dist/index.mjs +72 -71
  2. package/package.json +5 -6
  3. package/src/check.ts +0 -478
  4. package/src/cli-flags.ts +0 -8
  5. package/src/click/wire.ts +0 -158
  6. package/src/config/action.ts +0 -329
  7. package/src/config/cli.ts +0 -71
  8. package/src/config/default-dsl-config.ts +0 -1645
  9. package/src/config/disclosure.ts +0 -170
  10. package/src/config/dsl-loader.ts +0 -339
  11. package/src/config/dsl-types.ts +0 -581
  12. package/src/config/edit-chrome.ts +0 -559
  13. package/src/config/help.ts +0 -151
  14. package/src/config/ident.ts +0 -22
  15. package/src/config/layout-ops.ts +0 -177
  16. package/src/config/loader/actions.ts +0 -972
  17. package/src/config/loader/cache.ts +0 -206
  18. package/src/config/loader/cross-ref.ts +0 -714
  19. package/src/config/loader/cycles.ts +0 -148
  20. package/src/config/loader/diagnostics.ts +0 -99
  21. package/src/config/loader/discovery.ts +0 -182
  22. package/src/config/loader/edit-mode.ts +0 -137
  23. package/src/config/loader/emit-schema.ts +0 -68
  24. package/src/config/loader/globals.ts +0 -269
  25. package/src/config/loader/helpers.ts +0 -48
  26. package/src/config/loader/layout.ts +0 -693
  27. package/src/config/loader/looks.ts +0 -96
  28. package/src/config/loader/menu-synth.ts +0 -435
  29. package/src/config/loader/merge.ts +0 -115
  30. package/src/config/loader/persist-target.ts +0 -67
  31. package/src/config/loader/presets.ts +0 -119
  32. package/src/config/loader/refs.ts +0 -100
  33. package/src/config/loader/reserved-namespace.ts +0 -38
  34. package/src/config/loader/segments.ts +0 -120
  35. package/src/config/loader/validate-core.ts +0 -737
  36. package/src/config/loader/variables.ts +0 -260
  37. package/src/config/menu-keys.ts +0 -139
  38. package/src/config/option-domain.ts +0 -164
  39. package/src/config/presets.ts +0 -326
  40. package/src/config/settings-menu.ts +0 -775
  41. package/src/daemon/acquire.ts +0 -684
  42. package/src/daemon/cache/git.ts +0 -649
  43. package/src/daemon/cache/render.ts +0 -623
  44. package/src/daemon/cache/session-usage-store.ts +0 -720
  45. package/src/daemon/cache/watchers.ts +0 -249
  46. package/src/daemon/client-debug.ts +0 -120
  47. package/src/daemon/client-stats.ts +0 -130
  48. package/src/daemon/client-transport.ts +0 -273
  49. package/src/daemon/client.ts +0 -78
  50. package/src/daemon/config-overrides-store.ts +0 -663
  51. package/src/daemon/debug-types.ts +0 -91
  52. package/src/daemon/debug.ts +0 -264
  53. package/src/daemon/fork-bomb-breaker.ts +0 -351
  54. package/src/daemon/limits.ts +0 -211
  55. package/src/daemon/log.ts +0 -81
  56. package/src/daemon/parent-watchdog.ts +0 -87
  57. package/src/daemon/paths.ts +0 -211
  58. package/src/daemon/process-fingerprint.ts +0 -146
  59. package/src/daemon/protocol.ts +0 -292
  60. package/src/daemon/render-payload.ts +0 -1256
  61. package/src/daemon/server.ts +0 -1330
  62. package/src/daemon/session-state-file.ts +0 -108
  63. package/src/daemon/session-state.ts +0 -237
  64. package/src/daemon/socket-lease.ts +0 -209
  65. package/src/daemon/socket-ownership.ts +0 -209
  66. package/src/daemon/stats.ts +0 -235
  67. package/src/daemon/verbs/config-validators.ts +0 -250
  68. package/src/daemon/verbs/index.ts +0 -706
  69. package/src/daemon/verbs/state-validators.ts +0 -249
  70. package/src/daemon/verbs/validator-registry.ts +0 -457
  71. package/src/demo/dsl.ts +0 -143
  72. package/src/demo/mock-data.ts +0 -67
  73. package/src/demo/statusline.json5 +0 -94
  74. package/src/dsl/node-registry.ts +0 -374
  75. package/src/dsl/render.ts +0 -803
  76. package/src/help-text.ts +0 -90
  77. package/src/index.ts +0 -210
  78. package/src/install/currency.ts +0 -197
  79. package/src/install/index.ts +0 -557
  80. package/src/proc/launch.ts +0 -459
  81. package/src/proc/stats-handle.ts +0 -13
  82. package/src/render/action.ts +0 -883
  83. package/src/render/active-segment.ts +0 -78
  84. package/src/render/diagnostic-style.ts +0 -23
  85. package/src/render/diagnostic-text.ts +0 -77
  86. package/src/render/error-glyph.ts +0 -53
  87. package/src/render/menu.ts +0 -257
  88. package/src/render/outcome-plan.ts +0 -45
  89. package/src/render/picker.ts +0 -372
  90. package/src/render/segment-color.ts +0 -74
  91. package/src/render/split-lines.ts +0 -51
  92. package/src/render/strip.ts +0 -228
  93. package/src/segments/cache.ts +0 -131
  94. package/src/segments/context.ts +0 -190
  95. package/src/segments/git.ts +0 -1084
  96. package/src/segments/metrics.ts +0 -187
  97. package/src/segments/pricing.ts +0 -452
  98. package/src/segments/session.ts +0 -23
  99. package/src/segments/tmux.ts +0 -74
  100. package/src/template-engine/cells.ts +0 -90
  101. package/src/template-engine/colors.ts +0 -124
  102. package/src/template-engine/engine.ts +0 -108
  103. package/src/template-engine/funcs.ts +0 -232
  104. package/src/template-engine/index.ts +0 -11
  105. package/src/template-engine/layout.ts +0 -133
  106. package/src/template-engine/scope.ts +0 -62
  107. package/src/template-engine/sparkline.ts +0 -79
  108. package/src/themes/index.ts +0 -20
  109. package/src/themes/palette-resolvers.ts +0 -84
  110. package/src/themes/policy.ts +0 -393
  111. package/src/utils/cache.ts +0 -206
  112. package/src/utils/claude.ts +0 -683
  113. package/src/utils/color-support.ts +0 -118
  114. package/src/utils/formatters.ts +0 -99
  115. package/src/utils/logger.ts +0 -5
  116. package/src/utils/outcome.ts +0 -33
  117. package/src/utils/schema-validator.ts +0 -126
  118. package/src/utils/single-flight.ts +0 -57
  119. package/src/utils/terminal-width.ts +0 -51
  120. package/src/utils/terminal.ts +0 -11
  121. package/src/utils/transcript-fs.ts +0 -279
  122. package/src/var-system/index.ts +0 -24
  123. package/src/var-system/sources.ts +0 -1047
  124. package/src/var-system/store.ts +0 -223
  125. package/src/var-system/types.ts +0 -57
  126. package/src/version.ts +0 -17
@@ -1,133 +0,0 @@
1
- // [LAW:single-enforcer] All per-segment width/justify/truncate enforcement
2
- // runs through applySegmentLayout. RichText owns the slice/pad/truncate
3
- // primitives; this function chooses which to call from the segment-level
4
- // options. No second path exists.
5
- //
6
- // [LAW:dataflow-not-control-flow] Every step is unconditional in shape;
7
- // option values (width, justify, truncate) decide what the output is, not
8
- // whether the step runs. "auto" width is not a branch that skips logic —
9
- // it is a value that selects "collapse only, no resize" over "collapse then
10
- // size to width".
11
- //
12
- // [LAW:types-are-the-program] With RichText as the cell type, every layout
13
- // operation is span-preserving by construction. There is no rebuild path,
14
- // no slice-then-restyle dance: `richText.truncate({width, mode, marker})`
15
- // and `richText.align(justify, width)` clip and shift spans through every
16
- // cut. The bzh.9 limitation (truncation drops per-part fg) cannot be
17
- // expressed in this shape — its preconditions don't exist.
18
-
19
- import { RichText } from "@promptctl/rich-js";
20
- import type { Style } from "@promptctl/rich-js";
21
- import type { Template } from "@promptctl/go-template-js";
22
-
23
- export type JustifyMode = "left" | "center" | "right";
24
- export type TruncateMode = "right" | "left" | "middle";
25
-
26
- export interface SegmentLayoutOptions {
27
- /** "auto" → content-sized; a positive integer → fixed terminal-cell width. */
28
- width: "auto" | number;
29
- /** Alignment within a fixed-width segment. Ignored when width is "auto". */
30
- justify: JustifyMode;
31
- /** Overflow strategy when content exceeds a fixed width. Ignored when "auto". */
32
- truncate: TruncateMode;
33
- /**
34
- * Spaces synthesized inside the collapsed cell on each side (the resolved
35
- * globals.padding). [LAW:types-are-the-program] Required so every layout
36
- * site states the value — the walk threads the one render-wide resolution;
37
- * there is no per-site re-default. Applied BEFORE width sizing, so padding
38
- * sits inside a fixed `width` (the legacy intra-cell semantics: the joiners
39
- * sit between cells; padding sits inside the bg fill).
40
- */
41
- padding: number;
42
- /** Glyph inserted at the overflow cut point. Default "…". */
43
- truncateMarker?: string;
44
- /**
45
- * Style for synthesized whitespace — RichText pads using plain spaces.
46
- * The padding inherits the cell's wrapping style at render time, so the
47
- * segment bg/fg is continuous across padded gaps without a second style
48
- * assignment here.
49
- */
50
- baseStyle?: Style;
51
- }
52
-
53
- /**
54
- * Evaluate a `when` predicate template against `scope`.
55
- * Returns false only when the evaluated text equals the string "false".
56
- * A missing template means the segment is always visible.
57
- *
58
- * [LAW:dataflow-not-control-flow] Visibility is a value that flows out of the
59
- * template engine. The engine always runs; the output value decides visibility.
60
- */
61
- export function evaluateWhen(
62
- template: Template<RichText> | undefined,
63
- scope: object,
64
- ): boolean {
65
- if (template === undefined) return true;
66
- const fragments = template.evaluate(scope);
67
- return fragments.map((f) => f.plain).join("") !== "false";
68
- }
69
-
70
- /**
71
- * Collapse a visual line's cells into the ONE strip item the unit contributes
72
- * for that line. [LAW:single-enforcer] A unit (segment, or an inline leaf) is
73
- * one strip item — the powerline joiner caps BETWEEN units, never inside one,
74
- * so a unit's interior bg/fg variation is paint, not a structural seam the
75
- * joiner reads. Each input cell's wrapping style becomes a span over its range
76
- * and its interior spans (including OSC-8 links) carry through, so every
77
- * clickable region survives as its own span — serialized as one OSC-8 region
78
- * each. `baseStyle` is the wrapping default so synthesized padding and gaps
79
- * inherit the unit's bg.
80
- */
81
- function collapseToCell(
82
- cells: readonly RichText[],
83
- baseStyle?: Style,
84
- ): RichText {
85
- const merged = RichText.fromFragments(cells);
86
- merged.end = "";
87
- merged.noWrap = true;
88
- if (baseStyle !== undefined && !baseStyle.isNull) merged.style = baseStyle;
89
- return merged;
90
- }
91
-
92
- /**
93
- * Lay out one segment visual line: collapse its cells into a single strip
94
- * item, then size that item to the requested width. Returns `[]` for an empty
95
- * line (a unit that rendered nothing contributes no strip item) or `[cell]`
96
- * for one — never more, so the caller's branchless spread handles both.
97
- *
98
- * [LAW:dataflow-not-control-flow] `width` is the value that selects the sizing
99
- * op: "auto" keeps the content-sized cell as-is; a fixed width truncates when
100
- * over and pad-aligns when under. Truncation/align are span-preserving, so the
101
- * collapsed link structure survives every cut.
102
- */
103
- export function applySegmentLayout(
104
- cells: readonly RichText[],
105
- options: SegmentLayoutOptions,
106
- ): RichText[] {
107
- const {
108
- width,
109
- justify,
110
- truncate,
111
- truncateMarker = "…",
112
- baseStyle,
113
- padding,
114
- } = options;
115
-
116
- if (cells.length === 0) return [];
117
-
118
- // [LAW:one-source-of-truth] The DSL path's ONE intra-cell padding
119
- // application — the same rich-js pad primitive toCell (render/strip.ts)
120
- // uses on the legacy shape, threading the same resolved globals.padding.
121
- // pad() shifts spans, so OSC-8 link regions survive; the spaces inherit
122
- // the cell's wrapping style, so the segment bg is continuous.
123
- const cell = collapseToCell(cells, baseStyle).pad(padding);
124
- if (width === "auto") return [cell];
125
-
126
- if (cell.cellLength > width) {
127
- cell.truncate(width, { mode: truncate, marker: truncateMarker });
128
- } else if (cell.cellLength < width) {
129
- cell.align(justify, width);
130
- }
131
-
132
- return [cell];
133
- }
@@ -1,62 +0,0 @@
1
- // [LAW:dataflow-not-control-flow] The scope Proxy converts a flat variable
2
- // store (keys like "session.id", "git.branch", "cwd") into the nested object
3
- // shape the template engine expects for ".session.id" field access.
4
- // No data is materialised — the proxy navigates namespace prefixes lazily and
5
- // calls store.read() only when a leaf is reached, so MobX dependency tracking
6
- // fires at the point of actual reads inside a computed body.
7
- //
8
- // The engine's getField() uses `name in obj` before `obj[name]`, so the
9
- // proxy must define a `has` trap as well as `get`.
10
-
11
- import type { VariableStore } from "../var-system/store.js";
12
-
13
- // Build the scope object the engine receives as `.` (dot).
14
- // Call once per render; the returned object is a read-only view of the store
15
- // at evaluation time — do not cache across renders.
16
- export function buildScope(store: VariableStore): object {
17
- const names = new Set(store.names());
18
- return makeProxy(store, names, "");
19
- }
20
-
21
- function makeProxy(
22
- store: VariableStore,
23
- names: Set<string>,
24
- prefix: string,
25
- ): object {
26
- return new Proxy(Object.create(null) as object, {
27
- has(_, key: string | symbol): boolean {
28
- if (typeof key !== "string") return false;
29
- const fullKey = prefix ? `${prefix}.${key}` : key;
30
- // Leaf: exact variable.
31
- if (names.has(fullKey)) return true;
32
- // Interior: a namespace prefix for at least one stored variable.
33
- const nsPrefix = `${fullKey}.`;
34
- for (const n of names) {
35
- if (n.startsWith(nsPrefix)) return true;
36
- }
37
- return false;
38
- },
39
-
40
- get(_, key: string | symbol): unknown {
41
- if (typeof key !== "string") return undefined;
42
- const fullKey = prefix ? `${prefix}.${key}` : key;
43
-
44
- // Leaf: exact variable in the store.
45
- if (names.has(fullKey)) {
46
- return store.read(fullKey);
47
- }
48
-
49
- // Interior: a namespace prefix for at least one stored variable.
50
- // Return a nested proxy; MobX tracking fires only at the leaf read.
51
- const nsPrefix = `${fullKey}.`;
52
- for (const n of names) {
53
- if (n.startsWith(nsPrefix)) {
54
- return makeProxy(store, names, fullKey);
55
- }
56
- }
57
-
58
- // Unknown: `has` returned false so the engine will throw MissingFieldError.
59
- return undefined;
60
- },
61
- });
62
- }
@@ -1,79 +0,0 @@
1
- // [LAW:effects-at-boundaries] A sparkline is a PURE projection: a numeric
2
- // series in, a string of block glyphs out. It reads no clock, touches no
3
- // store, accumulates nothing — any history it draws is owned by the daemon
4
- // cache and handed in as data (cf. session-usage-store's burn-rate ring).
5
- // [LAW:one-source-of-truth] The renderer operates on number[] (the real
6
- // domain); the var-system can only carry a scalar across the payload→template
7
- // seam, so `parseSeries` decodes the delimited string form at that one edge —
8
- // the wire shape and the domain shape have a single, tested conversion.
9
-
10
- // The eight-level block ramp, lowest→highest. Index into this is the only
11
- // place a value's normalized height becomes a glyph.
12
- export const SPARK_LEVELS = [
13
- "▁", // ▁
14
- "▂", // ▂
15
- "▃", // ▃
16
- "▄", // ▄
17
- "▅", // ▅
18
- "▆", // ▆
19
- "▇", // ▇
20
- "█", // █
21
- ] as const;
22
-
23
- const LEVELS = SPARK_LEVELS.length;
24
-
25
- // Render a numeric series as a unicode mini-graph.
26
- //
27
- // `width` caps the glyph count to fit a cell: the MOST RECENT `width` samples
28
- // are shown (tail slice), so a fixed-width cell tracks the live tail of a
29
- // growing series. Omitted → every sample renders; `width <= 0` → empty.
30
- //
31
- // Heights are RELATIVE to the rendered window's own min/max — a sparkline shows
32
- // shape, never absolute magnitude, so the full ramp is always used when the
33
- // window varies. [LAW:dataflow-not-control-flow] The mapping is one unconditional
34
- // fold over the values; the only data-driven value is `range`, and a flat
35
- // window (range === 0) falls to the lowest tier by the same formula's limit
36
- // (height-above-min is 0 for every sample), not a special-cased branch.
37
- export function renderSparkline(values: number[], width?: number): string {
38
- const window =
39
- width === undefined ? values : width <= 0 ? [] : values.slice(-width);
40
- if (window.length === 0) return "";
41
-
42
- let min = window[0]!;
43
- let max = window[0]!;
44
- for (const v of window) {
45
- if (v < min) min = v;
46
- if (v > max) max = v;
47
- }
48
- const range = max - min;
49
-
50
- let out = "";
51
- for (const v of window) {
52
- // range === 0 ⇒ every sample sits at its own min ⇒ height 0 ⇒ lowest tier.
53
- const idx =
54
- range === 0 ? 0 : Math.round(((v - min) / range) * (LEVELS - 1));
55
- out += SPARK_LEVELS[idx]!;
56
- }
57
- return out;
58
- }
59
-
60
- // Decode the delimited string a series travels as across the scalar var-system
61
- // seam into the number[] the renderer consumes. Empty / blank tokens are the
62
- // genuine "no sample" form (an empty payload field is ""), so they drop; a
63
- // non-empty, non-numeric token is malformed input and fails LOUDLY rather than
64
- // being silently skipped into a wrong-shaped graph. [LAW:no-silent-failure]
65
- export function parseSeries(s: string): number[] {
66
- const out: number[] = [];
67
- for (const tok of s.split(",")) {
68
- const t = tok.trim();
69
- if (t === "") continue;
70
- const n = Number(t);
71
- if (!Number.isFinite(n)) {
72
- throw new TypeError(
73
- `sparkline: non-numeric series element ${JSON.stringify(tok)}`,
74
- );
75
- }
76
- out.push(n);
77
- }
78
- return out;
79
- }
@@ -1,20 +0,0 @@
1
- // [LAW:single-enforcer] Public barrel for the themes module. Name/string policy
2
- // lives in policy.ts; memoized resolver construction (name→resolver and
3
- // transposition) lives in palette-resolvers.ts. rich-js owns palettes,
4
- // hydration, all color math, and the anchor rule — cc-candybar keeps no color
5
- // arithmetic of its own.
6
- export {
7
- resolvePaletteName,
8
- effectiveThemeName,
9
- effectiveLookName,
10
- lookKeyByName,
11
- effectiveStripStyle,
12
- effectiveAutoWrap,
13
- effectivePadding,
14
- isStripStyle,
15
- listResolvablePaletteNames,
16
- STRIP_STYLES,
17
- } from "./policy.js";
18
- export type { StripStyle } from "./policy.js";
19
-
20
- export { paletteForThemeName, transposedPalette } from "./palette-resolvers.js";
@@ -1,84 +0,0 @@
1
- // Memoized Palette construction over rich-js. cc-candybar moves theme
2
- // NAMES and ThemeKey axes (data); rich-js owns every color value operation. Two
3
- // memos live here: a theme name -> base palette, and a (base, ThemeKey) ->
4
- // transposed palette. They compose — the per-render base palette feeds the
5
- // per-segment transposition (the session look's axes + the segment's hue shift,
6
- // folded into one key by the caller).
7
- //
8
- // [LAW:no-shared-mutable-globals] Single owner: this module. Both Maps are pure
9
- // memos of pure rich-js functions, keyed by immutable inputs (resolved theme
10
- // name; palette name + the four ThemeKey axes). rich-js palettes are immutable
11
- // registry singletons, so a cached palette never goes stale. Key spaces are
12
- // bounded by #themes and #themes × #declared looks × #distinct hueShifts
13
- // (hueShift = look shift + segIndex*hueStep, segIndex bounded by layout; look
14
- // axes bounded by the loaded configs' looks blocks) — both small. Shared on
15
- // purpose: a theme's base palette and its gruvbox+42° transposition are each
16
- // computed once per process, not once per RenderCache entry or per render.
17
- // Read/written only through the two functions below.
18
-
19
- import { transposePalette, getThemePalette } from "@promptctl/rich-js";
20
- import type { ThemeKey, Palette } from "@promptctl/rich-js";
21
- import { resolvePaletteName } from "./policy.js";
22
-
23
- const baseCache = new Map<string, Palette>();
24
- const transposeCache = new Map<string, Palette>();
25
-
26
- /**
27
- * The Palette for a theme name (aliases resolved). Memoized.
28
- *
29
- * [LAW:single-enforcer] The one place a theme name becomes a Palette —
30
- * the per-render base palette and per-segment `palette:` overrides both flow
31
- * through here. A name that does not resolve is registry/resolver drift, never
32
- * user error: the loader validates `globals.palette` and the set-state verb
33
- * validates session theme values against the resolvable set, so by the time a
34
- * name reaches here it must resolve. [LAW:no-defensive-null-guards] the throw is
35
- * the loud failure for that broken invariant, not a fallback.
36
- */
37
- export function paletteForThemeName(name: string): Palette {
38
- const resolved = resolvePaletteName(name);
39
- const hit = baseCache.get(resolved);
40
- if (hit !== undefined) return hit;
41
-
42
- const palette = getThemePalette(resolved);
43
- if (palette === null) {
44
- throw new Error(
45
- `Palette "${name}" (resolved "${resolved}") did not resolve in the ` +
46
- `theme registry — allowed names and the registry are inconsistent`,
47
- );
48
- }
49
- baseCache.set(resolved, palette);
50
- return palette;
51
- }
52
-
53
- /**
54
- * `base` transposed by a full ThemeKey — the adapted-palette constructor:
55
- * (base palette, key) → palette. The caller
56
- * composes whatever axes it carries (a look's four axes, the per-segment hue
57
- * shift) into ONE key and this makes ONE transposePalette call — never chain
58
- * two transpositions: chaining double-pays OKLCH quantization AND collides this
59
- * memo (a transposed palette keeps the base palette's name, so a re-transposed
60
- * gruvbox-with-look and plain gruvbox would share cache keys).
61
- *
62
- * [LAW:dataflow-not-control-flow] The key is data; the identity key flows
63
- * through transposePalette's isIdentityKey fast-path (byte-exact, no
64
- * round-trip) — no branch here. rich-js hue-locks ANCHORED_ROOTS
65
- * (error/success/warning), so semantic meaning is preserved by construction —
66
- * no local exemption list to drift.
67
- *
68
- * [LAW:single-enforcer] The sole place a transposed palette is built — a
69
- * future look `roles` remap is additive at this one seam. The memo miss
70
- * (undefined) is genuine optionality — not-yet-computed — not a defended
71
- * invariant. [LAW:one-source-of-truth] The cache key carries every axis of the
72
- * ThemeKey: two keys differing on any axis are distinct palettes.
73
- */
74
- export function transposedPalette(base: Palette, key: ThemeKey): Palette {
75
- const cacheKey =
76
- `${base.name} ${key.hueShift} ${key.chromaScale} ` +
77
- `${key.lightnessScale} ${key.lightnessShift}`;
78
- const hit = transposeCache.get(cacheKey);
79
- if (hit !== undefined) return hit;
80
-
81
- const transposed = transposePalette(base, key);
82
- transposeCache.set(cacheKey, transposed);
83
- return transposed;
84
- }