@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,91 +0,0 @@
1
- // [LAW:types-are-the-program] Wire-level snapshot shapes for the `debug`
2
- // protocol message. The `what` discriminator carries the response shape
3
- // forward — a client requesting "vars" gets vars data, "segments" gets
4
- // segments data, "config" gets config data. There is no `data: unknown`
5
- // field that callers must shape-check.
6
- //
7
- // [LAW:one-source-of-truth] These types are the single contract between the
8
- // daemon's introspection layer (src/daemon/debug.ts) and any external
9
- // consumer (the future `cc-candybar vars` / `lint` CLIs, debug tooling).
10
- // The protocol wraps them; the introspector produces them.
11
- //
12
- // Lives in its own module to break a potential cycle: protocol.ts re-exports
13
- // these for the wire type, debug.ts produces them, and both could otherwise
14
- // pull each other in.
15
-
16
- import type { VarType, VarValue } from "../var-system/types";
17
- import type { DslConfig, SourceKind } from "../config/dsl-types";
18
-
19
- // [LAW:one-source-of-truth] DEBUG_WHATS is the canonical list; DebugWhat is
20
- // *derived* from it via indexed access on the `as const` tuple type. Adding
21
- // a new entry to the array automatically expands DebugWhat — and the switch
22
- // in buildDebugSnapshot (src/daemon/debug.ts) becomes non-exhaustive,
23
- // failing the typecheck until a new arm is added. The dispatcher arm and
24
- // the canonical list are kept in lockstep by the type system, not by
25
- // human discipline.
26
- export const DEBUG_WHATS = ["vars", "segments", "config"] as const;
27
- export type DebugWhat = (typeof DEBUG_WHATS)[number];
28
-
29
- // Wire-side type guard for an untrusted JSON value. Used by the daemon at
30
- // the request boundary; symmetrically usable by future CLI shims that
31
- // validate user input before sending the frame.
32
- // [LAW:one-source-of-truth] Implemented in terms of DEBUG_WHATS so the
33
- // guard cannot drift from the canonical list — a new `what` added to
34
- // DEBUG_WHATS becomes accepted by isDebugWhat with no second-site edit.
35
- export function isDebugWhat(v: unknown): v is DebugWhat {
36
- return (
37
- typeof v === "string" && (DEBUG_WHATS as readonly string[]).includes(v)
38
- );
39
- }
40
-
41
- // One row of the `vars` snapshot. Captures everything an operator needs to
42
- // answer "is this variable computing? did it fail? when did it last update?"
43
- // without re-reading config or grepping logs.
44
- export interface VarSnapshot {
45
- readonly name: string;
46
- // The DSL source kind that declared this variable (literal/env/input/...).
47
- // null when a variable exists in the store but was not declared via DSL —
48
- // present for completeness so a programmatic-only var still shows up in
49
- // introspection rather than being silently invisible.
50
- readonly source: SourceKind | null;
51
- readonly type: VarType;
52
- // Current store value. For Computed nodes this triggers re-evaluation if
53
- // MobX has invalidated the cache; for Box nodes it is the last value set.
54
- readonly value: VarValue;
55
- readonly lastError: {
56
- readonly timestampMs: number;
57
- readonly message: string;
58
- } | null;
59
- // Wall-clock ms since the box was last set (Box) or null for Computed
60
- // nodes whose freshness is governed by MobX invalidation, not a single
61
- // timestamp. Null is structurally distinct from 0 so consumers can
62
- // distinguish "no age tracking applies" from "just updated."
63
- readonly ageMs: number | null;
64
- }
65
-
66
- // One row of the `segments` snapshot.
67
- export interface SegmentSnapshot {
68
- readonly name: string;
69
- // The template source string (verbatim, as authored in the config).
70
- readonly template: string;
71
- // Names of variables potentially referenced by the template, found via
72
- // static analysis: dotted paths inside `{{ ... }}` actions, matched
73
- // against the store's declared names. Exact runtime deps may be a subset
74
- // (branches not taken), but every name returned IS in the store.
75
- readonly referencedVars: readonly string[];
76
- // The last rendered output for this segment, when the daemon has captured
77
- // one. null today — the daemon does not yet render through the DSL spine
78
- // (see bzh.2). Populated when the daemon flips to renderDsl.
79
- readonly lastRender: string | null;
80
- }
81
-
82
- // [LAW:types-are-the-program] The discriminated union ensures every response
83
- // carries exactly the data shape its `what` promises. There is no path that
84
- // produces e.g. `{ what: "vars", segments: [...] }` — the type forbids it.
85
- export type DebugSnapshot =
86
- | { readonly what: "vars"; readonly vars: readonly VarSnapshot[] }
87
- | {
88
- readonly what: "segments";
89
- readonly segments: readonly SegmentSnapshot[];
90
- }
91
- | { readonly what: "config"; readonly config: DslConfig | null };
@@ -1,264 +0,0 @@
1
- // [LAW:single-enforcer] One module owns the projection from daemon DSL
2
- // state (VariableStore + SourceRegistry + DslConfig + CompiledConfig) to
3
- // the wire-level DebugSnapshot. buildDebugSnapshot dispatches via an
4
- // exhaustive switch on `what` — TypeScript enforces every DebugWhat arm
5
- // at compile time (the function's return-type narrowing fails if a case
6
- // is missing), so adding a new `what` requires one new arm here, one new
7
- // DEBUG_WHATS entry, and one new DebugSnapshot variant — the type system
8
- // keeps the three sites in lockstep.
9
- //
10
- // [LAW:one-source-of-truth] The introspector reads through the live
11
- // VariableStore (current values), SourceRegistry (lastErrors), VarNode
12
- // (lastUpdatedMs), and DslConfig (declared source kinds, segment templates).
13
- // There is no parallel cache, no shadow snapshot kept in sync — the daemon
14
- // has one DSL state and this module projects it.
15
- //
16
- // [LAW:dataflow-not-control-flow] The state slot (DaemonDslState | null) is
17
- // the only branch: null state → empty snapshots; populated state → real
18
- // snapshots. No special-case introspection paths for the "DSL not active
19
- // yet" case — the same code produces both outcomes from the same data.
20
- //
21
- // Today the daemon does not yet hold a DSL state (bzh.2 has not fired); all
22
- // snapshots are empty in production. When bzh.2 wires the store, the
23
- // snapshots populate without any change to this module or the protocol.
24
-
25
- import type { VariableStore } from "../var-system/store";
26
- import type { SourceRegistry } from "../var-system/sources";
27
- import type { DslConfig, SourceKind, VariableDecl } from "../config/dsl-types";
28
- import { walkNodes } from "../config/dsl-types";
29
- import { extractTemplateRefs } from "../config/dsl-loader";
30
- import type { CompiledConfig } from "../dsl/render";
31
- import type {
32
- DebugSnapshot,
33
- DebugWhat,
34
- SegmentSnapshot,
35
- VarSnapshot,
36
- } from "./debug-types";
37
-
38
- // The daemon's DSL state. Bundled because the four fields are co-installed
39
- // by registerDslConfig — exposing them as independently-optional would let
40
- // callers represent illegal combinations (e.g. store with no config).
41
- export interface DaemonDslState {
42
- readonly store: VariableStore;
43
- readonly registry: SourceRegistry;
44
- readonly config: DslConfig;
45
- readonly compiled: CompiledConfig;
46
- // [LAW:dataflow-not-control-flow] Per-segment last-render strings live in
47
- // the same state bundle the renderer mutates. Today (legacy renderer) it
48
- // is empty; bzh.2 populates it from inside renderDsl.
49
- readonly lastRenderBySegment: ReadonlyMap<string, string>;
50
- }
51
-
52
- // ─── Dispatcher ──────────────────────────────────────────────────────────────
53
-
54
- // [LAW:dataflow-not-control-flow] One arm per `what` — the discriminator is
55
- // data; the branch chooses the projection function, not whether projection
56
- // runs. Adding a new `what` is one new arm + one new projection + one new
57
- // DebugSnapshot variant — the type system enforces all three.
58
- export function buildDebugSnapshot(
59
- what: DebugWhat,
60
- state: DaemonDslState | null,
61
- ): DebugSnapshot {
62
- switch (what) {
63
- case "vars":
64
- return { what, vars: introspectVars(state) };
65
- case "segments":
66
- return { what, segments: introspectSegments(state) };
67
- case "config":
68
- return { what, config: introspectConfig(state) };
69
- }
70
- }
71
-
72
- // ─── vars ────────────────────────────────────────────────────────────────────
73
-
74
- // Project every variable currently registered in the store into one
75
- // VarSnapshot. Names sorted for deterministic snapshot tests. Source kind
76
- // is looked up from the DslConfig (top-level variables + per-segment
77
- // `vars` blocks); a variable not found in either is reported with
78
- // source=null so it still appears in introspection.
79
- export function introspectVars(
80
- state: DaemonDslState | null,
81
- ): readonly VarSnapshot[] {
82
- if (state === null) return [];
83
-
84
- const { store, registry, config } = state;
85
- const sourceByName = buildSourceKindIndex(config);
86
- const names = store.names().sort();
87
-
88
- const out: VarSnapshot[] = [];
89
- for (const name of names) {
90
- // [LAW:single-enforcer] One requireNode lookup per row. Reading the
91
- // value through node.read() instead of store.read(name) avoids a
92
- // second Map.get + requireNode round-trip in the inner loop and
93
- // makes the per-row data dependency obvious: every field below
94
- // comes from this one node.
95
- const node = store.getNode(name);
96
- const err = registry.getLastError(name);
97
- // [LAW:no-defensive-null-guards] No try/catch around node.read():
98
- // every SourceRegistry-declared variable either holds a typed
99
- // fallback (declareShell/declareFile/declareGit/declareInput catch
100
- // internally and write a fallback) or is a computed whose deriver
101
- // also catches (declareTemplate). Cycles are detected eagerly at
102
- // register time (declareTemplate's force-read). So a read-throw
103
- // here would be a *programming* error, not a runtime condition
104
- // the snapshot should mask. Letting it propagate keeps the failure
105
- // loud at the source instead of laundering it as a synthesized
106
- // lastError with an unstable Date.now() timestamp.
107
- //
108
- // [LAW:single-enforcer] lastError is sourced from SourceRegistry
109
- // only. There is no second timestamp-producer that could drift
110
- // from the registry's record.
111
- out.push({
112
- name,
113
- source: sourceByName.get(name) ?? null,
114
- type: node.type,
115
- value: node.read(),
116
- lastError:
117
- err !== undefined
118
- ? { timestampMs: err.timestamp, message: err.message }
119
- : null,
120
- ageMs: ageFromNode(node.lastUpdatedMs()),
121
- });
122
- }
123
- return out;
124
- }
125
-
126
- function ageFromNode(lastUpdatedMs: number | null): number | null {
127
- if (lastUpdatedMs === null) return null;
128
- return Math.max(0, Date.now() - lastUpdatedMs);
129
- }
130
-
131
- // Build a name → SourceKind index from the DslConfig. Walks top-level
132
- // variables and each segment's per-segment vars block; segment-local vars
133
- // live under the namespaced key `<segName>.<varName>` in the store (same
134
- // shape registerDslConfig uses to declare them).
135
- function buildSourceKindIndex(
136
- config: DslConfig,
137
- ): ReadonlyMap<string, SourceKind> {
138
- const index = new Map<string, SourceKind>();
139
- for (const [name, decl] of Object.entries(config.variables)) {
140
- index.set(name, sourceKindOf(decl));
141
- }
142
- for (const [segName, seg] of Object.entries(config.segments)) {
143
- if (!seg.vars) continue;
144
- for (const [varName, decl] of Object.entries(seg.vars)) {
145
- index.set(`${segName}.${varName}`, sourceKindOf(decl));
146
- }
147
- }
148
- return index;
149
- }
150
-
151
- function sourceKindOf(decl: VariableDecl): SourceKind {
152
- return decl.kind;
153
- }
154
-
155
- // ─── segments ────────────────────────────────────────────────────────────────
156
-
157
- export function introspectSegments(
158
- state: DaemonDslState | null,
159
- ): readonly SegmentSnapshot[] {
160
- if (state === null) return [];
161
-
162
- const { store, config, lastRenderBySegment } = state;
163
- const declaredNames = new Set(store.names());
164
- // [LAW:dataflow-not-control-flow] Walk in layout order so the introspection
165
- // snapshot mirrors render order — operators reading the snapshot see the
166
- // same sequence the bar produces, not an alphabetical reshuffling.
167
- const segNames = orderedSegmentNames(config);
168
-
169
- const out: SegmentSnapshot[] = [];
170
- for (const name of segNames) {
171
- const seg = config.segments[name];
172
- if (!seg) continue;
173
- out.push({
174
- name,
175
- template: seg.template,
176
- referencedVars: extractReferencedVars(seg.template, declaredNames),
177
- lastRender: lastRenderBySegment.get(name) ?? null,
178
- });
179
- }
180
- return out;
181
- }
182
-
183
- // Layout order, with any declared-but-not-laid-out segments appended in
184
- // declaration order so they still appear in the snapshot (an operator
185
- // debugging "why isn't this rendering" wants to see the segment, not have
186
- // it filtered out for being absent from layout).
187
- function orderedSegmentNames(config: DslConfig): readonly string[] {
188
- const out: string[] = [];
189
- const seen = new Set<string>();
190
- for (const node of walkNodes(config.root)) {
191
- if (node.kind !== "segment") continue;
192
- if (config.segments[node.name] && !seen.has(node.name)) {
193
- out.push(node.name);
194
- seen.add(node.name);
195
- }
196
- }
197
- for (const name of Object.keys(config.segments)) {
198
- if (!seen.has(name)) {
199
- out.push(name);
200
- seen.add(name);
201
- }
202
- }
203
- return out;
204
- }
205
-
206
- // [LAW:single-enforcer] Static analysis of which variables a segment
207
- // template references. Raw candidate extraction (find dotted paths inside
208
- // `{{ ... }}` actions, strip string literals so `{{ printf ".foo" }}`
209
- // does not falsely match a declared `foo`) is delegated to
210
- // extractTemplateRefs in src/config/dsl-loader.ts — that helper already
211
- // owns the template-ref parsing rules and is exercised by the loader's
212
- // cycle detector. Reusing it means a future improvement to the parser
213
- // (e.g. supporting `$x.field` variable references) lands here for free.
214
- //
215
- // Static analysis (not runtime evaluation) is the right tool here:
216
- // evaluation would couple introspection to a working store and would
217
- // vary by current values (if/with branches taken). Static finds every
218
- // potentially-referenced name regardless of current state — which is
219
- // what an operator debugging "what does this segment depend on" needs.
220
- //
221
- // This function adds the introspection-specific layers on top of the raw
222
- // extraction:
223
- // 1. Intersect with the declared-name set (only report names that exist).
224
- // 2. Ancestor credit: a candidate `.session.id.extra` resolves to the
225
- // declared `session.id` if `extra` is not declared.
226
- // 3. Sort the result for deterministic snapshots.
227
- export function extractReferencedVars(
228
- template: string,
229
- declared: ReadonlySet<string>,
230
- ): readonly string[] {
231
- const found = new Set<string>();
232
- for (const candidate of extractTemplateRefs(template)) {
233
- if (declared.has(candidate)) {
234
- found.add(candidate);
235
- continue;
236
- }
237
- // Drop trailing segments until we hit a declared name. Handles
238
- // `.session.id.something_extra` where only `session.id` is declared —
239
- // still credit it as a reference to `session.id`.
240
- const parts = candidate.split(".");
241
- while (parts.length > 1) {
242
- parts.pop();
243
- const prefix = parts.join(".");
244
- if (declared.has(prefix)) {
245
- found.add(prefix);
246
- break;
247
- }
248
- }
249
- }
250
- return Array.from(found).sort();
251
- }
252
-
253
- // ─── config ──────────────────────────────────────────────────────────────────
254
-
255
- // [LAW:no-defensive-null-guards] No defensive copy. DslConfig is `readonly`
256
- // throughout and the wire-encoder JSON-serializes it; downstream callers
257
- // see a fresh value. Returning the live reference is the cheapest correct
258
- // answer.
259
- export function introspectConfig(
260
- state: DaemonDslState | null,
261
- ): DslConfig | null {
262
- if (state === null) return null;
263
- return state.config;
264
- }