pi-crew 0.9.67 → 0.10.1

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 (222) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/agents/analyst.md +1 -1
  3. package/agents/cold-verifier.md +3 -1
  4. package/agents/critic.md +1 -1
  5. package/agents/executor.md +1 -1
  6. package/agents/explorer.md +1 -1
  7. package/agents/planner.md +1 -1
  8. package/agents/reviewer.md +1 -1
  9. package/agents/security-reviewer.md +1 -1
  10. package/agents/test-engineer.md +1 -1
  11. package/agents/verifier.md +1 -1
  12. package/agents/writer.md +1 -1
  13. package/dist/index.mjs +65847 -60331
  14. package/docs/README.md +2 -0
  15. package/docs/actions-reference.md +31 -0
  16. package/docs/commands-reference.md +17 -6
  17. package/docs/resource-formats.md +13 -0
  18. package/package.json +9 -6
  19. package/schema.json +15 -1
  20. package/scripts/resource-sampler.mjs +36 -2
  21. package/skills/requirements-to-task-packet/SKILL.md +26 -0
  22. package/skills/widget-rendering/SKILL.md +7 -7
  23. package/src/agents/agent-config.ts +36 -14
  24. package/src/agents/discover-agents.ts +23 -14
  25. package/src/config/config-merge.ts +183 -0
  26. package/src/config/config-validation.ts +681 -0
  27. package/src/config/config.ts +22 -864
  28. package/src/config/defaults.ts +35 -1
  29. package/src/config/drift-detector.ts +1 -1
  30. package/src/config/env-vars.ts +691 -0
  31. package/src/config/role-tools.ts +8 -8
  32. package/src/config/sanitize-project-config.ts +172 -0
  33. package/src/config/types.ts +30 -0
  34. package/src/extension/async-notifier.ts +25 -2
  35. package/src/extension/crew-vibes/config.ts +2 -1
  36. package/src/extension/plan-orchestrate.ts +132 -0
  37. package/src/extension/registration/commands/dashboard.ts +158 -0
  38. package/src/extension/registration/commands/index.ts +35 -0
  39. package/src/extension/registration/commands/manage.ts +303 -0
  40. package/src/extension/registration/commands/run.ts +214 -0
  41. package/src/extension/registration/commands/shared.ts +631 -0
  42. package/src/extension/registration/commands/status.ts +60 -0
  43. package/src/extension/registration/commands.ts +13 -1224
  44. package/src/extension/registration/lifecycle-handlers.ts +126 -15
  45. package/src/extension/registration/subagent-tools.ts +218 -9
  46. package/src/extension/rpc-hmac.ts +5 -3
  47. package/src/extension/team-tool/api/heartbeat.ts +47 -10
  48. package/src/extension/team-tool/api/plan-approval.ts +9 -0
  49. package/src/extension/team-tool/api/task-claims.ts +109 -40
  50. package/src/extension/team-tool/cancel.ts +84 -50
  51. package/src/extension/team-tool/dispatch/index.ts +1 -0
  52. package/src/extension/team-tool/dispatch/run.ts +4 -1
  53. package/src/extension/team-tool/doctor.ts +103 -1
  54. package/src/extension/team-tool/orchestrate.ts +66 -1
  55. package/src/extension/team-tool/plans.ts +192 -0
  56. package/src/extension/team-tool/respond.ts +197 -65
  57. package/src/extension/team-tool/run-deadline.ts +16 -1
  58. package/src/extension/team-tool/run-intent.ts +63 -0
  59. package/src/extension/team-tool/run.ts +48 -18
  60. package/src/extension/team-tool/status.ts +84 -26
  61. package/src/extension/team-tool.ts +11 -2
  62. package/src/hooks/registry.ts +1 -6
  63. package/src/i18n.ts +9 -0
  64. package/src/prompt/prompt-runtime.ts +521 -2
  65. package/src/prompt/worker-events-channel.ts +173 -0
  66. package/src/runtime/README.md +8 -8
  67. package/src/runtime/async-runner.ts +7 -3
  68. package/src/runtime/background-runner.ts +42 -14
  69. package/src/runtime/broker/broker-issuer.ts +9 -2
  70. package/src/runtime/broker/crew-broker-tokens.ts +43 -6
  71. package/src/runtime/broker/crew-broker.ts +838 -10
  72. package/src/runtime/broker/wait-status-cache.ts +157 -0
  73. package/src/runtime/budget-enforcement.ts +281 -0
  74. package/src/runtime/child-pi/child-pi-spawn.ts +60 -14
  75. package/src/runtime/child-pi/child-pi-timers.ts +324 -0
  76. package/src/runtime/child-pi/child-pi.ts +97 -201
  77. package/src/runtime/child-pi/mock-fixtures.ts +16 -2
  78. package/src/runtime/crew-agent-records.ts +259 -14
  79. package/src/runtime/delegate-spawn.ts +148 -0
  80. package/src/runtime/deterministic-ast.ts +2 -1
  81. package/src/runtime/dispatch-batch.ts +945 -0
  82. package/src/runtime/finalize-run.ts +557 -0
  83. package/src/runtime/goal-workflow/adaptive-plan.ts +87 -13
  84. package/src/runtime/goal-workflow/dynamic-workflow-runner.ts +3 -2
  85. package/src/runtime/goal-workflow/goal-state-store.ts +1 -1
  86. package/src/runtime/group-join.ts +11 -125
  87. package/src/runtime/live-session/live-session-runtime.ts +26 -1
  88. package/src/runtime/merge-gate.ts +7 -1
  89. package/src/runtime/merge-loop.ts +130 -0
  90. package/src/runtime/model/model-budget-summary.ts +53 -0
  91. package/src/runtime/model/model-fallback.ts +32 -2
  92. package/src/runtime/model/pi-args.ts +10 -0
  93. package/src/runtime/model/provider-extensions.ts +10 -0
  94. package/src/runtime/orphan-worker-registry.ts +1 -1
  95. package/src/runtime/output/output-validator.ts +45 -0
  96. package/src/runtime/parent-guard.ts +3 -1
  97. package/src/runtime/peer-dep.ts +2 -1
  98. package/src/runtime/per-write-validator.ts +0 -5
  99. package/src/runtime/pi-spawn.ts +61 -15
  100. package/src/runtime/plan-approval.ts +125 -0
  101. package/src/runtime/plan-replan.ts +151 -0
  102. package/src/runtime/recovery/checkpoint.ts +0 -18
  103. package/src/runtime/recovery/crash-recovery.ts +95 -46
  104. package/src/runtime/scheduler-context.ts +98 -0
  105. package/src/runtime/scheduling/coalesce-tasks.ts +5 -0
  106. package/src/runtime/scheduling/global-worker-cap.ts +2 -1
  107. package/src/runtime/scheduling/nested-slots.ts +70 -0
  108. package/src/runtime/scheduling/run-coalesced-task-group.ts +64 -13
  109. package/src/runtime/scheduling/task-graph-scheduler.ts +0 -10
  110. package/src/runtime/scratchpad/README.md +10 -5
  111. package/src/runtime/scratchpad/guest.ts +103 -2
  112. package/src/runtime/scratchpad/protocol.ts +13 -1
  113. package/src/runtime/scratchpad/transform.ts +206 -12
  114. package/src/runtime/settings-store.ts +219 -0
  115. package/src/runtime/spawn-policy.ts +217 -0
  116. package/src/runtime/stale-reconciler.ts +87 -6
  117. package/src/runtime/subagent-manager.ts +25 -1
  118. package/src/runtime/task-output-context.ts +230 -9
  119. package/src/runtime/task-packet.ts +23 -1
  120. package/src/runtime/task-runner/child-executor.ts +106 -7
  121. package/src/runtime/task-runner/post-execution.ts +125 -1
  122. package/src/runtime/task-runner/pre-execution.ts +39 -1
  123. package/src/runtime/task-runner/prompt-builder.ts +51 -1
  124. package/src/runtime/task-runner/retrieval-orchestrator.ts +72 -18
  125. package/src/runtime/task-runner/spec-evidence.ts +403 -0
  126. package/src/runtime/task-runner/state-helpers.ts +26 -24
  127. package/src/runtime/task-runner.ts +11 -0
  128. package/src/runtime/team-runner.ts +129 -1671
  129. package/src/runtime/verification/spec-sandbox.ts +255 -0
  130. package/src/runtime/verification/verification-gates.ts +3 -2
  131. package/src/runtime/verification/verification-worktree.ts +2 -1
  132. package/src/runtime/workflow-phase-advance.ts +100 -0
  133. package/src/runtime/workspace-tree.ts +9 -0
  134. package/src/schema/config-schema.ts +65 -25
  135. package/src/schema/sensitive-config-paths.ts +64 -0
  136. package/src/schema/team-tool-schema.ts +13 -3
  137. package/src/state/README.md +4 -10
  138. package/src/state/atomic-write.ts +20 -3
  139. package/src/state/contracts.ts +38 -0
  140. package/src/state/coordination/mailbox.ts +12 -2
  141. package/src/state/event-log/cursor.ts +223 -0
  142. package/src/state/event-log/event-log-rotation.ts +12 -4
  143. package/src/state/event-log/event-log.ts +152 -369
  144. package/src/state/event-log/sequence-cache.ts +373 -0
  145. package/src/state/event-log/worker-atomic-writer.ts +2 -1
  146. package/src/state/stores/active-run-registry.ts +3 -2
  147. package/src/state/stores/manifest-io.ts +237 -0
  148. package/src/state/stores/ownership-map.ts +162 -0
  149. package/src/state/stores/plan-store.ts +241 -0
  150. package/src/state/stores/run-cache.ts +0 -90
  151. package/src/state/stores/spec-store.ts +189 -0
  152. package/src/state/stores/state-store.ts +66 -229
  153. package/src/state/types.ts +197 -0
  154. package/src/ui/dashboard-panes/plan-pane.ts +136 -0
  155. package/src/ui/dashboard-panes/progress-pane.ts +6 -0
  156. package/src/ui/dashboard-panes/transcript-pane.ts +31 -0
  157. package/src/ui/heartbeat-aggregator.ts +9 -1
  158. package/src/ui/keybinding-map.ts +54 -13
  159. package/src/ui/powerbar-publisher.ts +52 -1
  160. package/src/ui/run-dashboard.ts +31 -5
  161. package/src/ui/run-snapshot-cache.ts +57 -30
  162. package/src/ui/snapshot-types.ts +6 -1
  163. package/src/ui/widget/widget-renderer.ts +9 -1
  164. package/src/utils/file-coalescer.ts +0 -4
  165. package/src/utils/fs-errno.ts +66 -0
  166. package/src/utils/fs-watch.ts +1 -1
  167. package/src/utils/internal-error.ts +3 -1
  168. package/src/utils/paths.ts +11 -3
  169. package/src/utils/task-name-generator.ts +1 -8
  170. package/src/workflows/discover-workflows.ts +19 -2
  171. package/src/workflows/validate-workflow.ts +7 -1
  172. package/src/workflows/workflow-config.ts +10 -0
  173. package/src/workflows/workflow-serializer.ts +3 -0
  174. package/src/worktree/worktree-manager.ts +22 -0
  175. package/src/agents/agent-search.ts +0 -98
  176. package/src/benchmark/benchmark-runner.ts +0 -313
  177. package/src/benchmark/feedback-loop.ts +0 -73
  178. package/src/config/resilient-parser.ts +0 -117
  179. package/src/extension/crew-vibes/cat-frames.ts +0 -18
  180. package/src/extension/result-watcher.ts +0 -139
  181. package/src/observability/exporters/prometheus-exporter.ts +0 -54
  182. package/src/observability/metric-retention.ts +0 -64
  183. package/src/runtime/compaction/compaction-summary.ts +0 -278
  184. package/src/runtime/errors/crew-errors.ts +0 -162
  185. package/src/runtime/live-session/intercom-bridge.ts +0 -187
  186. package/src/runtime/loop-gates.ts +0 -128
  187. package/src/runtime/metric-parser.ts +0 -36
  188. package/src/runtime/output/stream-preview.ts +0 -184
  189. package/src/runtime/output/tool-progress.ts +0 -278
  190. package/src/runtime/phase-tracker.ts +0 -385
  191. package/src/runtime/pipeline-runner.ts +0 -523
  192. package/src/runtime/process/process-lifecycle.ts +0 -491
  193. package/src/runtime/recovery/retry-runner.ts +0 -330
  194. package/src/runtime/run-drift.ts +0 -219
  195. package/src/runtime/scratchpad/snapshot-hmac.ts +0 -167
  196. package/src/runtime/task-quality.ts +0 -199
  197. package/src/runtime/task-runner/run-projection.ts +0 -128
  198. package/src/runtime/verification/post-checks.ts +0 -142
  199. package/src/state/coordination/schedule.ts +0 -166
  200. package/src/state/event-log/jsonl-writer.ts +0 -115
  201. package/src/state/hook-instinct-bridge.ts +0 -94
  202. package/src/state/hook-integrations.ts +0 -51
  203. package/src/state/session-state-map.ts +0 -51
  204. package/src/state/stores/blob-store.ts +0 -308
  205. package/src/state/stores/instinct-store.ts +0 -275
  206. package/src/state/stores/observation-store.ts +0 -176
  207. package/src/state/tiered-eval.ts +0 -480
  208. package/src/state/types-eval.ts +0 -58
  209. package/src/tools/safe-bash-extension.ts +0 -54
  210. package/src/tools/safe-bash.ts +0 -505
  211. package/src/ui/agent-management-overlay.ts +0 -160
  212. package/src/ui/crew-footer.ts +0 -102
  213. package/src/ui/crew-select-list.ts +0 -114
  214. package/src/ui/dashboard-panes/capability-pane.ts +0 -77
  215. package/src/ui/transcript-entries.ts +0 -256
  216. package/src/utils/conflict-detect.ts +0 -721
  217. package/src/utils/fingerprint.ts +0 -180
  218. package/src/utils/gh-protocol.ts +0 -556
  219. package/src/utils/project-detector.ts +0 -160
  220. package/src/utils/sse-parser.ts +0 -131
  221. package/src/workflows/cost-estimator.ts +0 -34
  222. package/src/workflows/intermediate-store.ts +0 -166
@@ -0,0 +1,691 @@
1
+ /**
2
+ * Central env-var registry for the PI_CREW_* / PI_TEAMS_* families.
3
+ *
4
+ * Phase 3.2 (refactor-plan row 3.2) deliverable: a single place that
5
+ * enumerates every crew-family environment variable, its default, its
6
+ * parser family, and its mirror (PI_CREW_X ↔ PI_TEAMS_X) mapping, plus a
7
+ * single lookup function that preserves the exact read semantics of the
8
+ * original `process.env.X` sites.
9
+ *
10
+ * DESIGN NOTES (behavior-preservation contract):
11
+ * - `getCrewEnv(name)` returns the RAW string value (undefined when unset)
12
+ * so truthiness/existence checks (`if (getCrewEnv(...))`) and exact-string
13
+ * comparisons (`=== "1"`, `=== "success"`) behave identically to the
14
+ * original `process.env.X` reads. The registry `default` is applied by
15
+ * `getCrewEnvParsed` / the typed wrappers, NOT by the raw getter.
16
+ * - Mirror resolution: when a name has a `mirror`, `getCrewEnv` reproduces
17
+ * the original dual-read precedence:
18
+ * - `mirrorPrecedence: "teams"` → TEAMS ?? CREW (PI_TEAMS_HOME wins)
19
+ * - `mirrorPrecedence: "crew"` → CREW ?? TEAMS (PI_CREW wins)
20
+ * - `mirrorPrecedence: "or"` → no collapse — both names are read
21
+ * independently by the call site (e.g. `A === "0" || B === "0"`);
22
+ * `getCrewEnv` returns the raw value for the queried name only.
23
+ * - WRITE sites (e.g. `process.env.PI_CREW_BACKGROUND_MODE = "1"`) stay raw
24
+ * by design; the registry documents them via `doc`/`deprecated` notes.
25
+ *
26
+ * The CI gate `scripts/check-env-vars.mjs` fails on any raw
27
+ * `process.env.PI_CREW_*` / `PI_TEAMS_*` READ outside this file, so new
28
+ * reads must be routed through `getCrewEnv`.
29
+ */
30
+
31
+ export type CrewEnvParser = "string" | "int" | "number" | "boolean" | "json";
32
+ export type MirrorPrecedence = "crew" | "teams" | "or";
33
+
34
+ export interface CrewEnvVarSpec {
35
+ /** Canonical env var name (registry key == the literal env var name). */
36
+ name: string;
37
+ /**
38
+ * Default applied by `getCrewEnvParsed` / typed wrappers when the var is
39
+ * unset (or unparseable). The raw `getCrewEnv` returns undefined instead,
40
+ * preserving original existence/truthiness semantics.
41
+ */
42
+ default?: string | number | boolean;
43
+ /** Parser family used by `getCrewEnvParsed` (documentation + tests). */
44
+ parser?: CrewEnvParser;
45
+ /** Mirror name (the PI_CREW_ ↔ PI_TEAMS_ counterpart), if any. */
46
+ mirror?: string;
47
+ /** How dual PI_CREW_/PI_TEAMS_ reads resolve (see module doc). */
48
+ mirrorPrecedence?: MirrorPrecedence;
49
+ /** Value is (also) written via `process.env` at some site. */
50
+ writeOnly?: boolean;
51
+ /** Deprecation / status note. */
52
+ deprecated?: string;
53
+ /** Short doc: where it is read and what it controls. */
54
+ doc?: string;
55
+ }
56
+
57
+ /**
58
+ * The registry. Every name READ in src/ is mandatory; names found only in
59
+ * docs/tests are best-effort (marked with `deprecated`/`doc` notes).
60
+ */
61
+ export const CREW_ENV_VARS: Record<string, CrewEnvVarSpec> = {
62
+ // ── Mirror pairs — PI_TEAMS_HOME wins ────────────────────────────────
63
+ PI_CREW_HOME: {
64
+ name: "PI_CREW_HOME",
65
+ mirror: "PI_TEAMS_HOME",
66
+ mirrorPrecedence: "teams",
67
+ doc: "pi-crew home dir; PI_TEAMS_HOME wins (config.ts:174, paths.ts:58, crew-vibes/config.ts:16)",
68
+ },
69
+ PI_TEAMS_HOME: {
70
+ name: "PI_TEAMS_HOME",
71
+ mirror: "PI_CREW_HOME",
72
+ mirrorPrecedence: "teams",
73
+ doc: "pi-crew home dir — primary of the TEAMS??CREW pair",
74
+ },
75
+
76
+ // ── Mirror pairs — PI_CREW wins ──────────────────────────────────────
77
+ PI_CREW_DEPTH: {
78
+ name: "PI_CREW_DEPTH",
79
+ mirror: "PI_TEAMS_DEPTH",
80
+ mirrorPrecedence: "crew",
81
+ default: "0",
82
+ parser: "int",
83
+ doc: "current crew depth (pi-args.ts:72 reads CREW ?? TEAMS ?? '0')",
84
+ },
85
+ PI_TEAMS_DEPTH: {
86
+ name: "PI_TEAMS_DEPTH",
87
+ mirror: "PI_CREW_DEPTH",
88
+ mirrorPrecedence: "crew",
89
+ default: "0",
90
+ parser: "int",
91
+ doc: "crew depth mirror (fallback of PI_CREW_DEPTH)",
92
+ },
93
+ PI_CREW_MAX_DEPTH: {
94
+ name: "PI_CREW_MAX_DEPTH",
95
+ mirror: "PI_TEAMS_MAX_DEPTH",
96
+ mirrorPrecedence: "crew",
97
+ parser: "int",
98
+ doc: "max crew depth, clamped 1..10 (pi-args.ts:78)",
99
+ },
100
+ PI_TEAMS_MAX_DEPTH: {
101
+ name: "PI_TEAMS_MAX_DEPTH",
102
+ mirror: "PI_CREW_MAX_DEPTH",
103
+ mirrorPrecedence: "crew",
104
+ parser: "int",
105
+ doc: "max crew depth mirror (fallback of PI_CREW_MAX_DEPTH)",
106
+ },
107
+ PI_CREW_ROLE: {
108
+ name: "PI_CREW_ROLE",
109
+ mirror: "PI_TEAMS_ROLE",
110
+ mirrorPrecedence: "crew",
111
+ doc: "crew role name (role-permission.ts:46 reads CREW?.trim() || TEAMS?.trim())",
112
+ },
113
+ PI_TEAMS_ROLE: {
114
+ name: "PI_TEAMS_ROLE",
115
+ mirror: "PI_CREW_ROLE",
116
+ mirrorPrecedence: "crew",
117
+ doc: "crew role mirror (fallback of PI_CREW_ROLE)",
118
+ },
119
+ PI_CREW_VERIFICATION_PRESERVE_ENV: {
120
+ name: "PI_CREW_VERIFICATION_PRESERVE_ENV",
121
+ mirror: "PI_TEAMS_VERIFICATION_PRESERVE_ENV",
122
+ mirrorPrecedence: "crew",
123
+ doc: "extra env keys to preserve in verification commands (CREW ?? TEAMS ?? '')",
124
+ },
125
+ PI_TEAMS_VERIFICATION_PRESERVE_ENV: {
126
+ name: "PI_TEAMS_VERIFICATION_PRESERVE_ENV",
127
+ mirror: "PI_CREW_VERIFICATION_PRESERVE_ENV",
128
+ mirrorPrecedence: "crew",
129
+ doc: "verification preserve-env mirror (fallback of PI_CREW_...)",
130
+ },
131
+ PI_CREW_VERIFICATION_WORKTREE: {
132
+ name: "PI_CREW_VERIFICATION_WORKTREE",
133
+ mirror: "PI_TEAMS_VERIFICATION_WORKTREE",
134
+ mirrorPrecedence: "crew",
135
+ doc: "enable verification worktree sandbox; '1'/'true' (CREW ?? TEAMS)",
136
+ },
137
+ PI_TEAMS_VERIFICATION_WORKTREE: {
138
+ name: "PI_TEAMS_VERIFICATION_WORKTREE",
139
+ mirror: "PI_CREW_VERIFICATION_WORKTREE",
140
+ mirrorPrecedence: "crew",
141
+ doc: "verification worktree mirror (fallback of PI_CREW_...)",
142
+ },
143
+ PI_CREW_INHERIT_PROJECT_CONTEXT: {
144
+ name: "PI_CREW_INHERIT_PROJECT_CONTEXT",
145
+ mirror: "PI_TEAMS_INHERIT_PROJECT_CONTEXT",
146
+ mirrorPrecedence: "crew",
147
+ parser: "boolean",
148
+ doc: "inherit project context in worker prompts; CREW checked first (prompt-runtime.ts readBooleanEnvAny)",
149
+ },
150
+ PI_TEAMS_INHERIT_PROJECT_CONTEXT: {
151
+ name: "PI_TEAMS_INHERIT_PROJECT_CONTEXT",
152
+ mirror: "PI_CREW_INHERIT_PROJECT_CONTEXT",
153
+ mirrorPrecedence: "crew",
154
+ parser: "boolean",
155
+ doc: "inherit project context mirror (fallback of PI_CREW_...)",
156
+ },
157
+ PI_CREW_INHERIT_SKILLS: {
158
+ name: "PI_CREW_INHERIT_SKILLS",
159
+ mirror: "PI_TEAMS_INHERIT_SKILLS",
160
+ mirrorPrecedence: "crew",
161
+ parser: "boolean",
162
+ doc: "inherit skills in worker prompts; CREW checked first (prompt-runtime.ts readBooleanEnvAny)",
163
+ },
164
+ PI_TEAMS_INHERIT_SKILLS: {
165
+ name: "PI_TEAMS_INHERIT_SKILLS",
166
+ mirror: "PI_CREW_INHERIT_SKILLS",
167
+ mirrorPrecedence: "crew",
168
+ parser: "boolean",
169
+ doc: "inherit skills mirror (fallback of PI_CREW_...)",
170
+ },
171
+
172
+ // ── Mirror pairs — OR semantics (dual reads, no collapse) ─────────────
173
+ PI_CREW_ADAPTIVE_REPAIR: {
174
+ name: "PI_CREW_ADAPTIVE_REPAIR",
175
+ mirror: "PI_TEAMS_ADAPTIVE_REPAIR",
176
+ mirrorPrecedence: "or",
177
+ doc: "'0' disables adaptive-plan repair; either name may disable (adaptive-plan.ts:434)",
178
+ },
179
+ PI_TEAMS_ADAPTIVE_REPAIR: {
180
+ name: "PI_TEAMS_ADAPTIVE_REPAIR",
181
+ mirror: "PI_CREW_ADAPTIVE_REPAIR",
182
+ mirrorPrecedence: "or",
183
+ doc: "adaptive-repair mirror (read independently, OR'd with PI_CREW_...)",
184
+ },
185
+ PI_CREW_BG_REPORT_ON_FATAL: {
186
+ name: "PI_CREW_BG_REPORT_ON_FATAL",
187
+ mirror: "PI_TEAMS_BG_REPORT_ON_FATAL",
188
+ mirrorPrecedence: "or",
189
+ doc: "'0' disables --report-on-fatalerror; either name may disable (async-runner.ts:127)",
190
+ },
191
+ PI_TEAMS_BG_REPORT_ON_FATAL: {
192
+ name: "PI_TEAMS_BG_REPORT_ON_FATAL",
193
+ mirror: "PI_CREW_BG_REPORT_ON_FATAL",
194
+ mirrorPrecedence: "or",
195
+ doc: "bg-report mirror (read independently, OR'd with PI_CREW_...)",
196
+ },
197
+ PI_CREW_EXECUTE_WORKERS: {
198
+ name: "PI_CREW_EXECUTE_WORKERS",
199
+ mirror: "PI_TEAMS_EXECUTE_WORKERS",
200
+ mirrorPrecedence: "or",
201
+ doc: "'0' disables real worker execution; either name disables (team-tool.ts:376, run.ts, runtime-resolver.ts:91)",
202
+ },
203
+ PI_TEAMS_EXECUTE_WORKERS: {
204
+ name: "PI_TEAMS_EXECUTE_WORKERS",
205
+ mirror: "PI_CREW_EXECUTE_WORKERS",
206
+ mirrorPrecedence: "or",
207
+ doc: "execute-workers mirror (read independently, OR'd with PI_CREW_...)",
208
+ },
209
+ PI_CREW_VERIFICATION_SANITIZE_ENV: {
210
+ name: "PI_CREW_VERIFICATION_SANITIZE_ENV",
211
+ mirror: "PI_TEAMS_VERIFICATION_SANITIZE_ENV",
212
+ mirrorPrecedence: "or",
213
+ doc: "'0' disables verification env sanitization; either name disables (verification-gates.ts:69)",
214
+ },
215
+ PI_TEAMS_VERIFICATION_SANITIZE_ENV: {
216
+ name: "PI_TEAMS_VERIFICATION_SANITIZE_ENV",
217
+ mirror: "PI_CREW_VERIFICATION_SANITIZE_ENV",
218
+ mirrorPrecedence: "or",
219
+ doc: "verification sanitize mirror (read independently, OR'd with PI_CREW_...)",
220
+ },
221
+ PI_CREW_WORKER_ATOMIC_WRITER: {
222
+ name: "PI_CREW_WORKER_ATOMIC_WRITER",
223
+ mirror: "PI_TEAMS_WORKER_ATOMIC_WRITER",
224
+ mirrorPrecedence: "or",
225
+ doc: "'1' enables the worker-thread atomic writer; either name enables (worker-atomic-writer.ts:166)",
226
+ },
227
+ PI_TEAMS_WORKER_ATOMIC_WRITER: {
228
+ name: "PI_TEAMS_WORKER_ATOMIC_WRITER",
229
+ mirror: "PI_CREW_WORKER_ATOMIC_WRITER",
230
+ mirrorPrecedence: "or",
231
+ doc: "worker-atomic-writer mirror (read independently, OR'd with PI_CREW_...)",
232
+ },
233
+
234
+ // ── Single names read via process.env (dot notation) ──────────────────
235
+ PI_CREW_ALLOW_MOCK: {
236
+ name: "PI_CREW_ALLOW_MOCK",
237
+ parser: "boolean",
238
+ doc: "'1'/'true' allows PI_TEAMS_MOCK_CHILD_PI mock mode (mock-fixtures.ts:40)",
239
+ },
240
+ PI_CREW_ASYNC_EARLY_EXIT_GUARD: {
241
+ name: "PI_CREW_ASYNC_EARLY_EXIT_GUARD",
242
+ doc: "'0' skips the async-run early-exit guard (team-tool/run.ts:103)",
243
+ },
244
+ PI_CREW_BACKGROUND_MODE: {
245
+ name: "PI_CREW_BACKGROUND_MODE",
246
+ doc: "background-runner marker; READ at child-executor.ts:616 ('1'), WRITTEN at background-runner.ts:713/833 (= '1')",
247
+ },
248
+ PI_CREW_BROKER: {
249
+ name: "PI_CREW_BROKER",
250
+ doc: "'1'/'0' force broker enabled/disabled (defaults.ts:187, lifecycle-handlers.ts:908)",
251
+ },
252
+ PI_CREW_DEBUG: {
253
+ name: "PI_CREW_DEBUG",
254
+ doc: "truthiness enables background debug logging (background-runner.ts:63)",
255
+ },
256
+ PI_CREW_DEBUG_BUDGET: {
257
+ name: "PI_CREW_DEBUG_BUDGET",
258
+ doc: "'1' logs token budget (team-tool/run.ts:498)",
259
+ },
260
+ PI_CREW_DWF_SCRIPT_TIMEOUT_MS: {
261
+ name: "PI_CREW_DWF_SCRIPT_TIMEOUT_MS",
262
+ parser: "int",
263
+ default: 1_800_000,
264
+ doc: "dynamic-workflow script timeout; default 30 min (dynamic-workflow-runner.ts:226)",
265
+ },
266
+ PI_CREW_DWF_SKIP_DETERMINISM_CHECK: {
267
+ name: "PI_CREW_DWF_SKIP_DETERMINISM_CHECK",
268
+ doc: "'1' disables the DWF determinism check (deterministic-ast.ts:60)",
269
+ },
270
+ PI_CREW_INTERRUPT_GUARD_INTERVAL_MS: {
271
+ name: "PI_CREW_INTERRUPT_GUARD_INTERVAL_MS",
272
+ parser: "int",
273
+ default: 250,
274
+ doc: "interrupt-guard poll interval; default 250ms (background-runner.ts:217)",
275
+ },
276
+ PI_CREW_MAX_RUN_MS: {
277
+ name: "PI_CREW_MAX_RUN_MS",
278
+ parser: "int",
279
+ default: 7_200_000,
280
+ doc: "max background run duration; default 2h (background-runner.ts:31)",
281
+ },
282
+ PI_CREW_MAX_WORKERS: {
283
+ name: "PI_CREW_MAX_WORKERS",
284
+ parser: "int",
285
+ doc: "max concurrent workers; unset/empty/invalid → default max(2, cpus-2) (global-worker-cap.ts:33)",
286
+ },
287
+ PI_CREW_DISABLE_RESULT_READ_CACHE: {
288
+ name: "PI_CREW_DISABLE_RESULT_READ_CACHE",
289
+ doc: "'1' bypasses the per-run result-artifact read cache (R10-1 bypass control; task-output-context.ts createResultArtifactReadCache)",
290
+ },
291
+ PI_CREW_MOCK_LIVE_SESSION: {
292
+ name: "PI_CREW_MOCK_LIVE_SESSION",
293
+ doc: "'success' mocks a successful live-session (live-session-runtime.ts:558, runtime-resolver.ts:38/116)",
294
+ },
295
+ PI_CREW_PARENT_GUARD_INTERVAL_MS: {
296
+ name: "PI_CREW_PARENT_GUARD_INTERVAL_MS",
297
+ parser: "int",
298
+ default: 500,
299
+ doc: "parent-guard poll interval; default 500ms (parent-guard.ts:73)",
300
+ },
301
+ PI_CREW_PARENT_PID: {
302
+ name: "PI_CREW_PARENT_PID",
303
+ parser: "int",
304
+ doc: "parent process pid; >0 starts the parent guard (background-runner.ts:626)",
305
+ },
306
+ PI_CREW_SCRATCHPAD_DEMOTE_BASH: {
307
+ name: "PI_CREW_SCRATCHPAD_DEMOTE_BASH",
308
+ doc: "'1' demotes bash for scratchpad roles (agent-config.ts:199)",
309
+ },
310
+ PI_CREW_SKIP_HOME_CHECK: {
311
+ name: "PI_CREW_SKIP_HOME_CHECK",
312
+ doc: "'1' skips the PI_TEAMS_HOME escape check (config.ts:185)",
313
+ },
314
+ PI_CREW_SUPPRESS_RPC_WARNING: {
315
+ name: "PI_CREW_SUPPRESS_RPC_WARNING",
316
+ doc: "'1' suppresses the missing-RPC-secret warning (rpc-hmac.ts:145)",
317
+ },
318
+ PI_CREW_TRUST_PROJECT_AGENT_EXTENSIONS: {
319
+ name: "PI_CREW_TRUST_PROJECT_AGENT_EXTENSIONS",
320
+ doc: "'1' trusts project/.pi agent extensions (discover-agents.ts:445/544)",
321
+ },
322
+ PI_CREW_PLAN_UI: {
323
+ name: "PI_CREW_PLAN_UI",
324
+ doc: "'1' enables the Plan dashboard pane (7) + plans snapshot slice (WP-7/R7)",
325
+ },
326
+ PI_CREW_TRUST_PROJECT_DWF: {
327
+ name: "PI_CREW_TRUST_PROJECT_DWF",
328
+ doc: "'1' allows project-sourced .dwf.ts workflows (dynamic-workflow-runner.ts:154)",
329
+ },
330
+ PI_TEAMS_CHILD_RESPONSE_TIMEOUT_MS: {
331
+ name: "PI_TEAMS_CHILD_RESPONSE_TIMEOUT_MS",
332
+ parser: "int",
333
+ doc: "child Pi response timeout, bounded 1s..3.6M ms (child-pi.ts:356)",
334
+ },
335
+ PI_TEAMS_DEBUG: {
336
+ name: "PI_TEAMS_DEBUG",
337
+ doc: "truthiness gates debug-severity internal-error logging (internal-error.ts:4)",
338
+ },
339
+ PI_TEAMS_MOCK_CHILD_PI: {
340
+ name: "PI_TEAMS_MOCK_CHILD_PI",
341
+ doc: "mock child-pi mode; values 'success'/'json-success'/'adaptive-plan' (mock-fixtures.ts:35)",
342
+ },
343
+ PI_TEAMS_PI_BIN: {
344
+ name: "PI_TEAMS_PI_BIN",
345
+ doc: "explicit pi binary path for spawned children (pi-spawn.ts:262)",
346
+ },
347
+
348
+ // ── Single names read via process.env[...] (const/bracket sites) ──────
349
+ PI_CREW_MAX_OUTPUT: {
350
+ name: "PI_CREW_MAX_OUTPUT",
351
+ parser: "int",
352
+ doc: "max output tokens cap for background workers (prompt-runtime.ts:228)",
353
+ },
354
+ PI_CREW_STEERING_FILE: {
355
+ name: "PI_CREW_STEERING_FILE",
356
+ doc: "steering JSONL path polled by the worker (prompt-runtime.ts:260)",
357
+ },
358
+ PI_CREW_KEYBINDINGS: {
359
+ name: "PI_CREW_KEYBINDINGS",
360
+ parser: "json",
361
+ doc: "JSON keybinding override map (keybinding-map.ts:314/347)",
362
+ },
363
+ PI_CREW_RPC_SECRET: {
364
+ name: "PI_CREW_RPC_SECRET",
365
+ doc: "shared HMAC secret; READ at rpc-hmac.ts:26/41, WRITTEN/cleared at :31/:36",
366
+ },
367
+ PI_CREW_PEER_DEP_DIR: {
368
+ name: "PI_CREW_PEER_DEP_DIR",
369
+ doc: "parent-provided pi-coding-agent package dir hint (peer-dep.ts:81)",
370
+ },
371
+
372
+ // ── Names read from a passed-in env object (child-spawned env) ────────
373
+ PI_CREW_SCRATCHPAD: {
374
+ name: "PI_CREW_SCRATCHPAD",
375
+ doc: "'1' enables the scratchpad engine (scratchpad-lifecycle.ts:486/679, written by child-pi-spawn.ts)",
376
+ },
377
+ PI_CREW_KIND: {
378
+ name: "PI_CREW_KIND",
379
+ doc: "'subagent' marks child workers (scratchpad-lifecycle.ts:679, lifecycle-handlers.ts:892, zombie-scanner.ts:183)",
380
+ },
381
+ PI_CREW_TASK_ID: {
382
+ name: "PI_CREW_TASK_ID",
383
+ doc: "current task id for scratchpad/events (scratchpad-lifecycle.ts:90/227/280)",
384
+ },
385
+ PI_CREW_EVENTS_PATH: {
386
+ name: "PI_CREW_EVENTS_PATH",
387
+ doc: "events JSONL path for fire-and-forget metric events (scratchpad-lifecycle.ts:80)",
388
+ },
389
+ PI_CREW_ASK_ENABLED: {
390
+ name: "PI_CREW_ASK_ENABLED",
391
+ doc: "'1' enables the worker-side ask tool — dormant-until-env gate (written UNCONDITIONALLY by child-pi-spawn.ts, read by prompt-runtime.ts per ADR-0 WP-2 item 2)",
392
+ },
393
+ PI_CREW_STATE_ROOT: {
394
+ name: "PI_CREW_STATE_ROOT",
395
+ doc: "run stateRoot for the ask-tool mailbox poll (<stateRoot>/mailbox; written by child-pi-spawn.ts, read by prompt-runtime.ts per ADR-0 WP-2 item 2)",
396
+ },
397
+ PI_CREW_BROKER_RUN_ID: {
398
+ name: "PI_CREW_BROKER_RUN_ID",
399
+ doc: "broker run id; aliases PI_CREW_RUN_ID (scratchpad-lifecycle.ts:81, crew-broker-child.ts:51)",
400
+ },
401
+ PI_CREW_ARTIFACTS_ROOT: {
402
+ name: "PI_CREW_ARTIFACTS_ROOT",
403
+ doc: "artifacts root for scratchpad containment (scratchpad-lifecycle.ts:228/281)",
404
+ },
405
+ PI_CREW_SCRATCHPAD_SNAPSHOT: {
406
+ name: "PI_CREW_SCRATCHPAD_SNAPSHOT",
407
+ doc: "snapshot path for the post-cell snapshot (scratchpad-lifecycle.ts:229)",
408
+ },
409
+ PI_CREW_ATTEMPT: {
410
+ name: "PI_CREW_ATTEMPT",
411
+ default: "0",
412
+ doc: "current attempt number (scratchpad-lifecycle.ts:230 reads ?? '0')",
413
+ },
414
+ PI_CREW_SCRATCHPAD_RESTORE: {
415
+ name: "PI_CREW_SCRATCHPAD_RESTORE",
416
+ doc: "parent-set restore hint: previous attempt snapshot (scratchpad-lifecycle.ts:653)",
417
+ },
418
+ PI_CREW_SCRATCHPAD_RESTORE_MTIME: {
419
+ name: "PI_CREW_SCRATCHPAD_RESTORE_MTIME",
420
+ parser: "number",
421
+ doc: "swap-detection mtime pin for restore snapshots (scratchpad-lifecycle.ts:302)",
422
+ },
423
+ PI_CREW_MAX_AUTO_FALLBACKS: {
424
+ name: "PI_CREW_MAX_AUTO_FALLBACKS",
425
+ parser: "int",
426
+ doc: "max automatic model fallbacks (model-fallback.ts:527)",
427
+ },
428
+ PI_CREW_MODEL_FALLBACK_ORDER: {
429
+ name: "PI_CREW_MODEL_FALLBACK_ORDER",
430
+ doc: "'parentFirst' | 'asIs' fallback order (model-fallback.ts:555)",
431
+ },
432
+ PI_CREW_MODEL_REQUIRE_CREDENTIALS: {
433
+ name: "PI_CREW_MODEL_REQUIRE_CREDENTIALS",
434
+ parser: "boolean",
435
+ doc: "'1'/'0' override requireCredentials (model-fallback.ts:557/559)",
436
+ },
437
+ PI_CREW_MODEL: {
438
+ name: "PI_CREW_MODEL",
439
+ doc: "model override for subagents (model-fallback.ts:584)",
440
+ },
441
+ PI_CREW_BROKER_SOCKET: {
442
+ name: "PI_CREW_BROKER_SOCKET",
443
+ doc: "broker unix socket path for child handshake (crew-broker-child.ts:49)",
444
+ },
445
+ PI_CREW_BROKER_TOKEN: {
446
+ name: "PI_CREW_BROKER_TOKEN",
447
+ doc: "broker handshake token (crew-broker-child.ts:50)",
448
+ },
449
+ PI_CREW_BROKER_TASK_ID: {
450
+ name: "PI_CREW_BROKER_TASK_ID",
451
+ doc: "broker task id for child handshake (crew-broker-child.ts:51)",
452
+ },
453
+ PI_CREW_GUEST: {
454
+ name: "PI_CREW_GUEST",
455
+ doc: "'1' marks the guest scratchpad process (written by scratchpad-lifecycle.ts:167)",
456
+ },
457
+
458
+ // ── Docs/tests-only (best-effort; not read via process.env in src/) ───
459
+ PI_CREW_USE_BUNDLE: {
460
+ name: "PI_CREW_USE_BUNDLE",
461
+ doc: "read at root index.ts:78 (outside src/ gate scope): force strip-types loading when 0",
462
+ },
463
+ PI_CREW_SMOKE: {
464
+ name: "PI_CREW_SMOKE",
465
+ doc: "test-only: smoke-test helper flag (test/smoke/_helpers.ts)",
466
+ },
467
+ PI_CREW_RUN_PLATFORM_TESTS: {
468
+ name: "PI_CREW_RUN_PLATFORM_TESTS",
469
+ doc: "test-only: enables platform tests (test/platform)",
470
+ },
471
+ PI_CREW_HARD_KILL_GRACE_MS: {
472
+ name: "PI_CREW_HARD_KILL_GRACE_MS",
473
+ doc: "scripts-only: watchdog hard-kill grace (scripts/watchdog-harness.ts)",
474
+ },
475
+ PI_CREW_LIVE_MODEL: {
476
+ name: "PI_CREW_LIVE_MODEL",
477
+ doc: "docs/test-only: live-session model selection",
478
+ },
479
+ PI_CREW_ENABLE_EXPERIMENTAL_LIVE_SESSION: {
480
+ name: "PI_CREW_ENABLE_EXPERIMENTAL_LIVE_SESSION",
481
+ doc: "docs/test-only: experimental live-session opt-in",
482
+ },
483
+ PI_CREW_RUN_ID: {
484
+ name: "PI_CREW_RUN_ID",
485
+ doc: "test fixture name; src uses PI_CREW_BROKER_RUN_ID instead",
486
+ },
487
+ PI_TEAMS_CONFIG_KEYS: {
488
+ name: "PI_TEAMS_CONFIG_KEYS",
489
+ doc: "docs/test-only",
490
+ },
491
+ PI_TEAMS_MOCK: {
492
+ name: "PI_TEAMS_MOCK",
493
+ doc: "docs/test-only",
494
+ },
495
+ PI_CREW_VERIFICATION: {
496
+ name: "PI_CREW_VERIFICATION",
497
+ deprecated: "partial fixture name; real vars are PI_CREW_VERIFICATION_*",
498
+ doc: "docs/test-only",
499
+ },
500
+ PI_TEAMS_VERIFICATION: {
501
+ name: "PI_TEAMS_VERIFICATION",
502
+ deprecated: "partial fixture name; real vars are PI_TEAMS_VERIFICATION_*",
503
+ doc: "docs/test-only",
504
+ },
505
+ PI_CREW_ATOMIC_WRITER: {
506
+ name: "PI_CREW_ATOMIC_WRITER",
507
+ deprecated: "superseded by PI_CREW_WORKER_ATOMIC_WRITER",
508
+ doc: "docs/test-only",
509
+ },
510
+ PI_CREW_BROKER_DIAG_UI: {
511
+ name: "PI_CREW_BROKER_DIAG_UI",
512
+ deprecated: "removed",
513
+ doc: "docs/test-only",
514
+ },
515
+ PI_CREW_DEBUG_KILL: {
516
+ name: "PI_CREW_DEBUG_KILL",
517
+ doc: "docs/test-only",
518
+ },
519
+ PI_CREW_DWF_SANDBOX_DRY_RUN: {
520
+ name: "PI_CREW_DWF_SANDBOX_DRY_RUN",
521
+ doc: "docs/test-only",
522
+ },
523
+ PI_CREW_HOOK: {
524
+ name: "PI_CREW_HOOK",
525
+ doc: "docs/test-only",
526
+ },
527
+ PI_CREW_POOL_HEALTH: {
528
+ name: "PI_CREW_POOL_HEALTH",
529
+ doc: "docs/test-only",
530
+ },
531
+ PI_CREW_QUIET_PREFLIGHT: {
532
+ name: "PI_CREW_QUIET_PREFLIGHT",
533
+ doc: "docs/test-only",
534
+ },
535
+ PI_CREW_SAFE_BASH: {
536
+ name: "PI_CREW_SAFE_BASH",
537
+ deprecated: "dead",
538
+ doc: "docs/test-only",
539
+ },
540
+ PI_CREW_SCRATCHPAD_EXPERIMENT: {
541
+ name: "PI_CREW_SCRATCHPAD_EXPERIMENT",
542
+ doc: "docs/test-only",
543
+ },
544
+ PI_CREW_SESSION_DEPTH: {
545
+ name: "PI_CREW_SESSION_DEPTH",
546
+ deprecated: "legacy name; code uses PI_CREW_DEPTH (ADR drift history 2026-08-09)",
547
+ doc: "docs/test-only",
548
+ },
549
+ PI_CREW_SIG: {
550
+ name: "PI_CREW_SIG",
551
+ doc: "docs/test-only",
552
+ },
553
+ PI_CREW_SNAPSHOT_HMAC_KEY: {
554
+ name: "PI_CREW_SNAPSHOT_HMAC_KEY",
555
+ deprecated: "reverted (2026-08-13)",
556
+ doc: "docs/test-only",
557
+ },
558
+ PI_CREW_SNAPSHOT_HMAC_STRICT: {
559
+ name: "PI_CREW_SNAPSHOT_HMAC_STRICT",
560
+ deprecated: "reverted (2026-08-13)",
561
+ doc: "docs/test-only",
562
+ },
563
+ PI_CREW_TEST_REAL_MODEL: {
564
+ name: "PI_CREW_TEST_REAL_MODEL",
565
+ doc: "docs/test-only",
566
+ },
567
+ PI_CREW_TOOLING_429_NOTE: {
568
+ name: "PI_CREW_TOOLING_429_NOTE",
569
+ doc: "docs/test-only",
570
+ },
571
+ PI_CREW_MAX_OUTPUT_TOKENS: {
572
+ name: "PI_CREW_MAX_OUTPUT_TOKENS",
573
+ deprecated: "legacy name; actual var is PI_CREW_MAX_OUTPUT (comment-only in src)",
574
+ doc: "docs/test-only",
575
+ },
576
+ PI_CREW_GOAL_OSCILLATION_EMBEDDINGS: {
577
+ name: "PI_CREW_GOAL_OSCILLATION_EMBEDDINGS",
578
+ doc: "docs/test-only",
579
+ },
580
+ PI_CREW_OPENAI_API_KEY: {
581
+ name: "PI_CREW_OPENAI_API_KEY",
582
+ doc: "comment-only in src (env-filter secret-name example)",
583
+ },
584
+ PI_CREW_SECRET_TOKEN: {
585
+ name: "PI_CREW_SECRET_TOKEN",
586
+ doc: "comment-only in src (env-filter secret-name example)",
587
+ },
588
+ PI_CREW_REFUSE_GATE_PATTERNS: {
589
+ name: "PI_CREW_REFUSE_GATE_PATTERNS",
590
+ doc: "docs-only",
591
+ },
592
+ PI_CREW_PROCEED_PATTERNS: {
593
+ name: "PI_CREW_PROCEED_PATTERNS",
594
+ doc: "docs-only",
595
+ },
596
+ PI_CREW_ENFORCEMENT_PATTERNS: {
597
+ name: "PI_CREW_ENFORCEMENT_PATTERNS",
598
+ doc: "docs-only",
599
+ },
600
+ // Pure test fixtures (placeholder names used by tests to prove isolation).
601
+ PI_CREW_DIR: { name: "PI_CREW_DIR", doc: "test fixture" },
602
+ PI_CREW_ROOT: { name: "PI_CREW_ROOT", doc: "test fixture" },
603
+ PI_CREW_FOO: { name: "PI_CREW_FOO", doc: "test fixture" },
604
+ PI_CREW_VAR: { name: "PI_CREW_VAR", doc: "test fixture" },
605
+ PI_CREW_X: { name: "PI_CREW_X", doc: "test fixture" },
606
+ PI_CREW_TEST_SECRET_VALUE: { name: "PI_CREW_TEST_SECRET_VALUE", doc: "test fixture" },
607
+ PI_TEAMS_BAR: { name: "PI_TEAMS_BAR", doc: "test fixture" },
608
+ };
609
+
610
+ /**
611
+ * Raw crew-env lookup. Returns the raw string (undefined when unset) with
612
+ * mirror-alias fallback applied per the entry's `mirrorPrecedence`. This is
613
+ * the behavior-preserving replacement for `process.env.PI_CREW_X` reads.
614
+ */
615
+ export function getCrewEnv(name: string): string | undefined {
616
+ const spec = CREW_ENV_VARS[name];
617
+ if (!spec?.mirror || spec.mirrorPrecedence === "or") {
618
+ return process.env[name];
619
+ }
620
+ const crewName = name.startsWith("PI_TEAMS_") ? spec.mirror : name;
621
+ const teamsName = name.startsWith("PI_TEAMS_") ? name : spec.mirror;
622
+ if (spec.mirrorPrecedence === "teams") {
623
+ return process.env[teamsName] ?? process.env[crewName];
624
+ }
625
+ return process.env[crewName] ?? process.env[teamsName];
626
+ }
627
+
628
+ /**
629
+ * Parsed lookup: applies the registry parser + default. Returns the raw
630
+ * string for string/unparsed entries, `undefined` when unset with no
631
+ * default. Only use where the generic parse matches the call-site semantics;
632
+ * the raw `getCrewEnv` is the default choice for behavior preservation.
633
+ */
634
+ export function getCrewEnvParsed(name: string): unknown {
635
+ const spec = CREW_ENV_VARS[name];
636
+ const raw = getCrewEnv(name);
637
+ const fallback = (): unknown => spec?.default;
638
+ if (raw === undefined) return fallback();
639
+ if (!spec?.parser || spec.parser === "string") return raw;
640
+ switch (spec.parser) {
641
+ case "int": {
642
+ const n = Number.parseInt(raw, 10);
643
+ return Number.isNaN(n) ? fallback() : n;
644
+ }
645
+ case "number": {
646
+ const n = Number(raw);
647
+ return Number.isNaN(n) ? fallback() : n;
648
+ }
649
+ case "boolean": {
650
+ const normalized = raw.trim().toLowerCase();
651
+ if (normalized === "1" || normalized === "true" || normalized === "yes") return true;
652
+ if (normalized === "0" || normalized === "false" || normalized === "no") return false;
653
+ return fallback();
654
+ }
655
+ case "json": {
656
+ try {
657
+ return JSON.parse(raw);
658
+ } catch {
659
+ return fallback();
660
+ }
661
+ }
662
+ }
663
+ return raw;
664
+ }
665
+
666
+ /** Typed wrapper: boolean parse of a registered crew env var. */
667
+ export function getCrewEnvBool(name: string): boolean | undefined {
668
+ const value = getCrewEnvParsed(name);
669
+ return typeof value === "boolean" ? value : undefined;
670
+ }
671
+
672
+ /** Typed wrapper: integer parse of a registered crew env var. */
673
+ export function getCrewEnvInt(name: string): number | undefined {
674
+ const value = getCrewEnvParsed(name);
675
+ return typeof value === "number" ? value : undefined;
676
+ }
677
+
678
+ /** Typed wrapper: string value (raw, mirror-resolved). */
679
+ export function getCrewEnvString(name: string): string | undefined {
680
+ return getCrewEnv(name);
681
+ }
682
+
683
+ /** All registered crew env var names (for the gate + completeness tests). */
684
+ export function crewEnvNames(): string[] {
685
+ return Object.keys(CREW_ENV_VARS);
686
+ }
687
+
688
+ /** True when the registry covers `name` (mirror or not). */
689
+ export function isCrewEnvRegistered(name: string): boolean {
690
+ return Object.hasOwn(CREW_ENV_VARS, name);
691
+ }