fix: shrink default OpenCode install surface and gate hooks-runtime (#2140)

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
This commit is contained in:
Matt Van Horn 2026-06-06 22:26:14 -07:00 committed by GitHub
parent 53d4b7d664
commit 80233f1b72
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 70 additions and 8 deletions

View File

@ -11,6 +11,14 @@
"workflow-quality"
]
},
"opencode": {
"description": "Default OpenCode setup with commands, platform configs, and quality workflow support. It intentionally excludes hooks-runtime; opt in with --modules hooks-runtime.",
"modules": [
"commands-core",
"platform-configs",
"workflow-quality"
]
},
"core": {
"description": "Minimal harness baseline with commands, hooks, platform configs, and quality workflow support.",
"modules": [

View File

@ -111,6 +111,18 @@ const LEGACY_LANGUAGE_EXTRA_MODULE_IDS = Object.freeze({
swift: [],
typescript: ['framework-language'],
});
const TARGET_DEFAULT_PROFILE_IDS = Object.freeze({
opencode: 'opencode',
});
const TARGET_DEFAULT_EXCLUSIONS = Object.freeze({
opencode: [
{
moduleId: 'hooks-runtime',
reason: 'OpenCode defaults intentionally exclude hooks-runtime until users opt in.',
optInCommand: './install.sh --target opencode --modules hooks-runtime',
},
],
});
function readJson(filePath, label) {
try {
@ -416,6 +428,22 @@ function expandComponentIdsToModuleIds(componentIds, manifests) {
return dedupeStrings(expandedModuleIds);
}
function getTargetDefaultProfileId(target, manifests) {
const profileId = target ? TARGET_DEFAULT_PROFILE_IDS[target] : null;
return profileId && manifests.profiles[profileId] ? profileId : null;
}
function getTargetDefaultExclusions(target, manifests) {
const exclusions = target ? TARGET_DEFAULT_EXCLUSIONS[target] : null;
if (!Array.isArray(exclusions)) {
return [];
}
return exclusions
.filter(exclusion => manifests.modulesById.has(exclusion.moduleId))
.map(exclusion => ({ ...exclusion }));
}
function resolveLegacyCompatibilitySelection(options = {}) {
const manifests = loadInstallManifests(options);
const target = options.target || null;
@ -471,11 +499,29 @@ function resolveLegacyCompatibilitySelection(options = {}) {
function resolveInstallPlan(options = {}) {
const manifests = loadInstallManifests(options);
const profileId = options.profileId || null;
const requestedProfileId = options.profileId || null;
const explicitModuleIds = dedupeStrings(options.moduleIds);
const includedComponentIds = dedupeStrings(options.includeComponentIds);
const excludedComponentIds = dedupeStrings(options.excludeComponentIds);
const requestedModuleIds = [];
const target = options.target || null;
if (target && !SUPPORTED_INSTALL_TARGETS.includes(target)) {
throw new Error(
`Unknown install target: ${target}. Expected one of ${SUPPORTED_INSTALL_TARGETS.join(', ')}`
);
}
const shouldUseTargetDefaultProfile = !requestedProfileId
&& explicitModuleIds.length === 0
&& includedComponentIds.length === 0;
const targetDefaultProfileId = shouldUseTargetDefaultProfile
? getTargetDefaultProfileId(target, manifests)
: null;
const profileId = requestedProfileId || targetDefaultProfileId;
const targetDefaultExclusions = targetDefaultProfileId
? getTargetDefaultExclusions(target, manifests)
: [];
if (profileId) {
const profile = manifests.profiles[profileId];
@ -501,13 +547,12 @@ function resolveInstallPlan(options = {}) {
excludedModuleOwners.set(moduleId, owners);
}
}
const target = options.target || null;
if (target && !SUPPORTED_INSTALL_TARGETS.includes(target)) {
throw new Error(
`Unknown install target: ${target}. Expected one of ${SUPPORTED_INSTALL_TARGETS.join(', ')}`
);
for (const exclusion of targetDefaultExclusions) {
const owners = excludedModuleOwners.get(exclusion.moduleId) || [];
owners.push(`${target} default`);
excludedModuleOwners.set(exclusion.moduleId, owners);
}
const validatedProjectRoot = readOptionalStringOption(options, 'projectRoot');
const validatedHomeDir = readOptionalStringOption(options, 'homeDir');
const targetPlanningInput = target
@ -533,7 +578,10 @@ function resolveInstallPlan(options = {}) {
const selectedIds = new Set();
const skippedTargetIds = new Set();
const excludedIds = new Set(excludedModuleIds);
const excludedIds = new Set([
...excludedModuleIds,
...targetDefaultExclusions.map(exclusion => exclusion.moduleId),
]);
const visitingIds = new Set();
const resolvedIds = new Set();
@ -622,6 +670,12 @@ function resolveInstallPlan(options = {}) {
explicitModuleIds,
includedComponentIds,
excludedComponentIds,
targetDefaultProfileId,
targetDefaultExclusions,
warnings: targetDefaultExclusions.map(exclusion => (
`${exclusion.moduleId} is intentionally excluded from the OpenCode default. `
+ `Opt in with: ${exclusion.optInCommand}`
)),
selectedModuleIds: selectedModules.map(module => module.id),
skippedModuleIds: skippedModules.map(module => module.id),
excludedModuleIds: excludedModules.map(module => module.id),