@enfocussw/switch-scripting-context 25.11.1-beta.3 → 25.11.1-beta.4

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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,37 @@ All notable changes to this package are documented here. Format follows
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [25.11.1-beta.4] - 2026-09-20
9
+
10
+ ### Added
11
+
12
+ - Guidance in `docs/switch-project/property-editors.md` for a property whose shape varies by a
13
+ type selector. Declare an enum master and one dependent per shape instead of encoding JSON in a
14
+ single property, so each shape gets a native editor and most parsing disappears. Includes the
15
+ two constraints: the master must be static, and a hidden dependent throws when read.
16
+ - A rule in `docs/switch-api/logging.md` against adding a script-level verbosity property. Switch
17
+ already gates `Debug` behind a preference, so the property duplicates a control the user has and
18
+ costs a pane row and translated strings.
19
+
20
+ ### Changed
21
+
22
+ - `init` and `remove` now write to a docs folder named `docs-for-agents` instead of
23
+ `switch-docs`. Re-running `init` after an upgrade deletes the old folder, drops its gitignore
24
+ line, and repoints the generated AI config files, so no stale copy of the docs is left for an
25
+ agent to load. Pass `--docs-dir switch-docs` to keep the old name.
26
+ - The `DetailedInfo` item in `docs/switch-appstore/app-guidelines.md` no longer reads as requiring
27
+ it on every property and connection. It is optional, matching what the property documentation
28
+ and app manual guidance already said, and points at the app manual as the surface users read.
29
+
30
+ ### Fixed
31
+
32
+ - The secret property row in `docs/switch-project/property-editors.md` listed `password` as an
33
+ editor chain. It is a `Type`, and there is no such editor token, so following the row produced an
34
+ invalid declaration.
35
+ - The array property row in `docs/switch-project/property-editors.md` claimed the chain always
36
+ returns a `string[]`, which the modal editor table contradicts. Both files now say the behaviour
37
+ is unverified and that code should handle a bare string too.
38
+
8
39
  ## [25.11.1-beta.3] - 2026-09-17
9
40
 
10
41
  ### Added
package/README.md CHANGED
@@ -4,7 +4,7 @@ AI coding assistant context for [Enfocus Switch](https://www.enfocus.com/en/swit
4
4
 
5
5
  Installs curated API reference docs and generates config files for 8 AI coding agents (Claude Code, GitHub Copilot, Cursor, Codex CLI/OpenCode, Gemini CLI, Windsurf, Zed, and Cline) so AI assistants understand the Switch scripting API out of the box.
6
6
 
7
- See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-context@25.11.1-beta.3/CHANGELOG.md) (also included in this package) for what's changed between versions.
7
+ See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-context@25.11.1-beta.4/CHANGELOG.md) (also included in this package) for what's changed between versions.
8
8
 
9
9
  ## Usage
10
10
 
@@ -45,20 +45,25 @@ so the beta line precedes GA and leaves `25.11.0` free for the first published r
45
45
 
46
46
  ## What it does
47
47
 
48
- 1. Copies the Switch API reference docs to `switch-docs/` in your project
48
+ 1. Copies the Switch API reference docs to `docs-for-agents/` in your project
49
49
  2. Generates AI config files for each tool (see below)
50
- 3. Appends `switch-docs/` to `.gitignore`
50
+ 3. Appends `docs-for-agents/` to `.gitignore`
51
+
52
+ Versions before this one used `switch-docs/` as the folder name. Re-running `init` deletes that
53
+ folder and its `.gitignore` line, so your agents do not find a second, stale copy of the docs. It
54
+ only deletes a `switch-docs/` folder that `init` itself wrote. Pass `--docs-dir switch-docs` to
55
+ stay on the old name.
51
56
 
52
57
  ### Generated files
53
58
 
54
59
  | Tool | File | How context is loaded |
55
60
  |---|---|---|
56
- | Claude Code / ClawCode | `CLAUDE.md` | `@switch-docs/switch-scripting.md` import; hub file routes to specific API docs on demand |
61
+ | Claude Code / ClawCode | `CLAUDE.md` | `@docs-for-agents/switch-scripting.md` import; hub file routes to specific API docs on demand |
57
62
  | GitHub Copilot | `.github/copilot-instructions.md` | `#file:` reference to hub |
58
63
  | GitHub Copilot (scoped) | `.github/instructions/switch-scripting.instructions.md` | `applyTo: "**/*.ts"`; auto-attaches to every TypeScript file edit |
59
64
  | Cursor | `.cursor/rules/switch-scripting.mdc` | Inline key rules + full API file path list |
60
65
  | Codex CLI / OpenCode | `AGENTS.md` | Inline key rules + full API file path list |
61
- | Gemini CLI | `GEMINI.md` | `@switch-docs/switch-scripting.md` import |
66
+ | Gemini CLI | `GEMINI.md` | `@docs-for-agents/switch-scripting.md` import |
62
67
  | Windsurf | `.windsurfrules` | Inline key rules + full API file path list |
63
68
  | Zed | `.rules` | Inline key rules + full API file path list |
64
69
  | Cline | `.clinerules` | Inline key rules + full API file path list |
@@ -84,7 +89,7 @@ A few things this gets you without asking for them by name:
84
89
  properties (app path/licence) are off-limits and left to SwitchScripter's GUI instead.
85
90
 
86
91
  Re-run `init` after upgrading this package so the copied docs and generated config files catch up.
87
- See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-context@25.11.1-beta.3/CHANGELOG.md) for what changed.
92
+ See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-context@25.11.1-beta.4/CHANGELOG.md) for what changed.
88
93
 
89
94
  ## Options
90
95
 
@@ -94,7 +99,7 @@ npx switch-scripting-context init [options]
94
99
  --tools <list> Tools to configure. Default: all
95
100
  IDs: claude, copilot, cursor, codex, gemini, windsurf, zed, cline
96
101
  Aliases: opencode (→ codex), clawcode (→ claude)
97
- --docs-dir <dir> Destination folder for docs. Default: switch-docs
102
+ --docs-dir <dir> Destination folder for docs. Default: docs-for-agents
98
103
  --force Overwrite existing AI config files instead of merging
99
104
  --dry-run Print what would happen without writing any files
100
105
  ```
@@ -124,7 +129,7 @@ To undo `init`, run `remove`. By default it deletes the docs folder, the Switch
124
129
  npx switch-scripting-context remove [options]
125
130
 
126
131
  --tools <list> Only remove these tools' config. Default: remove everything
127
- --docs-dir <dir> Docs folder to remove. Default: switch-docs
132
+ --docs-dir <dir> Docs folder to remove. Default: docs-for-agents
128
133
  --dry-run Print what would happen without writing any files
129
134
  ```
130
135
 
@@ -143,7 +148,7 @@ npm install --save-dev "https://github.com/enfocus-switch/types-switch-scripting
143
148
 
144
149
  ## Included docs
145
150
 
146
- The `switch-docs/` folder contains:
151
+ The `docs-for-agents/` folder contains:
147
152
 
148
153
  - `switch-scripting.md`: master index with execution environment rules and "load when" routing table
149
154
  <!-- docs-index:readme begin -->
package/dist/init.d.ts CHANGED
@@ -35,4 +35,11 @@ export declare function findMarkerRange(content: string): [number, number] | nul
35
35
  export declare function packageVersion(root?: string): string;
36
36
  /** The comment init writes as the first line of the copied hub file. */
37
37
  export declare function versionStamp(version: string): string;
38
+ /**
39
+ * Drop the `docsDir/` line init added, together with the comment line directly above it.
40
+ * The comment and the path are matched as one unit so that a project carrying entries for
41
+ * two docs folders (one left by an older version, one current) keeps the comment belonging
42
+ * to the entry that stays.
43
+ */
44
+ export declare function stripGitignoreEntry(content: string, docsDir: string): string;
38
45
  export declare function run(argv?: string[]): Promise<void>;
package/dist/init.js CHANGED
@@ -44,6 +44,7 @@ exports.buildIdMap = buildIdMap;
44
44
  exports.findMarkerRange = findMarkerRange;
45
45
  exports.packageVersion = packageVersion;
46
46
  exports.versionStamp = versionStamp;
47
+ exports.stripGitignoreEntry = stripGitignoreEntry;
47
48
  exports.run = run;
48
49
  const fs = __importStar(require("fs"));
49
50
  const path = __importStar(require("path"));
@@ -92,6 +93,13 @@ const INLINE_CORE_RULES = `## Core rules
92
93
  - After editing \`main.ts\`, transpile with \`SwitchScriptTool --transpile <folder>\` — do not use \`tsc\` directly.
93
94
  - Never use a script folder in production — pack with \`SwitchScriptTool --pack\` first; folders are excluded from flow exports.`;
94
95
  // ─── Content generators ──────────────────────────────────────────────────────
96
+ // Claude Code and Gemini CLI resolve @file imports themselves, so their generated
97
+ // block is just a pointer to switch-scripting.md; the routing table and key rules
98
+ // living there are the actual instructions. Codex, Windsurf, Zed, and Cline don't
99
+ // reliably follow that import syntax, so their generators (generateInlineBlock)
100
+ // paste INLINE_CORE_RULES and the routing table directly into the generated file
101
+ // instead. Don't collapse these into one shared generator; the split is deliberate,
102
+ // not duplication.
95
103
  function generateClaudeMd(docsDir) {
96
104
  return `${MARKER_BEGIN}
97
105
  ## Switch Scripting (Enfocus Switch)
@@ -395,6 +403,33 @@ function stampDocsVersion(packageRoot, destDir, dryRun) {
395
403
  fs.writeFileSync(hubPath, `${stamp}\n${fs.readFileSync(hubPath, 'utf8')}`, 'utf8');
396
404
  console.log(` ${rel} → stamped ${stamp}`);
397
405
  }
406
+ // ─── Legacy docs folder ──────────────────────────────────────────────────────
407
+ /** Docs folder name written by versions before the rename to docs-for-agents. */
408
+ const LEGACY_DOCS_DIR = 'switch-docs';
409
+ /**
410
+ * Delete the docs folder an older version wrote under its old name.
411
+ *
412
+ * init regenerates every AI config block in place, so after an upgrade the configs point at
413
+ * the new folder and nothing reads the old one. It is gitignored, so nothing surfaces it
414
+ * either, but an agent grepping the project still finds and loads the stale copy. The folder
415
+ * is only removed when it holds the hub file init writes, so a folder of the same name that
416
+ * this tool did not create is left alone.
417
+ */
418
+ function removeLegacyDocsDir(targetRoot, docsDir, dryRun) {
419
+ if (docsDir === LEGACY_DOCS_DIR)
420
+ return;
421
+ const legacyDir = path.join(targetRoot, LEGACY_DOCS_DIR);
422
+ if (!fs.existsSync(path.join(legacyDir, HUB_FILE)))
423
+ return;
424
+ if (dryRun) {
425
+ console.log(` [dry-run] ${LEGACY_DOCS_DIR}/ → deleted (docs folder from an earlier version)`);
426
+ }
427
+ else {
428
+ fs.rmSync(legacyDir, { recursive: true, force: true });
429
+ console.log(` ${LEGACY_DOCS_DIR}/ → deleted (docs folder from an earlier version)`);
430
+ }
431
+ removeGitignoreEntry(targetRoot, LEGACY_DOCS_DIR, dryRun);
432
+ }
398
433
  // ─── .gitignore update ───────────────────────────────────────────────────────
399
434
  function updateGitignore(targetRoot, docsDir, dryRun) {
400
435
  const gitignorePath = path.join(targetRoot, '.gitignore');
@@ -408,7 +443,10 @@ function updateGitignore(targetRoot, docsDir, dryRun) {
408
443
  console.log(` [dry-run] .gitignore → append ${docsDir}/ entry`);
409
444
  return;
410
445
  }
411
- fs.appendFileSync(gitignorePath, entry, 'utf8');
446
+ // entry opens with its own blank-line separator, so normalise what the file already
447
+ // ends with. Without this, appending after an entry that was just removed leaves a
448
+ // widening gap in the file on every upgrade.
449
+ fs.writeFileSync(gitignorePath, content.replace(/\n*$/, '\n') + entry, 'utf8');
412
450
  console.log(` .gitignore → appended ${docsDir}/ entry`);
413
451
  }
414
452
  /** AI config files that init may have created, for all tools or only the given tool ids. */
@@ -472,15 +510,25 @@ function removeAiConfig(filePath, file, docsDir, targetRoot, dryRun) {
472
510
  console.log(` ${rel} → removed Switch section`);
473
511
  }
474
512
  }
513
+ function escapeRegExp(s) {
514
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
515
+ }
516
+ /**
517
+ * Drop the `docsDir/` line init added, together with the comment line directly above it.
518
+ * The comment and the path are matched as one unit so that a project carrying entries for
519
+ * two docs folders (one left by an older version, one current) keeps the comment belonging
520
+ * to the entry that stays.
521
+ */
522
+ function stripGitignoreEntry(content, docsDir) {
523
+ const pattern = new RegExp(`(\n# switch-scripting-context \\(AI context docs[^\n]*\\))?\n${escapeRegExp(docsDir)}/\n`, 'g');
524
+ return content.replace(pattern, '\n');
525
+ }
475
526
  function removeGitignoreEntry(targetRoot, docsDir, dryRun) {
476
527
  const gitignorePath = path.join(targetRoot, '.gitignore');
477
528
  if (!fs.existsSync(gitignorePath))
478
529
  return;
479
530
  const content = fs.readFileSync(gitignorePath, 'utf8');
480
- // Remove the comment line and the docsDir/ line added by init
481
- const updated = content
482
- .replace(/\n# switch-scripting-context \(AI context docs[^\n]*\)\n/g, '\n')
483
- .replace(new RegExp(`\n${docsDir}/\n`, 'g'), '\n');
531
+ const updated = stripGitignoreEntry(content, docsDir);
484
532
  if (updated === content)
485
533
  return;
486
534
  if (dryRun) {
@@ -521,6 +569,7 @@ function remove(options) {
521
569
  else {
522
570
  console.log(` ${options.docsDir}/ → not found, skipping`);
523
571
  }
572
+ removeLegacyDocsDir(targetRoot, options.docsDir, options.dryRun);
524
573
  // 2. Remove AI config sections / files
525
574
  console.log('\nCleaning AI config files...');
526
575
  for (const { filePath, file } of aiConfigFiles(targetRoot, options.docsDir)) {
@@ -540,6 +589,7 @@ function init(options) {
540
589
  console.log('\nDry run — no files will be written.\n');
541
590
  // 1. Copy docs
542
591
  console.log('Copying docs...');
592
+ removeLegacyDocsDir(targetRoot, options.docsDir, options.dryRun);
543
593
  copyDocs(packageRoot, docsDestDir, options.dryRun);
544
594
  stampDocsVersion(packageRoot, docsDestDir, options.dryRun);
545
595
  // 2. Generate AI config files
@@ -573,12 +623,12 @@ function parseArgs(argv) {
573
623
  let toolsExplicit = false;
574
624
  const initOptions = {
575
625
  tools: TOOL_REGISTRY.map(t => t.id),
576
- docsDir: 'switch-docs',
626
+ docsDir: 'docs-for-agents',
577
627
  force: false,
578
628
  dryRun: false,
579
629
  };
580
630
  const removeOptions = {
581
- docsDir: 'switch-docs',
631
+ docsDir: 'docs-for-agents',
582
632
  dryRun: false,
583
633
  };
584
634
  for (let i = 1; i < args.length; i++) {
@@ -658,7 +708,7 @@ Options (init):
658
708
  IDs: claude, copilot, cursor, codex, gemini, windsurf, zed, cline
659
709
  Aliases: opencode (→ codex), clawcode (→ claude)
660
710
  Default: all tools
661
- --docs-dir <dir> Destination folder for docs in target project (default: switch-docs)
711
+ --docs-dir <dir> Destination folder for docs in target project (default: docs-for-agents)
662
712
  --force Overwrite existing AI config files rather than merging
663
713
  --dry-run Print what would happen without writing any files
664
714
  --help Show this help message
@@ -666,7 +716,7 @@ Options (init):
666
716
  Options (remove):
667
717
  --tools <list> Only remove these tools' config; keeps the docs folder and other tools
668
718
  Default: remove everything, same as listing every tool
669
- --docs-dir <dir> Docs folder to remove (default: switch-docs)
719
+ --docs-dir <dir> Docs folder to remove (default: docs-for-agents)
670
720
  --dry-run Print what would happen without writing any files
671
721
 
672
722
  Examples:
@@ -24,6 +24,13 @@ and how often to log is a deliberate choice, not a default.
24
24
  | `Info` | Normal, expected checkpoints worth surfacing to a flow operator without them needing debug mode (e.g. "processed 40 records", "output written to X"). |
25
25
  | `Debug` | Verbose detail for diagnosing execution. Many users leave debug logging enabled in production to self-diagnose issues and to help app developers and Enfocus Support — leave meaningful checkpoints in, but trim noisy or no-longer-useful debug logs before shipping. **`Debug` messages only reach the log database if the Switch preference "Log debug messages" is turned on** (off by default) — see [logs-and-dataroot.md](../switch-project/logs-and-dataroot.md#retention-and-the-debug-level-gate). |
26
26
 
27
+ ## Don't add a verbosity property
28
+
29
+ Switch already has the switch: `Debug` messages only reach the log database when the preference
30
+ "Log debug messages" is on. A script-level "log detail" or "verbose logging" property duplicates a
31
+ control the user already has, adds a row to the property pane, and (for an app) adds strings to
32
+ translate. Put verbose detail behind `LogLevel.Debug` and let the preference govern it.
33
+
27
34
  ## Logging in loops
28
35
 
29
36
  Don't categorically avoid logging inside loops — per-item logs can matter (e.g. a per-job error).
@@ -162,11 +162,15 @@ Unlike the sections above, these are documented in full here rather than deferri
162
162
  approval. Note that an unsigned app always loads under the **Custom** subcategory regardless of
163
163
  what it declares — the declared subcategory only takes effect once Enfocus has signed the app, and
164
164
  review may change it.
165
- - [ ] **`DetailedInfo` is present on every property and every connection**, not just `Tooltip`.
166
- Switch Designer can export a *flow's* HTML documentation from every element in it, so an empty
167
- `DetailedInfo` produces a blank entry there if a flow builder ever generates one — see
165
+ - [ ] **`DetailedInfo` is written wherever it adds something a `Tooltip` can't carry** — not
166
+ mechanically on every property. It is optional: Switch Designer can export a *flow's* HTML
167
+ documentation from every element in it, so an empty `DetailedInfo` produces a blank entry there
168
+ if a flow builder ever generates one, which is a reason to fill it in where the property warrants
169
+ it, not a reason to pad out every trivial one. See
168
170
  [property-documentation.md](../switch-project/property-documentation.md) for what to write in it, and when
169
- it's fine to leave blank.
171
+ it's fine to leave blank. The [app manual](app-manual.md#flow-elements-properties) is the surface
172
+ users are far more likely to read, and it needs real per-property content regardless of what
173
+ `DetailedInfo` holds.
170
174
  - [ ] **`Description`, `Compatibility`, `SupportInfo` and `AppDiscovery` are filled in.** These are
171
175
  required to create the `.enfpack` at all, and `SupportInfo` must point at *your* support channel,
172
176
  never Enfocus Support — see [app-store-listing.md](app-store-listing.md) for what to write
@@ -158,9 +158,9 @@ offer it as the property's only editor — pair it with a module-free option (e.
158
158
 
159
159
  | Property kind | Recommended `Editor` chain | Why |
160
160
  |---|---|---|
161
- | Secret (password, token, API key) | `password` only | Masks the value and avoids leaking it via logs or variable inspection if a var/expression editor were combined. |
161
+ | Secret (password, token, API key) | `inline` only, with `Type="password"` | Masks the value and avoids leaking it via logs or variable inspection if a var/expression editor were combined. `password` is a `Type`, not an editor token — there is no `password` entry in the [modal editor](#modal-editors) list, so `Editor="password"` is wrong. |
162
162
  | Scalar job-specific value (job ID, copy count, company name, date, etc.) | `inline` (`Type` matching the value) + `sltextwithvar` + `scriptexp` | Hard-coded default, plus dynamic substitution and full expression evaluation. |
163
- | Array/list job-specific value | `stringlist` + `mltextwithvar` + `scriptexp` | One item per line; keeps both the hard-coded and dynamic paths returning a `string[]`. |
163
+ | Array/list job-specific value | `stringlist` + `mltextwithvar` + `scriptexp` | One item per line. **Caveat:** the intent is that every path returns a `string[]`, but the [modal editor table](#modal-editors) lists `mltextwithvar` as returning a single string, and which one holds for this chain is unverified. Handle both — split on newlines when a bare string comes back. |
164
164
  | Structured blob text (XML/JSON/HTML, email body) | `description` + `mltextwithvar` + `scriptexp` | Free multi-line text suits a single blob of content better than a line-per-item list. |
165
165
  | Boolean used as a `Dependency` master | `inline` only | Other properties' visibility depends on a value known at design time. |
166
166
  | Boolean consumed directly by script logic (not a `Dependency` master) | `inline` + `conditionwithvar` + `scriptexp` | Safe to toggle dynamically since nothing else depends on it for visibility. Also covers booleans that are themselves a `Dependency` *dependent* (not a master). |
@@ -174,6 +174,50 @@ offer it as the property's only editor — pair it with a module-free option (e.
174
174
  combined with `sltextwithvar`/`scriptexp` too, but this is uncommon in practice and not covered by a
175
175
  dedicated row above.
176
176
 
177
+ ### A property whose shape varies by a type selector
178
+
179
+ When what a property must hold depends on another property's value — a map for one type, an
180
+ ordered list for another, a pair of labelled strings for a third — don't reach for one property
181
+ holding JSON or a hand-rolled line format. Declare an enum master and one dependent per shape, each
182
+ with the editor that natively fits it, and read only the dependent the master currently shows.
183
+
184
+ The shapes then need no parsing at all in the common cases, and the property pane shows one
185
+ type-appropriate editor with a label that explains itself instead of a text box whose format lives
186
+ in the documentation:
187
+
188
+ ```xml
189
+ <!-- master: enum, inline only, so the value is known at flow-configuration time -->
190
+ <QType UserDefined="true" Type="enum:(not used);List;Ordered;Pair" Editor="inline" Subtype="inline"
191
+ LocalizedTagName="Type" Tooltip="" DetailedInfo="" Validation="Standard"
192
+ Default="(not used)">(not used)</QType>
193
+
194
+ <!-- one dependent per shape; each is hidden unless its condition holds -->
195
+ <QList UserDefined="true" Type="stringlist" Editor="stringlist" Subtype="stringlist"
196
+ Dependency="QType" DependencyCondition="Equals" Dependencyvalue="List"
197
+ LocalizedTagName="Items" Tooltip="" DetailedInfo="" Validation="Standard"></QList>
198
+ <QLow UserDefined="true" Type="string" Editor="description" Subtype=""
199
+ Dependency="QType" DependencyCondition="Equals" Dependencyvalue="Pair"
200
+ LocalizedTagName="What a low value means" Tooltip="" DetailedInfo=""
201
+ Validation="Standard" Default=""></QLow>
202
+ ```
203
+
204
+ Adding `(not used)` to the master's items makes it double as the group's on/off switch, so the
205
+ group needs no separate boolean.
206
+
207
+ Two constraints come with the pattern:
208
+
209
+ - The master must be an enum or a boolean with `inline` only, per the rows above. A dynamic master
210
+ makes the visible set differ per job, which the dependents' own editors cannot account for.
211
+ - Reading a hidden dependent throws `"Invalid tag: <tag>"`. Check the master's value, or call
212
+ `hasProperty(tag)`, before every read — see
213
+ [script-declaration.md § Dependency](script-declaration.md#custom-property-elements-elementfields).
214
+ This bites hardest in a loop over jobs or connections, where the throw repeats on every
215
+ invocation.
216
+
217
+ A shape the master cannot enumerate, or one that must vary per job, is the case this pattern does
218
+ not cover; that is where a single `description` property holding a structured blob is the honest
219
+ answer.
220
+
177
221
  ---
178
222
 
179
223
  ## Notes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enfocussw/switch-scripting-context",
3
- "version": "25.11.1-beta.3",
3
+ "version": "25.11.1-beta.4",
4
4
  "description": "AI coding assistant context for Enfocus Switch scripting (Node.js/TypeScript)",
5
5
  "keywords": [
6
6
  "switch",