#!/usr/bin/env node 'use strict'; const fs = require('fs'); const path = require('path'); function fail(message) { throw new Error(message); } function isWithin(root, candidate) { const relative = path.relative(root, candidate); return relative === '' || ( relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative) ); } function validatePlan(payload, projectDir, requireDryRun) { const expectedRoot = path.resolve(projectDir, '.claude'); if (!payload || typeof payload !== 'object' || !payload.plan) { fail('Install output is missing a plan.'); } if (requireDryRun && payload.dryRun !== true) { fail('Install plan did not report dryRun=true.'); } if (payload.plan.target !== 'claude-project') { fail('Install plan target is not claude-project.'); } if ( typeof payload.plan.installRoot !== 'string' || path.resolve(payload.plan.installRoot) !== expectedRoot ) { fail('Install root is not confined to the isolated project.'); } if (!Array.isArray(payload.plan.operations) || payload.plan.operations.length === 0) { fail('Install plan has no operations.'); } for (const operation of payload.plan.operations) { if ( !operation || typeof operation.destinationPath !== 'string' || !isWithin(expectedRoot, path.resolve(operation.destinationPath)) ) { fail('Install plan contains an operation outside the isolated project root.'); } } } function main() { try { const projectDir = process.argv[2]; if (!projectDir || !path.isAbsolute(projectDir)) { fail('Expected an absolute isolated project path.'); } const requireDryRun = process.argv.includes('--dry-run'); const payload = JSON.parse(fs.readFileSync(0, 'utf8')); validatePlan(payload, projectDir, requireDryRun); } catch (error) { process.stderr.write(`Error: ${error.message}\n`); process.exitCode = 1; } } if (require.main === module) { main(); } module.exports = { isWithin, validatePlan };