dsh-gitbash-shell 0.26.1 → 0.27.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,43 @@
3
3
  > 倒序排列,新版本条目在最上面。条目格式:`## vX.Y.Z — YYYY-MM-DD` + 类型(feat / fix / docs / chore)+ 要点 + 相关链接。
4
4
  > 纪律见 AGENTS.md「变更记录纪律」:发版前先更新本文件并随版本提交;事故复盘、复现与真机验证记录也记在这里。
5
5
 
6
+ ## v0.27.0 — 2026-09-25
7
+
8
+ **类型**:feat(新设置「子代理/队员是否也使用 Git Bash」,默认开启 —— 用户 2026-09-25 追加需求)
9
+
10
+ ### 需求与语义
11
+ 用户原话:「gitbash 插件也是专门给个设置是否让子代理或者子队员使用 gitbash,默认启动。」
12
+
13
+ - **开关 `subagentDialect`(本插件行 Config 的 volatile 布尔,**默认 `true`**;旧宿主 ≤0.1.6 在 settings 命名空间 `gitbash-shell` 声明同名字段,**缺键 = true**)。
14
+ - **开(默认)**:委托代理 —— 子代理(`subagent`/`subagent_fork`)、团队队员(`spawn_teammate` 走 continuable-subagent 的 `spawn`/`fork`)、**嵌套子代理** —— 与主代理享受同一条方言链路。
15
+ - **关**:方言只对主代理生效,委托出去的请求回退官方 shell 语义(提示词不改写、路径参数不翻译、结果/报错不回显为 MSYS、`run_code` 程序字面量不翻译、不下发 `DSH_PATH_DIALECT`)。
16
+
17
+ ### 委托身份的判据(先查清链路,再动代码)
18
+ - 用**会话头**判定:`origin === 'subagent' || delegationDepth > 0` —— 与 dsh 自己的 `packages/deliverables/workspace-changes/src/index.ts:59-60` 同一对字段;由子代理驱动在 `packages/subagent/subagent/src/child-agent.ts:139-155` (`childSessionMeta`) 打上,`spawn`/`fork` 两种 provider 与嵌套深度都走它。
19
+ - 纯函数 `isDelegatedAgent(agent)` + 唯一判定点 `dialectApplies(dialect, agent)`;条件挂在 `assembleContext.agent`(`packages/core/agent/src/dispatch.ts:174` 的 `assembleContextFor` 传 `{ agent, scope }`)与 `exec.agent` / `execution.agent` 上。
20
+ - **未知形状一律视为"非委托"**(保留方言):判定不出来时按主代理处理。
21
+
22
+ ### 覆盖到的五个消费点(全部接同一个 gate,避免"半方言")
23
+ ① `system-prompt/assemble` 的源头改写与 run_code 句;② 指令 context 的 `text(context)` provider;③ `tools/execute` 的入参翻译 + 成功面回显;④ `tools/post-execute` 的失败面 `content`/`error.message`;⑤ `shellEnv.resolve(execution)` 的 `DSH_PATH_DIALECT` 事实。
24
+
25
+ ### 能力边界(如实写明,写进 README/AGENTS)
26
+ dsh **每个进程只有一个 shell 执行器**(`ctx.shell` 是单例服务),所以 **Git Bash 二进制本身仍是全局的**,本开关管的是**方言/翻译层**;关闭后委托代理见到与写出的是 Windows 形式路径,而 Git Bash 同样接受 `C:/...`,行为自洽。
27
+
28
+ ### 测试与证据
29
+ - 冒烟 **86/86 绿**:新增 3 条(① `isDelegatedAgent`/`dialectApplies` 矩阵:origin、depth 1/2、root、未知/抛错/`agent` 缺失,以及卡片写入断言;② OFF 时主代理保留、委托代理被挡 + 五个消费点都接 gate 的源码断言;③ 旧宿主/老配置**缺键 = true** 的回退);`tests/align-official.mjs` 四变体仍全绿(本版不动组合)。
30
+ - **真机两态(隔离 `DSH_HOME` + 新建 profile + 插件副本 `link:` 安装,真实 dsh 0.1.7-rc.2,本机 macOS)**:探针用 `ctx.agents.create()` 造**真**的 root / child(`origin:'subagent', delegationDepth:1`)/ nested(depth 2)三个 agent(实测会话头 `undefined` / `"subagent":1` / `"subagent":2`),再对每个 agent 调**真的** `ctx.systemPrompt.assemble({ agent, scope: agent })`:
31
+
32
+ | 开关 | main(root) | subagent | nested |
33
+ | --- | --- | --- | --- |
34
+ | **默认 ON** | 方言指令 = yes | **yes** | **yes** |
35
+ | **OFF**(行 Config `subagentDialect: false`) | yes | **no** | **no** |
36
+
37
+ ⇒ 两态下委托代理的方言确实不同(指令 context 出现/消失即 gate 的可观测面),主代理两态都保留。
38
+ **平台说明**:macOS 上方言/执行器面本来被 `process.platform === 'win32'` 门控,本次把**插件副本**的两处组装门(`system-prompt/assemble` 与指令 context)强制打开以取得请求级证据(报告中如实标注);**win32 真机仍未覆盖**(执行器是单例,与方言开关无关,不受本版影响)。
39
+ - 设置卡:方言区新增一行(21 语言 `sub.label`/`sub.hint`),写入本行 `subagentDialect`;文案明确"二进制仍全局、此开关管方言/翻译层"。
40
+
41
+ - 相关:用户需求(2026-09-25 追加);实现不变量见 AGENTS.md §4g,验证装置见「验证清单」第 8 条。
42
+
6
43
  ## v0.26.1 — 2026-09-25
7
44
 
8
45
  **类型**:fix(v0.26.0 的 workflow 互斥按「意图」而非「生效态」收敛:后端不可用时用户会白丢 workflow 能力)
package/README.md CHANGED
@@ -101,6 +101,22 @@ dsh-ptc-cordis-preset 报告它的 `PTC 创造模式` 已经是 Git Bash 版。
101
101
  0.24.x 的四个变体逐字不变;判定细节、生效时机与两侧同步方式见下方
102
102
  [「与 dsh-ptc-cordis-preset 联动」](#与-dsh-ptc-cordis-preset-联动)。
103
103
 
104
+ ### 子代理/队员是否也用 Git Bash:`subagentDialect`(默认开,v0.27.0)
105
+
106
+ ```yaml
107
+ - id: gitbash-shell
108
+ config:
109
+ subagentDialect: true # 默认;false = 方言只对主代理生效
110
+ ```
111
+
112
+ 默认开启时,子代理、团队队员(含嵌套子代理)与主代理走**同一条**方言链路:提示词里的路径同样是 `/c/...` 形式、
113
+ 路径参数同样被翻译、结果与报错同样回显为 MSYS 形式、`run_code` 程序里的路径字面量同样被翻译,`DSH_PATH_DIALECT` 环境事实也照常下发。
114
+ 关闭后这些**只对主代理生效**:委托出去的请求保持官方 shell 语义(提示词不改写、路径参数原样传递),适合"子代理要跑原生 Windows 工具链"的场景。
115
+
116
+ > 能力边界(如实说明):dsh **每个进程只有一个 shell 执行器**(`ctx.shell` 是单例服务),所以 Git Bash **二进制本身仍是全局的**,
117
+ > 这个开关管的是**方言/翻译层**,不是"换一个 shell"。关闭后委托代理见到与写出的是 Windows 形式路径(`C:/...`),Git Bash 同样接受,行为自洽。
118
+ > 委托身份的判据用会话头的 `origin === 'subagent'` / `delegationDepth > 0`(与 dsh 自身一致),判定不出来时按主代理处理(保留方言)。
119
+
104
120
  配合 `agent-presets` 的 `default`,新会话直接落在 Git Bash 模式,免去每次在
105
121
  模式选择器里翻找(原版 shipped 模式无法替换或隐藏——部署级、只读):
106
122
 
package/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-external/dsh-gitbash-shell",
3
- "version": "0.26.1",
3
+ "version": "0.27.0",
4
4
  "main": "./src/index.js",
5
5
  "description": "Windows 全模式 Git Bash:用 Git for Windows bash 替换 PowerShell 执行器,并物化 standard/minimal/code/cordis 的 Git Bash 变体 preset。双 era 适配 dsh <= 0.1.1(内置 id 'code')与 >= 0.1.2(改名 'ptc'),启动探测自动选择,preset id 永不变。联动:dsh-ptc-cordis-preset(两者同装时 PTC 创造模式自动物化为 Git Bash 版)+ dsh-better-sidebar(终端 UI 标签与模型 terminal_* 工具自动切到 Git Bash)。",
6
6
  "engines": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-gitbash-shell",
3
- "version": "0.26.1",
3
+ "version": "0.27.0",
4
4
  "description": "Windows 上让 agent 的每条 shell 命令改经 Git for Windows bash 执行;物化四个内置预设的 Git Bash 变体,统一 MSYS 盘根路径方言,侧栏终端接管可开关。· Run every agent shell command through Git for Windows bash on Windows; materialize Git Bash variants of the built-in presets, unify the MSYS drive-root path dialect, and adopt the sidebar terminal behind a switch.",
5
5
  "type": "module",
6
6
  "repository": {
package/src/client.js CHANGED
@@ -87,6 +87,8 @@ window.__ModuleLoader__.load({
87
87
  "split.hint": "glob 的绝对 pattern(/c/.../*.md)自动拆为 path + 相对 pattern;关闭则原样传递。",
88
88
  "code.label": "run_code 程序内路径",
89
89
  "code.hint": "run_code 程序里写的 /c/... 等路径字面量在执行前按同一张挂载表翻译;注释、插值模板、$VAR 与非路径字符串不动,扫描有任何不确定就整份不改。 并给程序补 TEMP/TMP:空 env 下 Windows 的 os.tmpdir() 会得到 undefined\\temp,程序会静默写错地方。",
90
+ "sub.label": "子代理/队员使用 Git Bash",
91
+ "sub.hint": "默认开启:子代理与团队队员(含嵌套子代理)的提示词方言、路径参数翻译、结果回显与 DSH_PATH_DIALECT 环境事实与主代理一致。关闭后这些只对主代理生效,子代理按官方 shell 语义运行(提示词不改写、路径参数不翻译);注意 dsh 每个进程只有一个 shell 执行器,所以 Git Bash 二进制本身仍是全局的,此开关管的是方言/翻译层。",
90
92
  "eol.label": "Git 行尾(与 Linux 一致)",
91
93
  "eol.hint": "模型跑的 git 命令按 Linux 行为:core.autocrlf=input、core.eol=lf。你自己终端的 git 与仓库里的 .gitattributes 都不受影响。",
92
94
  "bash.label": "Git Bash 路径",
@@ -127,6 +129,8 @@ window.__ModuleLoader__.load({
127
129
  "split.hint": "An absolute glob pattern (/c/.../*.md) splits into path + relative pattern; off passes it through verbatim.",
128
130
  "code.label": "run_code program paths",
129
131
  "code.hint": "Path literals inside a run_code program are translated through the same mount table before it runs; comments, interpolated templates, $VARs and non-path strings stay untouched, and any uncertainty leaves the whole program as written. It also seeds TEMP/TMP for the program: with an empty env Windows' os.tmpdir() returns undefined\\temp and writes land in a bogus folder.",
132
+ "sub.label": "Subagents/teammates use Git Bash",
133
+ "sub.hint": "On (default): subagents and team members — nested ones included — get the same prompt dialect, path-argument translation, result echo and DSH_PATH_DIALECT fact as the main agent. Off: those apply to the main agent only, and delegated agents run with the official shell semantics (no prompt rewrite, no path translation). Note that dsh has exactly one shell executor per process, so the Git Bash binary stays global; this switch governs the dialect/translation layers.",
130
134
  "eol.label": "Git line endings (Linux match)",
131
135
  "eol.hint": "Git commands the model runs behave like Linux: core.autocrlf=input, core.eol=lf. Your own terminal's git and a repository's .gitattributes are unaffected.",
132
136
  "bash.label": "Git Bash path",
@@ -177,6 +181,8 @@ window.__ModuleLoader__.load({
177
181
  "split.hint": "نمط glob المطلق يُقسم إلى path + نمط نسبي؛ الإيقاف يمرره كما هو.",
178
182
  "code.label": "مسارات برامج run_code",
179
183
  "code.hint": "تُترجم السلاسل النصية للمسارات المكتوبة داخل برنامج run_code عبر جدول التحميل نفسه قبل التشغيل؛ وتبقى التعليقات والقوالب ذات الإدراج و$VAR والسلاسل غير المسارية كما هي، وأي التباس يُبقي البرنامج كاملًا دون تغيير. وتُهيَّأ أيضًا TEMP/TMP للبرنامج: مع بيئة فارغة يعيد os.tmpdir() على ويندوز القيمة undefined\\temp فيُكتب في مكان خاطئ.",
184
+ "sub.label": "استخدام الوكلاء الفرعيين لـ Git Bash",
185
+ "sub.hint": "مُفعَّل (افتراضيًا): يحصل الوكلاء الفرعيون وأعضاء الفريق — بما في ذلك المتداخلون — على لهجة المطالبة وترجمة مسارات الوسائط وصدى النتائج وحقيقة DSH_PATH_DIALECT نفسها التي يحصل عليها الوكيل الرئيسي. عند الإيقاف تُطبَّق هذه على الوكيل الرئيسي فقط ويعمل الوكلاء المفوَّضون بدلالات الصدفة الرسمية (دون إعادة كتابة المطالبة أو ترجمة المسارات). لاحظ أن dsh يملك مُنفِّذ صدفة واحدًا لكل عملية، لذا يبقى ثنائي Git Bash عامًّا؛ هذا المفتاح يحكم طبقتي اللهجة والترجمة.",
180
186
  "eol.label": "نهايات أسطر Git (مطابقة لينكس)",
181
187
  "eol.hint": "أوامر git التي يشغّلها النموذج تتبع سلوك لينكس: core.autocrlf=input و core.eol=lf؛ لا يتأثر طرفيتك ولا ملف .gitattributes للمستودع.",
182
188
  "bash.label": "مسار Git Bash",
@@ -217,6 +223,8 @@ window.__ModuleLoader__.load({
217
223
  "split.hint": "Ein absolutes Glob-Muster zerfällt in Pfad + relatives Muster; aus übergibt es unverändert.",
218
224
  "code.label": "Pfade in run_code-Programmen",
219
225
  "code.hint": "Pfadliterale in einem run_code-Programm werden vor dem Start über dieselbe Mount-Tabelle übersetzt; Kommentare, interpolierte Templates, $VARs und Nicht-Pfad-Strings bleiben unangetastet, und bei Unklarheit bleibt das ganze Programm unverändert. Zusätzlich werden TEMP/TMP für das Programm gesetzt: bei leerer Umgebung liefert os.tmpdir() unter Windows undefined\\temp und schreibt an einen falschen Ort.",
226
+ "sub.label": "Subagenten/Teammitglieder nutzen Git Bash",
227
+ "sub.hint": "An (Standard): Subagenten und Teammitglieder — auch verschachtelte — erhalten denselben Prompt-Dialekt, dieselbe Pfadargument-Übersetzung, dieselbe Ergebnisanzeige und dieselbe DSH_PATH_DIALECT-Tatsache wie der Hauptagent. Aus: Das gilt nur für den Hauptagenten, delegierte Agenten laufen mit den offiziellen Shell-Semantiken (keine Prompt-Umschreibung, keine Pfadübersetzung). Beachte: dsh hat genau einen Shell-Executor pro Prozess, das Git-Bash-Binary bleibt also global; dieser Schalter steuert die Dialekt-/Übersetzungsschichten.",
220
228
  "eol.label": "Git-Zeilenenden (Linux-gleich)",
221
229
  "eol.hint": "Vom Modell ausgeführte git-Befehle verhalten sich wie unter Linux: core.autocrlf=input, core.eol=lf. Dein eigenes Terminal und die .gitattributes eines Repos bleiben unberührt.",
222
230
  "bash.label": "Git-Bash-Pfad",
@@ -257,6 +265,8 @@ window.__ModuleLoader__.load({
257
265
  "split.hint": "Un motif glob absolu se scinde en chemin + motif relatif ; désactivé le passe tel quel.",
258
266
  "code.label": "chemins dans les programmes run_code",
259
267
  "code.hint": "Les littéraux de chemin écrits dans un programme run_code sont traduits via la même table de montage avant exécution; commentaires, gabarits interpolés, $VAR et chaînes non-chemin restent intacts, et la moindre incertitude laisse le programme tel quel. TEMP/TMP sont aussi fournis au programme : avec un env vide, os.tmpdir() sous Windows renvoie undefined\\temp et écrit au mauvais endroit.",
268
+ "sub.label": "Les sous-agents utilisent Git Bash",
269
+ "sub.hint": "Activé (par défaut) : les sous-agents et membres d'équipe — y compris imbriqués — reçoivent le même dialecte de prompt, la même traduction des chemins d'arguments, le même écho de résultat et le même fait DSH_PATH_DIALECT que l'agent principal. Désactivé : ces éléments ne s'appliquent qu'à l'agent principal et les agents délégués suivent les sémantiques de shell officielles (pas de réécriture du prompt, pas de traduction des chemins). À noter : dsh n'a qu'un seul exécuteur de shell par processus, le binaire Git Bash reste donc global ; cet interrupteur régit les couches de dialecte et de traduction.",
260
270
  "eol.label": "fins de ligne Git (comme Linux)",
261
271
  "eol.hint": "Les commandes git lancées par le modèle suivent le comportement Linux : core.autocrlf=input, core.eol=lf. Votre terminal et les .gitattributes du dépôt ne sont pas touchés.",
262
272
  "bash.label": "Chemin Git Bash",
@@ -297,6 +307,8 @@ window.__ModuleLoader__.load({
297
307
  "split.hint": "एब्सोल्यूट glob पैटर्न path + रिलेटिव पैटर्न में विभाजित होता है; बंद इसे वैसे ही पास करता है।",
298
308
  "code.label": "run_code प्रोग्राम पथ",
299
309
  "code.hint": "run_code प्रोग्राम में लिखे पथ लिटरल चलने से पहले उसी माउंट तालिका से अनूदित होते हैं; टिप्पणियाँ, इंटरपोलेटेड टेम्पलेट, $VAR और गैर-पथ स्ट्रिंग अछूते रहते हैं, और किसी भी अनिश्चितता पर पूरा प्रोग्राम अपरिवर्तित रहता है। साथ ही प्रोग्राम के लिए TEMP/TMP भर दिए जाते हैं: खाली env में Windows पर os.tmpdir() undefined\\temp देता है और गलत जगह लिखता है।",
310
+ "sub.label": "सबएजेंट/टीम सदस्य Git Bash इस्तेमाल करें",
311
+ "sub.hint": "चालू (डिफ़ॉल्ट): सबएजेंट और टीम सदस्य — नेस्टेड सहित — मुख्य एजेंट जैसा ही प्रॉम्प्ट डायलेक्ट, पाथ आर्ग्युमेंट अनुवाद, परिणाम इको और DSH_PATH_DIALECT तथ्य पाते हैं। बंद: ये केवल मुख्य एजेंट पर लागू होते हैं और प्रतिनिधित एजेंट आधिकारिक शेल अर्थ में चलते हैं (प्रॉम्प्ट नहीं बदलता, पाथ अनुवाद नहीं होता)। ध्यान दें: dsh में प्रति प्रोसेस एक ही शेल एक्ज़ीक्यूटर होता है, इसलिए Git Bash बाइनरी वैश्विक रहती है; यह स्विच डायलेक्ट/अनुवाद परतों को नियंत्रित करता है।",
300
312
  "eol.label": "Git पंक्ति-अंत (Linux जैसा)",
301
313
  "eol.hint": "मॉडल द्वारा चलाए git कमांड Linux व्यवहार अपनाते हैं: core.autocrlf=input, core.eol=lf। आपका टर्मिनल और रेपो का .gitattributes अछूते रहते हैं।",
302
314
  "bash.label": "Git Bash पथ",
@@ -337,6 +349,8 @@ window.__ModuleLoader__.load({
337
349
  "split.hint": "Pattern glob absolut dipecah menjadi path + pattern relatif; nonaktif meneruskannya apa adanya.",
338
350
  "code.label": "jalur dalam program run_code",
339
351
  "code.hint": "Literal jalur yang ditulis di program run_code diterjemahkan lewat tabel mount yang sama sebelum dijalankan; komentar, template berinterpolasi, $VAR, dan string non-jalur dibiarkan, dan bila ada keraguan seluruh program tidak diubah. TEMP/TMP juga diisi untuk program: dengan env kosong, os.tmpdir() di Windows mengembalikan undefined\\temp dan menulis ke lokasi salah.",
352
+ "sub.label": "Subagen/teman tim memakai Git Bash",
353
+ "sub.hint": "Aktif (bawaan): subagen dan anggota tim — termasuk yang bersarang — mendapat dialek prompt, terjemahan argumen path, gema hasil, dan fakta DSH_PATH_DIALECT yang sama seperti agen utama. Nonaktif: semuanya hanya berlaku untuk agen utama dan agen yang didelegasikan berjalan dengan semantik shell resmi (prompt tidak ditulis ulang, path tidak diterjemahkan). Catatan: dsh hanya punya satu eksekutor shell per proses, jadi biner Git Bash tetap global; sakelar ini mengatur lapisan dialek/terjemahan.",
340
354
  "eol.label": "akhir baris Git (sama seperti Linux)",
341
355
  "eol.hint": "Perintah git yang dijalankan model mengikuti perilaku Linux: core.autocrlf=input, core.eol=lf. Terminal Anda dan .gitattributes repo tidak terpengaruh.",
342
356
  "bash.label": "Path Git Bash",
@@ -377,6 +391,8 @@ window.__ModuleLoader__.load({
377
391
  "split.hint": "Un pattern glob assoluto si divide in percorso + pattern relativo; off lo passa invariato.",
378
392
  "code.label": "percorsi nei programmi run_code",
379
393
  "code.hint": "I letterali di percorso scritti in un programma run_code vengono tradotti con la stessa tabella di mount prima dell'esecuzione; commenti, template interpolati, $VAR e stringhe non di percorso restano intatti e qualsiasi incertezza lascia il programma invariato. Inoltre TEMP/TMP vengono forniti al programma: con env vuoto, os.tmpdir() su Windows restituisce undefined\\temp e scrive nel posto sbagliato.",
394
+ "sub.label": "Subagenti/compagni usano Git Bash",
395
+ "sub.hint": "Attivo (predefinito): subagenti e membri del team — anche annidati — ricevono lo stesso dialetto del prompt, la stessa traduzione dei percorsi negli argomenti, lo stesso eco dei risultati e lo stesso fatto DSH_PATH_DIALECT dell'agente principale. Disattivo: valgono solo per l'agente principale e gli agenti delegati usano le semantiche di shell ufficiali (nessuna riscrittura del prompt, nessuna traduzione dei percorsi). Nota: dsh ha un solo esecutore di shell per processo, quindi il binario Git Bash resta globale; questo interruttore governa gli strati di dialetto e traduzione.",
380
396
  "eol.label": "fine riga Git (come Linux)",
381
397
  "eol.hint": "I comandi git eseguiti dal modello seguono il comportamento Linux: core.autocrlf=input, core.eol=lf. Il tuo terminale e i .gitattributes del repo non vengono toccati.",
382
398
  "bash.label": "Percorso Git Bash",
@@ -417,6 +433,8 @@ window.__ModuleLoader__.load({
417
433
  "split.hint": "絶対 glob パターンを path + 相対パターンに分割;オフならそのまま渡します。",
418
434
  "code.label": "run_code プログラム内のパス",
419
435
  "code.hint": "run_code プログラム内に書いた /c/... などのパスリテラルは実行前に同じマウント表で変換されます。コメント・補間テンプレート・$VAR・パス以外の文字列は変更せず、解析に不確かさがあればプログラム全体をそのまま実行します。 さらにプログラムに TEMP/TMP を渡します: 空の env では Windows の os.tmpdir() が undefined\\temp を返し、誤った場所に書き込みます。",
436
+ "sub.label": "サブエージェント/チームメンバーも Git Bash を使う",
437
+ "sub.hint": "オン(既定):サブエージェントとチームメンバー(ネスト含む)は、メインエージェントと同じプロンプト方言・パス引数の翻訳・結果エコー・DSH_PATH_DIALECT の事実を受け取ります。オフ:これらはメインエージェントのみに適用され、委譲されたエージェントは公式の shell セマンティクスで動作します(プロンプト改写なし、パス翻訳なし)。なお dsh はプロセスごとに shell 実行器を 1 つだけ持つため、Git Bash バイナリ自体は常に全体共通です。このスイッチが制御するのは方言/翻訳の層です。",
420
438
  "eol.label": "Git の行末(Linux と同じ)",
421
439
  "eol.hint": "モデルが実行する git コマンドは Linux と同じ挙動になります: core.autocrlf=input、core.eol=lf。あなたのターミナルやリポジトリの .gitattributes は影響を受けません。",
422
440
  "bash.label": "Git Bash パス",
@@ -457,6 +475,8 @@ window.__ModuleLoader__.load({
457
475
  "split.hint": "절대 glob 패턴을 path + 상대 패턴으로 분할; 끄면 그대로 전달.",
458
476
  "code.label": "run_code 프로그램 경로",
459
477
  "code.hint": "run_code 프로그램에 쓴 /c/... 경로 리터럴은 실행 전에 같은 마운트 표로 변환됩니다. 주석, 보간 템플릿, $VAR, 경로가 아닌 문자열은 그대로 두고, 스캔이 불확실하면 프로그램 전체를 그대로 둡니다. 또한 프로그램에 TEMP/TMP를 채워 줍니다: 빈 env에서 Windows의 os.tmpdir()는 undefined\\temp를 반환해 엉뚱한 곳에 씁니다.",
478
+ "sub.label": "서브에이전트/팀원도 Git Bash 사용",
479
+ "sub.hint": "켬(기본): 서브에이전트와 팀원(중첩 포함)은 메인 에이전트와 동일한 프롬프트 방언, 경로 인자 번역, 결과 에코, DSH_PATH_DIALECT 사실을 받습니다. 끔: 이것들은 메인 에이전트에만 적용되고 위임된 에이전트는 공식 shell 의미로 동작합니다(프롬프트 재작성 없음, 경로 번역 없음). 참고로 dsh는 프로세스당 shell 실행기가 하나뿐이라 Git Bash 바이너리 자체는 항상 전역입니다. 이 스위치는 방언/번역 계층을 제어합니다.",
460
480
  "eol.label": "Git 줄바꿈(Linux와 동일)",
461
481
  "eol.hint": "모델이 실행하는 git 명령은 Linux 동작을 따릅니다: core.autocrlf=input, core.eol=lf. 사용자의 터미널과 저장소의 .gitattributes는 영향을 받지 않습니다.",
462
482
  "bash.label": "Git Bash 경로",
@@ -497,6 +517,8 @@ window.__ModuleLoader__.load({
497
517
  "split.hint": "Een absoluut glob-patroon splitst in pad + relatief patroon; uit geeft het ongewijzigd door.",
498
518
  "code.label": "paden in run_code-programma's",
499
519
  "code.hint": "Pad-literalen in een run_code-programma worden vóór uitvoering via dezelfde mounttabel vertaald; opmerkingen, geïnterpoleerde templates, $VAR's en niet-pad-strings blijven ongemoeid, en bij twijfel blijft het hele programma ongewijzigd. Ook worden TEMP/TMP voor het programma gezet: met een lege env geeft os.tmpdir() op Windows undefined\\temp en schrijft het op de verkeerde plek.",
520
+ "sub.label": "Subagenten/teammaten gebruiken Git Bash",
521
+ "sub.hint": "Aan (standaard): subagenten en teamleden — ook geneste — krijgen hetzelfde promptdialect, dezelfde padargument-vertaling, dezelfde resultaat-echo en hetzelfde DSH_PATH_DIALECT-feit als de hoofdagent. Uit: die gelden alleen voor de hoofdagent en gedelegeerde agenten draaien met de officiële shell-semantiek (geen promptherschrijving, geen padvertaling). Let op: dsh heeft één shell-uitvoerder per proces, dus het Git Bash-binary blijft globaal; deze schakelaar beheert de dialect-/vertaallagen.",
500
522
  "eol.label": "Git regeleinden (zoals Linux)",
501
523
  "eol.hint": "Git-opdrachten die het model uitvoert volgen Linux-gedrag: core.autocrlf=input, core.eol=lf. Je eigen terminal en de .gitattributes van een repo blijven onaangetast.",
502
524
  "bash.label": "Git Bash-pad",
@@ -537,6 +559,8 @@ window.__ModuleLoader__.load({
537
559
  "split.hint": "Absolutny wzorzec glob dzieli się na ścieżkę + wzorzec względny; wył. przekazuje bez zmian.",
538
560
  "code.label": "ścieżki w programach run_code",
539
561
  "code.hint": "Literały ścieżek w programie run_code są tłumaczone przez tę samą tabelę montowania przed uruchomieniem; komentarze, szablony z interpolacją, $VAR i ciągi niebędące ścieżkami pozostają nietknięte, a każda niepewność pozostawia program bez zmian. Dodatkowo ustawiane są TEMP/TMP dla programu: przy pustym env Windows zwraca z os.tmpdir() undefined\\temp i zapisuje w złym miejscu.",
562
+ "sub.label": "Subagenci/członkowie zespołu używają Git Bash",
563
+ "sub.hint": "Wł. (domyślnie): subagenci i członkowie zespołu — także zagnieżdżeni — otrzymują ten sam dialekt podpowiedzi, tłumaczenie argumentów ścieżek, echo wyników i fakt DSH_PATH_DIALECT co agent główny. Wył.: dotyczy to tylko agenta głównego, a agenci delegowani działają według oficjalnej semantyki powłoki (bez przepisywania podpowiedzi i tłumaczenia ścieżek). Uwaga: dsh ma jeden executor powłoki na proces, więc binarka Git Bash pozostaje globalna; ten przełącznik steruje warstwami dialektu i tłumaczenia.",
540
564
  "eol.label": "końce linii Git (jak w Linuksie)",
541
565
  "eol.hint": "Polecenia git uruchamiane przez model działają jak w Linuksie: core.autocrlf=input, core.eol=lf. Twój terminal i .gitattributes repozytorium pozostają nietknięte.",
542
566
  "bash.label": "Ścieżka Git Bash",
@@ -577,6 +601,8 @@ window.__ModuleLoader__.load({
577
601
  "split.hint": "Um padrão glob absoluto divide em caminho + padrão relativo; desligado passa-o inalterado.",
578
602
  "code.label": "caminhos em programas run_code",
579
603
  "code.hint": "Literais de caminho escritos num programa run_code são traduzidos pela mesma tabela de montagem antes da execução; comentários, modelos interpolados, $VAR e strings que não são caminhos ficam intactos, e qualquer incerteza deixa o programa como está. Também são definidos TEMP/TMP para o programa: com env vazio, os.tmpdir() no Windows devolve undefined\\temp e grava no lugar errado.",
604
+ "sub.label": "Subagentes/membros da equipa usam Git Bash",
605
+ "sub.hint": "Ligado (padrão): subagentes e membros da equipa — incluindo aninhados — recebem o mesmo dialeto de prompt, tradução de caminhos nos argumentos, eco de resultados e o mesmo facto DSH_PATH_DIALECT que o agente principal. Desligado: isso aplica-se apenas ao agente principal e os agentes delegados correm com a semântica oficial da shell (sem reescrita do prompt nem tradução de caminhos). Nota: o dsh tem um único executor de shell por processo, pelo que o binário Git Bash continua global; este interruptor governa as camadas de dialeto e tradução.",
580
606
  "eol.label": "fins de linha do Git (como no Linux)",
581
607
  "eol.hint": "Os comandos git executados pelo modelo seguem o comportamento do Linux: core.autocrlf=input, core.eol=lf. O seu terminal e os .gitattributes do repositório não são afetados.",
582
608
  "bash.label": "Caminho do Git Bash",
@@ -617,6 +643,8 @@ window.__ModuleLoader__.load({
617
643
  "split.hint": "Абсолютный glob-шаблон разбивается на path + относительный шаблон; выкл передаёт как есть.",
618
644
  "code.label": "пути в программах run_code",
619
645
  "code.hint": "Строковые литералы путей в программе run_code переводятся по той же таблице монтирования до запуска; комментарии, шаблоны с интерполяцией, $VAR и строки-не-пути не трогаются, а при любой неопределённости программа остаётся без изменений. Также программе задаются TEMP/TMP: при пустом env в Windows os.tmpdir() возвращает undefined\\temp и запись идёт не туда.",
646
+ "sub.label": "Субагенты и участники команды используют Git Bash",
647
+ "sub.hint": "Вкл. (по умолчанию): субагенты и участники команды — включая вложенных — получают тот же диалект подсказки, перевод путей в аргументах, эхо результатов и факт DSH_PATH_DIALECT, что и главный агент. Выкл.: это применяется только к главному агенту, а делегированные агенты работают с официальной семантикой оболочки (без перезаписи подсказки и перевода путей). Учтите: в dsh один исполнитель оболочки на процесс, поэтому сам бинарник Git Bash остаётся общим; этот переключатель управляет слоями диалекта и перевода.",
620
648
  "eol.label": "переводы строк Git (как в Linux)",
621
649
  "eol.hint": "Команды git, запускаемые моделью, ведут себя как в Linux: core.autocrlf=input, core.eol=lf. Ваш терминал и .gitattributes репозитория не затрагиваются.",
622
650
  "bash.label": "Путь Git Bash",
@@ -657,6 +685,8 @@ window.__ModuleLoader__.load({
657
685
  "split.hint": "Ett absolut glob-mönster delas i sökväg + relativt mönster; av skickar det oförändrat.",
658
686
  "code.label": "sökvägar i run_code-program",
659
687
  "code.hint": "Sökvägslitteraler i ett run_code-program översätts via samma monteringstabell före körning; kommentarer, interpolerade mallar, $VAR och strängar som inte är sökvägar lämnas orörda, och vid minsta osäkerhet lämnas hela programmet oförändrat. Dessutom sätts TEMP/TMP för programmet: med tom env ger os.tmpdir() i Windows undefined\\temp och skriver på fel ställe.",
688
+ "sub.label": "Subagenter/teammedlemmar använder Git Bash",
689
+ "sub.hint": "På (standard): subagenter och teammedlemmar — även nästlade — får samma promptdialekt, samma sökvägsöversättning i argument, samma resultat-eko och samma DSH_PATH_DIALECT-faktum som huvudagenten. Av: detta gäller bara huvudagenten och delegerade agenter kör med officiell shell-semantik (ingen promptomskrivning, ingen sökvägsöversättning). Obs: dsh har en enda shell-exekutor per process, så Git Bash-binären är fortfarande global; den här växeln styr dialekt-/översättningslagren.",
660
690
  "eol.label": "Git radslut (som Linux)",
661
691
  "eol.hint": "Git-kommandon som modellen kör följer Linux-beteende: core.autocrlf=input, core.eol=lf. Din egen terminal och repots .gitattributes påverkas inte.",
662
692
  "bash.label": "Git Bash-sökväg",
@@ -697,6 +727,8 @@ window.__ModuleLoader__.load({
697
727
  "split.hint": "pattern glob สัมบูรณ์แยกเป็น path + pattern สัมพัทธ์; ปิดส่งต่อตามเดิม",
698
728
  "code.label": "พาธในโปรแกรม run_code",
699
729
  "code.hint": "สตริงพาธที่เขียนในโปรแกรม run_code จะถูกแปลผ่านตาราง mount เดียวกันก่อนรัน ความคิดเห็น เทมเพลตที่มีการแทรก $VAR และสตริงที่ไม่ใช่พาธจะไม่ถูกแตะ และหากไม่แน่ใจทั้งโปรแกรมจะไม่ถูกแก้ไข และเติม TEMP/TMP ให้โปรแกรมด้วย: เมื่อ env ว่าง os.tmpdir() บน Windows จะคืน undefined\\temp แล้วเขียนผิดที่",
730
+ "sub.label": "ซับเอเจนต์/สมาชิกทีมใช้ Git Bash",
731
+ "sub.hint": "เปิด (ค่าเริ่มต้น): ซับเอเจนต์และสมาชิกทีม — รวมถึงแบบซ้อน — ได้รับไดอาเลกต์พรอมป์ต์ การแปลพาธในอาร์กิวเมนต์ การสะท้อนผลลัพธ์ และข้อเท็จจริง DSH_PATH_DIALECT เหมือนเอเจนต์หลัก ปิด: สิ่งเหล่านี้มีผลกับเอเจนต์หลักเท่านั้น และเอเจนต์ที่ถูกมอบหมายทำงานด้วยความหมาย shell อย่างเป็นทางการ (ไม่เขียนพรอมป์ต์ใหม่ ไม่แปลพาธ) หมายเหตุ dsh มีตัวรัน shell เดียวต่อโปรเซส ไบนารี Git Bash จึงยังเป็นส่วนกลาง สวิตช์นี้ควบคุมชั้นไดอาเลกต์/การแปล",
700
732
  "eol.label": "อักขระขึ้นบรรทัด Git (เหมือน Linux)",
701
733
  "eol.hint": "คำสั่ง git ที่โมเดลรันจะใช้พฤติกรรมแบบ Linux: core.autocrlf=input, core.eol=lf เทอร์มินัลของคุณและ .gitattributes ของ repo ไม่ได้รับผลกระทบ",
702
734
  "bash.label": "เส้นทาง Git Bash",
@@ -737,6 +769,8 @@ window.__ModuleLoader__.load({
737
769
  "split.hint": "Mutlak glob örüntüsü path + göreli örüntüye ayrılır; kapalı olduğu gibi geçirir.",
738
770
  "code.label": "run_code program yolları",
739
771
  "code.hint": "Bir run_code programında yazılan yol dizeleri çalıştırılmadan önce aynı bağlama tablosuyla çevrilir; yorumlar, enterpolasyonlu şablonlar, $VAR ve yol olmayan dizeler olduğu gibi kalır, herhangi bir belirsizlikte programın tamamı değişmeden bırakılır. Ayrıca programa TEMP/TMP verilir: boş env ile Windows'ta os.tmpdir() undefined\\temp döner ve yanlış yere yazar.",
772
+ "sub.label": "Alt ajanlar/ekip üyeleri Git Bash kullansın",
773
+ "sub.hint": "Açık (varsayılan): alt ajanlar ve ekip üyeleri — iç içe olanlar dahil — ana ajanla aynı istem lehçesini, yol argümanı çevirisini, sonuç yankısını ve DSH_PATH_DIALECT gerçeğini alır. Kapalı: bunlar yalnızca ana ajan için geçerlidir ve devredilen ajanlar resmî shell semantiğiyle çalışır (istem yeniden yazılmaz, yollar çevrilmez). Not: dsh'de süreç başına tek bir shell yürütücüsü vardır, bu yüzden Git Bash ikilisi genele aittir; bu anahtar lehçe/çeviri katmanlarını yönetir.",
740
774
  "eol.label": "Git satır sonları (Linux gibi)",
741
775
  "eol.hint": "Modelin çalıştırdığı git komutları Linux davranışını izler: core.autocrlf=input, core.eol=lf. Kendi terminaliniz ve deponun .gitattributes dosyası etkilenmez.",
742
776
  "bash.label": "Git Bash yolu",
@@ -777,6 +811,8 @@ window.__ModuleLoader__.load({
777
811
  "split.hint": "Pattern glob tuyệt đối tách thành path + pattern tương đối; tắt truyền nguyên văn.",
778
812
  "code.label": "đường dẫn trong chương trình run_code",
779
813
  "code.hint": "Chuỗi đường dẫn viết trong chương trình run_code được dịch qua cùng bảng mount trước khi chạy; chú thích, template nội suy, $VAR và chuỗi không phải đường dẫn được giữ nguyên, và mọi điểm không chắc chắn sẽ khiến cả chương trình không bị sửa. Đồng thời nạp TEMP/TMP cho chương trình: với env rỗng, os.tmpdir() trên Windows trả về undefined\\temp và ghi sai chỗ.",
814
+ "sub.label": "Subagent/thành viên nhóm dùng Git Bash",
815
+ "sub.hint": "Bật (mặc định): subagent và thành viên nhóm — kể cả lồng nhau — nhận cùng phương ngữ prompt, cách dịch đường dẫn trong tham số, tiếng vọng kết quả và sự thật DSH_PATH_DIALECT như agent chính. Tắt: những thứ này chỉ áp dụng cho agent chính, còn agent được ủy quyền chạy theo ngữ nghĩa shell chính thức (không viết lại prompt, không dịch đường dẫn). Lưu ý dsh chỉ có một bộ thực thi shell mỗi tiến trình, nên tệp nhị phân Git Bash vẫn là toàn cục; công tắc này điều khiển tầng phương ngữ/dịch.",
780
816
  "eol.label": "kết thúc dòng Git (giống Linux)",
781
817
  "eol.hint": "Các lệnh git do mô hình chạy theo hành vi Linux: core.autocrlf=input, core.eol=lf. Terminal của bạn và .gitattributes của repo không bị ảnh hưởng.",
782
818
  "bash.label": "Đường dẫn Git Bash",
@@ -817,6 +853,8 @@ window.__ModuleLoader__.load({
817
853
  "split.hint": "glob 嘅絕對 pattern 自動拆做 path + 相對 pattern;關閉就原樣傳遞。",
818
854
  "code.label": "run_code 程式內路徑",
819
855
  "code.hint": "run_code 程式內寫的 /c/... 路徑字面量會在執行前按同一張掛載表翻譯;註解、插值模板、$VAR 與非路徑字串不動,掃描有任何不確定就整份不改。 並為程式補上 TEMP/TMP:空 env 下 Windows 的 os.tmpdir() 會得到 undefined\\temp,程式會靜默寫錯位置。",
856
+ "sub.label": "子代理/隊員用 Git Bash",
857
+ "sub.hint": "預設開啟:子代理同團隊隊員(連嵌套)嘅提示詞方言、路徑參數翻譯、結果回顯同 DSH_PATH_DIALECT 環境事實都同主代理一致。閂咗就淨係主代理有,子代理跟官方 shell 語義行(提示詞唔改寫、路徑參數唔翻譯);留意 dsh 每個進程只有一個 shell 執行器,所以 Git Bash 本身仍然係全局嘅,呢個開關管嘅係方言/翻譯層。",
820
858
  "eol.label": "Git 行尾(與 Linux 一致)",
821
859
  "eol.hint": "模型執行的 git 指令採 Linux 行為:core.autocrlf=input、core.eol=lf。你自己終端的 git 與倉庫的 .gitattributes 都不受影響。",
822
860
  "bash.label": "Git Bash 路徑",
@@ -857,6 +895,8 @@ window.__ModuleLoader__.load({
857
895
  "split.hint": "glob 嘅絕對 pattern 自動拆做 path + 相對 pattern;關閉就原樣傳遞。",
858
896
  "code.label": "run_code 程式內路徑",
859
897
  "code.hint": "run_code 程式內寫的 /c/... 路徑字面量會在執行前按同一張掛載表翻譯;註解、插值模板、$VAR 與非路徑字串不動,掃描有任何不確定就整份不改。 並為程式補上 TEMP/TMP:空 env 下 Windows 的 os.tmpdir() 會得到 undefined\\temp,程式會靜默寫錯位置。",
898
+ "sub.label": "子代理/隊員用 Git Bash",
899
+ "sub.hint": "預設開啟:子代理同團隊隊員(連嵌套)嘅提示詞方言、路徑參數翻譯、結果回顯同 DSH_PATH_DIALECT 環境事實都同主代理一致。閂咗就淨係主代理有,子代理跟官方 shell 語義行(提示詞唔改寫、路徑參數唔翻譯);留意 dsh 每個進程只有一個 shell 執行器,所以 Git Bash 本身仍然係全局嘅,呢個開關管嘅係方言/翻譯層。",
860
900
  "eol.label": "Git 行尾(與 Linux 一致)",
861
901
  "eol.hint": "模型執行的 git 指令採 Linux 行為:core.autocrlf=input、core.eol=lf。你自己終端的 git 與倉庫的 .gitattributes 都不受影響。",
862
902
  "bash.label": "Git Bash 路徑",
@@ -897,6 +937,8 @@ window.__ModuleLoader__.load({
897
937
  "split.hint": "glob 的絕對 pattern 自動拆為 path + 相對 pattern;關閉則原樣傳遞。",
898
938
  "code.label": "run_code 程式內路徑",
899
939
  "code.hint": "run_code 程式內寫的 /c/... 路徑字面量會在執行前按同一張掛載表翻譯;註解、插值模板、$VAR 與非路徑字串不動,掃描有任何不確定就整份不改。 並為程式補上 TEMP/TMP:空 env 下 Windows 的 os.tmpdir() 會得到 undefined\\temp,程式會靜默寫錯位置。",
940
+ "sub.label": "子代理/隊員使用 Git Bash",
941
+ "sub.hint": "預設開啟:子代理與團隊隊員(含巢狀)的提示詞方言、路徑參數翻譯、結果回顯與 DSH_PATH_DIALECT 環境事實都與主代理一致。關閉後僅對主代理生效,子代理依官方 shell 語意執行(提示詞不改寫、路徑參數不翻譯);請注意 dsh 每個行程只有一個 shell 執行器,因此 Git Bash 本身仍是全域的,這個開關管的是方言/翻譯層。",
900
942
  "eol.label": "Git 行尾(與 Linux 一致)",
901
943
  "eol.hint": "模型執行的 git 指令採 Linux 行為:core.autocrlf=input、core.eol=lf。你自己終端的 git 與倉庫的 .gitattributes 都不受影響。",
902
944
  "bash.label": "Git Bash 路徑",
@@ -1202,6 +1244,9 @@ window.__ModuleLoader__.load({
1202
1244
  var errs = snap.value.errorDialect !== false;
1203
1245
  var splits = snap.value.globSplit !== false;
1204
1246
  var codes = snap.value.codePaths !== false;
1247
+ // v0.27.0: delegated agents (subagents / team members / nested
1248
+ // children) participate in the dialect unless this is switched off.
1249
+ var subagents = snap.value.subagentDialect !== false;
1205
1250
  var eolOn = snap.value.gitAutocrlf !== false;
1206
1251
  var dedupe = snap.value.suppressPeerCordis === true;
1207
1252
 
@@ -1253,6 +1298,15 @@ window.__ModuleLoader__.load({
1253
1298
  E("button", { type: "button", className: "gb-segBtn" + (!codes ? " gb-segActive" : ""), onClick: function () { if (codes) writeField("codePaths", false); } }, t("switch.off")),
1254
1299
  ),
1255
1300
  E("p", { className: "gb-hint" }, t("code.hint")),
1301
+ E("div", { className: "gb-row" },
1302
+ E("span", { className: "gb-rowLabel" }, t("sub.label") + ":"),
1303
+ E("span", { className: "gb-rowValue" }, subagents ? t("state.on") : t("state.off")),
1304
+ ),
1305
+ E("div", { className: "gb-seg" },
1306
+ E("button", { type: "button", className: "gb-segBtn" + (subagents ? " gb-segActive" : ""), onClick: function () { if (!subagents) writeField("subagentDialect", true); } }, t("switch.on")),
1307
+ E("button", { type: "button", className: "gb-segBtn" + (!subagents ? " gb-segActive" : ""), onClick: function () { if (subagents) writeField("subagentDialect", false); } }, t("switch.off")),
1308
+ ),
1309
+ E("p", { className: "gb-hint" }, t("sub.hint")),
1256
1310
  E("div", { className: "gb-row" },
1257
1311
  E("span", { className: "gb-rowLabel" }, t("eol.label") + ":"),
1258
1312
  E("span", { className: "gb-rowValue" }, eolOn ? t("state.on") : t("state.off")),
package/src/index.js CHANGED
@@ -180,6 +180,51 @@ export function pythonBackendActive(capability) {
180
180
  return intent && reported === 'python'
181
181
  }
182
182
 
183
+ /**
184
+ * Is this agent a DELEGATED one — a subagent, a team member, or a nested child
185
+ * of either? The canonical in-tree signal is the session header pair dsh's own
186
+ * workspace-changes plugin uses
187
+ * (`packages/deliverables/workspace-changes/src/index.ts:59-60`), stamped when
188
+ * the subagent driver creates a child
189
+ * (`packages/subagent/subagent/src/child-agent.ts:139-155`):
190
+ * `origin === 'subagent'` or a non-zero `delegationDepth`.
191
+ *
192
+ * Unknown shapes read as NOT delegated: applying the dialect is the helpful
193
+ * direction, and a diagnostic assembly without an agent must keep it.
194
+ * @param {object|undefined} agent - the assembling/executing agent, when known.
195
+ * @returns {boolean} true only when the agent is provably delegated.
196
+ */
197
+ export function isDelegatedAgent(agent) {
198
+ try {
199
+ const header = agent && agent.session ? agent.session.header : undefined
200
+ if (header === null || typeof header !== 'object') return false
201
+ if (header.origin === 'subagent') return true
202
+ return typeof header.delegationDepth === 'number' && header.delegationDepth > 0
203
+ } catch {
204
+ return false
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Does the Git Bash dialect apply to THIS agent (v0.27.0)? The row switch
210
+ * `subagentDialect` (default ON) decides whether delegated agents — subagents,
211
+ * team members, nested children — participate in the dialect at all; the main
212
+ * agent always does. A closed function so every consumer (prompt assembly,
213
+ * dispatch translation, result echo, failure text, the shell-env fact) answers
214
+ * the same way.
215
+ *
216
+ * Note the honest bound: dsh has exactly ONE shell provider per process, so
217
+ * the executor binary stays Git Bash for every agent; this gate governs the
218
+ * dialect/translation layers that this plugin owns.
219
+ * @param {object} dialect - the live dialect switches.
220
+ * @param {object|undefined} agent - the agent that owns this assembly/execution.
221
+ * @returns {boolean} true when the dialect applies to this agent.
222
+ */
223
+ export function dialectApplies(dialect, agent) {
224
+ if (!dialect || dialect.subagentDialect !== false) return true
225
+ return !isDelegatedAgent(agent)
226
+ }
227
+
183
228
  /**
184
229
  * The roster this plugin serves: the configured list, minus the variant a peer
185
230
  * already covers. Two independent facts must BOTH hold before anything is
@@ -823,6 +868,15 @@ export const Config = Schema === null ? undefined : Schema.object({
823
868
  globSplit: live(Schema.boolean().default(true)),
824
869
  errorDialect: live(Schema.boolean().default(true)),
825
870
  codePaths: live(Schema.boolean().default(true)),
871
+ /**
872
+ * Whether DELEGATED agents (subagents, team members, nested children) also
873
+ * use the Git Bash dialect (v0.27.0). Default ON — the historical behavior;
874
+ * OFF keeps the dialect to the main agent, so a delegated request carries the
875
+ * official shell semantics (no prompt rewrite, no path-argument translation,
876
+ * no echo rewrite, no DSH_PATH_DIALECT fact). The executor itself is one
877
+ * per-process provider, so Git Bash stays the binary either way.
878
+ */
879
+ subagentDialect: live(Schema.boolean().default(true)),
826
880
  gitAutocrlf: live(Schema.boolean().default(true)),
827
881
  bashPath: live(Schema.string().default('')),
828
882
  adoptSidebar: live(Schema.boolean().default(true)),
@@ -869,6 +923,8 @@ function makeLiveReader(ctx, config) {
869
923
  errorDialect: valueOf(config.errorDialect) === true,
870
924
  codePaths: valueOf(config.codePaths) === true,
871
925
  gitAutocrlf: valueOf(config.gitAutocrlf) === true,
926
+ // Default ON: delegated agents keep the dialect unless the user opts out.
927
+ subagentDialect: valueOf(config.subagentDialect) !== false,
872
928
  bashPath: typeof bash === 'string' ? bash : '',
873
929
  adoptSidebar: valueOf(config.adoptSidebar) !== false,
874
930
  }
@@ -943,7 +999,7 @@ export function readPosixPaths(ctxLike) {
943
999
  * first. All default ON (schema defaults); never throws.
944
1000
  */
945
1001
  export function readDialectSettings(ctxLike) {
946
- const fallback = { posixPaths: false, virtualMounts: false, globSplit: false, errorDialect: false, codePaths: false, gitAutocrlf: false, bashPath: '' }
1002
+ const fallback = { posixPaths: false, virtualMounts: false, globSplit: false, errorDialect: false, codePaths: false, gitAutocrlf: false, bashPath: '', subagentDialect: true }
947
1003
  try {
948
1004
  const settings = ctxLike && typeof ctxLike.get === 'function' ? ctxLike.get('settings') : undefined
949
1005
  const value = settings && typeof settings.get === 'function' ? settings.get(SETTINGS_NAMESPACE) : undefined
@@ -954,6 +1010,8 @@ export function readDialectSettings(ctxLike) {
954
1010
  globSplit: v.globSplit === true,
955
1011
  errorDialect: v.errorDialect === true,
956
1012
  codePaths: v.codePaths === true,
1013
+ // An old host without the key keeps the default (delegated agents covered).
1014
+ subagentDialect: v.subagentDialect !== false,
957
1015
  gitAutocrlf: v.gitAutocrlf === true,
958
1016
  bashPath: typeof v.bashPath === 'string' ? v.bashPath : '',
959
1017
  }
@@ -2336,6 +2394,7 @@ export async function apply(ctx, config = {}) {
2336
2394
  globSplit: Schema.boolean().default(true),
2337
2395
  errorDialect: Schema.boolean().default(true),
2338
2396
  codePaths: Schema.boolean().default(true),
2397
+ subagentDialect: Schema.boolean().default(true),
2339
2398
  gitAutocrlf: Schema.boolean().default(true),
2340
2399
  bashPath: Schema.string().default(''),
2341
2400
  adoptSidebar: Schema.boolean().default(true),
@@ -2391,8 +2450,17 @@ export async function apply(ctx, config = {}) {
2391
2450
  // git line endings and anything else non-DSH_* ride the executor's
2392
2451
  // own env layer (src/shell.js), not this registry.
2393
2452
  variables: { [PATH_DIALECT_KEY]: { description: PATH_DIALECT_DESCRIPTION } },
2394
- resolve() {
2395
- return liveSettings.posix() ? { [PATH_DIALECT_KEY]: PATH_DIALECT_VALUE } : {}
2453
+ resolve(execution) {
2454
+ try {
2455
+ const dialect = liveSettings.dialect()
2456
+ if (dialect.posixPaths !== true) return {}
2457
+ // The environment fact is per execution, so a delegated agent
2458
+ // the user excluded sees no DSH_PATH_DIALECT at all.
2459
+ if (!dialectApplies(dialect, execution && execution.agent)) return {}
2460
+ return { [PATH_DIALECT_KEY]: PATH_DIALECT_VALUE }
2461
+ } catch {
2462
+ return {}
2463
+ }
2396
2464
  },
2397
2465
  })
2398
2466
  envCtx.effect(() => unregister, 'dsh-gitbash-shell: shellEnv path-dialect fact')
@@ -2418,9 +2486,16 @@ export async function apply(ctx, config = {}) {
2418
2486
  // could corrupt pattern/default fields).
2419
2487
  if (process.platform === 'win32') {
2420
2488
  try {
2421
- ctx.on('system-prompt/assemble', (assembly, _assembleContext, next) => {
2489
+ ctx.on('system-prompt/assemble', (assembly, assembleContext, next) => {
2422
2490
  try {
2423
- if (liveSettings.posix() && assembly && typeof assembly === 'object') {
2491
+ /* v0.27.0: the main agent always participates; a DELEGATED agent
2492
+ (subagent / team member / nested child) only while the
2493
+ `subagentDialect` switch is on. Turning it off leaves the official
2494
+ prompt text untouched for those agents — no source replacement and
2495
+ no run_code hint — so they meet the shell they were composed for. */
2496
+ const dialect = liveSettings.dialect()
2497
+ const applies = dialectApplies(dialect, assembleContext && assembleContext.agent)
2498
+ if (applies && dialect.posixPaths === true && assembly && typeof assembly === 'object') {
2424
2499
  for (const section of Array.isArray(assembly.sections) ? assembly.sections : []) {
2425
2500
  if (section && typeof section.text === 'string') section.text = windowsToMsys(section.text)
2426
2501
  }
@@ -2491,7 +2566,10 @@ export async function apply(ctx, config = {}) {
2491
2566
  // `bash.workdir` went through raw, and an in-workspace `/c/...` write
2492
2567
  // fell outside the sandbox. One missed call site, five symptoms.
2493
2568
  const dialect = liveSettings.dialect()
2494
- if (dialect.posixPaths) {
2569
+ // v0.27.0: a delegated agent the user excluded keeps the official
2570
+ // semantics for BOTH faces of its calls — arguments go through
2571
+ // untouched and the result metadata is not echoed back in MSYS form.
2572
+ if (dialect.posixPaths && dialectApplies(dialect, exec && exec.agent)) {
2495
2573
  echo = true
2496
2574
  const env = dialect.virtualMounts ? buildTranslateEnv(dialect.bashPath) : null
2497
2575
  echoEnv = env
@@ -2542,6 +2620,10 @@ export async function apply(ctx, config = {}) {
2542
2620
  let contentPatch
2543
2621
  try {
2544
2622
  const dialect = liveSettings.dialect()
2623
+ // Same agent gate as the dispatch wrapper: one call, one dialect.
2624
+ // RETURN the downstream promise: a waterfall listener that swallows
2625
+ // it would hand the caller `undefined` instead of the decision.
2626
+ if (!dialectApplies(dialect, exec && exec.agent)) return next()
2545
2627
  if (dialect.posixPaths && dialect.errorDialect && exec && result && typeof result === 'object'
2546
2628
  && result.isError === true && Array.isArray(result.content)) {
2547
2629
  const env = dialect.virtualMounts ? buildTranslateEnv(dialect.bashPath) : null
@@ -2588,10 +2670,14 @@ export async function apply(ctx, config = {}) {
2588
2670
  pctx.effect(() => pctx.systemPrompt.context({
2589
2671
  name: 'gitbash-shell:posix-paths',
2590
2672
  order: 126,
2591
- text: () => {
2673
+ text: (assembleContext) => {
2592
2674
  try {
2593
2675
  const dialect = liveSettings.dialect()
2594
2676
  if (dialect.posixPaths !== true) return ''
2677
+ // A delegated agent whose dialect the user turned off meets the
2678
+ // official shell semantics: no directive, the same way no
2679
+ // translation happens for its calls.
2680
+ if (!dialectApplies(dialect, assembleContext && assembleContext.agent)) return ''
2595
2681
  return dialect.virtualMounts === false ? POSIX_DIRECTIVE_TEXT_STRICT : POSIX_DIRECTIVE_TEXT
2596
2682
  } catch {
2597
2683
  return ''
@@ -2717,4 +2803,4 @@ export async function apply(ctx, config = {}) {
2717
2803
  }
2718
2804
 
2719
2805
  // Test surface: pure helpers, no Cordis context required.
2720
- export const _internal = { PRESET_IDS, PEER_COVERED_PRESET_ID, PEER_CAPABILITY, PEER_PYTHON_FIELD, PEER_PYTHON_BACKEND_FIELD, peerFact, peerBackend, pythonBackendActive, effectivePresetIds, detectPeerCoverage, readSuppressPeerCordis, translateDispatch, translateMsysPath, translatePathArguments, rewriteCodePaths, scanCodeLiterals, programPrelude, translateGlobArguments, buildTranslateEnv, rewriteErrorContent, rewriteErrorMessage, rewriteFailureMessage, msysEcho, driveToMsys, pathEcho, ERROR_CONTENT_TOOLS, readPosixPaths, readAdoptSidebar, readDialectSettings, windowsToMsys, rewriteResultPaths, adoptSidebarShell, MARKER_FILE, classify, materialize, cleanupOnDispose, firstUserRoot, hashTree, skillsHashes, syncDecision, installRegisterShim, baseForRoster, detectBase, pickComposition, personaEraForText, detectPersonaEra, injectPresentRow, hostHasToolPresent, detectPresentSupport, injectPluginManagerRow, hostHasPluginManagerTools, rowFormOf, rowFormsOf, alignEngineRow, alignRalphRow, ROW_SOURCE }
2806
+ export const _internal = { PRESET_IDS, PEER_COVERED_PRESET_ID, PEER_CAPABILITY, isDelegatedAgent, dialectApplies, PEER_PYTHON_FIELD, PEER_PYTHON_BACKEND_FIELD, peerFact, peerBackend, pythonBackendActive, effectivePresetIds, detectPeerCoverage, readSuppressPeerCordis, translateDispatch, translateMsysPath, translatePathArguments, rewriteCodePaths, scanCodeLiterals, programPrelude, translateGlobArguments, buildTranslateEnv, rewriteErrorContent, rewriteErrorMessage, rewriteFailureMessage, msysEcho, driveToMsys, pathEcho, ERROR_CONTENT_TOOLS, readPosixPaths, readAdoptSidebar, readDialectSettings, windowsToMsys, rewriteResultPaths, adoptSidebarShell, MARKER_FILE, classify, materialize, cleanupOnDispose, firstUserRoot, hashTree, skillsHashes, syncDecision, installRegisterShim, baseForRoster, detectBase, pickComposition, personaEraForText, detectPersonaEra, injectPresentRow, hostHasToolPresent, detectPresentSupport, injectPluginManagerRow, hostHasPluginManagerTools, rowFormOf, rowFormsOf, alignEngineRow, alignRalphRow, ROW_SOURCE }