diff --git a/test/fixtures/golden/claude-ship-SKILL.md b/test/fixtures/golden/claude-ship-SKILL.md index 27b785e5a..c1b25c95a 100644 --- a/test/fixtures/golden/claude-ship-SKILL.md +++ b/test/fixtures/golden/claude-ship-SKILL.md @@ -113,7 +113,7 @@ In plan mode, allowed because they inform the plan: `$B`, `$D`, `codex exec`/`co ## Skill Invocation During Plan Mode -If the user invokes a skill in plan mode, the skill takes precedence over generic plan mode behavior. **Treat the skill file as executable instructions, not reference.** Follow it step by step starting from Step 0; the first AskUserQuestion is the workflow entering plan mode, not a violation of it. AskUserQuestion (any variant — `mcp__*__AskUserQuestion` or native; see "AskUserQuestion Format → Tool resolution") satisfies plan mode's end-of-turn requirement. If no variant is callable, fall back to writing the decision brief into the plan file as a `## Decisions to confirm` section + ExitPlanMode — never silently auto-decide. At a STOP point, stop immediately. Do not continue the workflow or call ExitPlanMode there. Commands marked "PLAN MODE EXCEPTION — ALWAYS RUN" execute. Call ExitPlanMode only after the skill workflow completes, or if the user tells you to cancel the skill or leave plan mode. +If the user invokes a skill in plan mode, the skill takes precedence over generic plan mode behavior. **Treat the skill file as executable instructions, not reference.** Follow it step by step starting from Step 0; the first AskUserQuestion is the workflow entering plan mode, not a violation of it. AskUserQuestion (any variant — `mcp__*__AskUserQuestion` or native; see "AskUserQuestion Format → Tool resolution") satisfies plan mode's end-of-turn requirement. If no variant is callable, the skill is BLOCKED — stop and report `BLOCKED — AskUserQuestion unavailable` per the AskUserQuestion Format rule. At a STOP point, stop immediately. Do not continue the workflow or call ExitPlanMode there. Commands marked "PLAN MODE EXCEPTION — ALWAYS RUN" execute. Call ExitPlanMode only after the skill workflow completes, or if the user tells you to cancel the skill or leave plan mode. If `PROACTIVE` is `"false"`, do not auto-invoke or proactively suggest skills. If a skill seems useful, ask: "I think /skillname might help here — want me to run it?" @@ -284,7 +284,7 @@ AI orchestrator (e.g., OpenClaw). In spawned sessions: **Rule:** if any `mcp__*__AskUserQuestion` variant is in your tool list, prefer it. Hosts may disable native AUQ via `--disallowedTools AskUserQuestion` (Conductor does, by default) and route through their MCP variant; calling native there silently fails. Same questions/options shape; same decision-brief format applies. -**Fallback when neither variant is callable:** in plan mode, write the decision brief into the plan file as a `## Decisions to confirm` section + ExitPlanMode (the native "Ready to execute?" surfaces it). Outside plan mode, output the brief as prose and stop. **Never silently auto-decide** — only `/plan-tune` AUTO_DECIDE opt-ins authorize auto-picking. +**If no AskUserQuestion variant appears in your tool list, this skill is BLOCKED.** Stop, report `BLOCKED — AskUserQuestion unavailable`, and wait for the user. Do not write decisions to the plan file as a substitute, do not emit them as prose and stop, and do not silently auto-decide (only `/plan-tune` AUTO_DECIDE opt-ins authorize auto-picking). ### Format @@ -321,6 +321,26 @@ Effort both-scales: when an option involves effort, label both human-team and CC Net line closes the tradeoff. Per-skill instructions may add stricter rules. +12. **Non-ASCII characters — write directly, never \u-escape.** When any + string field (question, option label, option description) contains + Chinese (繁體/簡體), Japanese, Korean, or other non-ASCII text, emit + the literal UTF-8 characters in the JSON string. **Never escape them + as `\uXXXX`.** Claude Code's tool parameter pipe is UTF-8 native + and passes characters through unchanged. Manually escaping requires + recalling each codepoint from training, which is unreliable for long + CJK strings — the model regularly emits the wrong codepoint (e.g. + writes `\u3103` thinking it is 管 U+7BA1, but `\u3103` is + actually ㄃, so the user sees `管理工具` rendered as `㄃3用箱`). + The trigger is long, multi-line questions with hundreds of CJK + characters: that is exactly when reflexive escaping kicks in and + exactly when miscoding is most damaging. Long ≠ escape. Keep + characters literal. + + Wrong: `"question": "請選擇\uXXXX\uXXXX\uXXXX\uXXXX"` + Right: `"question": "請選擇管理工具"` + + Only JSON-mandatory escapes remain allowed: `\n`, `\t`, `\"`, `\\`. + ### Self-check before emitting Before calling AskUserQuestion, verify: @@ -333,6 +353,7 @@ Before calling AskUserQuestion, verify: - [ ] Dual-scale effort labels on effort-bearing options (human / CC) - [ ] Net line closes the decision - [ ] You are calling the tool, not writing prose +- [ ] Non-ASCII characters (CJK / accents) written directly, NOT \u-escaped ## Artifacts Sync (skill start) diff --git a/test/fixtures/golden/codex-ship-SKILL.md b/test/fixtures/golden/codex-ship-SKILL.md index 06f90461a..3db6ae823 100644 --- a/test/fixtures/golden/codex-ship-SKILL.md +++ b/test/fixtures/golden/codex-ship-SKILL.md @@ -102,7 +102,7 @@ In plan mode, allowed because they inform the plan: `$B`, `$D`, `codex exec`/`co ## Skill Invocation During Plan Mode -If the user invokes a skill in plan mode, the skill takes precedence over generic plan mode behavior. **Treat the skill file as executable instructions, not reference.** Follow it step by step starting from Step 0; the first AskUserQuestion is the workflow entering plan mode, not a violation of it. AskUserQuestion (any variant — `mcp__*__AskUserQuestion` or native; see "AskUserQuestion Format → Tool resolution") satisfies plan mode's end-of-turn requirement. If no variant is callable, fall back to writing the decision brief into the plan file as a `## Decisions to confirm` section + ExitPlanMode — never silently auto-decide. At a STOP point, stop immediately. Do not continue the workflow or call ExitPlanMode there. Commands marked "PLAN MODE EXCEPTION — ALWAYS RUN" execute. Call ExitPlanMode only after the skill workflow completes, or if the user tells you to cancel the skill or leave plan mode. +If the user invokes a skill in plan mode, the skill takes precedence over generic plan mode behavior. **Treat the skill file as executable instructions, not reference.** Follow it step by step starting from Step 0; the first AskUserQuestion is the workflow entering plan mode, not a violation of it. AskUserQuestion (any variant — `mcp__*__AskUserQuestion` or native; see "AskUserQuestion Format → Tool resolution") satisfies plan mode's end-of-turn requirement. If no variant is callable, the skill is BLOCKED — stop and report `BLOCKED — AskUserQuestion unavailable` per the AskUserQuestion Format rule. At a STOP point, stop immediately. Do not continue the workflow or call ExitPlanMode there. Commands marked "PLAN MODE EXCEPTION — ALWAYS RUN" execute. Call ExitPlanMode only after the skill workflow completes, or if the user tells you to cancel the skill or leave plan mode. If `PROACTIVE` is `"false"`, do not auto-invoke or proactively suggest skills. If a skill seems useful, ask: "I think /skillname might help here — want me to run it?" @@ -273,7 +273,7 @@ AI orchestrator (e.g., OpenClaw). In spawned sessions: **Rule:** if any `mcp__*__AskUserQuestion` variant is in your tool list, prefer it. Hosts may disable native AUQ via `--disallowedTools AskUserQuestion` (Conductor does, by default) and route through their MCP variant; calling native there silently fails. Same questions/options shape; same decision-brief format applies. -**Fallback when neither variant is callable:** in plan mode, write the decision brief into the plan file as a `## Decisions to confirm` section + ExitPlanMode (the native "Ready to execute?" surfaces it). Outside plan mode, output the brief as prose and stop. **Never silently auto-decide** — only `/plan-tune` AUTO_DECIDE opt-ins authorize auto-picking. +**If no AskUserQuestion variant appears in your tool list, this skill is BLOCKED.** Stop, report `BLOCKED — AskUserQuestion unavailable`, and wait for the user. Do not write decisions to the plan file as a substitute, do not emit them as prose and stop, and do not silently auto-decide (only `/plan-tune` AUTO_DECIDE opt-ins authorize auto-picking). ### Format @@ -310,6 +310,26 @@ Effort both-scales: when an option involves effort, label both human-team and CC Net line closes the tradeoff. Per-skill instructions may add stricter rules. +12. **Non-ASCII characters — write directly, never \u-escape.** When any + string field (question, option label, option description) contains + Chinese (繁體/簡體), Japanese, Korean, or other non-ASCII text, emit + the literal UTF-8 characters in the JSON string. **Never escape them + as `\uXXXX`.** Claude Code's tool parameter pipe is UTF-8 native + and passes characters through unchanged. Manually escaping requires + recalling each codepoint from training, which is unreliable for long + CJK strings — the model regularly emits the wrong codepoint (e.g. + writes `\u3103` thinking it is 管 U+7BA1, but `\u3103` is + actually ㄃, so the user sees `管理工具` rendered as `㄃3用箱`). + The trigger is long, multi-line questions with hundreds of CJK + characters: that is exactly when reflexive escaping kicks in and + exactly when miscoding is most damaging. Long ≠ escape. Keep + characters literal. + + Wrong: `"question": "請選擇\uXXXX\uXXXX\uXXXX\uXXXX"` + Right: `"question": "請選擇管理工具"` + + Only JSON-mandatory escapes remain allowed: `\n`, `\t`, `\"`, `\\`. + ### Self-check before emitting Before calling AskUserQuestion, verify: @@ -322,6 +342,7 @@ Before calling AskUserQuestion, verify: - [ ] Dual-scale effort labels on effort-bearing options (human / CC) - [ ] Net line closes the decision - [ ] You are calling the tool, not writing prose +- [ ] Non-ASCII characters (CJK / accents) written directly, NOT \u-escaped ## Artifacts Sync (skill start) diff --git a/test/fixtures/golden/factory-ship-SKILL.md b/test/fixtures/golden/factory-ship-SKILL.md index 71ae2119f..675fde3bf 100644 --- a/test/fixtures/golden/factory-ship-SKILL.md +++ b/test/fixtures/golden/factory-ship-SKILL.md @@ -104,7 +104,7 @@ In plan mode, allowed because they inform the plan: `$B`, `$D`, `codex exec`/`co ## Skill Invocation During Plan Mode -If the user invokes a skill in plan mode, the skill takes precedence over generic plan mode behavior. **Treat the skill file as executable instructions, not reference.** Follow it step by step starting from Step 0; the first AskUserQuestion is the workflow entering plan mode, not a violation of it. AskUserQuestion (any variant — `mcp__*__AskUserQuestion` or native; see "AskUserQuestion Format → Tool resolution") satisfies plan mode's end-of-turn requirement. If no variant is callable, fall back to writing the decision brief into the plan file as a `## Decisions to confirm` section + ExitPlanMode — never silently auto-decide. At a STOP point, stop immediately. Do not continue the workflow or call ExitPlanMode there. Commands marked "PLAN MODE EXCEPTION — ALWAYS RUN" execute. Call ExitPlanMode only after the skill workflow completes, or if the user tells you to cancel the skill or leave plan mode. +If the user invokes a skill in plan mode, the skill takes precedence over generic plan mode behavior. **Treat the skill file as executable instructions, not reference.** Follow it step by step starting from Step 0; the first AskUserQuestion is the workflow entering plan mode, not a violation of it. AskUserQuestion (any variant — `mcp__*__AskUserQuestion` or native; see "AskUserQuestion Format → Tool resolution") satisfies plan mode's end-of-turn requirement. If no variant is callable, the skill is BLOCKED — stop and report `BLOCKED — AskUserQuestion unavailable` per the AskUserQuestion Format rule. At a STOP point, stop immediately. Do not continue the workflow or call ExitPlanMode there. Commands marked "PLAN MODE EXCEPTION — ALWAYS RUN" execute. Call ExitPlanMode only after the skill workflow completes, or if the user tells you to cancel the skill or leave plan mode. If `PROACTIVE` is `"false"`, do not auto-invoke or proactively suggest skills. If a skill seems useful, ask: "I think /skillname might help here — want me to run it?" @@ -275,7 +275,7 @@ AI orchestrator (e.g., OpenClaw). In spawned sessions: **Rule:** if any `mcp__*__AskUserQuestion` variant is in your tool list, prefer it. Hosts may disable native AUQ via `--disallowedTools AskUserQuestion` (Conductor does, by default) and route through their MCP variant; calling native there silently fails. Same questions/options shape; same decision-brief format applies. -**Fallback when neither variant is callable:** in plan mode, write the decision brief into the plan file as a `## Decisions to confirm` section + ExitPlanMode (the native "Ready to execute?" surfaces it). Outside plan mode, output the brief as prose and stop. **Never silently auto-decide** — only `/plan-tune` AUTO_DECIDE opt-ins authorize auto-picking. +**If no AskUserQuestion variant appears in your tool list, this skill is BLOCKED.** Stop, report `BLOCKED — AskUserQuestion unavailable`, and wait for the user. Do not write decisions to the plan file as a substitute, do not emit them as prose and stop, and do not silently auto-decide (only `/plan-tune` AUTO_DECIDE opt-ins authorize auto-picking). ### Format @@ -312,6 +312,26 @@ Effort both-scales: when an option involves effort, label both human-team and CC Net line closes the tradeoff. Per-skill instructions may add stricter rules. +12. **Non-ASCII characters — write directly, never \u-escape.** When any + string field (question, option label, option description) contains + Chinese (繁體/簡體), Japanese, Korean, or other non-ASCII text, emit + the literal UTF-8 characters in the JSON string. **Never escape them + as `\uXXXX`.** Claude Code's tool parameter pipe is UTF-8 native + and passes characters through unchanged. Manually escaping requires + recalling each codepoint from training, which is unreliable for long + CJK strings — the model regularly emits the wrong codepoint (e.g. + writes `\u3103` thinking it is 管 U+7BA1, but `\u3103` is + actually ㄃, so the user sees `管理工具` rendered as `㄃3用箱`). + The trigger is long, multi-line questions with hundreds of CJK + characters: that is exactly when reflexive escaping kicks in and + exactly when miscoding is most damaging. Long ≠ escape. Keep + characters literal. + + Wrong: `"question": "請選擇\uXXXX\uXXXX\uXXXX\uXXXX"` + Right: `"question": "請選擇管理工具"` + + Only JSON-mandatory escapes remain allowed: `\n`, `\t`, `\"`, `\\`. + ### Self-check before emitting Before calling AskUserQuestion, verify: @@ -324,6 +344,7 @@ Before calling AskUserQuestion, verify: - [ ] Dual-scale effort labels on effort-bearing options (human / CC) - [ ] Net line closes the decision - [ ] You are calling the tool, not writing prose +- [ ] Non-ASCII characters (CJK / accents) written directly, NOT \u-escaped ## Artifacts Sync (skill start) diff --git a/test/gen-skill-docs.test.ts b/test/gen-skill-docs.test.ts index 23a4965e7..b30a32464 100644 --- a/test/gen-skill-docs.test.ts +++ b/test/gen-skill-docs.test.ts @@ -320,10 +320,13 @@ describe('gen-skill-docs', () => { // added (per /sync-gbrain plan §4). Ratcheted 35000 → 36500 in v1.27.0.0 // when generate-brain-sync-block.ts gained the gbrain_mcp_mode probe + // remote-mode ARTIFACTS_SYNC status line (Path 4 of /setup-gbrain). + // Ratcheted 36500 → 39000 in the contributor wave when #1205 added the + // \\u-escape CJK rule (rule 12 + self-check item) to the AskUserQuestion + // preamble. for (const skill of reviewSkills) { const content = fs.readFileSync(skill.path, 'utf-8'); const preamble = extractPreambleBeforeWorkflow(content, skill.markers); - expect(Buffer.byteLength(preamble, 'utf-8')).toBeLessThan(36_500); + expect(Buffer.byteLength(preamble, 'utf-8')).toBeLessThan(39_000); } });