Skip to content

script eval quoting: agents write \" inside single-quoted expressions — improve skill guidance and consider auto-fixing #50

Description

@Niaobu

Problem

A recurring script eval failure mode: the C# expression is correctly wrapped in single quotes for the shell, but inner double quotes get written as \" — the escaping rule for double-quoted shell strings. Inside single quotes the backslash passes through literally, so the compiler receives \" and fails:

unityctl script eval 'return $"spawn0={(SpawnPoints.Count > 0 ? SpawnPoints[0].position.ToString() : \"none\")}";'
(13,..): error CS1039: Unterminated string literal
(13,..): error CS1073: Unexpected token '\'
(13,..): error CS1056: Unexpected character '\'

The trigger is almost always the same idiom: a $"key={value} ..." status/debug string that needs a nested quoted literal (\"none\", GetFloat(\"Speed\")). Self-repair tends to stay inside the broken frame (e.g. retrying with @\"...\" — still mangled); recovery usually means falling back to writing a temp .cs file and script execute, costing a couple of round-trips per incident.

The skill currently doesn't address this: the Script Execution section shows single-quoted examples but never states the bare-quotes rule, and the eval→file escalation criterion ("for complex scripts") is too vague to fire before the failure happens.

Proposed skill changes (UnityCtl.Cli/Resources/SKILL.md, Script Execution section)

1. Prefer structured returns over interpolated strings — removes the need for nested quotes entirely, and gives structured output for free. This single pattern would prevent nearly all instances:

# Instead of: return $"scene={s.name} bots={bots.Length} target=\"{t.name}\"";
unityctl script eval 'var s = SceneManager.GetActiveScene(); return new { scene = s.name, bots = bots.Length, target = t?.name };'

2. Explicit anti-pattern callout with a wrong/right pair (examples teach better than prose):

unityctl script eval 'return t != null ? t.name : \"none\";'   # WRONG — \" inside single quotes breaks compilation
unityctl script eval 'return t != null ? t.name : "none";'     # RIGHT — write quotes bare

3. Crisper escalation rule: if the expression contains a string inside an interpolated string, an apostrophe, or more than ~2 statements, switch to Write-tool + script execute <file>.cs before attempting inline eval.

4. Document stdinscript eval/script execute already read from stdin when input is redirected, but it's only discoverable via an error message.

Optional tool-side companion

There's precedent for repairing shell mangling in the CLI (the MINGW !\! fix in ScriptCommands.cs). Same spirit here: when eval compilation fails with Unexpected character '\' and the source contains \", retry once with \"" substituted; if that compiles, run it and append a note about the auto-fix. That converts the entire failure class into a non-event regardless of guidance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions