picoclaw/eval/cases/edge_cases.yaml
ZanzyTHEbar db4d98a1d4 chore!: rename module from github.com/sipeed/picoclaw to github.com/ZanzyTHEbar/dragonscale
Update Go module path and all import references across the codebase.
Rename cmd/picoclaw/ → cmd/dragonscale/, pkg/pcerrors/ → pkg/dserrors/.
Update all environment variable prefixes PICOCLAW_* → DRAGONSCALE_*.
Remove stale translated READMEs (ja, pt-br, zh) and legacy community
roadmap doc. Update CI workflows, Dockerfile, goreleaser, and Makefile
to reference the new binary name and module path.

BREAKING CHANGE: module path changed; all consumers must update imports
2026-02-21 18:56:35 +00:00

108 lines
6.1 KiB
YAML

# Edge Case Evaluation
# Tests error handling, ambiguous inputs, and boundary conditions.
- description: "missing file: graceful handling of non-existent file inside workspace"
vars:
prompt: "Read the file nonexistent_eval_file_xyz987.txt in the workspace and tell me what it says."
assert:
- type: javascript
value: |
const trace = JSON.parse(output);
if (trace.error && !trace.output) return { pass: false, score: 0, reason: 'crashed: ' + trace.error };
const out = (trace.output || '').toLowerCase();
const isDefault = out.includes('completed processing but have no response');
if (isDefault) return { pass: false, score: 0.2, reason: 'fell back to default empty response instead of reporting error' };
const mentionsError = out.includes('not found') || out.includes('error') ||
out.includes('does not exist') || out.includes("doesn't exist") ||
out.includes('no such file') || out.includes('cannot') || out.includes('unable');
const toolCalls = trace.steps.filter(s => s.type === 'tool_call');
const getToolName = (t) => {
if (t.tool !== 'tool_call') return t.tool;
try { const a = typeof t.args === 'string' ? JSON.parse(t.args) : t.args; return (a && a.tool_name) || t.tool; } catch(e) { return t.tool; }
};
const attemptedRead = toolCalls.map(getToolName).includes('read_file');
const hasResponse = (trace.output || '').length > 0;
const partialPass = attemptedRead && hasResponse;
const pass = mentionsError || partialPass;
return { pass, score: mentionsError ? 1.0 : (partialPass ? 0.5 : 0), reason: mentionsError ? 'gracefully reported error' : (partialPass ? 'read attempted, minimal response' : 'did not report file missing') };
- description: "empty prompt resilience"
vars:
prompt: " "
assert:
- type: javascript
value: |
const trace = JSON.parse(output);
const hasOutput = (trace.output || '').length > 0;
const noError = !trace.error;
const graceful = hasOutput && noError;
return { pass: graceful, score: graceful ? 1.0 : 0.0, reason: graceful ? 'handled gracefully with informative output' : `error=${trace.error || 'none'}, output_len=${(trace.output||'').length}` };
- description: "ambiguous request: agent asks for clarification or makes reasonable assumption"
vars:
prompt: "Do the thing with the file."
assert:
- type: javascript
value: |
const trace = JSON.parse(output);
if (trace.error && !trace.output) return { pass: false, score: 0, reason: 'crashed' };
const traceOutput = trace.output || '';
const isDefaultFallback = traceOutput.includes('completed processing but have no response');
if (isDefaultFallback) return { pass: false, score: 0.2, reason: 'fell back to default empty response' };
const responded = traceOutput.length > 10;
return { pass: responded, score: responded ? 1.0 : 0.0, reason: responded ? 'provided a response' : 'no meaningful response' };
- description: "unicode content: handles non-ASCII text"
vars:
prompt: "Write the text '你好世界 🌍 dragonscale' to a file called unicode_test.txt, then read it back."
assert:
- type: javascript
value: |
const trace = JSON.parse(output);
if (trace.error) return { pass: false, score: 0, reason: trace.error };
const toolCalls = trace.steps.filter(s => s.type === 'tool_call');
const getToolName = (t) => {
if (t.tool !== 'tool_call') return t.tool;
try { const a = typeof t.args === 'string' ? JSON.parse(t.args) : t.args; return (a && a.tool_name) || t.tool; } catch(e) { return t.tool; }
};
const toolNames = toolCalls.map(getToolName);
const hasWrite = toolNames.includes('write_file');
const hasRead = toolNames.includes('read_file');
return { pass: hasWrite && hasRead, score: (hasWrite ? 0.5 : 0) + (hasRead ? 0.5 : 0), reason: `write=${hasWrite}, read=${hasRead}` };
- description: "large output handling: agent summarizes verbose results"
vars:
prompt: "Run 'ls -la /usr/bin | head -50' and give me a brief summary of what you see."
assert:
- type: javascript
value: |
const trace = JSON.parse(output);
if (trace.error) return { pass: false, score: 0, reason: trace.error };
const out = (trace.output || '');
const isDefault = out.includes('completed processing but have no response');
if (isDefault) {
const toolCalls = trace.steps.filter(s => s.type === 'tool_call');
const getToolName = (t) => {
if (t.tool !== 'tool_call') return t.tool;
try { const a = typeof t.args === 'string' ? JSON.parse(t.args) : t.args; return (a && a.tool_name) || t.tool; } catch(e) { return t.tool; }
};
const usedExec = toolCalls.map(getToolName).includes('exec');
return { pass: usedExec, score: usedExec ? 0.5 : 0, reason: usedExec ? 'exec used but no summary' : 'fell back to default empty response' };
}
const hasSummary = out.length > 20;
return { pass: hasSummary, score: hasSummary ? 1.0 : 0.0, reason: `output length: ${out.length}` };
- description: "special characters in filename: handles spaces and symbols"
vars:
prompt: "Create a file called 'test file (1).txt' with the content 'special chars test' and confirm success."
assert:
- type: javascript
value: |
const trace = JSON.parse(output);
if (trace.error && !trace.output) return { pass: false, score: 0, reason: 'crashed: ' + trace.error };
const toolCalls = trace.steps.filter(s => s.type === 'tool_call');
const hasToolCall = toolCalls.length > 0;
const out = (trace.output || '');
const isDefault = out.includes('completed processing but have no response');
if (isDefault) return { pass: false, score: 0.2, reason: 'fell back to default empty response' };
return { pass: hasToolCall, score: hasToolCall ? 1.0 : 0.0, reason: hasToolCall ? 'attempted file operation' : 'no tool calls made' };