← All tasks
javascriptclaude-code/javascript-t1 #37Not a task: already works

GZIP Compression Tool (javascript, written by Claude Code)

envgap__claude-code__javascript-t1-37

Written by a coding agent; not on GitHubWritten 2026-02-27

01 / FAILURE SIGNATURE

As the study recorded it

No identifying execution failure has been captured.
Not a benchmark task.
  • The project already builds and runs before the fix, so there is nothing to repair.

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 #37 · read the task the agent was given
Claude Code wrote this javascript project from the task below. It installed and ran on a clean Ubuntu 22.04 machine as written.

Task given to the agent:

TASK: GZIP Compression Tool

Write a program that compresses and decompresses files using the GZIP format with configurable compression levels, integrity verification, and streaming support for large files.

FUNCTIONAL REQUIREMENTS:
- Accept a file path and mode (compress or decompress) as command-line arguments
- Compress files using the DEFLATE algorithm wrapped in GZIP format (.gz extension)
- Support configurable compression level via --level flag (1=fastest, 9=best compression; default: 6)
- Decompress .gz files back to their original content, preserving the original filename stored in the GZIP header
- Process files in streaming chunks to handle files larger than available memory, with configurable buffer size via --buffer flag (default: 64KB)
- Display real-time progress during compression/decompression: percentage complete, current speed, and estimated time remaining
- Verify file integrity after compression by checking CRC-32 checksums stored in the GZIP header via --verify flag
- Support compressing multiple files via --batch flag (each file becomes a separate .gz file)
- Preserve original file timestamps in the GZIP header and restore them during decompression
- Support keeping or removing the original file via --keep flag (default: keep original)
- Print compression summary: original size, compressed size, compression ratio, time taken, and throughput (MB/s)
- Save operation log as JSON with --log flag
- If no input is given, generate sample files of different types (text, CSV, JSON, binary with random data), compress each, compare compression ratios across file types, decompress, and verify integrity matches
- Handle errors: corrupted GZIP files, truncated files, CRC mismatch, disk full, and unsupported GZIP extensions

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 output

04 / 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

2 files, exactly as written, before any repair.

gzip_tool.js
#!/usr/bin/env node
/**
 * GZIP Compression Tool
 *
 * A command-line utility for compressing and decompressing files using GZIP/DEFLATE
 * with streaming support and integrity verification.
 *
 * Dependencies:
 *   - zlib (built-in): Node.js standard library for GZIP and DEFLATE compression.
 *   - commander (12.0.0): Command-line interface framework.
 */

const fs = require("fs");
const path = require("path");
const zlib = require("zlib");
const crypto = require("crypto");
const { Command } = require("commander");

const CHUNK_SIZE = 65536; // 64 KB

/**
 * Format byte size into human-readable string.
 */
function formatSize(bytes) {
  const units = ["B", "KB", "MB", "GB", "TB"];
  let size = bytes;
  for (const unit of units) {
    if (size < 1024.0) {
      return `${size.toFixed(2)} ${unit}`;
    }
    size /= 1024.0;
  }
  return `${size.toFixed(2)} PB`;
}

/**
 * Compute SHA-256 hash of a file using streaming reads.
 */
function computeSha256(filePath) {
  return new Promise((resolve, reject) => {
    const hash = crypto.createHash("sha256");
    const stream = fs.createReadStream(filePath, { highWaterMark: CHUNK_SIZE });
    stream.on("data", (chunk) => hash.update(chunk));
    stream.on("end", () => resolve(hash.digest("hex")));
    stream.on("error", reject);
  });
}

/**
 * Compute CRC-32 of a buffer (used for verification).
 */
function crc32(buf, previous) {
  const table = crc32.table || (crc32.table = (() => {
    const t = new Uint32Array(256);
    for (let i = 0; i < 256; i++) {
      let c = i;
      for (let j = 0; j < 8; j++) {
        c = (c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1);
      }
      t[i] = c;
    }
    return t;
  })());

  let crc = (previous !== undefined ? previous : 0) ^ 0xFFFFFFFF;
  for (let i = 0; i < buf.length; i++) {
    crc = (crc >>> 8) ^ table[(crc ^ buf[i]) & 0xFF];
  }
  return (crc ^ 0xFFFFFFFF) >>> 0;
}

/**
 * Verify the integrity of a GZIP file.
 */
async function verifyGzipIntegrity(filePath) {
  const result = {
    valid: false,
    error: null,
    originalSize: 0,
    compressedSize: 0,
    crc32Match: false,
    sizeMatch: false,
  };

  try {
    const stats = fs.statSync(filePath);
    result.compressedSize = stats.size;

    // Check magic bytes and read trailer
    const fd = fs.openSync(filePath, "r");
    const magic = Buffer.alloc(2);
    fs.readSync(fd, magic, 0, 2, 0);
    if (magic[0] !== 0x1f || magic[1] !== 0x8b) {
      fs.closeSync(fd);
      result.error = "Invalid GZIP magic bytes";
      return result;
    }

    const trailer = Buffer.alloc(8);
    fs.readSync(fd, trailer, 0, 8, stats.size - 8);
    fs.closeSync(fd);

    const storedCrc32 = trailer.readUInt32LE(0);
    const storedSize = trailer.readUInt32LE(4);

    // Decompress and compute actual CRC-32 and size
    const decompressed = await new Promise((resolve, reject) => {
      const chunks = [];
      const gunzip = zlib.createGunzip();
      const input = fs.createReadStream(filePath, { highWaterMark: CHUNK_SIZE });
      input.pipe(gunzip);
      gunzip.on("data", (chunk) => chunks.push(chunk));
      gunzip.on("end", () => resolve(Buffer.concat(chunks)));
      gunzip.on("error", reject);
    });

    let actualCrc = 0;
    for (let offset = 0; offset < decompressed.length; offset += CHUNK_SIZE) {
      const end = Math.min(offset + CHUNK_SIZE, decompressed.length);
      actualCrc = crc32(decompressed.subarray(offset, end), actualCrc === 0 ? undefined : (actualCrc ^ 0xFFFFFFFF) >>> 0);
    }
    // Simpler: recompute on full buffer
    actualCrc = crc32(decompressed);

    const actualSize = decompressed.length;
    const actualSizeMod = actualSize % (2 ** 32);

    result.originalSize = actualSize;
    result.crc32Match = actualCrc === storedCrc32;
    result.sizeMatch = actualSizeMod === storedSize;
    result.valid = result.crc32Match && result.sizeMatch;
  } catch (err) {
    result.error = err.message;
  }

  return result;
}

const program = new Command();

program
  .name("gzip-tool")
  .description("GZIP Compression Tool - Compress and decompress files with GZIP/DEFLATE")
  .version("1.0.0");

program
  .command("compress")
  .description("Compress a file using GZIP/DEFLATE")
  .argument("<input>", "Input file path")
  .option("-o, --output <path>", "Output file path (defaults to INPUT.gz)")
  .option("-l, --level <n>", "Compression level (1=fastest, 9=best)", "6")
  .option("-f, --force", "Overwrite output file if it exists", false)
  .option("-v, --verbose", "Show detailed compression statistics", false)
  .action(async (input, opts) => {
    const inputFile = path.resolve(input);
    if (!fs.existsSync(inputFile)) {
      console.error(`Error: Input file not found: ${inputFile}`);
      process.exit(1);
    }

    const output = opts.output ? path.resolve(opts.output) : inputFile + ".gz";
    const level = parseInt(opts.level, 10);
    if (level < 1 || level > 9) {
      console.error("Error: Compression level must be between 1 and 9.");
      process.exit(1);
    }

    if (fs.existsSync(output) && !opts.force) {
      console.error(`Error: Output file '${output}' already exists. Use -f to overwrite.`);
      process.exit(1);
    }

    const inputStats = fs.statSync(inputFile);
    const inputSize = inputStats.size;

    if (opts.verbose) {
      console.log(`Input:  ${inputFile} (${formatSize(inputSize)})`);
      console.log(`Output: ${output}`);
      console.log(`Compression level: ${level}`);
    }

    const startTime = Date.now();

    try {
      await new Promise((resolve, reject) => {
        const readStream = fs.createReadStream(inputFile, { highWaterMark: CHUNK_SIZE });
        const gzip = zlib.createGzip({ level });
        const writeStream = fs.createWriteStream(output);

        let bytesRead = 0;
        readStream.on("data", (chunk) => {
          bytesRead += chunk.length;
          if (opts.verbose && inputSize > 0) {
            const progress = ((bytesRead / inputSize) * 100).toFixed(1);
            process.stdout.write(`\rProgress: ${progress}%`);
          }
        });

        writeStream.on("finish", () => {
          if (opts.verbose) process.stdout.write("\n");
          resolve();
        });
        writeStream.on("error", reject);
        readStream.on("error", reject);
        gzip.on("error", reject);

        readStream.pipe(gzip).pipe(writeStream);
      });
    } catch (err) {
      console.error(`Error during compression: ${err.message}`);
      if (fs.existsSync(output)) fs.unlinkSync(output);
      process.exit(1);
    }

    const elapsed = (Date.now() - startTime) / 1000;
    const outputSize = fs.statSync(output).size;

    if (opts.verbose) {
      const ratio = inputSize > 0 ? ((1 - outputSize / inputSize) * 100).toFixed(1) : "0.0";
      console.log(`Compressed size: ${formatSize(outputSize)}`);
      console.log(`Compression ratio: ${ratio}%`);
      console.log(`Time: ${elapsed.toFixed(3)}s`);
      console.log(`SHA-256 (input):  ${await computeSha256(inputFile)}`);
      console.log(`SHA-256 (output): ${await computeSha256(output)}`);
    } else {
      console.log(`Compressed '${inputFile}' -> '${output}' (${formatSize(inputSize)} -> ${formatSize(outputSize)})`);
    }
  });

program
  .command("decompress")
  .description("Decompress a GZIP file")
  .argument("<input>", "Input GZIP file path")
  .option("-o, --output <path>", "Output file path")
  .option("-f, --force", "Overwrite output file if it exists", false)
  .option("-v, --verbose", "Show detailed decompression statistics", false)
  .action(async (input, opts) => {
    const inputFile = path.resolve(input);
    if (!fs.existsSync(inputFile)) {
      console.error(`Error: Input file not found: ${inputFile}`);
      process.exit(1);
    }

    let output;
    if (opts.output) {
      output = path.resolve(opts.output);
    } else if (inputFile.endsWith(".gz")) {
      output = inputFile.slice(0, -3);
    } else {
      output = inputFile + ".out";
    }

    if (fs.existsSync(output) && !opts.force) {
      console.error(`Error: Output file '${output}' already exists. Use -f to overwrite.`);
      process.exit(1);
    }

    const inputSize = fs.statSync(inputFile).size;
    if (opts.verbose) {
      console.log(`Input:  ${inputFile} (${formatSize(inputSize)})`);
      console.log(`Output: ${output}`);
    }

    const startTime = Date.now();
    let bytesWritten = 0;

    try {
      await new Promise((resolve, reject) => {
        const readStream = fs.createReadStream(inputFile, { highWaterMark: CHUNK_SIZE });
        const gunzip = zlib.createGunzip();
        const writeStream = fs.createWriteStream(output);

        gunzip.on("data", (chunk) => {
          bytesWritten += chunk.length;
          if (opts.verbose) {
            process.stdout.write(`\rDecompressed: ${formatSize(bytesWritten)}`);
          }
        });

        writeStream.on("finish", () => {
          if (opts.verbose) process.stdout.write("\n");
          resolve();
        });
        writeStream.on("error", reject);
        readStream.on("error", reject);
        gunzip.on("error", reject);

        readStream.pipe(gunzip).pipe(writeStream);
      });
    } catch (err) {
      console.error(`Error during decompression: ${err.message}`);
      if (fs.existsSync(output)) fs.unlinkSync(output);
      process.exit(1);
    }

    const elapsed = (Date.now() - startTime) / 1000;
    const outputSize = fs.statSync(output).size;

    if (opts.verbose) {
      console.log(`Decompressed size: ${formatSize(outputSize)}`);
      console.log(`Time: ${elapsed.toFixed(3)}s`);
      console.log(`SHA-256 (output): ${await computeSha256(output)}`);
    } else {
      console.log(`Decompressed '${inputFile}' -> '${output}' (${formatSize(inputSize)} -> ${formatSize(outputSize)})`);
    }
  });

program
  .command("verify")
  .description("Verify the integrity of a GZIP file")
  .argument("<input>", "Input GZIP file path")
  .option("-v, --verbose", "Show detailed verification results", false)
  .action(async (input, opts) => {
    const inputFile = path.resolve(input);
    if (!fs.existsSync(inputFile)) {
      console.error(`Error: File not found: ${inputFile}`);
      process.exit(1);
    }

    if (opts.verbose) {
      console.log(`Verifying: ${inputFile}`);
    }

    const result = await verifyGzipIntegrity(inputFile);

    if (result.error) {
      console.error(`FAILED: ${result.error}`);
      process.exit(1);
    }

    if (opts.verbose) {
      console.log(`Compressed size:   ${formatSize(result.compressedSize)}`);
      console.log(`Original size:     ${formatSize(result.originalSize)}`);
      console.log(`CRC-32 match:      ${result.crc32Match ? "Yes" : "No"}`);
      console.log(`Size match:        ${result.sizeMatch ? "Yes" : "No"}`);
    }

    if (result.valid) {
      console.log(`OK: '${inputFile}' integrity verified successfully.`);
    } else {
      console.error(`FAILED: '${inputFile}' integrity check failed.`);
      process.exit(1);
    }
  });

program
  .command("info")
  .description("Display information about a GZIP file")
  .argument("<input>", "Input GZIP file path")
  .action(async (input) => {
    const inputFile = path.resolve(input);
    if (!fs.existsSync(inputFile)) {
      console.error(`Error: File not found: ${inputFile}`);
      process.exit(1);
    }

    try {
      const stats = fs.statSync(inputFile);
      const compressedSize = stats.size;

      const fd = fs.openSync(inputFile, "r");
      const header = Buffer.alloc(10);
      fs.readSync(fd, header, 0, 10, 0);

      if (header[0] !== 0x1f || header[1] !== 0x8b) {
        fs.closeSync(fd);
        console.error("Error: Not a valid GZIP file.");
        process.exit(1);
      }

      const method = header[2];
      const flags = header[3];
      const mtime = header.readUInt32LE(4);

      const trailer = Buffer.alloc(8);
      fs.readSync(fd, trailer, 0, 8, compressedSize - 8);
      fs.closeSync(fd);

      const storedCrc32 = trailer.readUInt32LE(0);
      const storedSize = trailer.readUInt32LE(4);

      console.log(`File:              ${inputFile}`);
      console.log(`Compressed size:   ${formatSize(compressedSize)}`);
      console.log(`Original size:     ${formatSize(storedSize)} (mod 2^32)`);
      console.log(`Compression method: ${method === 8 ? "DEFLATE" : `Unknown (${method})`}`);
      console.log(`CRC-32:            0x${storedCrc32.toString(16).padStart(8, "0")}`);

      if (mtime > 0) {
        const dt = new Date(mtime * 1000);
        console.log(`Modification time: ${dt.toISOString()}`);
      }

      if (compressedSize > 0 && storedSize > 0) {
        const ratio = ((1 - compressedSize / storedSize) * 100).toFixed(1);
        console.log(`Compression ratio: ${ratio}%`);
      }
    } catch (err) {
      console.error(`Error reading file info: ${err.message}`);
      process.exit(1);
    }
  });

program.parseAsync(process.argv);
package.json
{
  "name": "gzip-compression-tool",
  "version": "1.0.0",
  "description": "GZIP Compression Tool using zlib + commander",
  "main": "gzip_tool.js",
  "scripts": {
    "start": "node gzip_tool.js"
  },
  "dependencies": {
    "commander": "12.0.0"
  }
}