Honor ancestor hook disable config

AI assistance disclosure: Codex implemented and verified this fix under maintainer direction.
This commit is contained in:
Paul Bakaus
2026-09-02 09:37:19 -07:00
parent 0e1f94acae
commit c2404197e4
2 changed files with 15 additions and 0 deletions
+3
View File
@@ -1352,6 +1352,9 @@ function automaticHookMode(ctx) {
if (!hookEnabledAt(activeRoot)) return 'none';
const manifests = HOOK_MANIFESTS_BY_PROVIDER[IMPECCABLE_PROVIDER_ID] || [];
for (const root of hookManifestSearchRoots(ctx)) {
// A manifest can live above the resolved product. Honor the hook lifecycle
// config beside that manifest before treating it as active coverage.
if (!hookEnabledAt(root)) continue;
for (const rel of manifests) {
const raw = readJson(path.join(root, rel));
if (raw?.hooks && valueHasHookMarker(raw.hooks)) {
+12
View File
@@ -1219,6 +1219,18 @@ describe('context.mjs CLI', () => {
});
assert.equal(res.status, 0, res.stderr);
assert.doesNotMatch(res.stdout, /MANUAL_DETECTOR_REQUIRED:/);
fs.mkdirSync(path.join(repo, '.impeccable'), { recursive: true });
fs.writeFileSync(path.join(repo, '.impeccable', 'config.local.json'), JSON.stringify({
hook: { enabled: false },
}));
const disabled = spawnSync(process.execPath, [path.join(scripts, 'context.mjs')], {
cwd: project,
encoding: 'utf8',
env: { ...process.env, IMPECCABLE_NO_UPDATE_CHECK: '1', IMPECCABLE_NO_STALENESS_CHECK: '1' },
});
assert.equal(disabled.status, 0, disabled.stderr);
assert.match(disabled.stdout, /MANUAL_DETECTOR_REQUIRED:/);
});
it('does not borrow a hook manifest from the invoking workspace when targeting a sibling', () => {