fix: resolve four bug reports (#2290, #2282, #2276, #2272)

- #2290 suggest-compact: honor ECC_CONTEXT_WINDOW_TOKENS / CLAUDE_CODE_AUTO_COMPACT_WINDOW
  so 400k-window models (Opus 4.x) no longer report ~double context usage; add
  override + isolation tests in transcript-context.test.js.
- #2282 install: bare-language syntax is legacy-only by design, but the error
  now distinguishes a supported-but-wrong-mode target (gemini/codex/…) from a
  genuinely unknown one and points to --profile/--modules/--skills.
- #2276 cost-report: the command + cost-tracking skill targeted a SQLite DB no
  tracker writes. Repoint both at the real ~/.claude/metrics/costs.jsonl (JSONL,
  estimated_cost_usd), reduce cumulative-per-session snapshots to latest-per-session,
  and use node instead of sqlite3 for cross-platform support.
- #2272 gateguard: make the 'confirm no existing file' checklist item
  tool-agnostic (Glob/Grep or find/grep via Bash) so hosts without a Glob tool
  don't get a dead tool call.

Full suite 2839/2839; lint green.
This commit is contained in:
Affaan Mustafa
2026-06-18 16:49:58 -04:00
parent 51184b692e
commit b3268fef80
7 changed files with 325 additions and 424 deletions
+132 -154
View File
@@ -5,20 +5,12 @@ const { execFileSync } = require('child_process');
const { toCursorAgentRelativePath } = require('./cursor-agent-names');
const { LEGACY_INSTALL_TARGETS, parseInstallArgs } = require('./install/request');
const {
SUPPORTED_INSTALL_TARGETS,
listLegacyCompatibilityLanguages,
resolveLegacyCompatibilitySelection,
resolveInstallPlan,
} = require('./install-manifests');
const { SUPPORTED_INSTALL_TARGETS, listLegacyCompatibilityLanguages, resolveLegacyCompatibilitySelection, resolveInstallPlan } = require('./install-manifests');
const { getInstallTargetAdapter } = require('./install-targets/registry');
const LANGUAGE_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
const CLAUDE_ECC_NAMESPACE = 'ecc';
const EXCLUDED_GENERATED_SOURCE_SUFFIXES = [
'/ecc-install-state.json',
'/ecc/install-state.json',
];
const EXCLUDED_GENERATED_SOURCE_SUFFIXES = ['/ecc-install-state.json', '/ecc/install-state.json'];
function getSourceRoot() {
return path.join(__dirname, '../..');
@@ -26,9 +18,7 @@ function getSourceRoot() {
function getPackageVersion(sourceRoot) {
try {
const packageJson = JSON.parse(
fs.readFileSync(path.join(sourceRoot, 'package.json'), 'utf8')
);
const packageJson = JSON.parse(fs.readFileSync(path.join(sourceRoot, 'package.json'), 'utf8'));
return packageJson.version || null;
} catch (_error) {
return null;
@@ -37,9 +27,7 @@ function getPackageVersion(sourceRoot) {
function getManifestVersion(sourceRoot) {
try {
const modulesManifest = JSON.parse(
fs.readFileSync(path.join(sourceRoot, 'manifests', 'install-modules.json'), 'utf8')
);
const modulesManifest = JSON.parse(fs.readFileSync(path.join(sourceRoot, 'manifests', 'install-modules.json'), 'utf8'));
return modulesManifest.version || 1;
} catch (_error) {
return 1;
@@ -52,7 +40,7 @@ function getRepoCommit(sourceRoot) {
cwd: sourceRoot,
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'ignore'],
timeout: 5000,
timeout: 5000
}).trim();
} catch (_error) {
return null;
@@ -64,32 +52,35 @@ function readDirectoryNames(dirPath) {
return [];
}
return fs.readdirSync(dirPath, { withFileTypes: true })
return fs
.readdirSync(dirPath, { withFileTypes: true })
.filter(entry => entry.isDirectory())
.map(entry => entry.name)
.sort();
}
function listAvailableLanguages(sourceRoot = getSourceRoot()) {
return [...new Set([
...listLegacyCompatibilityLanguages(),
...readDirectoryNames(path.join(sourceRoot, 'rules'))
.filter(name => name !== 'common'),
])].sort();
return [...new Set([...listLegacyCompatibilityLanguages(), ...readDirectoryNames(path.join(sourceRoot, 'rules')).filter(name => name !== 'common')])].sort();
}
function validateLegacyTarget(target) {
if (!LEGACY_INSTALL_TARGETS.includes(target)) {
if (LEGACY_INSTALL_TARGETS.includes(target)) {
return;
}
// A target can be fully supported yet not installable via the bare-language
// positional syntax (which is legacy-only). Guide the user to the right mode
// instead of implying the target is unknown (#2282).
if (SUPPORTED_INSTALL_TARGETS.includes(target)) {
throw new Error(
`Unknown install target: ${target}. Expected one of ${LEGACY_INSTALL_TARGETS.join(', ')}`
`Target '${target}' is supported, but the bare-language install syntax only accepts ${LEGACY_INSTALL_TARGETS.join(', ')}. ` +
`Install '${target}' with a component selection instead, e.g. \`install.sh --target ${target} --profile full\` ` +
`(or --modules <id,...> / --skills <id,...>).`
);
}
throw new Error(`Unknown install target: ${target}. Expected one of ${SUPPORTED_INSTALL_TARGETS.join(', ')}`);
}
const IGNORED_DIRECTORY_NAMES = new Set([
'node_modules',
'.git',
]);
const IGNORED_DIRECTORY_NAMES = new Set(['node_modules', '.git']);
function listFilesRecursive(dirPath) {
if (!fs.existsSync(dirPath)) {
@@ -141,7 +132,7 @@ function buildCopyFileOperation({ moduleId, sourcePath, sourceRelativePath, dest
destinationPath,
strategy,
ownership: 'managed',
scaffoldOnly: false,
scaffoldOnly: false
};
}
@@ -156,20 +147,20 @@ function addRecursiveCopyOperations(operations, options) {
for (const relativeFile of relativeFiles) {
const sourceRelativePath = path.join(options.sourceRelativeDir, relativeFile);
const sourcePath = path.join(options.sourceRoot, sourceRelativePath);
const destinationRelativePath = typeof options.destinationRelativePathTransform === 'function'
? options.destinationRelativePathTransform(relativeFile, sourceRelativePath)
: relativeFile;
const destinationRelativePath = typeof options.destinationRelativePathTransform === 'function' ? options.destinationRelativePathTransform(relativeFile, sourceRelativePath) : relativeFile;
if (!destinationRelativePath) {
continue;
}
const destinationPath = path.join(options.destinationDir, destinationRelativePath);
operations.push(buildCopyFileOperation({
moduleId: options.moduleId,
sourcePath,
sourceRelativePath,
destinationPath,
strategy: options.strategy || 'preserve-relative-path',
}));
operations.push(
buildCopyFileOperation({
moduleId: options.moduleId,
sourcePath,
sourceRelativePath,
destinationPath,
strategy: options.strategy || 'preserve-relative-path'
})
);
}
return relativeFiles.length;
@@ -181,13 +172,15 @@ function addFileCopyOperation(operations, options) {
return false;
}
operations.push(buildCopyFileOperation({
moduleId: options.moduleId,
sourcePath,
sourceRelativePath: options.sourceRelativePath,
destinationPath: options.destinationPath,
strategy: options.strategy || 'preserve-relative-path',
}));
operations.push(
buildCopyFileOperation({
moduleId: options.moduleId,
sourcePath,
sourceRelativePath: options.sourceRelativePath,
destinationPath: options.destinationPath,
strategy: options.strategy || 'preserve-relative-path'
})
);
return true;
}
@@ -218,7 +211,7 @@ function addCursorAgentDataScaffoldOperations(operations, options) {
sourceRoot: options.sourceRoot,
sourceRelativePath: path.join('scaffolds', 'cursor', 'ecc-agent-data.json'),
destinationPath: path.join(options.targetRoot, 'ecc-agent-data.json'),
strategy: 'preserve-relative-path',
strategy: 'preserve-relative-path'
});
addFileCopyOperation(operations, {
@@ -226,21 +219,17 @@ function addCursorAgentDataScaffoldOperations(operations, options) {
sourceRoot: options.sourceRoot,
sourceRelativePath: path.join('scaffolds', 'cursor', 'rules', 'ecc-agent-data-home.mdc'),
destinationPath: path.join(options.targetRoot, 'rules', 'ecc-agent-data-home.mdc'),
strategy: 'preserve-relative-path',
strategy: 'preserve-relative-path'
});
addJsonMergeOperation(operations, {
moduleId: options.moduleId,
sourceRoot: options.sourceRoot,
sourceRelativePath: path.join('scaffolds', 'cursor', 'hooks.json'),
destinationPath: path.join(options.targetRoot, 'hooks.json'),
destinationPath: path.join(options.targetRoot, 'hooks.json')
});
const cursorSessionHookDeps = [
path.join('scripts', 'hooks', 'cursor-session-env.js'),
path.join('scripts', 'lib', 'agent-data-home.js'),
path.join('scripts', 'lib', 'utils.js'),
];
const cursorSessionHookDeps = [path.join('scripts', 'hooks', 'cursor-session-env.js'), path.join('scripts', 'lib', 'agent-data-home.js'), path.join('scripts', 'lib', 'utils.js')];
for (const sourceRelativePath of cursorSessionHookDeps) {
addFileCopyOperation(operations, {
@@ -248,7 +237,7 @@ function addCursorAgentDataScaffoldOperations(operations, options) {
sourceRoot: options.sourceRoot,
sourceRelativePath,
destinationPath: path.join(options.targetRoot, sourceRelativePath),
strategy: 'preserve-relative-path',
strategy: 'preserve-relative-path'
});
}
}
@@ -267,7 +256,7 @@ function addJsonMergeOperation(operations, options) {
strategy: 'merge-json',
ownership: 'managed',
scaffoldOnly: false,
mergePayload: readJsonObject(sourcePath, options.sourceRelativePath),
mergePayload: readJsonObject(sourcePath, options.sourceRelativePath)
});
return true;
@@ -279,7 +268,8 @@ function addMatchingRuleOperations(operations, options) {
return 0;
}
const files = fs.readdirSync(sourceDir, { withFileTypes: true })
const files = fs
.readdirSync(sourceDir, { withFileTypes: true })
.filter(entry => entry.isFile() && options.matcher(entry.name))
.map(entry => entry.name)
.sort();
@@ -287,18 +277,17 @@ function addMatchingRuleOperations(operations, options) {
for (const fileName of files) {
const sourceRelativePath = path.join(options.sourceRelativeDir, fileName);
const sourcePath = path.join(options.sourceRoot, sourceRelativePath);
const destinationPath = path.join(
options.destinationDir,
options.rename ? options.rename(fileName) : fileName
);
const destinationPath = path.join(options.destinationDir, options.rename ? options.rename(fileName) : fileName);
operations.push(buildCopyFileOperation({
moduleId: options.moduleId,
sourcePath,
sourceRelativePath,
destinationPath,
strategy: options.strategy || 'flatten-copy',
}));
operations.push(
buildCopyFileOperation({
moduleId: options.moduleId,
sourcePath,
sourceRelativePath,
destinationPath,
strategy: options.strategy || 'flatten-copy'
})
);
}
return files.length;
@@ -324,7 +313,7 @@ function planClaudeStyleLegacyInstall(context, { adapterId, adapterRootInput, ru
moduleId: 'legacy-claude-rules',
sourceRoot: context.sourceRoot,
sourceRelativeDir: path.join('rules', 'common'),
destinationDir: path.join(rulesDir, 'common'),
destinationDir: path.join(rulesDir, 'common')
});
for (const language of context.languages) {
@@ -343,7 +332,7 @@ function planClaudeStyleLegacyInstall(context, { adapterId, adapterRootInput, ru
moduleId: 'legacy-claude-rules',
sourceRoot: context.sourceRoot,
sourceRelativeDir: path.join('rules', language),
destinationDir: path.join(rulesDir, language),
destinationDir: path.join(rulesDir, language)
});
}
@@ -356,7 +345,7 @@ function planClaudeStyleLegacyInstall(context, { adapterId, adapterRootInput, ru
installStatePath,
operations,
warnings,
selectedModules: ['legacy-claude-rules'],
selectedModules: ['legacy-claude-rules']
};
}
@@ -364,7 +353,7 @@ function planClaudeLegacyInstall(context) {
return planClaudeStyleLegacyInstall(context, {
adapterId: 'claude',
adapterRootInput: { homeDir: context.homeDir },
rulesDir: context.claudeRulesDir || null,
rulesDir: context.claudeRulesDir || null
});
}
@@ -372,7 +361,7 @@ function planClaudeProjectLegacyInstall(context) {
return planClaudeStyleLegacyInstall(context, {
adapterId: 'claude-project',
adapterRootInput: { repoRoot: context.projectRoot },
rulesDir: null,
rulesDir: null
});
}
@@ -388,14 +377,12 @@ function planCursorLegacyInstall(context) {
sourceRoot: context.sourceRoot,
sourceRelativeDir: path.join('.cursor', 'rules'),
destinationDir: path.join(targetRoot, 'rules'),
matcher: fileName => /^common-.*\.md$/.test(fileName),
matcher: fileName => /^common-.*\.md$/.test(fileName)
});
for (const language of context.languages) {
if (!LANGUAGE_NAME_PATTERN.test(language)) {
warnings.push(
`Invalid language name '${language}'. Only alphanumeric, dash, and underscore are allowed`
);
warnings.push(`Invalid language name '${language}'. Only alphanumeric, dash, and underscore are allowed`);
continue;
}
@@ -404,7 +391,7 @@ function planCursorLegacyInstall(context) {
sourceRoot: context.sourceRoot,
sourceRelativeDir: path.join('.cursor', 'rules'),
destinationDir: path.join(targetRoot, 'rules'),
matcher: fileName => fileName.startsWith(`${language}-`) && fileName.endsWith('.md'),
matcher: fileName => fileName.startsWith(`${language}-`) && fileName.endsWith('.md')
});
if (matches === 0) {
@@ -417,44 +404,44 @@ function planCursorLegacyInstall(context) {
sourceRoot: context.sourceRoot,
sourceRelativeDir: path.join('.cursor', 'agents'),
destinationDir: path.join(targetRoot, 'agents'),
destinationRelativePathTransform: toCursorAgentRelativePath,
destinationRelativePathTransform: toCursorAgentRelativePath
});
addRecursiveCopyOperations(operations, {
moduleId: 'legacy-cursor-install',
sourceRoot: context.sourceRoot,
sourceRelativeDir: path.join('.cursor', 'skills'),
destinationDir: path.join(targetRoot, 'skills'),
destinationDir: path.join(targetRoot, 'skills')
});
addRecursiveCopyOperations(operations, {
moduleId: 'legacy-cursor-install',
sourceRoot: context.sourceRoot,
sourceRelativeDir: path.join('.cursor', 'commands'),
destinationDir: path.join(targetRoot, 'commands'),
destinationDir: path.join(targetRoot, 'commands')
});
addRecursiveCopyOperations(operations, {
moduleId: 'legacy-cursor-install',
sourceRoot: context.sourceRoot,
sourceRelativeDir: path.join('.cursor', 'hooks'),
destinationDir: path.join(targetRoot, 'hooks'),
destinationDir: path.join(targetRoot, 'hooks')
});
addFileCopyOperation(operations, {
moduleId: 'legacy-cursor-install',
sourceRoot: context.sourceRoot,
sourceRelativePath: path.join('.cursor', 'hooks.json'),
destinationPath: path.join(targetRoot, 'hooks.json'),
destinationPath: path.join(targetRoot, 'hooks.json')
});
addJsonMergeOperation(operations, {
moduleId: 'legacy-cursor-install',
sourceRoot: context.sourceRoot,
sourceRelativePath: '.mcp.json',
destinationPath: path.join(targetRoot, 'mcp.json'),
destinationPath: path.join(targetRoot, 'mcp.json')
});
addCursorAgentDataScaffoldOperations(operations, {
moduleId: 'legacy-cursor-install',
sourceRoot: context.sourceRoot,
targetRoot,
targetRoot
});
return {
@@ -466,7 +453,7 @@ function planCursorLegacyInstall(context) {
installStatePath,
operations,
warnings,
selectedModules: ['legacy-cursor-install'],
selectedModules: ['legacy-cursor-install']
};
}
@@ -478,9 +465,7 @@ function planAntigravityLegacyInstall(context) {
const warnings = [];
if (isDirectoryNonEmpty(path.join(targetRoot, 'rules'))) {
warnings.push(
`Destination ${path.join(targetRoot, 'rules')}/ already exists and files may be overwritten`
);
warnings.push(`Destination ${path.join(targetRoot, 'rules')}/ already exists and files may be overwritten`);
}
addMatchingRuleOperations(operations, {
@@ -489,14 +474,12 @@ function planAntigravityLegacyInstall(context) {
sourceRelativeDir: path.join('rules', 'common'),
destinationDir: path.join(targetRoot, 'rules'),
matcher: fileName => fileName.endsWith('.md'),
rename: fileName => `common-${fileName}`,
rename: fileName => `common-${fileName}`
});
for (const language of context.languages) {
if (!LANGUAGE_NAME_PATTERN.test(language)) {
warnings.push(
`Invalid language name '${language}'. Only alphanumeric, dash, and underscore are allowed`
);
warnings.push(`Invalid language name '${language}'. Only alphanumeric, dash, and underscore are allowed`);
continue;
}
@@ -512,7 +495,7 @@ function planAntigravityLegacyInstall(context) {
sourceRelativeDir: path.join('rules', language),
destinationDir: path.join(targetRoot, 'rules'),
matcher: fileName => fileName.endsWith('.md'),
rename: fileName => `${language}-${fileName}`,
rename: fileName => `${language}-${fileName}`
});
}
@@ -520,19 +503,19 @@ function planAntigravityLegacyInstall(context) {
moduleId: 'legacy-antigravity-install',
sourceRoot: context.sourceRoot,
sourceRelativeDir: 'commands',
destinationDir: path.join(targetRoot, 'workflows'),
destinationDir: path.join(targetRoot, 'workflows')
});
addRecursiveCopyOperations(operations, {
moduleId: 'legacy-antigravity-install',
sourceRoot: context.sourceRoot,
sourceRelativeDir: 'agents',
destinationDir: path.join(targetRoot, 'skills'),
destinationDir: path.join(targetRoot, 'skills')
});
addRecursiveCopyOperations(operations, {
moduleId: 'legacy-antigravity-install',
sourceRoot: context.sourceRoot,
sourceRelativeDir: 'skills',
destinationDir: path.join(targetRoot, 'skills'),
destinationDir: path.join(targetRoot, 'skills')
});
return {
@@ -544,7 +527,7 @@ function planAntigravityLegacyInstall(context) {
installStatePath,
operations,
warnings,
selectedModules: ['legacy-antigravity-install'],
selectedModules: ['legacy-antigravity-install']
};
}
@@ -561,7 +544,7 @@ function createLegacyInstallPlan(options = {}) {
projectRoot,
homeDir,
languages: Array.isArray(options.languages) ? options.languages : [],
claudeRulesDir: options.claudeRulesDir || process.env.CLAUDE_RULES_DIR || null,
claudeRulesDir: options.claudeRulesDir || process.env.CLAUDE_RULES_DIR || null
};
let plan;
@@ -578,7 +561,7 @@ function createLegacyInstallPlan(options = {}) {
const source = {
repoVersion: getPackageVersion(sourceRoot),
repoCommit: getRepoCommit(sourceRoot),
manifestVersion: getManifestVersion(sourceRoot),
manifestVersion: getManifestVersion(sourceRoot)
};
const statePreview = createStatePreview({
@@ -589,14 +572,14 @@ function createLegacyInstallPlan(options = {}) {
profile: null,
modules: [],
legacyLanguages: context.languages,
legacyMode: true,
legacyMode: true
},
resolution: {
selectedModules: plan.selectedModules,
skippedModules: [],
skippedModules: []
},
operations: plan.operations,
source,
source
});
return {
@@ -605,7 +588,7 @@ function createLegacyInstallPlan(options = {}) {
adapter: {
id: plan.adapter.id,
target: plan.adapter.target,
kind: plan.adapter.kind,
kind: plan.adapter.kind
},
targetRoot: plan.targetRoot,
installRoot: plan.installRoot,
@@ -613,7 +596,7 @@ function createLegacyInstallPlan(options = {}) {
warnings: plan.warnings,
languages: context.languages,
operations: plan.operations,
statePreview,
statePreview
};
}
@@ -621,19 +604,15 @@ function createLegacyCompatInstallPlan(options = {}) {
const sourceRoot = options.sourceRoot || getSourceRoot();
const projectRoot = options.projectRoot || process.cwd();
const target = options.target || 'claude';
const includeComponentIds = Array.isArray(options.includeComponentIds)
? [...options.includeComponentIds]
: [];
const excludeComponentIds = Array.isArray(options.excludeComponentIds)
? [...options.excludeComponentIds]
: [];
const includeComponentIds = Array.isArray(options.includeComponentIds) ? [...options.includeComponentIds] : [];
const excludeComponentIds = Array.isArray(options.excludeComponentIds) ? [...options.excludeComponentIds] : [];
validateLegacyTarget(target);
const selection = resolveLegacyCompatibilitySelection({
repoRoot: sourceRoot,
target,
legacyLanguages: options.legacyLanguages || [],
legacyLanguages: options.legacyLanguages || []
});
return createManifestInstallPlan({
@@ -651,25 +630,24 @@ function createLegacyCompatInstallPlan(options = {}) {
requestModuleIds: [],
requestIncludeComponentIds: includeComponentIds,
requestExcludeComponentIds: excludeComponentIds,
mode: 'legacy-compat',
mode: 'legacy-compat'
});
}
function materializeScaffoldOperation(sourceRoot, operation) {
if (operation.kind === 'merge-json') {
return [{
kind: 'merge-json',
moduleId: operation.moduleId,
sourceRelativePath: operation.sourceRelativePath,
destinationPath: operation.destinationPath,
strategy: operation.strategy || 'merge-json',
ownership: operation.ownership || 'managed',
scaffoldOnly: Object.hasOwn(operation, 'scaffoldOnly') ? operation.scaffoldOnly : false,
mergePayload: readJsonObject(
path.join(sourceRoot, operation.sourceRelativePath),
operation.sourceRelativePath
),
}];
return [
{
kind: 'merge-json',
moduleId: operation.moduleId,
sourceRelativePath: operation.sourceRelativePath,
destinationPath: operation.destinationPath,
strategy: operation.strategy || 'merge-json',
ownership: operation.ownership || 'managed',
scaffoldOnly: Object.hasOwn(operation, 'scaffoldOnly') ? operation.scaffoldOnly : false,
mergePayload: readJsonObject(path.join(sourceRoot, operation.sourceRelativePath), operation.sourceRelativePath)
}
];
}
const sourcePath = path.join(sourceRoot, operation.sourceRelativePath);
@@ -683,13 +661,15 @@ function materializeScaffoldOperation(sourceRoot, operation) {
const stat = fs.statSync(sourcePath);
if (stat.isFile()) {
return [buildCopyFileOperation({
moduleId: operation.moduleId,
sourcePath,
sourceRelativePath: operation.sourceRelativePath,
destinationPath: operation.destinationPath,
strategy: operation.strategy,
})];
return [
buildCopyFileOperation({
moduleId: operation.moduleId,
sourcePath,
sourceRelativePath: operation.sourceRelativePath,
destinationPath: operation.destinationPath,
strategy: operation.strategy
})
];
}
const relativeFiles = listFilesRecursive(sourcePath).filter(relativeFile => {
@@ -703,7 +683,7 @@ function materializeScaffoldOperation(sourceRoot, operation) {
sourcePath: path.join(sourcePath, relativeFile),
sourceRelativePath,
destinationPath: path.join(operation.destinationPath, relativeFile),
strategy: operation.strategy,
strategy: operation.strategy
});
});
}
@@ -712,21 +692,19 @@ function createManifestInstallPlan(options = {}) {
const sourceRoot = options.sourceRoot || getSourceRoot();
const projectRoot = options.projectRoot || process.cwd();
const target = options.target || 'claude';
const legacyLanguages = Array.isArray(options.legacyLanguages)
? [...options.legacyLanguages]
: [];
const requestProfileId = Object.hasOwn(options, 'requestProfileId')
? options.requestProfileId
: (options.profileId || null);
const requestModuleIds = Object.hasOwn(options, 'requestModuleIds')
? [...options.requestModuleIds]
: (Array.isArray(options.moduleIds) ? [...options.moduleIds] : []);
const legacyLanguages = Array.isArray(options.legacyLanguages) ? [...options.legacyLanguages] : [];
const requestProfileId = Object.hasOwn(options, 'requestProfileId') ? options.requestProfileId : options.profileId || null;
const requestModuleIds = Object.hasOwn(options, 'requestModuleIds') ? [...options.requestModuleIds] : Array.isArray(options.moduleIds) ? [...options.moduleIds] : [];
const requestIncludeComponentIds = Object.hasOwn(options, 'requestIncludeComponentIds')
? [...options.requestIncludeComponentIds]
: (Array.isArray(options.includeComponentIds) ? [...options.includeComponentIds] : []);
: Array.isArray(options.includeComponentIds)
? [...options.includeComponentIds]
: [];
const requestExcludeComponentIds = Object.hasOwn(options, 'requestExcludeComponentIds')
? [...options.requestExcludeComponentIds]
: (Array.isArray(options.excludeComponentIds) ? [...options.excludeComponentIds] : []);
: Array.isArray(options.excludeComponentIds)
? [...options.excludeComponentIds]
: [];
const plan = resolveInstallPlan({
repoRoot: sourceRoot,
projectRoot,
@@ -735,14 +713,14 @@ function createManifestInstallPlan(options = {}) {
moduleIds: options.moduleIds || [],
includeComponentIds: options.includeComponentIds || [],
excludeComponentIds: options.excludeComponentIds || [],
target,
target
});
const adapter = getInstallTargetAdapter(target);
const operations = plan.operations.flatMap(operation => materializeScaffoldOperation(sourceRoot, operation));
const source = {
repoVersion: getPackageVersion(sourceRoot),
repoCommit: getRepoCommit(sourceRoot),
manifestVersion: getManifestVersion(sourceRoot),
manifestVersion: getManifestVersion(sourceRoot)
};
const statePreview = createStatePreview({
adapter,
@@ -754,14 +732,14 @@ function createManifestInstallPlan(options = {}) {
includeComponents: requestIncludeComponentIds,
excludeComponents: requestExcludeComponentIds,
legacyLanguages,
legacyMode: Boolean(options.legacyMode),
legacyMode: Boolean(options.legacyMode)
},
resolution: {
selectedModules: plan.selectedModuleIds,
skippedModules: plan.skippedModuleIds,
skippedModules: plan.skippedModuleIds
},
operations,
source,
source
});
return {
@@ -770,7 +748,7 @@ function createManifestInstallPlan(options = {}) {
adapter: {
id: adapter.id,
target: adapter.target,
kind: adapter.kind,
kind: adapter.kind
},
targetRoot: plan.targetRoot,
installRoot: plan.targetRoot,
@@ -787,7 +765,7 @@ function createManifestInstallPlan(options = {}) {
skippedModuleIds: plan.skippedModuleIds,
excludedModuleIds: plan.excludedModuleIds,
operations,
statePreview,
statePreview
};
}
@@ -800,5 +778,5 @@ module.exports = {
createLegacyInstallPlan,
getSourceRoot,
listAvailableLanguages,
parseInstallArgs,
parseInstallArgs
};