mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
611147a333 | ||
|
|
7d5c60d291 |
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "Impeccable design detector: immediate-tier checks after Edit/Write/MultiEdit on UI files, full-rule deep pass on Stop.",
|
||||
"description": "Impeccable design detector: immediate-tier checks after Edit/Write on UI files, full-rule deep pass on Stop.",
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write|MultiEdit",
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write|MultiEdit",
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
|
||||
@@ -44,7 +44,7 @@ The first argument is the action. Defaults to `status`.
|
||||
```
|
||||
|
||||
3. If `<action>` is `off`, follow up with a one-line note: "Done. New edits will not trigger the design hook in this project until you run `/impeccable hooks on`."
|
||||
4. If `<action>` is `on`, follow up with: "Done. The design hook will fire after the next Edit/Write/MultiEdit on a UI file."
|
||||
4. If `<action>` is `on`, follow up with: "Done. The design hook will fire after the next Edit/Write on a UI file."
|
||||
5. If `<action>` is `ignore-value`, `ignore-file`, or `ignore-rule`, just print the script output. The default scope is shared `.impeccable/config.json`; add `--local` only when the user explicitly asks for a private exception.
|
||||
6. If `<action>` is `status`, just print the script output. Do not add commentary unless the user asked a follow-up question.
|
||||
|
||||
|
||||
@@ -75,11 +75,11 @@ const HOOK_MANIFEST_TARGETS = [
|
||||
destRel: '.claude/settings.local.json',
|
||||
sharedDestRel: '.claude/settings.json',
|
||||
manifest: () => ({
|
||||
description: 'Impeccable design detector: immediate-tier checks after Edit/Write/MultiEdit on UI files, full-rule deep pass on Stop.',
|
||||
description: 'Impeccable design detector: immediate-tier checks after Edit/Write on UI files, full-rule deep pass on Stop.',
|
||||
hooks: {
|
||||
PostToolUse: [
|
||||
{
|
||||
matcher: 'Edit|Write|MultiEdit',
|
||||
matcher: 'Edit|Write',
|
||||
hooks: [
|
||||
{
|
||||
type: 'command',
|
||||
|
||||
@@ -137,9 +137,9 @@ const GROK_PROJECT_HOOK = '.grok/skills/impeccable/scripts/hook.mjs';
|
||||
|
||||
export function buildClaudeSettingsManifest() {
|
||||
return {
|
||||
description: 'Impeccable design detector: immediate-tier checks after Edit/Write/MultiEdit on UI files, full-rule deep pass on Stop.',
|
||||
description: 'Impeccable design detector: immediate-tier checks after Edit/Write on UI files, full-rule deep pass on Stop.',
|
||||
hooks: buildClaudeCompatibleHooks(
|
||||
'Edit|Write|MultiEdit',
|
||||
'Edit|Write',
|
||||
CLAUDE_PROJECT_HOOK,
|
||||
SYSTEM_MESSAGE_NOTICE,
|
||||
),
|
||||
@@ -155,7 +155,7 @@ export function buildClaudeSettingsManifest() {
|
||||
export function buildClaudePluginHooksManifest() {
|
||||
return {
|
||||
hooks: buildClaudeCompatibleHooks(
|
||||
'Edit|Write|MultiEdit',
|
||||
'Edit|Write',
|
||||
CLAUDE_PLUGIN_HOOK,
|
||||
SYSTEM_MESSAGE_NOTICE,
|
||||
),
|
||||
|
||||
@@ -44,7 +44,7 @@ The first argument is the action. Defaults to `status`.
|
||||
```
|
||||
|
||||
3. If `<action>` is `off`, follow up with a one-line note: "Done. New edits will not trigger the design hook in this project until you run `{{command_prefix}}impeccable hooks on`."
|
||||
4. If `<action>` is `on`, follow up with: "Done. The design hook will fire after the next Edit/Write/MultiEdit on a UI file."
|
||||
4. If `<action>` is `on`, follow up with: "Done. The design hook will fire after the next Edit/Write on a UI file."
|
||||
5. If `<action>` is `ignore-value`, `ignore-file`, or `ignore-rule`, just print the script output. The default scope is shared `.impeccable/config.json`; add `--local` only when the user explicitly asks for a private exception.
|
||||
6. If `<action>` is `status`, just print the script output. Do not add commentary unless the user asked a follow-up question.
|
||||
|
||||
|
||||
@@ -75,11 +75,11 @@ const HOOK_MANIFEST_TARGETS = [
|
||||
destRel: '.claude/settings.local.json',
|
||||
sharedDestRel: '.claude/settings.json',
|
||||
manifest: () => ({
|
||||
description: 'Impeccable design detector: immediate-tier checks after Edit/Write/MultiEdit on UI files, full-rule deep pass on Stop.',
|
||||
description: 'Impeccable design detector: immediate-tier checks after Edit/Write on UI files, full-rule deep pass on Stop.',
|
||||
hooks: {
|
||||
PostToolUse: [
|
||||
{
|
||||
matcher: 'Edit|Write|MultiEdit',
|
||||
matcher: 'Edit|Write',
|
||||
hooks: [
|
||||
{
|
||||
type: 'command',
|
||||
|
||||
@@ -72,7 +72,8 @@ describe('hook manifest builders', () => {
|
||||
const group = manifest.hooks.PostToolUse[0];
|
||||
const handler = group.hooks[0];
|
||||
|
||||
assert.equal(group.matcher, 'Edit|Write|MultiEdit');
|
||||
assert.equal(group.matcher, 'Edit|Write');
|
||||
assert.doesNotMatch(manifest.description, /MultiEdit/);
|
||||
assert.equal(handler.type, 'command');
|
||||
assert.equal(handler.timeout, 5);
|
||||
assert.equal(handler.statusMessage, 'Checking UI changes');
|
||||
@@ -356,7 +357,7 @@ describe('generated hook artifacts in repo', () => {
|
||||
assert.equal(manifest.description, undefined);
|
||||
|
||||
const handler = manifest.hooks.PostToolUse[0].hooks[0];
|
||||
assert.equal(manifest.hooks.PostToolUse[0].matcher, 'Edit|Write|MultiEdit');
|
||||
assert.equal(manifest.hooks.PostToolUse[0].matcher, 'Edit|Write');
|
||||
expectCommand(handler.command, 'skills/impeccable/scripts/hook.mjs');
|
||||
// Resolves relative to the installed plugin, not a `.claude/skills/` layout.
|
||||
assert.ok(handler.command.includes('${CLAUDE_PLUGIN_ROOT}'),
|
||||
@@ -375,6 +376,15 @@ describe('generated hook artifacts in repo', () => {
|
||||
assert.ok(fs.existsSync(path.join(REPO_ROOT, 'plugin/skills/impeccable/scripts/hook-lib.mjs')));
|
||||
});
|
||||
|
||||
it('keeps the marketplace hook repair matcher aligned with Claude Code', () => {
|
||||
const hookAdmin = fs.readFileSync(
|
||||
path.join(REPO_ROOT, 'plugin/skills/impeccable/scripts/hook-admin.mjs'),
|
||||
'utf8',
|
||||
);
|
||||
assert.match(hookAdmin, /matcher: 'Edit\|Write'/);
|
||||
assert.doesNotMatch(hookAdmin, /matcher: 'Edit\|Write\|MultiEdit'/);
|
||||
});
|
||||
|
||||
it('generated hook runtime can import the bundled detector', async () => {
|
||||
for (const scriptDir of [
|
||||
'.claude/skills/impeccable/scripts',
|
||||
|
||||
@@ -947,6 +947,11 @@ describe('hook-admin.mjs', () => {
|
||||
// impeccable entry must have been stripped, not accumulated.
|
||||
assert.equal(claude.split('skills/impeccable/scripts/hook.mjs').length - 1, 2);
|
||||
assert.match(claude, /"Stop"/);
|
||||
const claudeManifest = JSON.parse(claude);
|
||||
const impeccableGroup = claudeManifest.hooks.PostToolUse.find((group) =>
|
||||
group.hooks?.some((hook) => hook.command?.includes('skills/impeccable/scripts/hook.mjs')));
|
||||
assert.ok(impeccableGroup, 'repaired Claude settings should contain the Impeccable PostToolUse group');
|
||||
assert.equal(impeccableGroup.matcher, 'Edit|Write');
|
||||
|
||||
const codex = fs.readFileSync(path.join(cwd, '.codex', 'hooks.json'), 'utf-8');
|
||||
assert.match(codex, /\.agents\/skills\/impeccable\/scripts\/hook\.mjs/);
|
||||
|
||||
Reference in New Issue
Block a user