@exaudeus/workrail 3.27.0 → 3.29.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 (160) hide show
  1. package/dist/console/assets/{index-FtTaDku8.js → index-BZ6HkxGf.js} +1 -1
  2. package/dist/console/index.html +1 -1
  3. package/dist/manifest.json +3 -3
  4. package/docs/README.md +57 -0
  5. package/docs/adrs/001-hybrid-storage-backend.md +38 -0
  6. package/docs/adrs/002-four-layer-context-classification.md +38 -0
  7. package/docs/adrs/003-checkpoint-trigger-strategy.md +35 -0
  8. package/docs/adrs/004-opt-in-encryption-strategy.md +36 -0
  9. package/docs/adrs/005-agent-first-workflow-execution-tokens.md +105 -0
  10. package/docs/adrs/006-append-only-session-run-event-log.md +76 -0
  11. package/docs/adrs/007-resume-and-checkpoint-only-sessions.md +51 -0
  12. package/docs/adrs/008-blocked-nodes-architectural-upgrade.md +178 -0
  13. package/docs/adrs/009-bridge-mode-single-instance-mcp.md +195 -0
  14. package/docs/adrs/010-release-pipeline.md +89 -0
  15. package/docs/architecture/README.md +7 -0
  16. package/docs/architecture/refactor-audit.md +364 -0
  17. package/docs/authoring-v2.md +527 -0
  18. package/docs/authoring.md +873 -0
  19. package/docs/changelog-recent.md +201 -0
  20. package/docs/configuration.md +505 -0
  21. package/docs/ctc-mcp-proposal.md +518 -0
  22. package/docs/design/README.md +22 -0
  23. package/docs/design/agent-cascade-protocol.md +96 -0
  24. package/docs/design/autonomous-console-design-candidates.md +253 -0
  25. package/docs/design/autonomous-console-design-review.md +111 -0
  26. package/docs/design/autonomous-platform-mvp-discovery.md +525 -0
  27. package/docs/design/claude-code-source-deep-dive.md +713 -0
  28. package/docs/design/console-cyberpunk-ui-discovery.md +504 -0
  29. package/docs/design/console-execution-trace-candidates-final.md +160 -0
  30. package/docs/design/console-execution-trace-candidates.md +211 -0
  31. package/docs/design/console-execution-trace-design-candidates-v2.md +113 -0
  32. package/docs/design/console-execution-trace-design-review.md +74 -0
  33. package/docs/design/console-execution-trace-discovery.md +394 -0
  34. package/docs/design/console-execution-trace-final-review.md +77 -0
  35. package/docs/design/console-execution-trace-review.md +92 -0
  36. package/docs/design/console-performance-discovery.md +415 -0
  37. package/docs/design/console-ui-backlog.md +280 -0
  38. package/docs/design/daemon-architecture-discovery.md +853 -0
  39. package/docs/design/daemon-design-candidates.md +318 -0
  40. package/docs/design/daemon-design-review-findings.md +119 -0
  41. package/docs/design/daemon-engine-design-candidates.md +210 -0
  42. package/docs/design/daemon-engine-design-review.md +131 -0
  43. package/docs/design/daemon-execution-engine-discovery.md +280 -0
  44. package/docs/design/daemon-gap-analysis.md +554 -0
  45. package/docs/design/daemon-owns-console-plan.md +168 -0
  46. package/docs/design/daemon-owns-console-review.md +91 -0
  47. package/docs/design/daemon-owns-console.md +195 -0
  48. package/docs/design/data-model-erd.md +11 -0
  49. package/docs/design/design-candidates-consolidate-dev-staleness.md +98 -0
  50. package/docs/design/design-candidates-walk-cache-depth-limit.md +80 -0
  51. package/docs/design/design-review-consolidate-dev-staleness.md +54 -0
  52. package/docs/design/design-review-walk-cache-depth-limit.md +48 -0
  53. package/docs/design/implementation-plan-consolidate-dev-staleness.md +142 -0
  54. package/docs/design/implementation-plan-walk-cache-depth-limit.md +141 -0
  55. package/docs/design/layer3b-ghost-nodes-design-candidates.md +229 -0
  56. package/docs/design/layer3b-ghost-nodes-design-review.md +93 -0
  57. package/docs/design/layer3b-ghost-nodes-implementation-plan.md +219 -0
  58. package/docs/design/list-workflows-latency-fix-plan.md +128 -0
  59. package/docs/design/list-workflows-latency-fix-review.md +55 -0
  60. package/docs/design/list-workflows-latency-fix.md +109 -0
  61. package/docs/design/native-context-management-api.md +11 -0
  62. package/docs/design/performance-sweep-2026-04.md +96 -0
  63. package/docs/design/routines-guide.md +219 -0
  64. package/docs/design/sequence-diagrams.md +11 -0
  65. package/docs/design/subagent-design-principles.md +220 -0
  66. package/docs/design/temporal-patterns-design-candidates.md +312 -0
  67. package/docs/design/temporal-patterns-design-review-findings.md +163 -0
  68. package/docs/design/test-isolation-from-config-file.md +335 -0
  69. package/docs/design/v2-core-design-locks.md +2746 -0
  70. package/docs/design/v2-lock-registry.json +734 -0
  71. package/docs/design/workflow-authoring-v2.md +1044 -0
  72. package/docs/design/workflow-docs-spec.md +218 -0
  73. package/docs/design/workflow-extension-points.md +687 -0
  74. package/docs/design/workrail-auto-trigger-system.md +359 -0
  75. package/docs/design/workrail-config-file-discovery.md +513 -0
  76. package/docs/docker.md +110 -0
  77. package/docs/generated/v2-lock-closure-plan.md +26 -0
  78. package/docs/generated/v2-lock-coverage.json +797 -0
  79. package/docs/generated/v2-lock-coverage.md +177 -0
  80. package/docs/ideas/backlog.md +3927 -0
  81. package/docs/ideas/design-candidates-mcp-resilience.md +208 -0
  82. package/docs/ideas/design-review-findings-mcp-resilience.md +119 -0
  83. package/docs/ideas/implementation_plan.md +249 -0
  84. package/docs/ideas/third-party-workflow-setup-design-thinking.md +1948 -0
  85. package/docs/implementation/02-architecture.md +316 -0
  86. package/docs/implementation/04-testing-strategy.md +124 -0
  87. package/docs/implementation/09-simple-workflow-guide.md +835 -0
  88. package/docs/implementation/13-advanced-validation-guide.md +874 -0
  89. package/docs/implementation/README.md +21 -0
  90. package/docs/integrations/claude-code.md +300 -0
  91. package/docs/integrations/firebender.md +315 -0
  92. package/docs/migration/v0.1.0.md +147 -0
  93. package/docs/naming-conventions.md +45 -0
  94. package/docs/planning/README.md +104 -0
  95. package/docs/planning/github-ticketing-playbook.md +195 -0
  96. package/docs/plans/README.md +24 -0
  97. package/docs/plans/agent-managed-ticketing-design.md +605 -0
  98. package/docs/plans/agentic-orchestration-roadmap.md +112 -0
  99. package/docs/plans/assessment-gates-engine-handoff.md +536 -0
  100. package/docs/plans/content-coherence-and-references.md +151 -0
  101. package/docs/plans/library-extraction-plan.md +340 -0
  102. package/docs/plans/mr-review-workflow-redesign.md +1451 -0
  103. package/docs/plans/native-context-management-epic.md +11 -0
  104. package/docs/plans/perf-fixes-design-candidates.md +225 -0
  105. package/docs/plans/perf-fixes-design-review-findings.md +61 -0
  106. package/docs/plans/perf-fixes-new-issues-candidates.md +264 -0
  107. package/docs/plans/perf-fixes-new-issues-review.md +110 -0
  108. package/docs/plans/prompt-fragments.md +53 -0
  109. package/docs/plans/ui-ux-workflow-design-candidates.md +120 -0
  110. package/docs/plans/ui-ux-workflow-discovery.md +100 -0
  111. package/docs/plans/ui-ux-workflow-review.md +48 -0
  112. package/docs/plans/v2-followup-enhancements.md +587 -0
  113. package/docs/plans/workflow-categories-candidates.md +105 -0
  114. package/docs/plans/workflow-categories-discovery.md +110 -0
  115. package/docs/plans/workflow-categories-review.md +51 -0
  116. package/docs/plans/workflow-discovery-model-candidates.md +94 -0
  117. package/docs/plans/workflow-discovery-model-discovery.md +74 -0
  118. package/docs/plans/workflow-discovery-model-review.md +48 -0
  119. package/docs/plans/workflow-source-setup-phase-1.md +245 -0
  120. package/docs/plans/workflow-source-setup-phase-2.md +361 -0
  121. package/docs/plans/workflow-staleness-detection-candidates.md +104 -0
  122. package/docs/plans/workflow-staleness-detection-review.md +58 -0
  123. package/docs/plans/workflow-staleness-detection.md +80 -0
  124. package/docs/plans/workflow-v2-design.md +69 -0
  125. package/docs/plans/workflow-v2-roadmap.md +74 -0
  126. package/docs/plans/workflow-validation-design.md +98 -0
  127. package/docs/plans/workflow-validation-roadmap.md +108 -0
  128. package/docs/plans/workrail-platform-vision.md +420 -0
  129. package/docs/reference/agent-context-cleaner-snippet.md +94 -0
  130. package/docs/reference/agent-context-guidance.md +140 -0
  131. package/docs/reference/context-optimization.md +284 -0
  132. package/docs/reference/example-workflow-repository-template/.github/workflows/validate.yml +125 -0
  133. package/docs/reference/example-workflow-repository-template/README.md +268 -0
  134. package/docs/reference/example-workflow-repository-template/workflows/example-workflow.json +80 -0
  135. package/docs/reference/external-workflow-repositories.md +916 -0
  136. package/docs/reference/feature-flags-architecture.md +472 -0
  137. package/docs/reference/feature-flags.md +349 -0
  138. package/docs/reference/god-tier-workflow-validation.md +272 -0
  139. package/docs/reference/loop-optimization.md +209 -0
  140. package/docs/reference/loop-validation.md +176 -0
  141. package/docs/reference/loops.md +465 -0
  142. package/docs/reference/mcp-platform-constraints.md +59 -0
  143. package/docs/reference/recovery.md +88 -0
  144. package/docs/reference/releases.md +177 -0
  145. package/docs/reference/troubleshooting.md +105 -0
  146. package/docs/reference/workflow-execution-contract.md +998 -0
  147. package/docs/roadmap/README.md +22 -0
  148. package/docs/roadmap/legacy-planning-status.md +103 -0
  149. package/docs/roadmap/now-next-later.md +70 -0
  150. package/docs/roadmap/open-work-inventory.md +389 -0
  151. package/docs/tickets/README.md +39 -0
  152. package/docs/tickets/next-up.md +76 -0
  153. package/docs/workflow-management.md +317 -0
  154. package/docs/workflow-templates.md +423 -0
  155. package/docs/workflow-validation.md +184 -0
  156. package/docs/workflows.md +254 -0
  157. package/package.json +3 -1
  158. package/spec/authoring-spec.json +61 -16
  159. package/workflows/workflow-for-workflows.json +252 -93
  160. package/workflows/workflow-for-workflows.v2.json +188 -77
@@ -0,0 +1,513 @@
1
+ # WorkRail Config File: Discovery and Architecture Brief
2
+
3
+ **Status:** Discovery complete
4
+ **Date:** 2026-04-06
5
+ **Author:** Discovery workflow (wr.discovery v3.1.0)
6
+
7
+ ---
8
+
9
+ ## Context / Ask
10
+
11
+ WorkRail is configured entirely through environment variables passed in each IDE's MCP server block
12
+ (Cursor `.cursor/mcp.json`, Claude Code `.claude.json`, Firebender config, etc.). When a flag is
13
+ added or changed, every IDE config file must be updated by hand. The user wants a single
14
+ `~/.workrail/config` file that all IDEs pick up automatically, with env vars still available as
15
+ overrides.
16
+
17
+ **Desired outcome:** An architecture brief and requirements list ready to turn into a ticket.
18
+
19
+ ---
20
+
21
+ ## Path Recommendation
22
+
23
+ **Path:** `landscape_first`
24
+
25
+ **Rationale:** The solution space is bounded and familiar (dotfile config loading is a solved
26
+ pattern). The core question is "which design fits best here?" not "are we solving the right
27
+ problem?". The landscape -- existing flags, where they are read, and how the codebase is already
28
+ structured -- is the dominant input. A full-spectrum reframe would add ceremony without sharpening
29
+ the answer.
30
+
31
+ ---
32
+
33
+ ## Landscape Packet
34
+
35
+ ### Current State Summary
36
+
37
+ WorkRail reads configuration from `process.env` at startup in multiple layers:
38
+
39
+ **Layer 1: Structured config (validated via Zod, `src/config/app-config.ts`)**
40
+
41
+ These are parsed through `loadConfig({ env: process.env, ... })` with Zod schema validation,
42
+ returning a `Result` type. The DI container calls this at startup.
43
+
44
+ | Variable | Default | Description |
45
+ |----------|---------|-------------|
46
+ | `CACHE_TTL` | `300000` | Workflow cache TTL (ms) |
47
+ | `WORKRAIL_WORKFLOWS_DIR` | cwd | Override workflow search root |
48
+ | `WORKRAIL_DISABLE_UNIFIED_DASHBOARD` | `0` | Disable unified dashboard |
49
+ | `WORKRAIL_DISABLE_AUTO_OPEN` | `0` | Disable browser auto-open |
50
+ | `WORKRAIL_DASHBOARD_PORT` | `3456` | Dashboard HTTP port |
51
+
52
+ **Layer 2: Feature flags (boolean toggles, `src/config/feature-flags.ts`)**
53
+
54
+ Read by `EnvironmentFeatureFlagProvider` which accepts a `Record<string, string | undefined>` env
55
+ source. Flags have typed keys, defaults, stability markers, and descriptions.
56
+
57
+ | Variable | Default | Stable | Description |
58
+ |----------|---------|--------|-------------|
59
+ | `WORKRAIL_ENABLE_SESSION_TOOLS` | `true` | yes | Session management tools |
60
+ | `WORKRAIL_ENABLE_EXPERIMENTAL_WORKFLOWS` | `false` | no | Load experimental/ dir |
61
+ | `WORKRAIL_VERBOSE_LOGGING` | `false` | yes | Debug logging |
62
+ | `WORKRAIL_ENABLE_AGENTIC_ROUTINES` | `true` | yes | Agentic orchestration |
63
+ | `WORKRAIL_ENABLE_LEAN_WORKFLOWS` | `false` | no | Lean workflow variants |
64
+ | `WORKRAIL_AUTHORITATIVE_DESCRIPTIONS` | `false` | no | Imperative tool language |
65
+ | `WORKRAIL_ENABLE_V2_TOOLS` | `true` | yes | V2 MCP tools |
66
+ | `WORKRAIL_CLEAN_RESPONSE_FORMAT` | `false` | no | Clean response format |
67
+
68
+ **Layer 3: Ad-hoc env flags (read via direct `process.env[]` access)**
69
+
70
+ Scattered across the codebase; not behind the structured config or feature-flags system.
71
+
72
+ | Variable | Where read | Description |
73
+ |----------|-----------|-------------|
74
+ | `WORKRAIL_DEV` | `src/mcp/dev-mode.ts`, `src/mcp/assert-output.ts` | Unified dev flag (staleness + timing + perf endpoint) |
75
+ | `WORKRAIL_JSON_RESPONSES` | `src/mcp/handler-factory.ts` | Force JSON response format |
76
+ | `WORKRAIL_CLEAN_RESPONSE_FORMAT` | `src/env-flags.ts` | Also read directly (duplicate) |
77
+ | `WORKRAIL_LOG_LEVEL` | `src/utils/logger.ts` | Log level |
78
+ | `WORKRAIL_LOG_FORMAT` | `src/utils/logger.ts` | Log format (human or json) |
79
+ | `WORKRAIL_DATA_DIR` | `src/v2/infra/local/data-dir/index.ts` | Override data directory |
80
+ | `WORKRAIL_CACHE_DIR` | `src/infrastructure/storage/enhanced-multi-source-workflow-storage.ts` | Cache base directory |
81
+ | `WORKFLOW_STORAGE_PATH` | `src/mcp/handlers/shared/request-workflow-reader.ts`, `enhanced-multi-source-workflow-storage.ts` | Additional workflow dirs (colon-sep) |
82
+ | `WORKFLOW_GIT_REPOS` | `enhanced-multi-source-workflow-storage.ts` | Git repo URLs |
83
+ | `WORKFLOW_GIT_REPO_URL` | same | Single repo URL |
84
+ | `WORKFLOW_GIT_REPO_BRANCH` | same | Branch to use |
85
+ | `WORKFLOW_GIT_SYNC_INTERVAL` | same | Sync interval (minutes) |
86
+ | `WORKFLOW_REGISTRY_URL` | same | Remote registry URL |
87
+ | `WORKFLOW_REGISTRY_API_KEY` | same | Registry API key |
88
+ | `WORKFLOW_REGISTRY_TIMEOUT` | same | Registry timeout (ms) |
89
+ | `WORKFLOW_INCLUDE_BUNDLED` | `enhanced-multi-source-workflow-storage.ts` | Include built-in workflows |
90
+ | `WORKFLOW_INCLUDE_USER` | same | Include user workflows |
91
+ | `WORKFLOW_INCLUDE_PROJECT` | same | Include project workflows |
92
+ | `GITHUB_TOKEN` / `GITLAB_TOKEN` / `BITBUCKET_TOKEN` | same | VCS auth tokens |
93
+ | `GIT_TOKEN` / `WORKFLOW_GIT_AUTH_TOKEN` | same | Generic git auth fallbacks |
94
+ | `GIT_<HOSTNAME>_TOKEN` | same | Hostname-based auth tokens |
95
+
96
+ **Total distinct variables: 35+**
97
+
98
+ ### Existing Patterns and Precedents
99
+
100
+ 1. **`~/.workrail/` already exists** as the user data directory. It contains `workflows/`, `cache/`,
101
+ `sessions/`, `data/`, `logs/`. A `config.json` alongside these would be natural.
102
+
103
+ 2. **`loadConfig` in `app-config.ts`** already accepts `env: Record<string, string | undefined>` --
104
+ not `process.env` directly. This is the right extension point: pass a merged env record instead
105
+ of raw `process.env`.
106
+
107
+ 3. **`EnvironmentFeatureFlagProvider`** accepts the same `Record<string, string | undefined>` shape.
108
+ Same pattern.
109
+
110
+ 4. **`LocalDataDirV2`** reads `WORKRAIL_DATA_DIR` from its injected env. Same pattern -- already
111
+ injectable.
112
+
113
+ 5. **The DI composition root (`src/di/container.ts`)** is the single place where `process.env` is
114
+ injected into all of these. This is the correct and minimal seam to intercept.
115
+
116
+ 6. **`.workrail/bindings.json`** is already a project-level config file -- the project already has
117
+ a precedent for on-disk config.
118
+
119
+ 7. **Industry precedent:** dotenv-style overlay files (`.npmrc`, `~/.gitconfig`, `~/.cargo/config.toml`,
120
+ `~/.docker/config.json`) universally use a pattern where the file provides defaults and env vars
121
+ override.
122
+
123
+ ### Option Categories
124
+
125
+ - **A. Simple env-file load** -- load `~/.workrail/config` as a key=value (dotenv-style) file,
126
+ merge into `process.env` early, before the DI container runs.
127
+ - **B. Typed JSON config file** -- load `~/.workrail/config.json`, map to typed keys, merge into
128
+ the env record at the composition root (not into `process.env`).
129
+ - **C. TOML config file** -- same semantics as B but TOML format.
130
+ - **D. Two-tier: user config + project config** -- `~/.workrail/config.json` (global) plus
131
+ `.workrail/config.json` (project, gitignored-optional). Already has `.workrail/bindings.json`
132
+ precedent.
133
+ - **E. Do nothing, just document** -- accept env vars as the config surface, improve docs.
134
+
135
+ ### Contradictions and Disagreements
136
+
137
+ 1. `WORKRAIL_CLEAN_RESPONSE_FORMAT` is read in TWO places: once through `feature-flags.ts` (via
138
+ DI) and once directly in `src/env-flags.ts`. If config-file loading happens at the DI
139
+ composition root but `env-flags.ts` still reads `process.env` directly, the duplicate path will
140
+ be stale.
141
+
142
+ 2. Some flags are genuinely per-machine or per-IDE (e.g., `WORKFLOW_GIT_REPOS`, `WORKFLOW_STORAGE_PATH`
143
+ -- different machines have different repo paths). A global user config file must handle these
144
+ cases without forcing incorrect defaults.
145
+
146
+ 3. `WORKRAIL_DEV` is a development-only flag explicitly not documented for production use. It is
147
+ unlikely to belong in a user config file but should be considered.
148
+
149
+ 4. Auth tokens (`GITHUB_TOKEN`, etc.) belong in the environment, not in a config file (secret
150
+ management concern). They should be explicitly out of scope for the config file.
151
+
152
+ 5. `WORKRAIL_DATA_DIR` is injected via `LocalDataDirV2(process.env)` from the DI container -- it
153
+ could be supported in config but is rarely needed.
154
+
155
+ ### Evidence Gaps
156
+
157
+ - No current unit test covers the config-loading seam being injectable. Tests use
158
+ `EnvironmentFeatureFlagProvider.withEnv(env)` for feature flags but the broader `loadConfig` path
159
+ hasn't been verified for full injectability.
160
+ - The exact startup order (when `dev-mode.ts` and `env-flags.ts` module-level constants are
161
+ evaluated vs. when the DI container runs) needs to be checked. If those constants are evaluated
162
+ before the config file is read, merging at the DI level is insufficient for those two files.
163
+
164
+ ---
165
+
166
+ ## Problem Frame Packet
167
+
168
+ ### Users / Stakeholders
169
+
170
+ - **Primary user: the developer configuring WorkRail locally** -- wants to set flags once and have
171
+ all IDE integrations pick them up without maintaining parallel config blocks.
172
+ - **CI / automation** -- needs to override individual flags without a config file (env-only path
173
+ must remain fully functional).
174
+ - **Team members sharing workflow repos** -- may have different machine-specific paths; config file
175
+ must not force a shared value for per-machine settings.
176
+
177
+ ### Jobs, Goals, and Outcomes
178
+
179
+ - Set flags once, have all IDEs see them automatically.
180
+ - Add a new flag without touching N IDE config files.
181
+ - Keep CI clean (no config file in CI, just env vars).
182
+ - Preserve the ability for env vars to override the file (for per-IDE variation when legitimately needed).
183
+
184
+ ### Pains / Tensions / Constraints
185
+
186
+ 1. **The "scatter problem"**: 35+ env vars, 3+ IDE configs, manual sync required today.
187
+ 2. **Auth tokens must stay in env**: config files may be dotfiles-tracked in git; tokens cannot be
188
+ in a potentially-committed file.
189
+ 3. **Per-machine paths**: `WORKFLOW_GIT_REPOS` and `WORKFLOW_STORAGE_PATH` are typically different
190
+ per machine. They belong in the config file for that machine but should not be treated as global
191
+ team defaults.
192
+ 4. **Module-level constants** in `dev-mode.ts` and `env-flags.ts` are evaluated at import time,
193
+ before any DI container initialization. A config-file loading approach that only intercepts at
194
+ the DI level will miss these two.
195
+ 5. **Process boundary**: WorkRail runs as an MCP stdio server; `process.env` is set by the parent
196
+ process (the IDE). A config file must be loaded early in the server's own boot sequence.
197
+
198
+ ### Success Criteria
199
+
200
+ 1. A developer can set any flag in `~/.workrail/config.json` and have it take effect in all IDEs
201
+ without IDE-specific config changes.
202
+ 2. Env vars still override config file values (env takes precedence over file).
203
+ 3. Auth tokens (`GITHUB_TOKEN`, etc.) work correctly from env only -- not from config file.
204
+ 4. CI override: setting an env var in CI overrides the config file value without requiring a config
205
+ file to exist.
206
+ 5. If the config file is absent or malformed, WorkRail starts with defaults (file is optional).
207
+ 6. Module-level constants (`WORKRAIL_DEV`, `WORKRAIL_CLEAN_RESPONSE_FORMAT`) are resolved from the
208
+ same merged env, not from raw `process.env`.
209
+
210
+ ### Assumptions
211
+
212
+ - `~/.workrail/` is the right home for the config file (already established as the user data dir).
213
+ - JSON is the right format (already used for `.workrail/bindings.json`, workflow files, etc.).
214
+ - TypeScript / Node.js; no external config library like `cosmiconfig` is assumed to be available.
215
+ - The config file is not a secrets store.
216
+
217
+ ### Reframes / HMW Questions
218
+
219
+ - **HMW 1:** How might we make it easy to see which IDE is overriding which config value? (The
220
+ precedence chain should be observable.)
221
+ - **HMW 2:** How might we structure the config so that per-machine and per-IDE settings have an
222
+ obvious natural home? (Could the schema group "global" vs "local" keys, or add comments in a
223
+ JSONC format?)
224
+
225
+ ### What Could Make This Framing Wrong
226
+
227
+ - If `WORKRAIL_DEV` and similar module-level constants are moved into the feature-flags system
228
+ before this work, the "missing seam" problem at module load time disappears.
229
+ - If the real driver is "too many flags" (not "too many places to configure them"), the right
230
+ solution might be a flag-review pass + documentation improvement, not a new config file.
231
+
232
+ ---
233
+
234
+ ## Candidate Directions
235
+
236
+ ### Direction A: Env-file merge at process startup (dotenv-style)
237
+
238
+ Load `~/.workrail/config` as a dotenv file early in `src/mcp-server.ts` (before any module
239
+ with module-level constants is imported), merge into `process.env` for keys not already set.
240
+
241
+ **Fits the path because:** dotenv-style loading is a well-understood pattern in Node.js; it handles
242
+ the module-level constant problem because the load happens before any imports evaluate them.
243
+
244
+ **Strongest evidence for:** Simple. Covers all env vars including module-level constants. Standard
245
+ pattern (`dotenv` package or small custom parser). No schema changes needed.
246
+
247
+ **Strongest risk:** Mutates `process.env`, which violates the "immutability by default" coding
248
+ philosophy. Also, dotenv files have no structure -- they look like `.env` files, which users may
249
+ conflate with secrets files and hesitate to commit to dotfiles repos.
250
+
251
+ **When it should win:** If covering module-level constants is the top priority and simplicity
252
+ matters more than format elegance.
253
+
254
+ ---
255
+
256
+ ### Direction B: Typed JSON config merged at DI composition root (no process.env mutation)
257
+
258
+ Load `~/.workrail/config.json` at the DI composition root (`src/di/container.ts`) before the
259
+ first `loadConfig` call. Build a merged env record: `{ ...configFileEntries, ...process.env }`.
260
+ Pass this merged record to all consumers: `loadConfig`, `EnvironmentFeatureFlagProvider`,
261
+ `LocalDataDirV2`. Update `dev-mode.ts` and `env-flags.ts` to receive their values via DI
262
+ injection instead of reading `process.env` directly.
263
+
264
+ **Fits the path because:** It builds on the existing injectable pattern that `loadConfig` and
265
+ `EnvironmentFeatureFlagProvider` already use. Does not mutate global state. JSON is already the
266
+ project's config format.
267
+
268
+ **Strongest evidence for:** No `process.env` mutation. The injectable seam already exists for
269
+ two of the three layers. JSON schema can be validated with Zod (already a project dependency). The
270
+ config key names can map 1:1 to env var names initially, keeping the mental model simple.
271
+
272
+ **Strongest risk:** Requires refactoring `dev-mode.ts` and `env-flags.ts` away from module-level
273
+ constants -- they must not read `process.env` at import time. This is a non-trivial change in
274
+ scope; if it is deferred, those two flags still won't benefit from the config file.
275
+
276
+ **When it should win:** When architectural cleanliness and no global mutation matter more than
277
+ scope minimalism.
278
+
279
+ ---
280
+
281
+ ### Direction C: Two-tier config (user + project) JSON
282
+
283
+ Same as Direction B but with two config files: `~/.workrail/config.json` (user-global) and
284
+ `.workrail/config.json` in the project root (per-project, gitignore-able). Precedence:
285
+ `process.env > project config > user config`.
286
+
287
+ **Fits the path because:** Aligns with the existing `.workrail/bindings.json` project-level
288
+ precedent. Natural home for per-project overrides (e.g., `WORKFLOW_STORAGE_PATH` scoped to a
289
+ specific project).
290
+
291
+ **Strongest evidence for:** Models how gitconfig (`~/.gitconfig` + `.git/config`) and many other
292
+ tools work. The project-level file is already adjacent to `bindings.json` so the directory exists.
293
+
294
+ **Strongest risk:** More complex to implement and explain. The per-project config file could cause
295
+ surprises if committed to a team repo ("why do all team members get the same workflow path?").
296
+
297
+ **When it should win:** When per-project flag overrides are a real known use case, not speculation.
298
+
299
+ ---
300
+
301
+ ## Challenge Notes
302
+
303
+ **Challenging Direction B (the leading option):**
304
+
305
+ The strongest argument against B is the scope of the `dev-mode.ts` / `env-flags.ts` refactor. Both
306
+ files export module-level constants that are evaluated at import time -- this is intentional (the
307
+ comment in `env-flags.ts` says "MCP servers are long-lived processes; env vars are set at startup
308
+ and do not change at runtime. Caching here eliminates per-call lookups"). Injecting these through DI
309
+ means converting those module-level exports to injected singleton values, which means every consumer
310
+ of `DEV_MODE` and `CLEAN_RESPONSE_FORMAT` must change from `import { DEV_MODE }` to DI resolution.
311
+ That is a wider refactor than "load a config file".
312
+
313
+ **Resolution:** This is a real scope concern, but there is a pragmatic middle path. Direction B can
314
+ be implemented in two sub-phases:
315
+
316
+ - **Phase 1 (tight scope):** Load config file at the DI composition root, merge env record, pass to
317
+ `loadConfig` and `EnvironmentFeatureFlagProvider` only. This covers ~95% of the user-facing flags
318
+ without touching the module-level constants.
319
+ - **Phase 2 (cleanup):** Move `dev-mode.ts` and `env-flags.ts` to DI-injectable singletons.
320
+ `WORKRAIL_DEV` is a developer tool not needed by most users; deferring Phase 2 is acceptable.
321
+
322
+ Direction A (dotenv mutation) is rejected because mutating `process.env` creates implicit coupling
323
+ and violates the architectural direction of the codebase.
324
+
325
+ Direction C (two-tier) is rejected as speculative -- the per-project use case is not a known pain
326
+ point today. The project-level config can be added later if demand emerges.
327
+
328
+ ---
329
+
330
+ ## Decision Log
331
+
332
+ **Selected direction: B (JSON config merged at DI composition root), phased.**
333
+
334
+ **Why B won:**
335
+
336
+ 1. No `process.env` mutation -- consistent with immutability-by-default principle.
337
+ 2. The injectable seam (`loadConfig({ env: ... })` and `EnvironmentFeatureFlagProvider.withEnv(env)`)
338
+ already exists. The work is primarily plumbing: load file, build merged record, pass it through.
339
+ 3. JSON with Zod validation is already the project pattern (see `app-config.ts`). Schema can be a
340
+ subset of env vars -- just the ones that make sense to set globally.
341
+ 4. The two-phase approach handles the scope concern without deferring user value.
342
+
343
+ **Why A lost:**
344
+
345
+ Global `process.env` mutation is architecturally inconsistent with how the codebase is moving. It
346
+ also leaves the config surface untyped and unvalidated.
347
+
348
+ **Why C lost:**
349
+
350
+ The per-project config tier adds complexity for a use case that does not yet have evidence of user
351
+ demand. `.workrail/bindings.json` already handles workflow-level overrides; a second project-level
352
+ config file risks confusing the mental model.
353
+
354
+ **Accepted tradeoffs:**
355
+
356
+ - `WORKRAIL_DEV` and `WORKRAIL_CLEAN_RESPONSE_FORMAT` will NOT benefit from the config file in
357
+ Phase 1. This is acceptable: `WORKRAIL_DEV` is a developer-only flag, and `WORKRAIL_CLEAN_RESPONSE_FORMAT`
358
+ is already in the feature-flags system (the `env-flags.ts` version is a legacy duplicate).
359
+ - The config file will use env var names as keys (not a new abstraction layer). This keeps the
360
+ mental model simple: what you'd put in an IDE env block, you can put in the config file instead.
361
+
362
+ **Switch trigger:** If the `dev-mode.ts` module-level constant pattern is found to cause problems
363
+ in practice (e.g., users can't configure `WORKRAIL_DEV` from the file), Phase 2 should be pulled
364
+ forward.
365
+
366
+ ---
367
+
368
+ ## Resolution Notes
369
+
370
+ **Resolution mode:** `direct_recommendation`
371
+
372
+ **Confidence band:** HIGH for the config loading architecture. MEDIUM for the exact schema surface
373
+ (which keys belong in the file vs. env-only). The codebase evidence is unambiguous on the seam;
374
+ the "which keys" question has some judgment calls.
375
+
376
+ **Residual risks:**
377
+
378
+ 1. `env-flags.ts` still reads `process.env.WORKRAIL_CLEAN_RESPONSE_FORMAT` directly -- this will
379
+ shadow the feature-flags version if anyone sets the key in the config file (they'll see the DI
380
+ flag updated but not the module-level constant). Mitigation: delete the `env-flags.ts` export
381
+ entirely and consolidate on the DI path in Phase 1 (it is already the right place).
382
+
383
+ 2. Auth tokens are excluded from the config schema by design, but the schema validation needs to
384
+ explicitly reject or ignore any token-shaped key submitted to the config file.
385
+
386
+ 3. The config file is read from `~/.workrail/config.json` -- this path is hardcoded. On machines
387
+ where `~` is non-standard or the data dir is overridden via `WORKRAIL_DATA_DIR`, the config file
388
+ location may be surprising. Mitigation: use `os.homedir()` + `/.workrail/config.json`
389
+ consistently and document it.
390
+
391
+ ---
392
+
393
+ ## Final Summary
394
+
395
+ ### Architecture Brief
396
+
397
+ The correct implementation is a typed JSON config file at `~/.workrail/config.json`, loaded at the
398
+ DI composition root before the first `loadConfig` call. The file provides default env values that
399
+ are overridden by any key present in `process.env`. No mutation of `process.env`; the merged record
400
+ is passed through the existing injectable seams.
401
+
402
+ **Loading sequence:**
403
+
404
+ ```
405
+ ~/.workrail/config.json (defaults)
406
+ + process.env (overrides)
407
+ = merged env record
408
+ --> loadConfig(mergedEnv)
409
+ --> EnvironmentFeatureFlagProvider(mergedEnv)
410
+ --> LocalDataDirV2(mergedEnv)
411
+ ```
412
+
413
+ **Config file format:**
414
+
415
+ ```json
416
+ {
417
+ "WORKRAIL_ENABLE_LEAN_WORKFLOWS": "true",
418
+ "WORKRAIL_CLEAN_RESPONSE_FORMAT": "true",
419
+ "WORKRAIL_AUTHORITATIVE_DESCRIPTIONS": "true",
420
+ "WORKRAIL_ENABLE_V2_TOOLS": "true",
421
+ "WORKFLOW_STORAGE_PATH": "/Users/me/shared-workflows",
422
+ "WORKFLOW_GIT_REPOS": "https://github.com/myteam/workflows.git",
423
+ "CACHE_TTL": "0"
424
+ }
425
+ ```
426
+
427
+ Keys are the exact env var names. String values, same as env vars. Unknown keys: warn and ignore
428
+ (never error -- WorkRail should still start if a key is unknown).
429
+
430
+ **Precedence:** `process.env` > `~/.workrail/config.json` > compiled defaults.
431
+
432
+ **Excluded from config file schema (env-only):**
433
+
434
+ - All `*_TOKEN` keys (`GITHUB_TOKEN`, `GITLAB_TOKEN`, etc.) -- secrets management concern.
435
+ - `WORKRAIL_DEV` -- developer-only, not a user config surface.
436
+ - `NODE_ENV`, `VITEST` -- runtime/test framework vars.
437
+
438
+ **Phase 1 scope:**
439
+
440
+ 1. Add `loadWorkrailConfigFile(): Record<string, string>` utility in a new `src/config/config-file.ts`.
441
+ Uses `os.homedir()`, reads `~/.workrail/config.json` if it exists, validates with Zod, returns
442
+ empty record on absence or parse error (with a warning log).
443
+ 2. In `src/di/container.ts`, call `loadWorkrailConfigFile()` before `loadConfig()`. Build
444
+ `mergedEnv = { ...configFileValues, ...process.env }`. Pass `mergedEnv` to `loadConfig` and to
445
+ `EnvironmentFeatureFlagProvider`.
446
+ 3. Delete `src/env-flags.ts` (the `WORKRAIL_CLEAN_RESPONSE_FORMAT` module-level constant is already
447
+ covered by the feature-flags DI path; the duplicate is dead weight).
448
+ 4. Add `workrail init --config` CLI command that writes a commented `~/.workrail/config.json`
449
+ template with all supported keys and their defaults.
450
+ 5. Update `docs/configuration.md` with the new config file section, precedence order, and what
451
+ belongs in the file vs. env-only.
452
+
453
+ **Phase 2 scope (deferred):**
454
+
455
+ Move `dev-mode.ts` (`WORKRAIL_DEV`) to a DI-injectable singleton so it can also read from the
456
+ config file.
457
+
458
+ ### Requirements List (ticket-ready)
459
+
460
+ **Functional requirements:**
461
+
462
+ - FR1: WorkRail reads `~/.workrail/config.json` on startup if it exists.
463
+ - FR2: Any env var name (except excluded secrets and dev-only flags) may appear as a key in the config file.
464
+ - FR3: `process.env` values override config file values for the same key.
465
+ - FR4: If the config file is absent, WorkRail starts with compiled defaults (file is optional).
466
+ - FR5: If the config file is malformed (invalid JSON or invalid key types), WorkRail logs a warning
467
+ and starts with compiled defaults -- no crash.
468
+ - FR6: Unknown keys in the config file produce a warning log and are ignored.
469
+ - FR7: Auth token keys (`*_TOKEN`) are not read from the config file (excluded from schema or
470
+ ignored with a warning).
471
+
472
+ **Non-functional requirements:**
473
+
474
+ - NFR1: No mutation of `process.env`.
475
+ - NFR2: Config file loading uses `os.homedir()` for portability.
476
+ - NFR3: The merged env record is the only input to `loadConfig` and `EnvironmentFeatureFlagProvider`
477
+ (no other `process.env` access in those constructors).
478
+ - NFR4: Config loading failure is represented as a `Result` type, not a thrown exception.
479
+ - NFR5: Loading must complete before any DI registration that reads env vars.
480
+
481
+ **CLI / DX requirements:**
482
+
483
+ - DX1: `workrail init --config` writes a `~/.workrail/config.json` template with all supported
484
+ keys commented out and their defaults shown.
485
+ - DX2: `WORKRAIL_LOG_LEVEL=DEBUG` (or via config file) should log which keys were loaded from
486
+ the config file and which were overridden by `process.env`.
487
+
488
+ **Documentation requirements:**
489
+
490
+ - DOC1: `docs/configuration.md` must document the config file, its location, format, precedence
491
+ order, and excluded keys.
492
+ - DOC2: Existing env var documentation should note that the same keys work in the config file.
493
+
494
+ **Testing requirements:**
495
+
496
+ - TEST1: Unit test for `loadWorkrailConfigFile()` -- file absent, valid file, malformed JSON, unknown
497
+ keys, excluded token key.
498
+ - TEST2: Integration test for the DI composition root with a config file present -- verify that
499
+ config file values are visible to `loadConfig` and feature flags.
500
+ - TEST3: Override test -- env var overrides config file value for the same key.
501
+
502
+ ---
503
+
504
+ ## Next Actions
505
+
506
+ 1. Create a ticket from the requirements list above.
507
+ 2. Phase 1 implementation:
508
+ a. `src/config/config-file.ts` -- `loadWorkrailConfigFile()` with Zod schema.
509
+ b. `src/di/container.ts` -- inject merged env into `loadConfig` and `EnvironmentFeatureFlagProvider`.
510
+ c. Delete `src/env-flags.ts` -- consolidate on feature-flags DI path.
511
+ d. `workrail init --config` CLI subcommand.
512
+ e. Update `docs/configuration.md`.
513
+ 3. Phase 2 (separate ticket): move `WORKRAIL_DEV` to a DI singleton.
package/docs/docker.md ADDED
@@ -0,0 +1,110 @@
1
+ # WorkRail MCP Docker Usage Guide
2
+
3
+ ## Building the Docker Image
4
+
5
+ ```bash
6
+ # Build the Docker image
7
+ docker build -f Dockerfile.simple -t workrail-mcp .
8
+ ```
9
+
10
+ ## Using with MCP Clients
11
+
12
+ ### Claude Desktop
13
+
14
+ Add this to your `claude_desktop_config.json`:
15
+
16
+ ```json
17
+ {
18
+ "mcpServers": {
19
+ "workrail": {
20
+ "command": "docker",
21
+ "args": [
22
+ "run",
23
+ "--rm",
24
+ "-i",
25
+ "workrail-mcp"
26
+ ]
27
+ }
28
+ }
29
+ }
30
+ ```
31
+
32
+ ### VS Code MCP Extension
33
+
34
+ Add this to your `.vscode/mcp.json`:
35
+
36
+ ```json
37
+ {
38
+ "mcp": {
39
+ "servers": {
40
+ "workrail": {
41
+ "command": "docker",
42
+ "args": [
43
+ "run",
44
+ "--rm",
45
+ "-i",
46
+ "workrail-mcp"
47
+ ]
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### Other MCP Clients
55
+
56
+ Use the command pattern:
57
+ ```bash
58
+ docker run --rm -i workrail-mcp
59
+ ```
60
+
61
+ ## Testing the Docker Image
62
+
63
+ Test MCP functionality manually:
64
+
65
+ ```bash
66
+ # Test tools list
67
+ echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | docker run --rm -i workrail-mcp
68
+
69
+ # Test workflow list
70
+ echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"workflow_list","arguments":{}}}' | docker run --rm -i workrail-mcp
71
+
72
+ # Test getting a specific workflow
73
+ echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"workflow_get","arguments":{"id":"coding-task-workflow-agentic","mode":"metadata"}}}' | docker run --rm -i workrail-mcp
74
+ ```
75
+
76
+ ## Custom Workflows
77
+
78
+ To use custom workflows with Docker, mount a volume:
79
+
80
+ ```json
81
+ {
82
+ "mcpServers": {
83
+ "workrail": {
84
+ "command": "docker",
85
+ "args": [
86
+ "run",
87
+ "--rm",
88
+ "-i",
89
+ "-v", "/path/to/your/workflows:/app/custom-workflows",
90
+ "-e", "WORKFLOW_STORAGE_PATH=/app/custom-workflows",
91
+ "workrail-mcp"
92
+ ]
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ ## Requirements
99
+
100
+ - Docker installed and running
101
+ - MCP-compatible client (Claude Desktop, VS Code, etc.)
102
+ - Node.js 20+ (for building from source)
103
+
104
+ ## Notes
105
+
106
+ - The Docker image uses Node.js 20 Alpine for security and small size
107
+ - Runs as non-root user for security
108
+ - Includes all built-in workflows
109
+ - Communicates via stdin/stdout (standard MCP protocol)
110
+ - No network ports exposed (MCPs don't need them)
@@ -0,0 +1,26 @@
1
+ # v2 Lock Closure Plan
2
+
3
+ > **Auto-generated** — Do not edit manually.
4
+ > Registry version: 1.0.0
5
+
6
+ This file is a deterministic “what to do next” plan for driving **uncovered locks → 0**.
7
+
8
+ ---
9
+
10
+ ## Summary
11
+
12
+ - Total locks: **118**
13
+ - Covered: **118**
14
+ - Uncovered: **0**
15
+
16
+ ## Uncovered locks by priority
17
+
18
+ Rule: add `@enforces <lockId>` only when the test truly asserts the invariant.
19
+
20
+ ---
21
+
22
+ ## How to close a lock
23
+
24
+ 1. Add or extend a test that **asserts** the invariant.
25
+ 2. Add `@enforces <lockId>` in that test file JSDoc comment.
26
+ 3. Run `npm run generate:locks` and ensure uncovered locks decrease.