pi-crew 0.10.5 → 0.11.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 (128) hide show
  1. package/CHANGELOG.md +292 -0
  2. package/agents/analyst.md +37 -2
  3. package/agents/cold-verifier.md +10 -1
  4. package/agents/councillor-critic.md +39 -0
  5. package/agents/councillor-pragmatist.md +39 -0
  6. package/agents/councillor-skeptic.md +41 -0
  7. package/agents/critic.md +40 -2
  8. package/agents/designer.md +58 -0
  9. package/agents/executor.md +39 -2
  10. package/agents/explorer.md +38 -2
  11. package/agents/librarian.md +49 -0
  12. package/agents/oracle.md +54 -0
  13. package/agents/orchestrator.md +48 -0
  14. package/agents/planner.md +41 -2
  15. package/agents/reviewer.md +39 -2
  16. package/agents/security-reviewer.md +43 -2
  17. package/agents/test-engineer.md +48 -2
  18. package/agents/verifier.md +14 -1
  19. package/agents/writer.md +32 -2
  20. package/dist/index.mjs +35196 -34789
  21. package/package.json +170 -169
  22. package/scripts/watch-agent-transcript.mjs +120 -0
  23. package/skills/async-worker-recovery/SKILL.md +4 -1
  24. package/skills/child-pi-spawning/SKILL.md +4 -1
  25. package/skills/context-artifact-hygiene/SKILL.md +4 -1
  26. package/skills/council/SKILL.md +24 -45
  27. package/skills/delegation-patterns/SKILL.md +18 -1
  28. package/skills/distill-persona/SKILL.md +4 -1
  29. package/skills/distill-software/SKILL.md +4 -1
  30. package/skills/event-log-tracing/SKILL.md +4 -1
  31. package/skills/git-master/SKILL.md +4 -1
  32. package/skills/iterative-audit/SKILL.md +4 -1
  33. package/skills/live-agent-lifecycle/SKILL.md +4 -1
  34. package/skills/mailbox-interactive/SKILL.md +4 -1
  35. package/skills/model-routing-context/SKILL.md +10 -1
  36. package/skills/multi-perspective-review/SKILL.md +18 -1
  37. package/skills/observability-reliability/SKILL.md +4 -1
  38. package/skills/orchestration/SKILL.md +18 -1
  39. package/skills/ownership-session-security/SKILL.md +4 -1
  40. package/skills/pi-extension-lifecycle/SKILL.md +4 -1
  41. package/skills/post-mortem/SKILL.md +4 -1
  42. package/skills/read-only-explorer/SKILL.md +4 -1
  43. package/skills/real-test-pi-crew/SKILL.md +165 -12
  44. package/skills/requirements-to-task-packet/SKILL.md +10 -1
  45. package/skills/research/SKILL.md +4 -1
  46. package/skills/resource-discovery-config/SKILL.md +10 -1
  47. package/skills/runtime-state-reader/SKILL.md +4 -1
  48. package/skills/safe-bash/SKILL.md +4 -1
  49. package/skills/scrutinize/SKILL.md +24 -1
  50. package/skills/secure-agent-orchestration-review/SKILL.md +4 -1
  51. package/skills/state-mutation-locking/SKILL.md +4 -1
  52. package/skills/systematic-debugging/SKILL.md +4 -1
  53. package/skills/verification-before-done/SKILL.md +18 -1
  54. package/skills/widget-rendering/SKILL.md +4 -1
  55. package/skills/workspace-isolation/SKILL.md +4 -1
  56. package/skills/worktree-isolation/SKILL.md +4 -1
  57. package/src/config/config-validation.ts +1 -0
  58. package/src/config/types.ts +8 -0
  59. package/src/errors.ts +1 -1
  60. package/src/extension/context-status-injection.ts +2 -2
  61. package/src/extension/crew-input-router.ts +2 -0
  62. package/src/extension/crew-vibes/config.ts +1 -56
  63. package/src/extension/crew-vibes/figures.ts +5 -84
  64. package/src/extension/crew-vibes/font-detect.ts +1 -1
  65. package/src/extension/crew-vibes/index.ts +36 -328
  66. package/src/extension/crew-vibes/render.ts +2 -58
  67. package/src/extension/help.ts +1 -0
  68. package/src/extension/knowledge-injection.ts +19 -7
  69. package/src/extension/post-init-skill-check.ts +32 -0
  70. package/src/extension/register.ts +9 -1
  71. package/src/extension/registration/command-registration.ts +5 -1
  72. package/src/extension/registration/commands/schedules.ts +212 -0
  73. package/src/extension/registration/commands/shared.ts +56 -1
  74. package/src/extension/registration/hook-registration.ts +20 -3
  75. package/src/extension/registration/lifecycle-handlers.ts +16 -2
  76. package/src/extension/registration/schedule-toast-bridge.ts +109 -0
  77. package/src/extension/registration/tool-loop-guard.ts +243 -0
  78. package/src/extension/registration/viewers.ts +66 -1
  79. package/src/extension/team-tool/handle-schedule.ts +120 -1
  80. package/src/extension/team-tool/handle-settings.ts +10 -0
  81. package/src/extension/team-tool/run.ts +42 -1
  82. package/src/extension/team-tool-types.ts +6 -0
  83. package/src/prompt/prompt-runtime.ts +25 -6
  84. package/src/runtime/async-runner.ts +75 -11
  85. package/src/runtime/background-runner.ts +41 -0
  86. package/src/runtime/broker/crew-broker-client.ts +45 -2
  87. package/src/runtime/broker/crew-broker.ts +22 -27
  88. package/src/runtime/broker/protocol/request-parsers.ts +10 -2
  89. package/src/runtime/broker/stdin-handshake.ts +87 -0
  90. package/src/runtime/broker/wait-push.ts +45 -0
  91. package/src/runtime/detached-run-results.ts +25 -1
  92. package/src/runtime/foreground-watchdog.ts +24 -5
  93. package/src/runtime/live-session/live-session-runtime.ts +1 -1
  94. package/src/runtime/model/model-scope.ts +2 -2
  95. package/src/runtime/run-tracker.ts +65 -11
  96. package/src/runtime/scheduling/scheduler.ts +120 -6
  97. package/src/runtime/settings-store.ts +28 -2
  98. package/src/runtime/skill-instructions.ts +20 -4
  99. package/src/runtime/task-runner/child-executor.ts +1 -1
  100. package/src/runtime/task-runner/prompt-builder.ts +22 -9
  101. package/src/schema/config-schema.ts +1 -0
  102. package/src/skills/discover-skills.ts +2 -2
  103. package/src/state/coordination/locks.ts +17 -2
  104. package/src/ui/agents-jobs-browser.ts +785 -0
  105. package/src/ui/dashboard-panes/agents-pane.ts +7 -4
  106. package/src/ui/dashboard-panes/schedules-pane.ts +154 -0
  107. package/src/ui/inline-panel/crew-editor.ts +19 -6
  108. package/src/ui/inline-panel/index.ts +6 -0
  109. package/src/ui/key-utils.ts +3 -0
  110. package/src/ui/keybinding-map.ts +56 -2
  111. package/src/ui/mascot.ts +2 -1
  112. package/src/ui/overlays/agent-picker-overlay.ts +3 -3
  113. package/src/ui/overlays/confirm-overlay.ts +3 -2
  114. package/src/ui/overlays/mailbox-compose-overlay.ts +4 -3
  115. package/src/ui/overlays/mailbox-detail-overlay.ts +3 -3
  116. package/src/ui/run-dashboard.ts +257 -6
  117. package/src/ui/settings-overlay.ts +43 -3
  118. package/src/ui/transcript-viewer.ts +3 -2
  119. package/src/ui/widget/index.ts +61 -88
  120. package/src/ui/widget/widget-formatters.ts +7 -4
  121. package/src/ui/widget/widget-renderer.ts +134 -174
  122. package/src/ui/widget/widget-types.ts +0 -7
  123. package/src/utils/frontmatter.ts +7 -1
  124. package/src/utils/ndjson.ts +9 -1
  125. package/src/utils/relative-time.ts +33 -0
  126. package/src/extension/crew-vibes/footer.ts +0 -313
  127. package/src/extension/crew-vibes/speed.ts +0 -286
  128. package/src/ui/dock-footer.ts +0 -49
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: resource-discovery-config
3
- description: "pi-crew resource and configuration discovery workflow."
3
+ description: >
4
+ pi-crew resource and configuration discovery workflow.
5
+ When NOT to use: runtime state questions (use runtime-state-reader); model-specific config (use model-routing-context).
6
+
4
7
  origin: pi-crew
5
8
  triggers:
6
9
  - "discover agents"
@@ -58,3 +61,9 @@ node --experimental-strip-types --test test/unit/config-schema-validation.test.t
58
61
  npm test
59
62
  npm pack --dry-run
60
63
  ```
64
+
65
+ ## Self-restraint
66
+
67
+ "Creating nothing is a valid result." If the evidence does not support a meaningful change, say so explicitly rather than inventing one. The next attempt may find stronger evidence; an invented change now damages trust in every future report.
68
+
69
+ "Creating nothing" here means the current discovery already finds what consumers need. Registering resources nobody uses pollutes the discovery surface and slows every lookup.
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: runtime-state-reader
3
- description: Safe read-only navigation of pi-crew run state.
3
+ description: >
4
+ Safe read-only navigation of pi-crew run state.
5
+ When NOT to use: write actions or mutations (use state-mutation-locking); configuration changes (use resource-discovery-config).
6
+
4
7
  origin: pi-crew
5
8
  triggers:
6
9
  - "inspect manifest"
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: safe-bash
3
- description: "Safe shell-command workflow."
3
+ description: >
4
+ Safe shell-command workflow.
5
+ When NOT to use: subprocess orchestration (use child-pi-spawning); destructive operations without sandbox (use ownership-session-security).
6
+
4
7
  origin: pi-crew
5
8
  triggers:
6
9
  - "run this command"
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: scrutinize
3
- description: "Outsider-perspective review questioning intent before tracing code."
3
+ description: >
4
+ Outsider-perspective review questioning intent before tracing code.
5
+ When NOT to use: implementation work (use systematic-debugging); trivial one-line fixes that don't warrant outsider review.
6
+
4
7
  origin: pi-crew
5
8
  triggers:
6
9
  - "scrutinize this"
@@ -84,3 +87,23 @@ If ANY answer is NO → Stop. Complete scrutiny requirements before reporting.
84
87
  - **One simpler-alternative pass is MANDATORY.** Skip only if user says "don't question scope."
85
88
  - **Distinguish claim from verification.** "The PR says X" and "I traced X and confirmed" are different.
86
89
  - **No flattery, no hedging.** State the finding.
90
+
91
+ ## Budget
92
+
93
+ This skill applies a 3-attempt budget: 1 initial + max 2 re-attempts.
94
+
95
+ Stamp every invocation:
96
+
97
+ ```
98
+ attempt X of 3 (Y attempts remaining)
99
+ ```
100
+
101
+ An attempt is one full outsider-perspective review pass. Re-attempt when the review uncovers intent-level questions that change the approach.
102
+
103
+ Re-attempts only when the previous attempt materially changes the decision or risk. Do NOT spend a re-attempt on mechanical changes or already-resolved findings. When exhausted, escalate to the user with options (accept risk / change scope / exceptional budget).
104
+
105
+ ## Self-restraint
106
+
107
+ "Creating nothing is a valid result." If the evidence does not support a meaningful change, say so explicitly rather than inventing one. The next attempt may find stronger evidence; an invented change now damages trust in every future report.
108
+
109
+ "Creating nothing" here means concluding the intent was sound and the approach justified — no findings needed. An invented finding to justify the review round damages trust in every future review.
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: secure-agent-orchestration-review
3
- description: "Use when reviewing delegation, skill loading, tool access, worker prompts, artifacts, runtime config, state, ownership, or subprocess execution."
3
+ description: >
4
+ Use when reviewing delegation, skill loading, tool access, worker prompts, artifacts, runtime config, state, ownership, or subprocess execution.
5
+ When NOT to use: pure code quality issues without security implications (use multi-perspective-review); single-file fixes (use scrutinize).
6
+
4
7
  origin: pi-crew
5
8
  triggers:
6
9
  - "review delegation"
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: state-mutation-locking
3
- description: "Durable state mutation and locking workflow."
3
+ description: >
4
+ Durable state mutation and locking workflow.
5
+ When NOT to use: read-only inspection (use runtime-state-reader); single-process non-concurrent edits.
6
+
4
7
  origin: pi-crew
5
8
  triggers:
6
9
  - "modify manifest"
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: systematic-debugging
3
- description: "Four-phase debugging discipline with refuse gates."
3
+ description: >
4
+ Four-phase debugging discipline with refuse gates.
5
+ When NOT to use: trivial fixes where root cause is obvious; production incidents needing immediate rollback (use post-mortem after).
6
+
4
7
  origin: pi-crew
5
8
  triggers:
6
9
  - "debug this"
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: verification-before-done
3
- description: "Evidence before claims."
3
+ description: >
4
+ Evidence before claims.
5
+ When NOT to use: mid-task self-correction (use scrutinize); pure execution tasks where output IS evidence.
6
+
4
7
  origin: pi-crew
5
8
  triggers:
6
9
  - "done"
@@ -80,3 +83,17 @@ Stop before saying done if you are using words like "should", "probably", "looks
80
83
  - **Don't** use fuzzy language like "seems", "probably", "looks like"
81
84
  - **Don't** skip providing verification commands for claims
82
85
  - **Don't** claim done if you're still using hypotheses instead of evidence
86
+
87
+ ## Budget
88
+
89
+ This skill applies a 3-attempt budget: 1 initial + max 2 re-attempts.
90
+
91
+ Stamp every invocation:
92
+
93
+ ```
94
+ attempt X of 3 (Y attempts remaining)
95
+ ```
96
+
97
+ An attempt is one fresh verification run (identify command → run → read output → compare to claim). Re-attempt when output contradicts the claim or reveals a new failure mode.
98
+
99
+ Re-attempts only when the previous attempt materially changes the decision or risk. Do NOT spend a re-attempt on mechanical changes or already-resolved findings. When exhausted, escalate to the user with options (accept risk / change scope / exceptional budget).
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: widget-rendering
3
- description: "Pi TUI crew widget data sources, display priority, and rendering performance."
3
+ description: >
4
+ Pi TUI crew widget data sources, display priority, and rendering performance.
5
+ When NOT to use: non-TUI displays; backend data sources without widget context (use runtime-state-reader).
6
+
4
7
  origin: pi-crew
5
8
  triggers:
6
9
  - "empty agent"
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: workspace-isolation
3
- description: "Workspace isolation boundaries."
3
+ description: >
4
+ Workspace isolation boundaries.
5
+ When NOT to use: concurrent edits within same repo (use worktree-isolation); non-git projects.
6
+
4
7
  origin: pi-crew
5
8
  triggers:
6
9
  - "workspace isolation"
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: worktree-isolation
3
- description: "Conflict-safe git worktree workflow."
3
+ description: >
4
+ Conflict-safe git worktree workflow.
5
+ When NOT to use: non-git changes (use direct edit); single-commit patches (use git-master).
6
+
4
7
  origin: pi-crew
5
8
  triggers:
6
9
  - "create worktree"
@@ -640,6 +640,7 @@ function parseReliabilityConfig(value: unknown): CrewReliabilityConfig | undefin
640
640
  forcePreflight: parseWithSchema(Type.Boolean(), obj.forcePreflight),
641
641
  ambientStatusInjection: parseWithSchema(Type.Boolean(), obj.ambientStatusInjection),
642
642
  perWriteValidation: parseWithSchema(Type.Boolean(), obj.perWriteValidation),
643
+ loopGuard: parseWithSchema(Type.Boolean(), obj.loopGuard),
643
644
  scopeModels: parseWithSchema(Type.Boolean(), obj.scopeModels),
644
645
  };
645
646
  return Object.values(reliability).some((entry) => entry !== undefined) ? reliability : undefined;
@@ -274,6 +274,14 @@ export interface CrewReliabilityConfig {
274
274
  * Set to `false` to disable.
275
275
  */
276
276
  perWriteValidation?: boolean;
277
+ /**
278
+ * Tool loop guard (ARCH-1). Warns at 3 consecutive identical tool results
279
+ * (identical args + byte-identical output) and hard-blocks read-only file
280
+ * tools (read/grep/glob/find/ls) at 5 — the model-side infinite-loop
281
+ * failure mode. `ask` repeats within a turn are warned at 2 and the 3rd
282
+ * call refused. Default: true (opt-out). Set to `false` to disable.
283
+ */
284
+ loopGuard?: boolean;
277
285
  /**
278
286
  * Opt-in model scope enforcement (F7). When true, subagent model choices
279
287
  * that fall outside the user's pi `enabledModels` allowlist are flagged:
package/src/errors.ts CHANGED
@@ -64,7 +64,7 @@ const DEFAULT_HELP: Record<ErrorCode, string | undefined> = {
64
64
  [ErrorCode.RunStale]:
65
65
  "The worker stopped heartbeating and was treated as a zombie. Re-run the team (resume or fresh); if it recurs, check `runtime.executeWorkers` / system load.",
66
66
  [ErrorCode.ModelOutOfScope]:
67
- "The requested model is not in your pi `enabledModels` allowlist. Either pick a model listed in `enabledModels` (settings.json) or extend the allowlist. The scope gate is opt-in — disable `runtime.reliability.scopeModels` to allow any model.",
67
+ "The requested model is not in your pi `enabledModels` allowlist. Either pick a model listed in `enabledModels` (settings.json) or extend the allowlist. The scope gate is opt-in — disable `reliability.scopeModels` to allow any model.",
68
68
  };
69
69
 
70
70
  /**
@@ -28,7 +28,7 @@
28
28
  * - `emitContext` already wraps handlers in try/catch and emits errors instead
29
29
  * of crashing the loop (Pi `runner.ts:933`), so a throw here can't break the
30
30
  * agent — but we also guard defensively.
31
- * - Opt-out: `runtime.reliability.ambientStatusInjection: false` in config.
31
+ * - Opt-out: `reliability.ambientStatusInjection: false` in config.
32
32
  */
33
33
 
34
34
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
@@ -163,7 +163,7 @@ export function handleContextEvent(event: ContextEvent, cwd: string, sessionId?:
163
163
  * Register the ambient-status `context` event handler. Reads the project cwd
164
164
  * from the session context on each call (crew state is per-project).
165
165
  *
166
- * Pass `enabled: false` (from `runtime.reliability.ambientStatusInjection`) to
166
+ * Pass `enabled: false` (from `reliability.ambientStatusInjection`) to
167
167
  * disable the feature without unwiring the handler.
168
168
  */
169
169
  export function registerContextStatusInjection(pi: ExtensionAPI, opts: { enabled?: boolean } = {}): void {
@@ -34,6 +34,8 @@ export const CREW_PHRASES: ReadonlyArray<{ phrase: string; command: string }> =
34
34
  { phrase: "crew commands", command: "/team-help" },
35
35
  { phrase: "crew doctor", command: "/team-doctor" },
36
36
  { phrase: "crew diagnose", command: "/team-doctor" },
37
+ { phrase: "crew schedule", command: "/schedules" },
38
+ { phrase: "scheduled jobs", command: "/schedules" },
37
39
  { phrase: "teams", command: "/teams" },
38
40
  ];
39
41
 
@@ -4,12 +4,11 @@ import { getCrewEnv } from "../../config/env-vars.ts";
4
4
  import { hasCrewFontFile, isWebTerminal } from "./font-detect.ts";
5
5
 
6
6
  /**
7
- * Self-contained config for the crew-vibes module (speed + capacity meters).
7
+ * Self-contained config for the crew-vibes module (provider quota).
8
8
  * Stored in its own JSON file so it never touches the strict typebox schema
9
9
  * used by the rest of pi-crew.
10
10
  */
11
11
 
12
- export const SPEED_STATUS_ID = "pi-crew-speed";
13
12
  export const CAPACITY_STATUS_ID = "pi-crew-bar";
14
13
  export const PROVIDER_STATUS_ID = "pi-crew-bar";
15
14
 
@@ -23,21 +22,6 @@ export function configPath(): string {
23
22
 
24
23
  export type TokenDisplay = "off" | "tokens" | "percentage";
25
24
 
26
- export interface SpeedConfig {
27
- enabled: boolean;
28
- footer: boolean;
29
- indicator: boolean;
30
- label: string;
31
- renderIntervalMs: number;
32
- slidingWindowMs: number;
33
- minReliableDurationMs: number;
34
- maxDisplayTokS: number;
35
- defaultIntervalMs: number;
36
- minIntervalMs: number;
37
- maxIntervalMs: number;
38
- scale: number;
39
- }
40
-
41
25
  export interface CapacityConfig {
42
26
  enabled: boolean;
43
27
  tokenDisplay: TokenDisplay;
@@ -51,26 +35,11 @@ export interface CapacityConfig {
51
35
 
52
36
  export interface CrewVibesConfig {
53
37
  enabled: boolean;
54
- speed: SpeedConfig;
55
38
  capacity: CapacityConfig;
56
39
  }
57
40
 
58
41
  export const DEFAULT_CONFIG: CrewVibesConfig = {
59
42
  enabled: true,
60
- speed: {
61
- enabled: true,
62
- footer: false,
63
- indicator: true,
64
- label: "tok/s",
65
- renderIntervalMs: 250,
66
- slidingWindowMs: 1000,
67
- minReliableDurationMs: 1000,
68
- maxDisplayTokS: 500,
69
- defaultIntervalMs: 167,
70
- minIntervalMs: 50,
71
- maxIntervalMs: 250,
72
- scale: 6000,
73
- },
74
43
  capacity: {
75
44
  enabled: true,
76
45
  tokenDisplay: "tokens",
@@ -133,29 +102,6 @@ function tokenDisplayFrom(raw: unknown, fallback: TokenDisplay): TokenDisplay {
133
102
  return raw === "off" || raw === "tokens" || raw === "percentage" ? raw : fallback;
134
103
  }
135
104
 
136
- function normalizeSpeed(raw: unknown): SpeedConfig {
137
- const input = asRecord(raw);
138
- const speed: SpeedConfig = {
139
- enabled: boolFrom(input.enabled, DEFAULT_CONFIG.speed.enabled),
140
- footer: boolFrom(input.footer, DEFAULT_CONFIG.speed.footer),
141
- indicator: boolFrom(input.indicator, DEFAULT_CONFIG.speed.indicator),
142
- label: stringFrom(input.label, DEFAULT_CONFIG.speed.label),
143
- renderIntervalMs: positiveFrom(input.renderIntervalMs, DEFAULT_CONFIG.speed.renderIntervalMs),
144
- slidingWindowMs: positiveFrom(input.slidingWindowMs, DEFAULT_CONFIG.speed.slidingWindowMs),
145
- minReliableDurationMs: positiveFrom(input.minReliableDurationMs, DEFAULT_CONFIG.speed.minReliableDurationMs),
146
- maxDisplayTokS: positiveFrom(input.maxDisplayTokS, DEFAULT_CONFIG.speed.maxDisplayTokS),
147
- defaultIntervalMs: positiveFrom(input.defaultIntervalMs, DEFAULT_CONFIG.speed.defaultIntervalMs),
148
- minIntervalMs: positiveFrom(input.minIntervalMs, DEFAULT_CONFIG.speed.minIntervalMs),
149
- maxIntervalMs: positiveFrom(input.maxIntervalMs, DEFAULT_CONFIG.speed.maxIntervalMs),
150
- scale: positiveFrom(input.scale, DEFAULT_CONFIG.speed.scale),
151
- };
152
- if (speed.minIntervalMs > speed.maxIntervalMs) {
153
- speed.minIntervalMs = DEFAULT_CONFIG.speed.minIntervalMs;
154
- speed.maxIntervalMs = DEFAULT_CONFIG.speed.maxIntervalMs;
155
- }
156
- return speed;
157
- }
158
-
159
105
  function normalizeCapacity(raw: unknown): CapacityConfig {
160
106
  const input = asRecord(raw);
161
107
  return {
@@ -174,7 +120,6 @@ export function normalizeConfig(raw: unknown): CrewVibesConfig {
174
120
  const input = asRecord(raw);
175
121
  return {
176
122
  enabled: boolFrom(input.enabled, DEFAULT_CONFIG.enabled),
177
- speed: normalizeSpeed(input.speed),
178
123
  capacity: normalizeCapacity(input.capacity),
179
124
  };
180
125
  }
@@ -1,91 +1,12 @@
1
- import type { SpeedConfig } from "./config.ts";
2
- import { hasCrewFontFile, isWebTerminal } from "./font-detect.ts";
3
-
4
1
  /**
5
- * Crew figures replacing the original cat glyphs from pi-speeed / pi-chonk.
6
- *
7
- * The working indicator uses braille spinner characters by default — the
8
- * same characters pi uses for its built-in loading animation (loaders.ts
9
- * DEFAULT_FRAMES). These render on ANY terminal with basic Unicode support,
10
- * no custom font required.
2
+ * Capacity-stage helpers (shared by renderCapacity, which remains exported
3
+ * for its unit tests after the footer retirement).
11
4
  *
12
- * PUA glyphs (U+E700..U+E70F) from the bundled crew-vibes.ttf font are
13
- * available as an opt-in alternative (set speed.indicatorStyle = "pua" in
14
- * config). Requires the font to be installed via `npm run install:crew-font`
15
- * AND a terminal that renders Private Use Area codepoints.
5
+ * The speed-UI parts of this module (braille/PUA spinner frames,
6
+ * intervalForSpeed) were REMOVED with the tok/s speed UI (maintainer
7
+ * decision 2026-09-14) — pi's built-in working indicator is always used.
16
8
  */
17
9
 
18
- // ── Braille spinner frames (web terminal fallback) ───────────────────
19
- // Standard Unicode braille spinner — same characters pi uses for its
20
- // built-in loading animation. Renders on ANY terminal.
21
- const BRAILLE_FRAMES: readonly string[] = [
22
- "\u280B ", // ⠋
23
- "\u2819 ", // ⠙
24
- "\u2839 ", // ⠹
25
- "\u2838 ", // ⠸
26
- "\u283C ", // ⠼
27
- "\u2834 ", // ⠴
28
- "\u2826 ", // ⠦
29
- "\u2827 ", // ⠧
30
- "\u2807 ", // ⠇
31
- "\u280F ", // ⠏
32
- ] as const;
33
-
34
- // ── PUA runner frames (opt-in) ────────────────────────────────────────
35
- // 16 runner poses from the bundled crew-vibes.ttf font. Only usable when
36
- // the font is installed AND the terminal renders PUA codepoints correctly.
37
- // Each frame is one glyph + trailing space for constant 2-cell width.
38
- const PUA_CREW_FRAMES: readonly string[] = [
39
- "\uE700 ",
40
- "\uE701 ",
41
- "\uE702 ",
42
- "\uE703 ",
43
- "\uE704 ",
44
- "\uE705 ",
45
- "\uE706 ",
46
- "\uE707 ",
47
- "\uE708 ",
48
- "\uE709 ",
49
- "\uE70A ",
50
- "\uE70B ",
51
- "\uE70C ",
52
- "\uE70D ",
53
- "\uE70E ",
54
- "\uE70F ",
55
- ] as const;
56
-
57
- /**
58
- * Return the indicator frames for the given style.
59
- *
60
- * Default is `"braille"` — standard Unicode braille spinner (⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏)
61
- * that renders correctly on every terminal, every platform, with zero
62
- * font dependency. PUA runner-glyphs require crew-vibes.ttf installed AND
63
- * a terminal that does font fallback for Private Use Area codepoints —
64
- * Windows Terminal does NOT do this reliably, showing garbage chars even
65
- * with the font installed.
66
- *
67
- * To opt into the PUA runner look, pass `style: "pua"` explicitly.
68
- */
69
- export function crewFrames(style: "braille" | "pua" = "braille"): readonly string[] {
70
- // Even when explicitly requested, fall back to braille if the font is
71
- // missing or we're on a web terminal (which can't render PUA at all).
72
- if (style === "pua" && (isWebTerminal() || !hasCrewFontFile())) return BRAILLE_FRAMES;
73
- return style === "pua" ? PUA_CREW_FRAMES : BRAILLE_FRAMES;
74
- }
75
-
76
- // Re-export PUA frames for backward compatibility and direct consumers.
77
- export const RUN_CREW_FRAMES = PUA_CREW_FRAMES;
78
-
79
- /**
80
- * Map a tok/s reading to a working-indicator frame interval in ms.
81
- * Ported from pi-speeed's runcatInterval: interval = scale / speed, clamped
82
- * to [min, max]. A null/zero speed falls back to the default (idle) cadence.
83
- */
84
- export function intervalForSpeed(config: SpeedConfig, speed: number | null): number {
85
- if (speed === null || !Number.isFinite(speed) || speed <= 0) return config.defaultIntervalMs;
86
- return Math.max(config.minIntervalMs, Math.min(config.maxIntervalMs, Math.round(config.scale / speed)));
87
- }
88
-
89
10
  /**
90
11
  * Pick the capacity stage index (0..levels-1) for a context-fill percent.
91
12
  * Ported from pi-chonk's chonkIndex.
@@ -8,7 +8,7 @@ import { join } from "node:path";
8
8
  * guarantee the terminal can render PUA glyphs (many terminals have their
9
9
  * own font stacks). For reliable animation, braille fallback frames are
10
10
  * used by default; PUA frames are only activated when the user explicitly
11
- * enables them via config (speed.indicatorStyle = "pua").
11
+ * (used by the capacity icons).
12
12
  */
13
13
 
14
14
  function fontPath(): string {