Multi-Format Data Converter (javascript, written by Claude Code)
envgap__claude-code__javascript-t1-8
Written by a coding agent; not on GitHubWritten 2026-02-27
01 / FAILURE SIGNATURE
As the study recorded it
Invalid character in name - nested objects/arrays invalid as XML element names
Not a benchmark task.
- Its repair changed source code, so it is not an environment task.
02 / ENVIRONMENT RECIPE
- Base commit
Not freshly verified- Manifest
package.json- Reproduce
Awaiting issue-specific recipe- Run under trace
Awaiting a meaningful runtime command
03 / TASK AND FAILURE
claude-code/javascript-t1 #8 · read the task the agent was given
Claude Code wrote this javascript project from the task below. It does not run on a clean Ubuntu 22.04 machine as written.
Task given to the agent:
TASK: Multi-Format Data Converter
Write a program that converts data files between CSV, JSON, XML, and YAML formats while preserving data types, nested structures, and handling large files efficiently.
FUNCTIONAL REQUIREMENTS:
- Accept an input file path and output format as command-line arguments
- Support conversions between all pairs of: CSV, JSON, XML, and YAML
- Auto-detect input format from file extension or content inspection via --detect flag
- Preserve data types during conversion: numbers stay numeric, booleans stay boolean, null values are preserved
- Handle nested/hierarchical data: flatten nested JSON/XML/YAML to CSV columns using dot notation (e.g., address.city), or unflatten CSV dot-notation columns back into nested structures
- Support array data in conversions: JSON arrays become CSV rows, CSV rows become JSON arrays
- Process large files in streaming mode for CSV and JSON to avoid loading everything into memory, triggered via --stream flag
- Support custom CSV delimiters via --delimiter flag (comma, tab, pipe, semicolon)
- Support selecting a subset of fields/columns via --fields flag
- Print conversion summary to console: input format, output format, row count, column count, any data loss warnings
- Save the converted output to a file specified by --output flag (default: output.{format})
- If no input file is given, generate a sample dataset with nested objects, arrays, mixed types, and null values in JSON format, then convert it to all other formats
- Handle encoding differences (UTF-8, Latin-1) and BOM markers gracefully
Create a complete JavaScript project for a clean Ubuntu 22.04 machine with only Node.js 20+ (LTS) installed. Include:
- Source code
- package.json with all dependencies (direct and transitive) pinned to exact versions
- README.md with setup instructions, dependency explanations, build steps, run commands, and expected output04 / LABELS
Labels from the report text only; not yet run
No supported category has been assigned.
Label rules and the text that matched
[]
05 / FILES
The project as the agent wrote it
3 files, exactly as written, before any repair.
converter.js
#!/usr/bin/env node
/**
* Multi-Format Data Converter (Trial 1)
* Converts data between CSV, JSON, XML, and YAML formats.
* Uses: xml2js, js-yaml, csv-parse, csv-stringify
*/
const fs = require("fs");
const path = require("path");
const xml2js = require("xml2js");
const yaml = require("js-yaml");
const { parse: csvParse } = require("csv-parse/sync");
const { stringify: csvStringify } = require("csv-stringify/sync");
const SUPPORTED_FORMATS = new Set(["csv", "json", "xml", "yaml", "yml"]);
/**
* Auto-detect the input file format.
*/
function detectFormat(filepath) {
let ext = path.extname(filepath).toLowerCase().replace(".", "");
if (ext === "yml") ext = "yaml";
if (SUPPORTED_FORMATS.has(ext)) return ext;
// Content-based detection
const content = fs.readFileSync(filepath, "utf-8").trim();
const firstLine = content.split("\n")[0].trim();
if (firstLine.startsWith("{") || firstLine.startsWith("[")) return "json";
if (firstLine.startsWith("<?xml") || firstLine.startsWith("<")) return "xml";
if (firstLine.includes(":") && !firstLine.includes(",")) return "yaml";
return "csv";
}
/**
* Infer type from string value.
*/
function inferType(value) {
if (value === null || value === undefined || value === "") return null;
const v = String(value).trim();
if (v.toLowerCase() === "true" || v.toLowerCase() === "yes") return true;
if (v.toLowerCase() === "false" || v.toLowerCase() === "no") return false;
if (v.toLowerCase() === "null" || v.toLowerCase() === "none") return null;
if (/^-?\d+$/.test(v)) {
const num = parseInt(v, 10);
if (num >= Number.MIN_SAFE_INTEGER && num <= Number.MAX_SAFE_INTEGER)
return num;
}
if (/^-?\d+\.\d+$/.test(v)) return parseFloat(v);
return value;
}
/**
* Read CSV file.
*/
function readCsv(filepath) {
const content = fs.readFileSync(filepath, "utf-8");
if (!content.trim()) throw new Error("CSV file is empty or malformed");
try {
const records = csvParse(content, {
columns: true,
skip_empty_lines: true,
trim: true,
relax_column_count: true,
});
return records.map((record) => {
const typed = {};
for (const [key, val] of Object.entries(record)) {
typed[key] = inferType(val);
}
return typed;
});
} catch (e) {
throw new Error(`Malformed CSV: ${e.message}`);
}
}
/**
* Read JSON file.
*/
function readJson(filepath) {
const content = fs.readFileSync(filepath, "utf-8");
try {
return JSON.parse(content);
} catch (e) {
throw new Error(`Malformed JSON: ${e.message}`);
}
}
/**
* Read XML file.
*/
async function readXml(filepath) {
const content = fs.readFileSync(filepath, "utf-8");
try {
const parser = new xml2js.Parser({
explicitArray: false,
mergeAttrs: true,
valueProcessors: [xml2js.processors.parseNumbers, xml2js.processors.parseBooleans],
});
const result = await parser.parseStringPromise(content);
// Unwrap root element
if (result && typeof result === "object") {
const keys = Object.keys(result);
if (keys.length === 1) {
const inner = result[keys[0]];
if (inner && typeof inner === "object") {
const innerKeys = Object.keys(inner);
if (innerKeys.length === 1) {
const items = inner[innerKeys[0]];
if (Array.isArray(items)) return items;
}
// Check if any value is an array
for (const k of innerKeys) {
if (Array.isArray(inner[k])) return inner[k];
}
return inner;
}
return inner;
}
}
return result;
} catch (e) {
throw new Error(`Malformed XML: ${e.message}`);
}
}
/**
* Read YAML file.
*/
function readYaml(filepath) {
const content = fs.readFileSync(filepath, "utf-8");
try {
const data = yaml.load(content);
if (data === null || data === undefined) {
throw new Error("YAML file is empty");
}
return data;
} catch (e) {
if (e.message.startsWith("YAML file")) throw e;
throw new Error(`Malformed YAML: ${e.message}`);
}
}
/**
* Normalize data to array of objects.
*/
function normalizeToList(data) {
if (Array.isArray(data)) {
return data.map((item) =>
typeof item === "object" && item !== null ? item : { value: item }
);
}
if (typeof data === "object" && data !== null) return [data];
return [{ value: data }];
}
/**
* Flatten nested object for CSV output.
*/
function flattenObject(obj, prefix = "") {
const flat = {};
for (const [key, value] of Object.entries(obj)) {
const newKey = prefix ? `${prefix}.${key}` : key;
if (value && typeof value === "object" && !Array.isArray(value)) {
Object.assign(flat, flattenObject(value, newKey));
} else if (Array.isArray(value)) {
flat[newKey] = JSON.stringify(value);
} else {
flat[newKey] = value;
}
}
return flat;
}
/**
* Write CSV file.
*/
function writeCsv(data, filepath) {
const records = normalizeToList(data);
const flatRecords = records.map((r) => flattenObject(r));
// Collect all keys preserving order
const allKeys = [];
const seen = new Set();
for (const record of flatRecords) {
for (const key of Object.keys(record)) {
if (!seen.has(key)) {
allKeys.push(key);
seen.add(key);
}
}
}
const output = csvStringify(flatRecords, {
header: true,
columns: allKeys,
});
fs.writeFileSync(filepath, output, "utf-8");
console.log(`Written CSV to ${filepath}`);
}
/**
* Write JSON file.
*/
function writeJson(data, filepath) {
fs.writeFileSync(filepath, JSON.stringify(data, null, 2), "utf-8");
console.log(`Written JSON to ${filepath}`);
}
/**
* Write XML file.
*/
function writeXml(data, filepath) {
const records = normalizeToList(data);
const builder = new xml2js.Builder({
rootName: "root",
xmldec: { version: "1.0", encoding: "UTF-8" },
renderOpts: { pretty: true, indent: " ", newline: "\n" },
});
const xmlObj = { record: records };
const xmlStr = builder.buildObject(xmlObj);
fs.writeFileSync(filepath, xmlStr, "utf-8");
console.log(`Written XML to ${filepath}`);
}
/**
* Write YAML file.
*/
function writeYaml(data, filepath) {
const yamlStr = yaml.dump(data, {
indent: 2,
lineWidth: 120,
noRefs: true,
sortKeys: false,
});
fs.writeFileSync(filepath, yamlStr, "utf-8");
console.log(`Written YAML to ${filepath}`);
}
/**
* Infer schema from data.
*/
function inferSchema(data) {
const records = normalizeToList(data);
const schema = {};
for (const record of records) {
for (const [key, value] of Object.entries(record)) {
const typeName =
value === null
? "null"
: Array.isArray(value)
? "array"
: typeof value;
if (!(key in schema)) {
schema[key] = typeName;
} else if (schema[key] !== typeName && value !== null) {
schema[key] = "mixed";
}
}
}
return schema;
}
/**
* Generate sample data.
*/
function generateSampleData() {
return [
{
id: 1,
name: "Alice Johnson",
age: 30,
active: true,
score: 95.5,
address: { street: "123 Main St", city: "Springfield", state: "IL" },
tags: ["developer", "python"],
},
{
id: 2,
name: "Bob Smith",
age: 25,
active: false,
score: 88.0,
address: { street: "456 Oak Ave", city: "Portland", state: "OR" },
tags: ["designer", "css"],
},
{
id: 3,
name: "Carol White",
age: 35,
active: true,
score: 92.3,
address: { street: "789 Pine Rd", city: "Austin", state: "TX" },
tags: ["manager", "agile"],
},
];
}
/**
* Main conversion function.
*/
async function convert(inputPath, targetFormat, outputPath) {
let tf = targetFormat.toLowerCase().replace(".", "");
if (tf === "yml") tf = "yaml";
if (!SUPPORTED_FORMATS.has(tf)) {
throw new Error(`Unsupported target format: ${tf}`);
}
const sourceFormat = detectFormat(inputPath);
console.log(`Detected input format: ${sourceFormat}`);
const readers = {
csv: readCsv,
json: readJson,
xml: readXml,
yaml: readYaml,
};
let data;
if (sourceFormat === "xml") {
data = await readers[sourceFormat](inputPath);
} else {
data = readers[sourceFormat](inputPath);
}
const schema = inferSchema(normalizeToList(data));
console.log("Inferred schema:", schema);
if (!outputPath) {
const ext = path.extname(inputPath);
const base = inputPath.slice(0, -ext.length);
outputPath = `${base}.${tf}`;
}
const writers = { csv: writeCsv, json: writeJson, xml: writeXml, yaml: writeYaml };
writers[tf](data, outputPath);
return outputPath;
}
/**
* CLI entry point.
*/
async function main() {
const args = process.argv.slice(2);
if (args.length === 0 || args.includes("--generate-samples")) {
console.log("Generating sample data in all formats...");
const sample = generateSampleData();
const sampleDir = path.join(process.cwd(), "sample_output");
fs.mkdirSync(sampleDir, { recursive: true });
writeJson(sample, path.join(sampleDir, "sample.json"));
writeCsv(sample, path.join(sampleDir, "sample.csv"));
writeXml(sample, path.join(sampleDir, "sample.xml"));
writeYaml(sample, path.join(sampleDir, "sample.yaml"));
console.log(`Sample files generated in ${sampleDir}/`);
return;
}
let inputFile = null;
let targetFormat = null;
let outputFile = null;
let schemaOnly = false;
for (let i = 0; i < args.length; i++) {
switch (args[i]) {
case "-t":
case "--target":
targetFormat = args[++i];
break;
case "-o":
case "--output":
outputFile = args[++i];
break;
case "--schema":
schemaOnly = true;
break;
default:
if (!args[i].startsWith("-")) inputFile = args[i];
break;
}
}
if (!inputFile) {
console.error("Error: Input file is required");
console.error(
"Usage: node converter.js <input> -t <format> [-o <output>]"
);
process.exit(1);
}
if (!fs.existsSync(inputFile)) {
console.error(`Error: File not found: ${inputFile}`);
process.exit(1);
}
try {
if (schemaOnly) {
const format = detectFormat(inputFile);
const readers = { csv: readCsv, json: readJson, xml: readXml, yaml: readYaml };
let data;
if (format === "xml") {
data = await readers[format](inputFile);
} else {
data = readers[format](inputFile);
}
const schema = inferSchema(normalizeToList(data));
console.log("Inferred Schema:");
for (const [field, dtype] of Object.entries(schema)) {
console.log(` ${field}: ${dtype}`);
}
return;
}
if (!targetFormat) {
console.error("Error: Target format (-t) is required");
process.exit(1);
}
const output = await convert(inputFile, targetFormat, outputFile);
console.log(`Conversion complete: ${output}`);
} catch (e) {
console.error(`Error: ${e.message}`);
process.exit(1);
}
}
main();
package.json
{
"name": "multi-format-data-converter",
"version": "1.0.0",
"description": "Multi-Format Data Converter: CSV, JSON, XML, YAML",
"main": "converter.js",
"scripts": {
"start": "node converter.js",
"convert": "node converter.js"
},
"dependencies": {
"xml2js": "0.6.2",
"js-yaml": "4.1.0",
"csv-parse": "5.5.3",
"csv-stringify": "6.4.5"
}
}
README.md
# Multi-Format Data Converter (JavaScript - Trial 1) Converts data between CSV, JSON, XML, and YAML formats. ## Dependencies - xml2js@0.6.2 - js-yaml@4.1.0 - csv-parse@5.5.3 - csv-stringify@6.4.5 ## Installation ```bash npm install ``` ## Usage ```bash node converter.js input.json -t csv node converter.js data.csv -t yaml -o output.yaml node converter.js --schema data.json node converter.js --generate-samples ``` ## Features - Auto-detects input format - Supports CSV, JSON, XML, YAML conversions - Preserves data types - Handles nested structures - Schema inference - Sample data generation - Error handling for malformed input