fix: disable Claude co-author attribution by default

This commit is contained in:
haelyra
2026-08-10 17:11:04 -04:00
parent ae303fb6c1
commit ea8f984be9
6 changed files with 208 additions and 28 deletions
+35 -7
View File
@@ -18,6 +18,7 @@ const OFFICIAL_MARKETPLACE_NAME = 'ecc';
const OFFICIAL_MARKETPLACE_REPO = 'affaan-m/ecc';
const OFFICIAL_MARKETPLACE_URL = 'https://github.com/affaan-m/ECC';
const PROVIDER_COMMAND_TIMEOUT_MS = 120 * 1000;
const CLAUDE_COAUTHOR_SETTING_KEY = 'includeCoAuthoredBy';
const VALID_SCOPES = new Set(['user', 'project', 'local']);
const VALID_HOOK_MODES = new Set(['off', 'minimal', 'standard', 'strict']);
@@ -320,21 +321,39 @@ function deriveHookMode(settings) {
return options.hooks_enabled ? options.hook_profile : 'off';
}
function withClaudeCommitAttributionPreference(settings) {
if (settings?.[CLAUDE_COAUTHOR_SETTING_KEY] === true) {
return settings;
}
return {
...settings,
[CLAUDE_COAUTHOR_SETTING_KEY]: false,
};
}
function needsClaudeCommitAttributionPreferenceWrite(settings) {
return settings?.[CLAUDE_COAUTHOR_SETTING_KEY] !== false
&& settings?.[CLAUDE_COAUTHOR_SETTING_KEY] !== true;
}
function writeClaudePluginOptions(settingsPath, hooks) {
const settings = readSettings(settingsPath);
const pluginConfigs = settings.pluginConfigs || {};
const eccConfig = pluginConfigs[CURRENT_PLUGIN_ID] || {};
const options = eccConfig.options || {};
const nextOptions = hooks === undefined
? { ...options }
: {
...options,
...hookOptions(hooks),
};
const nextSettings = {
...settings,
...withClaudeCommitAttributionPreference(settings),
pluginConfigs: {
...pluginConfigs,
[CURRENT_PLUGIN_ID]: {
...eccConfig,
options: {
...options,
...hookOptions(hooks),
},
options: nextOptions,
},
},
};
@@ -609,8 +628,15 @@ function setupClaudePlugin(options = {}, dependencies = {}) {
run,
scope: inventory.scope,
});
if (options.hooks !== undefined || !inventory.installed) {
writeClaudePluginOptions(settingsPath, hooks);
const hooksToPersist = options.hooks !== undefined || !inventory.installed
? hooks
: undefined;
if (
options.hooks !== undefined
|| !inventory.installed
|| needsClaudeCommitAttributionPreferenceWrite(initialSettings)
) {
writeClaudePluginOptions(settingsPath, hooksToPersist);
}
return {
@@ -648,5 +674,7 @@ module.exports = {
runClaude,
setupClaudePlugin,
verifyPluginAtScope,
needsClaudeCommitAttributionPreferenceWrite,
withClaudeCommitAttributionPreference,
writeClaudePluginOptions,
};
+22 -8
View File
@@ -16,6 +16,7 @@ const {
ensurePluginAtScope,
hookOptions,
isOfficialMarketplace,
needsClaudeCommitAttributionPreferenceWrite,
parseMarketplaceList,
parsePluginList,
readSettings,
@@ -264,6 +265,7 @@ function migrateClaudePluginScope(options = {}, dependencies = {}) {
const hookConfiguration = options.hooks === undefined
? readStoredHookOptions(settings)
: hookOptions(options.hooks);
const needsCommitAttributionPreference = needsClaudeCommitAttributionPreferenceWrite(settings);
const marketplaces = parseMarketplaceList(
run(
@@ -296,14 +298,23 @@ function migrateClaudePluginScope(options = {}, dependencies = {}) {
...result,
dryRun: true,
preferencesUpdated: false,
plannedActions: options.hooks === undefined ? [] : [{
action: 'write-hook-preferences',
...hookConfiguration,
}],
plannedActions: [
...(options.hooks === undefined ? [] : [{
action: 'write-hook-preferences',
...hookConfiguration,
}]),
...(needsCommitAttributionPreference ? [{
action: 'write-commit-attribution-preference',
includeCoAuthoredBy: false,
}] : []),
],
};
}
if (options.hooks !== undefined) {
writeClaudePluginOptions(settingsPath, options.hooks);
if (options.hooks !== undefined || needsCommitAttributionPreference) {
writeClaudePluginOptions(
settingsPath,
options.hooks !== undefined ? options.hooks : undefined
);
return { ...result, preferencesUpdated: true };
}
return result;
@@ -371,8 +382,11 @@ function migrateClaudePluginScope(options = {}, dependencies = {}) {
const warnings = uninstallSource(run, paths, migration, options.scope);
verifyFinalState(run, paths, options.scope);
if (options.hooks !== undefined) {
writeClaudePluginOptions(settingsPath, options.hooks);
if (options.hooks !== undefined || needsCommitAttributionPreference) {
writeClaudePluginOptions(
settingsPath,
options.hooks !== undefined ? options.hooks : undefined
);
}
const result = {
+45
View File
@@ -105,6 +105,46 @@ function formatJson(value) {
return `${JSON.stringify(value, null, 2)}\n`;
}
function shouldSetClaudeCommitAttributionPreference(plan) {
if (!plan?.adapter || !['claude', 'claude-project'].includes(plan.adapter.target)) {
return false;
}
return plan.operations.some(operation => {
if (typeof operation?.destinationPath !== 'string') {
return false;
}
const relativePath = path.relative(plan.targetRoot, operation.destinationPath);
return relativePath && !relativePath.startsWith(`docs${path.sep}`) && relativePath !== 'docs';
});
}
function writeClaudeCommitAttributionPreference(settingsPath) {
let settings = {};
if (fs.existsSync(settingsPath)) {
try {
settings = readJsonObject(settingsPath, 'Claude settings');
} catch (_error) {
return false;
}
}
if (settings.includeCoAuthoredBy === true) {
return false;
}
fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
fs.writeFileSync(
settingsPath,
formatJson({
...settings,
includeCoAuthoredBy: false,
}),
'utf8'
);
return true;
}
function replacePluginRootPlaceholders(value, pluginRoot) {
if (!pluginRoot) {
return value;
@@ -325,6 +365,11 @@ function applyInstallPlan(plan, dependencies = {}) {
if (hasLegacyMigration) {
removeLegacyClaudeSkillFiles(migration, plan.targetRoot);
}
if (shouldSetClaudeCommitAttributionPreference(appliedPlan)) {
writeClaudeCommitAttributionPreference(path.join(plan.targetRoot, 'settings.json'));
}
const finalState = stateWithContentDigests(migration.finalState);
if (typeof beforeInstallStateWrite === 'function') {
beforeInstallStateWrite({ plan: appliedPlan, state: finalState });