@f5-sales-demo/xcsh 19.105.3 → 19.105.6

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 (41) hide show
  1. package/CHANGELOG.md +159 -28
  2. package/package.json +8 -8
  3. package/scripts/generate-api-spec-index.ts +7 -22
  4. package/scripts/generate-console-catalog.ts +2 -1
  5. package/scripts/sanitize-generated-content.ts +141 -0
  6. package/src/cli.ts +0 -3
  7. package/src/config/auto-config.ts +12 -1
  8. package/src/discovery/agents-md.ts +2 -2
  9. package/src/discovery/agents.ts +7 -7
  10. package/src/discovery/builtin.ts +14 -14
  11. package/src/discovery/claude-plugins.ts +6 -6
  12. package/src/discovery/claude.ts +10 -10
  13. package/src/discovery/cline.ts +2 -2
  14. package/src/discovery/codex.ts +10 -10
  15. package/src/discovery/cursor.ts +4 -4
  16. package/src/discovery/gemini.ts +7 -7
  17. package/src/discovery/github.ts +3 -3
  18. package/src/discovery/mcp-json.ts +2 -2
  19. package/src/discovery/opencode.ts +7 -7
  20. package/src/discovery/ssh.ts +2 -2
  21. package/src/discovery/vscode.ts +2 -2
  22. package/src/discovery/windsurf.ts +3 -3
  23. package/src/extensibility/extensions/loader.ts +0 -8
  24. package/src/extensibility/extensions/types.ts +0 -4
  25. package/src/internal-urls/build-info-runtime.ts +0 -1
  26. package/src/internal-urls/build-info.generated.ts +8 -8
  27. package/src/internal-urls/console-catalog.generated.ts +1 -1
  28. package/src/internal-urls/index.ts +0 -3
  29. package/src/internal-urls/terraform-resolve.ts +1 -1
  30. package/src/internal-urls/xcsh-protocol.ts +2 -75
  31. package/src/modes/interactive-mode.ts +0 -8
  32. package/src/prompts/system/system-prompt.md +63 -26
  33. package/src/prompts/tools/xcsh-api.md +114 -60
  34. package/src/sandbox/containment.ts +3 -6
  35. package/src/sdk.ts +0 -47
  36. package/src/session/compaction/compaction.ts +1 -1
  37. package/src/system-prompt.ts +0 -21
  38. package/src/discovery/language.ts +0 -46
  39. package/src/internal-urls/computer-profile.ts +0 -692
  40. package/src/internal-urls/profile-collectors.ts +0 -371
  41. package/src/internal-urls/user-profile.ts +0 -431
package/CHANGELOG.md CHANGED
@@ -2,10 +2,35 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [19.105.6] - 2026-07-31
6
+
7
+ ### Breaking Changes
8
+
9
+ - Removed the `registerProfileCollector()` extension API and the `xcsh://user` and `xcsh://computer` routes. Extensions must no longer register workstation or user identity collectors. ([#2674](https://github.com/f5-sales-demo/xcsh/issues/2674))
10
+
11
+ ### Removed
12
+
13
+ - Removed automatic collection, persistence, and prompt injection of user and workstation profile data, including names, contact details, employer and manager information, addresses, social identifiers, hostnames, and endpoint security inventory. ([#2674](https://github.com/f5-sales-demo/xcsh/issues/2674))
14
+
15
+ ### Fixed
16
+
17
+ - Fixed the checksum-pinned Zig installer on macOS and Windows native release runners and added cross-platform pre-merge validation ([#61](https://github.com/f5-sales-demo/xcsh/issues/61))
18
+
19
+ ## [19.105.5] - 2026-07-31
20
+
21
+ ### Fixed
22
+
23
+ - Added post-publication Homebrew install verification to the release workflow ([#2719](https://github.com/f5-sales-demo/xcsh/issues/2719))
24
+ - Replaced the deprecated Node 20 Zig setup action with a checksum-pinned official installer ([#61](https://github.com/f5-sales-demo/xcsh/issues/61))
25
+ - Invalidated stale release PRs immediately on new `main` pushes, before the full release-creation gate ([#2732](https://github.com/f5-sales-demo/xcsh/issues/2732))
26
+ - Preserved GPT-5.6 Sol High reasoning and token-limit metadata through generated LiteLLM model discovery ([#2729](https://github.com/f5-sales-demo/xcsh/issues/2729))
27
+ - Regenerated stale same-version release PRs when newer commits have merged into `main` ([#2727](https://github.com/f5-sales-demo/xcsh/issues/2727))
28
+
5
29
  ## [19.105.3] - 2026-07-31
6
30
 
7
31
  ### Fixed
8
32
 
33
+ - Removed Biome findings from generated Site CLI transport descriptions ([#2715](https://github.com/f5-sales-demo/xcsh/issues/2715))
9
34
  - Restricted LiteLLM `models.yml` setup, auto-fix, discovery-upgrade, and backup writes to owner-only permissions ([#2713](https://github.com/f5-sales-demo/xcsh/issues/2713))
10
35
  - Fixed `--no-tools` print requests forcing inactive `todo_write` through eager-todo enforcement ([#2711](https://github.com/f5-sales-demo/xcsh/issues/2711))
11
36
 
@@ -28,16 +53,23 @@
28
53
  ## [19.51.5] - 2026-06-26
29
54
 
30
55
  ### Fixed
31
- - Sign + notarize the embedded native addon (`pi_natives.*.node`) in `build-sign-macos` **before** it is embedded into the compiled binary. xcsh extracts the embedded `.node` to `~/.xcsh/natives/<ver>/` at runtime; previously that extracted copy was ad-hoc-signed, so managed/MDM Macs blocked the `dlopen` ("could not verify it is free of malware"). The addon is now Developer-ID-signed with hardened runtime and notarized, so Gatekeeper's online check passes it without manual approval.
56
+
57
+ - Sign + notarize the embedded native addon (`pi_natives.*.node`) in `build-sign-macos` **before** it is embedded into
58
+ the compiled binary. xcsh extracts the embedded `.node` to `~/.xcsh/natives/<ver>/` at runtime; previously that
59
+ extracted copy was ad-hoc-signed, so managed/MDM Macs blocked the `dlopen` ("could not verify it is free of
60
+ malware"). The addon is now Developer-ID-signed with hardened runtime and notarized, so Gatekeeper's online check
61
+ passes it without manual approval.
32
62
 
33
63
  ## [19.51.4] - 2026-06-26
34
64
 
35
65
  ### Added
66
+
36
67
  - Deterministic NL→XC console automation: the system prompt mandates the purpose-built `catalog_workflow_runner` console skill (extension-driven) and forbids the generic Puppeteer browser tool for F5 XC console pages; visible Chrome is framed as the flagship showcase, headless as the exception.
37
68
  - Native-messaging host auto-install on console-automation init (idempotent), with a baked-in Web Store URL and fail-fast guidance when the extension is not connected.
38
69
  - Gated, security-clean relay tracing in `chrome-host` for diagnosing the bridge-connect step.
39
70
 
40
71
  ### Fixed
72
+
41
73
  - Native host now uses the compiled `xcsh` binary (not `bun + cli.ts`), which survives Chrome's stripped-env launch.
42
74
  - Re-embedded console catalog/field-metadata with the `urn:xcsh:console:workflow:v1` schema and the tcp-load-balancer / network-interface defect fixes plus label corrections.
43
75
  - Pre-existing biome lint/format issues that were blocking CI.
@@ -62,7 +94,10 @@
62
94
 
63
95
  ### Changed
64
96
 
65
- - Salesforce tools extracted to marketplace plugin: sf_setup, sf_query, sf_org_display, and sf_pipeline_report are now available as an installable plugin (`@f5-sales-demo/xcsh-salesforce`) via the Extension API instead of built-in tools. Install with `xcsh plugin install salesforce`. Context discovery, pipeline reporting, and container-adapted authentication are preserved with full feature parity. ([#1059](https://github.com/f5-sales-demo/xcsh/issues/1059))
97
+ - Salesforce tools extracted to marketplace plugin: sf_setup, sf_query, sf_org_display, and sf_pipeline_report are now
98
+ available as an installable plugin (`@f5-sales-demo/xcsh-salesforce`) via the Extension API instead of built-in
99
+ tools. Install with `xcsh plugin install salesforce`. Context discovery, pipeline reporting, and container-adapted
100
+ authentication are preserved with full feature parity. ([#1059](https://github.com/f5-sales-demo/xcsh/issues/1059))
66
101
 
67
102
  ## [18.75.0] - 2026-05-23
68
103
 
@@ -74,7 +109,11 @@
74
109
 
75
110
  ### Fixed
76
111
 
77
- - Welcome banner cloud provider hints: AWS SSO token expiry now correctly suggests `aws sso login` instead of `aws configure`; Google Cloud check replaced `gcloud auth list` (false positives on expired tokens) with `gcloud auth print-access-token`; F5 XC Context surfaces `errorClass` (network/URL) in hints; GitLab `project_inaccessible` gets its own hint; Salesforce differentiates `session_expired` and `not_configured` hints ([#825](https://github.com/f5-sales-demo/xcsh/issues/825))
112
+ - Welcome banner cloud provider hints: AWS SSO token expiry now correctly suggests `aws sso login` instead of `aws
113
+ configure`; Google Cloud check replaced `gcloud auth list` (false positives on expired tokens) with `gcloud auth
114
+ print-access-token`; F5 XC Context surfaces `errorClass` (network/URL) in hints; GitLab `project_inaccessible` gets
115
+ its own hint; Salesforce differentiates `session_expired` and `not_configured` hints
116
+ ([#825](https://github.com/f5-sales-demo/xcsh/issues/825))
78
117
 
79
118
  ## [18.64.0] - 2026-05-13
80
119
 
@@ -87,7 +126,11 @@
87
126
 
88
127
  ### Changed
89
128
 
90
- - Regenerated API spec index from catalog v2.1.82: http_loadbalancer CRUD verification corrections (6 new server defaults, corrected minimum configs, cross-field dependencies, default_pool inline pool discovery, 5 composable routing approaches) and tcp_loadbalancer minimum config corrections (listen_port, origin_pools_weights, do_not_advertise format, 9 server defaults, forced hash_policy default) ([#753](https://github.com/f5-sales-demo/xcsh/issues/753), [#757](https://github.com/f5-sales-demo/xcsh/issues/757))
129
+ - Regenerated API spec index from catalog v2.1.82: http_loadbalancer CRUD verification corrections (6 new server
130
+ defaults, corrected minimum configs, cross-field dependencies, default_pool inline pool discovery, 5 composable
131
+ routing approaches) and tcp_loadbalancer minimum config corrections (listen_port, origin_pools_weights,
132
+ do_not_advertise format, 9 server defaults, forced hash_policy default)
133
+ ([#753](https://github.com/f5-sales-demo/xcsh/issues/753), [#757](https://github.com/f5-sales-demo/xcsh/issues/757))
91
134
 
92
135
  ## [18.53.0] - 2026-05-09
93
136
 
@@ -151,25 +194,40 @@
151
194
 
152
195
  ### Fixed
153
196
 
154
- - Fixed gutter width propagation in the fallback tool renderer: `#formatToolExecution()` now receives the actual available width at render-time and uses it for line truncation instead of a hardcoded 80-column limit. On narrow terminals (<82 cols) this prevents content wider than the gutter-adjusted viewport; on wide terminals it allows longer output lines. ([#117](https://github.com/f5-sales-demo/xcsh/issues/117))
197
+ - Fixed gutter width propagation in the fallback tool renderer: `#formatToolExecution()` now receives the actual
198
+ available width at render-time and uses it for line truncation instead of a hardcoded 80-column limit. On narrow
199
+ terminals (<82 cols) this prevents content wider than the gutter-adjusted viewport; on wide terminals it allows
200
+ longer output lines. ([#117](https://github.com/f5-sales-demo/xcsh/issues/117))
155
201
  - Fixed `resolveConfigValue` returning literal env var names (e.g. `"LITELLM_API_KEY"`) as API keys when the env var is unset, causing 401 errors on first launch. The resolver now rejects unresolved `ALL_CAPS_WITH_UNDERSCORES` patterns, matching the existing guard in `resolveYamlApiKeyConfig`. ([#241](https://github.com/f5-sales-demo/xcsh/issues/241))
156
202
 
157
203
  ### Changed
158
204
 
159
- - Renamed F5 XC credential system from "profile" to "context" to align with kubectl conventions. The `/profile` command is now `/context`, all types/classes use `Context*` naming (`ContextService`, `ContextStatus`, `F5XCContext`, etc.), on-disk paths changed from `profiles/` to `contexts/` and `active_profile` to `active_context`, and the status-line segment ID is now `context_f5xc`. ([#302](https://github.com/f5-sales-demo/xcsh/issues/302))
205
+ - Renamed F5 XC credential system from "profile" to "context" to align with kubectl conventions. The `/profile` command
206
+ is now `/context`, all types/classes use `Context*` naming (`ContextService`, `ContextStatus`, `F5XCContext`, etc.),
207
+ on-disk paths changed from `profiles/` to `contexts/` and `active_profile` to `active_context`, and the status-line
208
+ segment ID is now `context_f5xc`. ([#302](https://github.com/f5-sales-demo/xcsh/issues/302))
160
209
 
161
210
  ## [18.12.0] - 2026-04-23
162
211
 
163
212
  ### Changed
164
213
 
165
- - **System prompt realigned around the SE coworker primary mission.** The `<role>` block now leads with "technical coworker for F5 Distributed Cloud sales engineers" and names demos, MEDDPICC qualification, customer meeting preparation, and F5 XC product subject-matter expertise as primary activities — technical depth is retained as an explicit enabling credential, not subordinated. `<behavior>` reframes around the **presentation reflex** (confirming a capability before verifying it against current docs) with a conditional clause preserving the **deployment reflex** guard when the task is infrastructure. `<stakes>` leads with customer-facing risk (lost deals, damaged credibility, post-sale trust erosion) and retains infra stakes (outages, security exposures) as a secondary clause.
214
+ - **System prompt realigned around the SE coworker primary mission.** The `<role>` block now leads with "technical
215
+ coworker for F5 Distributed Cloud sales engineers" and names demos, MEDDPICC qualification, customer meeting
216
+ preparation, and F5 XC product subject-matter expertise as primary activities — technical depth is retained as an
217
+ explicit enabling credential, not subordinated. `<behavior>` reframes around the **presentation reflex** (confirming
218
+ a capability before verifying it against current docs) with a conditional clause preserving the **deployment reflex**
219
+ guard when the task is infrastructure. `<stakes>` leads with customer-facing risk (lost deals, damaged credibility,
220
+ post-sale trust erosion) and retains infra stakes (outages, security exposures) as a secondary clause.
166
221
  - **Identity section moved above Workspace in the rendered prompt.** Static behavioral anchors now occupy the highest-attention position at the top of the prompt, and dynamic context-file changes no longer invalidate the cache for static behavioral content.
167
222
  - **Replaced the sea-color epistemic-integrity example** with a bot-defense-SKU vs contract-claim scenario. The three examples now cover SE domain (product claim vs contract reality), infra domain (LB health-check probe layer), and technical domain (mutex race) — diverse and domain-grounded.
168
223
  - **Compressed the `xcsh://` routing instruction** from 3 lines to 2 lines. The redundant trigger-phrase enumeration is removed; the MUST directive is sufficient now that `xcsh://about` also documents the architecture.
169
224
 
170
225
  ### Added
171
226
 
172
- - **`.xcsh/rules/config-integrity.md`** — new scoped rule carrying the dependency-first IaC guidance that previously lived in the always-on `<config-integrity>` block. Fires on `tool:edit` and `tool:write` for `.tf`, `.yaml`, `.yml`, `.json`, `.sh`, `Makefile`, `Dockerfile`, `.toml`. Uses `condition: "."` (always-true regex) so the rules engine registers it — rules without a `condition` are silently dropped.
227
+ - **`.xcsh/rules/config-integrity.md`** — new scoped rule carrying the dependency-first IaC guidance that previously
228
+ lived in the always-on `<config-integrity>` block. Fires on `tool:edit` and `tool:write` for `.tf`, `.yaml`, `.yml`,
229
+ `.json`, `.sh`, `Makefile`, `Dockerfile`, `.toml`. Uses `condition: "."` (always-true regex) so the rules engine
230
+ registers it — rules without a `condition` are silently dropped.
173
231
  - **`xcsh://about` enriched** with `## Lineage` (upstream fork + maintainer), `## Architecture` (package role map), and `## Capabilities` (feature surface summary). On-demand only; zero system-prompt token cost.
174
232
 
175
233
  ### Removed
@@ -182,12 +240,24 @@ Refs: #254, #243.
182
240
 
183
241
  ### Removed
184
242
 
185
- - **All built-in themes except `xcsh-dark` and `xcsh-light` have been removed.** The 99 community themes previously shipped under `packages/coding-agent/src/modes/theme/defaults/` (`dark-ocean`, `dark-dracula`, `titanium`, `anthracite`, etc.), as well as the base `dark` and `light` themes, are no longer included. The hardcoded fallback when a user's theme fails to load now targets `xcsh-dark`. Users on a removed theme will fall back to `xcsh-dark` on next launch. User-authored themes under `~/.xcsh/agent/themes/` are unaffected.
243
+ - **All built-in themes except `xcsh-dark` and `xcsh-light` have been removed.** The 99 community themes previously
244
+ shipped under `packages/coding-agent/src/modes/theme/defaults/` (`dark-ocean`, `dark-dracula`, `titanium`,
245
+ `anthracite`, etc.), as well as the base `dark` and `light` themes, are no longer included. The hardcoded fallback
246
+ when a user's theme fails to load now targets `xcsh-dark`. Users on a removed theme will fall back to `xcsh-dark` on
247
+ next launch. User-authored themes under `~/.xcsh/agent/themes/` are unaffected.
186
248
 
187
249
  ### Changed
188
250
 
189
- - **TUI tool-call outcomes now render as a single colored gutter ball (●).** Inline `✓/✗/⚠` status icons were removed from every tool renderer. A new "warning" outcome (orange ball) signals non-error degraded states such as grep with zero matches, exa with zero results, ast-grep with zero matches, or ask falling back to a headless/empty-questions path. `xcsh-dark` uses `warmAmber` (#ffb347); `xcsh-light` uses `#b85e00` (WCAG AA on white). User-authored themes inherit via the `gutterWarning → warning` fallback chain.
190
- - **`AgentToolResult` and `tool_execution_end` events gain an optional `isWarning?: boolean`** alongside `isError`. Tools that want an orange gutter ball on zero-result or fallback paths set this field (or use the new `ToolResultBuilder.isWarning()` fluent method). Extensions subscribing to `tool_execution_end` and `tool_result` hook events now receive the flag; existing extensions are unaffected. Backwards-compatible unset means "not a warning."
251
+ - **TUI tool-call outcomes now render as a single colored gutter ball (●).** Inline `✓/✗/⚠` status icons were
252
+ removed from every tool renderer. A new "warning" outcome (orange ball) signals non-error degraded states such as
253
+ grep with zero matches, exa with zero results, ast-grep with zero matches, or ask falling back to a
254
+ headless/empty-questions path. `xcsh-dark` uses `warmAmber` (#ffb347); `xcsh-light` uses `#b85e00` (WCAG AA on
255
+ white). User-authored themes inherit via the `gutterWarning → warning` fallback chain.
256
+ - **`AgentToolResult` and `tool_execution_end` events gain an optional `isWarning?: boolean`** alongside `isError`.
257
+ Tools that want an orange gutter ball on zero-result or fallback paths set this field (or use the new
258
+ `ToolResultBuilder.isWarning()` fluent method). Extensions subscribing to `tool_execution_end` and `tool_result` hook
259
+ events now receive the flag; existing extensions are unaffected. Backwards-compatible — unset means "not a
260
+ warning."
191
261
  - **`formatEmptyMessage` and `formatErrorMessage` helpers no longer prepend ⚠/✗ glyphs.** Centralized fix so every tool renderer inherits the glyph-free output without a per-file workaround.
192
262
 
193
263
  Refs: #173.
@@ -196,7 +266,10 @@ Refs: #173.
196
266
 
197
267
  ### Fixed
198
268
 
199
- - Widened the `defaultThinkingLevel` schema enum to include `"off"`, which was already a supported runtime value via `resolveThinkingLevelForModel` but was not declared as a valid schema value. This closes a type-safety gap where programmatic callers (tests, config.yml edits) could set `"off"` without a `SettingValue` type narrowing it. The `/settings` UI dropdown is unchanged; the widening is schema-level only.
269
+ - Widened the `defaultThinkingLevel` schema enum to include `"off"`, which was already a supported runtime value via
270
+ `resolveThinkingLevelForModel` but was not declared as a valid schema value. This closes a type-safety gap where
271
+ programmatic callers (tests, config.yml edits) could set `"off"` without a `SettingValue` type narrowing it. The
272
+ `/settings` UI dropdown is unchanged; the widening is schema-level only.
200
273
 
201
274
  ### Changed
202
275
 
@@ -3887,7 +3960,10 @@ Refs: #173.
3887
3960
 
3888
3961
  ### Fixed
3889
3962
 
3890
- - External edits to `config.yml` are now preserved when omp reloads or saves unrelated settings. Previously, editing config.yml directly (e.g., removing a package from `packages` array) would be silently reverted on next omp startup when automatic setters like `setLastChangelogVersion()` triggered a save. ([#1046](https://github.com/badlogic/pi-mono/pull/1046) by [@nicobailonMD](https://github.com/nicobailonMD))
3963
+ - External edits to `config.yml` are now preserved when omp reloads or saves unrelated settings. Previously, editing
3964
+ config.yml directly (e.g., removing a package from `packages` array) would be silently reverted on next omp startup
3965
+ when automatic setters like `setLastChangelogVersion()` triggered a save.
3966
+ ([#1046](https://github.com/badlogic/pi-mono/pull/1046) by [@nicobailonMD](https://github.com/nicobailonMD))
3891
3967
 
3892
3968
  ## [8.13.0] - 2026-01-29
3893
3969
 
@@ -5037,7 +5113,13 @@ Refs: #173.
5037
5113
  ### Added
5038
5114
 
5039
5115
  - Exported `InteractiveModeOptions` type for programmatic SDK usage
5040
- - Exported additional UI components for extensions: `ArminComponent`, `AssistantMessageComponent`, `BashExecutionComponent`, `BranchSummaryMessageComponent`, `CompactionSummaryMessageComponent`, `CustomEditor`, `CustomMessageComponent`, `FooterComponent`, `ExtensionEditorComponent`, `ExtensionInputComponent`, `ExtensionSelectorComponent`, `LoginDialogComponent`, `ModelSelectorComponent`, `OAuthSelectorComponent`, `SessionSelectorComponent`, `SettingsSelectorComponent`, `ShowImagesSelectorComponent`, `ThemeSelectorComponent`, `ThinkingSelectorComponent`, `ToolExecutionComponent`, `TreeSelectorComponent`, `UserMessageComponent`, `UserMessageSelectorComponent`
5116
+ - Exported additional UI components for extensions: `ArminComponent`, `AssistantMessageComponent`,
5117
+ `BashExecutionComponent`, `BranchSummaryMessageComponent`, `CompactionSummaryMessageComponent`, `CustomEditor`,
5118
+ `CustomMessageComponent`, `FooterComponent`, `ExtensionEditorComponent`, `ExtensionInputComponent`,
5119
+ `ExtensionSelectorComponent`, `LoginDialogComponent`, `ModelSelectorComponent`, `OAuthSelectorComponent`,
5120
+ `SessionSelectorComponent`, `SettingsSelectorComponent`, `ShowImagesSelectorComponent`, `ThemeSelectorComponent`,
5121
+ `ThinkingSelectorComponent`, `ToolExecutionComponent`, `TreeSelectorComponent`, `UserMessageComponent`,
5122
+ `UserMessageSelectorComponent`
5041
5123
  - Exported `renderDiff`, `truncateToVisualLines`, and related types for extension use
5042
5124
  - `setFooter()` and `setHeader()` methods on `ExtensionUIContext` for custom footer/header components
5043
5125
  - `setEditorComponent()` method on `ExtensionUIContext` for custom editor components
@@ -5484,7 +5566,12 @@ Refs: #173.
5484
5566
 
5485
5567
  ### Added
5486
5568
 
5487
- - Added 65 new built-in color themes including dark variants (abyss, aurora, cavern, copper, cosmos, eclipse, ember, equinox, lavender, lunar, midnight, nebula, rainforest, reef, sakura, slate, solstice, starfall, swamp, taiga, terminal, tundra, twilight, volcanic), light variants (aurora-day, canyon, cirrus, coral, dawn, dunes, eucalyptus, frost, glacier, haze, honeycomb, lagoon, lavender, meadow, mint, opal, orchard, paper, prism, sand, savanna, soleil, wetland, zenith), and material themes (alabaster, amethyst, anthracite, basalt, birch, graphite, limestone, mahogany, marble, obsidian, onyx, pearl, porcelain, quartz, sandstone, titanium)
5569
+ - Added 65 new built-in color themes including dark variants (abyss, aurora, cavern, copper, cosmos, eclipse, ember,
5570
+ equinox, lavender, lunar, midnight, nebula, rainforest, reef, sakura, slate, solstice, starfall, swamp, taiga,
5571
+ terminal, tundra, twilight, volcanic), light variants (aurora-day, canyon, cirrus, coral, dawn, dunes, eucalyptus,
5572
+ frost, glacier, haze, honeycomb, lagoon, lavender, meadow, mint, opal, orchard, paper, prism, sand, savanna, soleil,
5573
+ wetland, zenith), and material themes (alabaster, amethyst, anthracite, basalt, birch, graphite, limestone, mahogany,
5574
+ marble, obsidian, onyx, pearl, porcelain, quartz, sandstone, titanium)
5488
5575
 
5489
5576
  ### Fixed
5490
5577
 
@@ -6319,7 +6406,11 @@ Total color count increased from 46 to 50. See [docs/theme.md](docs/theme.md) fo
6319
6406
 
6320
6407
  ### Breaking
6321
6408
 
6322
- - **Session hooks API redesign**: Merged `branch` event into `session` event. `BranchEvent`, `BranchEventResult` types and `pi.on("branch", ...)` removed. Use `pi.on("session", ...)` with `reason: "before_branch" | "branch"` instead. `AgentSession.branch()` returns `{ cancelled }` instead of `{ skipped }`. `AgentSession.reset()` and `switchSession()` now return `boolean` (false if cancelled by hook). RPC commands `reset`, `switch_session`, and `branch` now include `cancelled` in response data. ([#278](https://github.com/badlogic/pi-mono/issues/278))
6409
+ - **Session hooks API redesign**: Merged `branch` event into `session` event. `BranchEvent`, `BranchEventResult` types
6410
+ and `pi.on("branch", ...)` removed. Use `pi.on("session", ...)` with `reason: "before_branch" | "branch"` instead.
6411
+ `AgentSession.branch()` returns `{ cancelled }` instead of `{ skipped }`. `AgentSession.reset()` and
6412
+ `switchSession()` now return `boolean` (false if cancelled by hook). RPC commands `reset`, `switch_session`, and
6413
+ `branch` now include `cancelled` in response data. ([#278](https://github.com/badlogic/pi-mono/issues/278))
6323
6414
 
6324
6415
  ### Added
6325
6416
 
@@ -6475,7 +6566,11 @@ Total color count increased from 46 to 50. See [docs/theme.md](docs/theme.md) fo
6475
6566
 
6476
6567
  - **Subagent example improvements**: Parallel mode now streams updates from all tasks. Chain mode shows all completed steps during streaming. Expanded view uses proper markdown rendering with syntax highlighting. Usage footer shows turn count.
6477
6568
 
6478
- - **Skills standard compliance**: Skills now adhere to the [Agent Skills standard](https://agentskills.io/specification). Validates name (must match parent directory, lowercase, max 64 chars), description (required, max 1024 chars), and frontmatter fields. Warns on violations but remains lenient. Prompt format changed to XML structure. Removed `{baseDir}` placeholder in favor of relative paths. ([#231](https://github.com/badlogic/pi-mono/issues/231))
6569
+ - **Skills standard compliance**: Skills now adhere to the [Agent Skills
6570
+ standard](https://agentskills.io/specification). Validates name (must match parent directory, lowercase, max 64
6571
+ chars), description (required, max 1024 chars), and frontmatter fields. Warns on violations but remains lenient.
6572
+ Prompt format changed to XML structure. Removed `{baseDir}` placeholder in favor of relative paths.
6573
+ ([#231](https://github.com/badlogic/pi-mono/issues/231))
6479
6574
 
6480
6575
  ### Fixed
6481
6576
 
@@ -6540,7 +6635,10 @@ Total color count increased from 46 to 50. See [docs/theme.md](docs/theme.md) fo
6540
6635
 
6541
6636
  ### Fixed
6542
6637
 
6543
- - Fixed Claude models via GitHub Copilot re-answering all previous prompts in multi-turn conversations. The issue was that assistant message content was sent as an array instead of a string, which Copilot's Claude adapter misinterpreted. Also added missing `Openai-Intent: conversation-edits` header and fixed `X-Initiator` logic to check for any assistant/tool message in history. ([#209](https://github.com/badlogic/pi-mono/issues/209))
6638
+ - Fixed Claude models via GitHub Copilot re-answering all previous prompts in multi-turn conversations. The issue was
6639
+ that assistant message content was sent as an array instead of a string, which Copilot's Claude adapter
6640
+ misinterpreted. Also added missing `Openai-Intent: conversation-edits` header and fixed `X-Initiator` logic to check
6641
+ for any assistant/tool message in history. ([#209](https://github.com/badlogic/pi-mono/issues/209))
6544
6642
 
6545
6643
  - Detect image MIME type via file magic (read tool and `@file` attachments), not filename extension.
6546
6644
 
@@ -6628,7 +6726,11 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
6628
6726
 
6629
6727
  ### Added
6630
6728
 
6631
- - **Inline image rendering**: Terminals supporting Kitty graphics protocol (Kitty, Ghostty, WezTerm) or iTerm2 inline images now render images inline in tool output. Aspect ratio is preserved by querying terminal cell dimensions on startup. Toggle with `/show-images` command or `terminal.showImages` setting. Falls back to text placeholder on unsupported terminals or when disabled. ([#177](https://github.com/badlogic/pi-mono/pull/177) by [@nicobailon](https://github.com/nicobailon))
6729
+ - **Inline image rendering**: Terminals supporting Kitty graphics protocol (Kitty, Ghostty, WezTerm) or iTerm2 inline
6730
+ images now render images inline in tool output. Aspect ratio is preserved by querying terminal cell dimensions on
6731
+ startup. Toggle with `/show-images` command or `terminal.showImages` setting. Falls back to text placeholder on
6732
+ unsupported terminals or when disabled. ([#177](https://github.com/badlogic/pi-mono/pull/177) by
6733
+ [@nicobailon](https://github.com/nicobailon))
6632
6734
 
6633
6735
  - **Gemini 3 Pro thinking levels**: Thinking level selector now works with Gemini 3 Pro models. Minimal/low map to Google's LOW, medium/high map to Google's HIGH. ([#176](https://github.com/badlogic/pi-mono/pull/176) by [@markusylisiurunen](https://github.com/markusylisiurunen))
6634
6736
 
@@ -6664,7 +6766,11 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
6664
6766
 
6665
6767
  ### Added
6666
6768
 
6667
- - **Skills system**: Auto-discover and load instruction files on-demand. Supports Claude Code (`~/.claude/skills/*/SKILL.md`), Codex CLI (`~/.codex/skills/`), and OMP-native formats (`~/.omp/agent/skills/`, `.omp/skills/`). Skills are listed in system prompt with descriptions, agent loads them via read tool when needed. Supports `{baseDir}` placeholder. Disable with `--no-skills` or `skills.enabled: false` in settings. ([#169](https://github.com/badlogic/pi-mono/issues/169))
6769
+ - **Skills system**: Auto-discover and load instruction files on-demand. Supports Claude Code
6770
+ (`~/.claude/skills/*/SKILL.md`), Codex CLI (`~/.codex/skills/`), and OMP-native formats (`~/.omp/agent/skills/`,
6771
+ `.omp/skills/`). Skills are listed in system prompt with descriptions, agent loads them via read tool when needed.
6772
+ Supports `{baseDir}` placeholder. Disable with `--no-skills` or `skills.enabled: false` in settings.
6773
+ ([#169](https://github.com/badlogic/pi-mono/issues/169))
6668
6774
 
6669
6775
  - **Version flag**: Added `--version` / `-v` flag to display the current version and exit. ([#170](https://github.com/badlogic/pi-mono/pull/170))
6670
6776
 
@@ -6672,7 +6778,11 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
6672
6778
 
6673
6779
  ### Added
6674
6780
 
6675
- - **Auto-retry on transient errors**: Automatically retries requests when providers return overloaded, rate limit, or server errors (429, 500, 502, 503, 504). Uses exponential backoff (2s, 4s, 8s). Shows retry status in TUI with option to cancel via Escape. Configurable in `settings.json` via `retry.enabled`, `retry.maxRetries`, `retry.baseDelayMs`. RPC mode emits `auto_retry_start` and `auto_retry_end` events. ([#157](https://github.com/badlogic/pi-mono/issues/157))
6781
+ - **Auto-retry on transient errors**: Automatically retries requests when providers return overloaded, rate limit, or
6782
+ server errors (429, 500, 502, 503, 504). Uses exponential backoff (2s, 4s, 8s). Shows retry status in TUI with option
6783
+ to cancel via Escape. Configurable in `settings.json` via `retry.enabled`, `retry.maxRetries`, `retry.baseDelayMs`.
6784
+ RPC mode emits `auto_retry_start` and `auto_retry_end` events.
6785
+ ([#157](https://github.com/badlogic/pi-mono/issues/157))
6676
6786
 
6677
6787
  - **HTML export line numbers**: Read tool calls in HTML exports now display line number ranges (e.g., `file.txt:10-20`) when offset/limit parameters are used, matching the TUI display format. Line numbers appear in yellow color for better visibility. ([#166](https://github.com/badlogic/pi-mono/issues/166))
6678
6788
 
@@ -6698,7 +6808,12 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
6698
6808
 
6699
6809
  ### Added
6700
6810
 
6701
- - **Hooks system**: TypeScript modules that extend agent behavior by subscribing to lifecycle events. Hooks can intercept tool calls, prompt for confirmation, modify results, and inject messages from external sources. Auto-discovered from `~/.omp/agent/hooks/*.ts` and `.omp/hooks/*.ts`. Thanks to [@nicobailon](https://github.com/nicobailon) for the collaboration on the design and implementation. ([#145](https://github.com/badlogic/pi-mono/issues/145), supersedes [#158](https://github.com/badlogic/pi-mono/pull/158))
6811
+ - **Hooks system**: TypeScript modules that extend agent behavior by subscribing to lifecycle events. Hooks can
6812
+ intercept tool calls, prompt for confirmation, modify results, and inject messages from external sources.
6813
+ Auto-discovered from `~/.omp/agent/hooks/*.ts` and `.omp/hooks/*.ts`. Thanks to
6814
+ [@nicobailon](https://github.com/nicobailon) for the collaboration on the design and implementation.
6815
+ ([#145](https://github.com/badlogic/pi-mono/issues/145), supersedes
6816
+ [#158](https://github.com/badlogic/pi-mono/pull/158))
6702
6817
 
6703
6818
  - **`pi.send()` API**: Hooks can inject messages into the agent session from external sources (file watchers, webhooks, CI systems). If streaming, messages are queued; otherwise a new agent loop starts immediately.
6704
6819
 
@@ -6736,7 +6851,10 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
6736
6851
 
6737
6852
  ### Breaking Changes
6738
6853
 
6739
- - **New RPC protocol**: The RPC mode (`--mode rpc`) has been completely redesigned with a new JSON protocol. The old protocol is no longer supported. See [`docs/rpc.md`](docs/rpc.md) for the new protocol documentation and [`test/rpc-example.ts`](test/rpc-example.ts) for a working example. Includes `RpcClient` TypeScript class for easy integration. ([#91](https://github.com/badlogic/pi-mono/issues/91))
6854
+ - **New RPC protocol**: The RPC mode (`--mode rpc`) has been completely redesigned with a new JSON protocol. The old
6855
+ protocol is no longer supported. See [`docs/rpc.md`](docs/rpc.md) for the new protocol documentation and
6856
+ [`test/rpc-example.ts`](test/rpc-example.ts) for a working example. Includes `RpcClient` TypeScript class for easy
6857
+ integration. ([#91](https://github.com/badlogic/pi-mono/issues/91))
6740
6858
 
6741
6859
  ### Changed
6742
6860
 
@@ -6746,7 +6864,10 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
6746
6864
 
6747
6865
  ### Changed
6748
6866
 
6749
- - **Major code refactoring**: Restructured codebase for better maintainability and separation of concerns. Moved files into organized directories (`core/`, `modes/`, `utils/`, `cli/`). Extracted `AgentSession` class as central session management abstraction. Split `main.ts` and `tui-renderer.ts` into focused modules. See `DEVELOPMENT.md` for the new code map. ([#153](https://github.com/badlogic/pi-mono/issues/153))
6867
+ - **Major code refactoring**: Restructured codebase for better maintainability and separation of concerns. Moved files
6868
+ into organized directories (`core/`, `modes/`, `utils/`, `cli/`). Extracted `AgentSession` class as central session
6869
+ management abstraction. Split `main.ts` and `tui-renderer.ts` into focused modules. See `DEVELOPMENT.md` for the new
6870
+ code map. ([#153](https://github.com/badlogic/pi-mono/issues/153))
6750
6871
 
6751
6872
  ## [0.14.2] - 2025-12-08
6752
6873
 
@@ -6772,13 +6893,20 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
6772
6893
 
6773
6894
  ### Added
6774
6895
 
6775
- - **OpenAI compatibility overrides in models.json**: Custom models using `openai-completions` API can now specify a `compat` object to override provider quirks (`supportsStore`, `supportsDeveloperRole`, `supportsReasoningEffort`, `maxTokensField`). Useful for LiteLLM, custom proxies, and other non-standard endpoints. ([#133](https://github.com/badlogic/pi-mono/issues/133), thanks @fink-andreas for the initial idea and PR)
6896
+ - **OpenAI compatibility overrides in models.json**: Custom models using `openai-completions` API can now specify a
6897
+ `compat` object to override provider quirks (`supportsStore`, `supportsDeveloperRole`, `supportsReasoningEffort`,
6898
+ `maxTokensField`). Useful for LiteLLM, custom proxies, and other non-standard endpoints.
6899
+ ([#133](https://github.com/badlogic/pi-mono/issues/133), thanks @fink-andreas for the initial idea and PR)
6776
6900
 
6777
6901
  - **xhigh thinking level**: Added `xhigh` thinking level for OpenAI codex-max models. Cycle through thinking levels with Shift+Tab; `xhigh` appears only when using a codex-max model. ([#143](https://github.com/badlogic/pi-mono/issues/143))
6778
6902
 
6779
6903
  - **Collapse changelog setting**: Add `"collapseChangelog": true` to `~/.omp/agent/settings.json` to show a condensed "Updated to vX.Y.Z" message instead of the full changelog after updates. Use `/changelog` to view the full changelog. ([#148](https://github.com/badlogic/pi-mono/issues/148))
6780
6904
 
6781
- - **Bash mode**: Execute shell commands directly from the editor by prefixing with `!` (e.g., `!ls -la`). Output streams in real-time, is added to the LLM context, and persists in session history. Supports multiline commands, cancellation (Escape), truncation for large outputs, and preview/expand toggle (Ctrl+O). Also available in RPC mode via `{"type":"bash","command":"..."}`. ([#112](https://github.com/badlogic/pi-mono/pull/112), original implementation by [@markusylisiurunen](https://github.com/markusylisiurunen))
6905
+ - **Bash mode**: Execute shell commands directly from the editor by prefixing with `!` (e.g., `!ls -la`). Output
6906
+ streams in real-time, is added to the LLM context, and persists in session history. Supports multiline commands,
6907
+ cancellation (Escape), truncation for large outputs, and preview/expand toggle (Ctrl+O). Also available in RPC mode
6908
+ via `{"type":"bash","command":"..."}`. ([#112](https://github.com/badlogic/pi-mono/pull/112), original implementation
6909
+ by [@markusylisiurunen](https://github.com/markusylisiurunen))
6782
6910
 
6783
6911
  ## [0.13.2] - 2025-12-07
6784
6912
 
@@ -6834,7 +6962,10 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
6834
6962
  ### Added
6835
6963
 
6836
6964
  - **Fuzzy search models and sessions**: Implemented a simple fuzzy search for models and sessions (e.g., `codexmax` now finds `gpt-5.1-codex-max`). ([#122](https://github.com/badlogic/pi-mono/pull/122) by [@markusylisiurunen](https://github.com/markusylisiurunen))
6837
- - **Prompt History Navigation**: Browse previously submitted prompts using Up/Down arrow keys when the editor is empty. Press Up to cycle through older prompts, Down to return to newer ones or clear the editor. Similar to shell history and Claude Code's prompt history feature. History is session-scoped and stores up to 100 entries. ([#121](https://github.com/badlogic/pi-mono/pull/121) by [@nicobailon](https://github.com/nicobailon))
6965
+ - **Prompt History Navigation**: Browse previously submitted prompts using Up/Down arrow keys when the editor is empty.
6966
+ Press Up to cycle through older prompts, Down to return to newer ones or clear the editor. Similar to shell history
6967
+ and Claude Code's prompt history feature. History is session-scoped and stores up to 100 entries.
6968
+ ([#121](https://github.com/badlogic/pi-mono/pull/121) by [@nicobailon](https://github.com/nicobailon))
6838
6969
  - **`/resume` Command**: Switch to a different session mid-conversation. Opens an interactive selector showing all available sessions. Equivalent to the `--resume` CLI flag but can be used without restarting the agent. ([#117](https://github.com/badlogic/pi-mono/pull/117) by [@hewliyang](https://github.com/hewliyang))
6839
6970
 
6840
6971
  ## [0.12.11] - 2025-12-05
@@ -6954,7 +7085,7 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
6954
7085
 
6955
7086
  ### Fixed
6956
7087
 
6957
- - Absolute glob patterns (e.g., `/Users/foo/**/*.ts`) are now handled correctly. Previously the leading `/` was being stripped, causing the pattern to be interpreted relative to the current directory.
7088
+ - Absolute glob patterns (e.g., `/Users/example/**/*.ts`) are now handled correctly. Previously the leading `/` was being stripped, causing the pattern to be interpreted relative to the current directory.
6958
7089
 
6959
7090
  ## [0.11.7] - 2025-12-01
6960
7091
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@f5-sales-demo/xcsh",
4
- "version": "19.105.3",
4
+ "version": "19.105.6",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/f5-sales-demo/xcsh",
7
7
  "author": "Can Boluk",
@@ -57,13 +57,13 @@
57
57
  "dependencies": {
58
58
  "@agentclientprotocol/sdk": "1.3.0",
59
59
  "@mozilla/readability": "^0.6",
60
- "@f5-sales-demo/xcsh-stats": "19.105.3",
61
- "@f5-sales-demo/pi-agent-core": "19.105.3",
62
- "@f5-sales-demo/pi-ai": "19.105.3",
63
- "@f5-sales-demo/pi-natives": "19.105.3",
64
- "@f5-sales-demo/pi-resource-management": "19.105.3",
65
- "@f5-sales-demo/pi-tui": "19.105.3",
66
- "@f5-sales-demo/pi-utils": "19.105.3",
60
+ "@f5-sales-demo/xcsh-stats": "19.105.6",
61
+ "@f5-sales-demo/pi-agent-core": "19.105.6",
62
+ "@f5-sales-demo/pi-ai": "19.105.6",
63
+ "@f5-sales-demo/pi-natives": "19.105.6",
64
+ "@f5-sales-demo/pi-resource-management": "19.105.6",
65
+ "@f5-sales-demo/pi-tui": "19.105.6",
66
+ "@f5-sales-demo/pi-utils": "19.105.6",
67
67
  "@sinclair/typebox": "^0.34",
68
68
  "@xterm/headless": "^6.0",
69
69
  "ajv": "^8.20",
@@ -5,6 +5,7 @@ import * as os from "node:os";
5
5
  import * as path from "node:path";
6
6
  import { $ } from "bun";
7
7
  import { isLocalSpecsCurrent } from "./api-specs-version";
8
+ import { sanitizeAcmePlaceholders, sanitizePublicIpv4Examples } from "./sanitize-generated-content";
8
9
 
9
10
  interface SpecPathOperation {
10
11
  operationId?: string;
@@ -108,30 +109,11 @@ const RESERVED_EMAIL_DOMAINS = new Set(["example.com", "example.net", "example.o
108
109
  */
109
110
  function sanitizeEmails(text: string): string {
110
111
  // The lookbehind skips URL userinfo (`https://token:secret@host`), which is not a contact address.
111
- return text.replace(/(?<![:/])\b[A-Za-z0-9._%+-]+@([A-Za-z0-9.-]+\.[A-Za-z]{2,})\b/g, (whole, domain) =>
112
+ return text.replace(/(?<![:/])\b[A-Za-z0-9._%+-]+@([A-Za-z0-9.-]+\.[A-Za-z]+)\b/g, (whole, domain) =>
112
113
  RESERVED_EMAIL_DOMAINS.has(String(domain).toLowerCase()) ? whole : "dana@example.com",
113
114
  );
114
115
  }
115
116
 
116
- /**
117
- * Upstream specs use ACME as a placeholder tenant, company and hostname. STYLE_GUIDE.md bans it:
118
- * it is not trademark-cleared, and in TLS content the name already belongs to RFC 8555. Rewrite it
119
- * to the `Example` pattern here rather than in the emitted file, so a regeneration cannot bring it
120
- * back (#2650).
121
- *
122
- * `_acme-challenge` is the RFC 8555 DNS-01 record label, not the placeholder, and must survive.
123
- */
124
- function sanitizePlaceholders(text: string): string {
125
- // The sentinel must contain no form of the word being rewritten, or the rewrite eats it.
126
- const CHALLENGE = " RFC8555_DNS01 ";
127
- return text
128
- .replace(/_acme-challenge/gi, CHALLENGE)
129
- .replace(/ACME/g, "Example")
130
- .replace(/Acme/g, "Example")
131
- .replace(/acme/g, "example")
132
- .replaceAll(CHALLENGE, "_acme-challenge");
133
- }
134
-
135
117
  const MAX_RETRIES = 3;
136
118
  const INITIAL_BACKOFF_MS = 2000;
137
119
 
@@ -587,7 +569,7 @@ const output = [
587
569
  .filter(l => l !== undefined)
588
570
  .join("\n");
589
571
 
590
- await Bun.write(outputPath, sanitizeEmails(sanitizePlaceholders(output)));
572
+ await Bun.write(outputPath, sanitizePublicIpv4Examples(sanitizeEmails(sanitizeAcmePlaceholders(output))));
591
573
 
592
574
  const outputSize = (Buffer.byteLength(output) / 1024 / 1024).toFixed(1);
593
575
  console.log(
@@ -631,7 +613,10 @@ if (catalog) {
631
613
  "",
632
614
  ].join("\n");
633
615
 
634
- await Bun.write(catalogOutputPath, sanitizeEmails(sanitizePlaceholders(catalogOutput)));
616
+ await Bun.write(
617
+ catalogOutputPath,
618
+ sanitizePublicIpv4Examples(sanitizeEmails(sanitizeAcmePlaceholders(catalogOutput))),
619
+ );
635
620
  const catalogSize = (Buffer.byteLength(catalogOutput) / 1024 / 1024).toFixed(1);
636
621
  console.log(
637
622
  `Generated ${path.relative(process.cwd(), catalogOutputPath)} (${categories.length} categories, ${catalogSize} MB)`,
@@ -2,6 +2,7 @@
2
2
  // scripts/generate-console-catalog.ts
3
3
  import * as fs from "node:fs";
4
4
  import * as path from "node:path";
5
+ import { sanitizePublicIpv4Examples } from "./sanitize-generated-content";
5
6
 
6
7
  const repoRoot = path.resolve(import.meta.dir, "..");
7
8
  const outputPath = path.join(repoRoot, "src/internal-urls/console-catalog.generated.ts");
@@ -98,7 +99,7 @@ const output = [
98
99
  "",
99
100
  ].join("\n");
100
101
 
101
- await Bun.write(outputPath, sanitizeTenantHosts(output));
102
+ await Bun.write(outputPath, sanitizePublicIpv4Examples(sanitizeTenantHosts(output)));
102
103
  console.log(
103
104
  `Wrote ${outputPath} (workflows=${Object.keys(data.workflows).length}, resources=${Object.keys(data.resources).length})`,
104
105
  );