@shirayner/ace 0.1.9-SNAPSHOT → 0.1.11-SNAPSHOT

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shirayner/ace",
3
- "version": "0.1.9-SNAPSHOT",
3
+ "version": "0.1.11-SNAPSHOT",
4
4
  "description": "AI Coding Environment - One command to set up your Claude Code harness",
5
5
  "bin": {
6
6
  "ace": "./bin/ace.js"
@@ -21,6 +21,19 @@ description: |
21
21
 
22
22
  ## 硬规则(不可跳过)
23
23
 
24
+ ### 规则 0:Pre-execution Checkpoint(结构性屏障)
25
+
26
+ **在发出第一个修改性工具调用(Edit/Write/创建或修改文件的 Bash)之前,必须通过此检查:**
27
+
28
+ > 我是否已完成 Step 3 的对齐确认,且用户已通过 AskUserQuestion 确认?
29
+
30
+ - **是** → 继续执行
31
+ - **否** → **立即停止**,返回规则 1 执行对齐流程
32
+
33
+ 此规则存在的原因:auto mode 的"立即执行"指令会与对齐要求冲突。当模型感到"这个任务很简单,不需要对齐"时,恰恰是最需要对齐的时刻——因为"简单"往往意味着隐含决策被忽略了。
34
+
35
+ **Auto mode 优化的是执行效率,不是对齐质量。跳过对齐不是"更快"——是"更可能做错"。**
36
+
24
37
  ### 规则 1:首轮对齐(MANDATORY — 优先于 auto mode)
25
38
 
26
39
  接收目标后,**必须完成以下三步才能开始执行**。
@@ -35,7 +48,14 @@ description: |
35
48
 
36
49
  目标:不只是理解用户说了什么,而是理解用户**真正需要**什么——包括他们自己可能没意识到的部分。
37
50
 
38
- **Step 2: 澄清** — **调用 AskUserQuestion 工具**向用户批量澄清歧义和关键决策点。复杂项目可多轮澄清。仅当目标完全明确无歧义时可跳过。
51
+ **Step 2: 澄清** — **调用 AskUserQuestion 工具**向用户批量澄清歧义和关键决策点。复杂项目可多轮澄清。
52
+
53
+ 跳过条件(必须**同时满足全部**才可跳过 Step 2,直接进入 Step 3):
54
+ - 用户在**同一会话中**已明确表达过完整意图,且你在 Step 1 分析后未发现任何隐含决策点
55
+ - 不存在"用户可能会惊讶"的假设需要验证
56
+ - 任务是对前一个已对齐目标的延续性修复(而非新目标)
57
+
58
+ **如果不确定是否需要澄清 → 澄清。** 默认执行,跳过是例外。
39
59
 
40
60
  澄清时采用引导性提问(而非纯选择题):
41
61
  - "你提到了 X,但我注意到这还关联到 Y——这是否也在范围内?"
@@ -14,7 +14,6 @@ const componentLabels = {
14
14
  rules: 'Rules',
15
15
  plugin: 'Plugin',
16
16
  hooks: 'Hooks',
17
- hookify: 'Safety Guards',
18
17
  memory: 'Memory',
19
18
  };
20
19
 
@@ -155,7 +154,7 @@ export async function initCommand(options) {
155
154
  'Customize',
156
155
  ' Change role edit ~/.claude/memory/user_profile.md',
157
156
  ' Adjust rules edit ~/.claude/ace/rules/',
158
- ' Safety guards edit ~/.claude/hookify.ace.*.local.md',
157
+ ' Safety guards edit ~/.claude/hooks/ace.*.sh',
159
158
  ' Verify setup ace doctor',
160
159
  ].join('\n'),
161
160
  'Next steps'
@@ -17,7 +17,7 @@ export async function uninstallCommand(options) {
17
17
  const { confirm } = await inquirer.prompt([{
18
18
  type: 'confirm',
19
19
  name: 'confirm',
20
- message: 'This will remove all ace-managed files (rules, plugin, hooks, hookify rules). Continue?',
20
+ message: 'This will remove all ace-managed files (rules, plugin, hooks). Continue?',
21
21
  default: false,
22
22
  }]);
23
23
  if (!confirm) {
@@ -96,38 +96,44 @@ export async function uninstallCommand(options) {
96
96
  errors.push({ component: 'plugin', error: err.message });
97
97
  }
98
98
 
99
- // 3. Remove hookify rules
100
- const spinner3 = ora('Removing hookify rules...').start();
99
+ // 3. Remove hook scripts
100
+ const spinner3 = ora('Removing hooks...').start();
101
101
  try {
102
- const hookifyFiles = COMPONENTS.hookify.files;
103
- for (const file of hookifyFiles) {
102
+ const hookFiles = [...(COMPONENTS.hooks.files || []), ...(COMPONENTS.hooks.conditional || [])];
103
+ for (const file of hookFiles) {
104
104
  const destPath = path.join(CLAUDE_DIR, file.dest);
105
105
  if (await fs.pathExists(destPath)) {
106
106
  await fs.remove(destPath);
107
107
  removed.push(file.dest);
108
108
  }
109
109
  }
110
- spinner3.succeed('hookify rules removed');
110
+ spinner3.succeed('hooks removed');
111
111
  } catch (err) {
112
- spinner3.fail('hookify rules removal failed');
113
- errors.push({ component: 'hookify', error: err.message });
112
+ spinner3.fail('hooks removal failed');
113
+ errors.push({ component: 'hooks', error: err.message });
114
114
  }
115
115
 
116
- // 4. Remove hook scripts
117
- const spinner4 = ora('Removing hooks...').start();
116
+ // 4. Remove legacy hookify rules (cleanup from older versions)
117
+ const spinner4 = ora('Removing legacy hookify rules...').start();
118
118
  try {
119
- const hookFiles = COMPONENTS.hooks.conditional;
120
- for (const file of hookFiles) {
121
- const destPath = path.join(CLAUDE_DIR, file.dest);
122
- if (await fs.pathExists(destPath)) {
123
- await fs.remove(destPath);
124
- removed.push(file.dest);
119
+ const hookifyPattern = /^hookify\.ace\..+\.local\.md$/;
120
+ const claudeFiles = await fs.readdir(CLAUDE_DIR);
121
+ let hookifyRemoved = 0;
122
+ for (const file of claudeFiles) {
123
+ if (hookifyPattern.test(file)) {
124
+ await fs.remove(path.join(CLAUDE_DIR, file));
125
+ removed.push(file);
126
+ hookifyRemoved++;
125
127
  }
126
128
  }
127
- spinner4.succeed('hooks removed');
129
+ if (hookifyRemoved > 0) {
130
+ spinner4.succeed(`legacy hookify rules removed (${hookifyRemoved})`);
131
+ } else {
132
+ spinner4.succeed('no legacy hookify rules found');
133
+ }
128
134
  } catch (err) {
129
- spinner4.fail('hooks removal failed');
130
- errors.push({ component: 'hooks', error: err.message });
135
+ spinner4.fail('legacy hookify removal failed');
136
+ errors.push({ component: 'hookify-legacy', error: err.message });
131
137
  }
132
138
 
133
139
  // 5. Restore CLAUDE.md and settings.json from pre-install backups
@@ -17,9 +17,9 @@ export const MARKETPLACE_DIR = path.join(CLAUDE_DIR, 'plugins', 'marketplaces',
17
17
  export const PLUGIN_KEY = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
18
18
 
19
19
  export const PRESETS = {
20
- full: ['core', 'rules', 'plugin', 'hooks', 'hookify', 'memory'],
20
+ full: ['core', 'rules', 'plugin', 'hooks', 'memory'],
21
21
  minimal: ['core', 'rules', 'plugin'],
22
- safe: ['core', 'rules', 'plugin', 'hookify', 'memory'],
22
+ safe: ['core', 'rules', 'plugin', 'memory'],
23
23
  };
24
24
 
25
25
  export const ROLES = {
@@ -58,13 +58,12 @@ export const SPEC_TEMPLATE_FILES = [
58
58
 
59
59
  /**
60
60
  * Patterns for files owned by ACE - these are overwritten directly on init without prompting.
61
- * Used to identify ACE-owned content in ace/, hooks/, and hookify/.
61
+ * Used to identify ACE-owned content in ace/ and hooks/.
62
62
  */
63
63
  export const ACE_OWNED_PATTERNS = [
64
64
  /^ace\/rules\//, // ace/rules/*.md (v2.0+)
65
65
  /^rules\/ace\//, // rules/ace/*.md (legacy, for migration detection)
66
66
  /^hooks\/ace\./, // hooks/ace.*.sh
67
- /^hookify\.ace\./, // hookify.ace.*.local.md
68
67
  ];
69
68
 
70
69
  /**
@@ -120,19 +119,6 @@ export const COMPONENTS = {
120
119
  { src: 'hooks/ace.java-compile-check.sh', dest: 'hooks/ace.java-compile-check.sh', roles: ['backend', 'fullstack'] },
121
120
  ],
122
121
  },
123
- hookify: {
124
- description: 'Safety guard rules (block dangerous ops, protect secrets, safe git, code quality, require verification)',
125
- required: false,
126
- files: [
127
- { src: 'hookify/hookify.ace.block-dangerous-ops.local.md', dest: 'hookify.ace.block-dangerous-ops.local.md' },
128
- { src: 'hookify/hookify.ace.protect-secrets.local.md', dest: 'hookify.ace.protect-secrets.local.md' },
129
- { src: 'hookify/hookify.ace.safe-git-commands.local.md', dest: 'hookify.ace.safe-git-commands.local.md' },
130
- { src: 'hookify/hookify.ace.code-quality-gate.local.md', dest: 'hookify.ace.code-quality-gate.local.md' },
131
- { src: 'hookify/hookify.ace.require-verification.local.md', dest: 'hookify.ace.require-verification.local.md' },
132
- { src: 'hookify/hookify.ace.dangerous-commands.local.md', dest: 'hookify.ace.dangerous-commands.local.md' },
133
- { src: 'hookify/hookify.ace.sensitive-data.local.md', dest: 'hookify.ace.sensitive-data.local.md' },
134
- ],
135
- },
136
122
  memory: {
137
123
  description: 'Global memory templates',
138
124
  required: false,
package/src/core/ui.js CHANGED
@@ -92,6 +92,5 @@ export const componentLabels = {
92
92
  rules: 'Rules',
93
93
  plugin: 'Plugin',
94
94
  hooks: 'Hooks',
95
- hookify: 'Safety Guards',
96
95
  memory: 'Memory',
97
96
  };
@@ -26,11 +26,10 @@
26
26
  - ~/.claude/ace/rules/gitflow.md — GitFlow 工作流(分支管理时阅读)
27
27
 
28
28
  ## 流程门禁优先级
29
- Auto mode 不覆盖 aspec/OpenSpec 流程门禁。标注"不可跳过"的门禁步骤(需求澄清、设计澄清、审批确认)在任何执行模式下均必须执行,不得以"减少打断"为由跳过。
29
+ Auto mode 不覆盖 auto-goal/aspec/OpenSpec 流程门禁。标注"不可跳过"的门禁步骤(需求澄清、设计澄清、审批确认)在任何执行模式下均必须执行,不得以"减少打断"为由跳过。
30
30
 
31
31
  ## 安全策略
32
32
  安全由外部机制保障,不占用上下文 token:
33
33
  - settings.json deny 规则 → 硬拦截 rm -rf、sudo 等
34
- - Shell hooks → 进程级检查(编译、类型检查)
35
- - Hookify 插件 → 模式匹配拦截(危险命令、敏感文件)
34
+ - Shell hooks → 进程级检查(编译、类型检查、内容审查)
36
35
  <!-- ace:managed:end -->
@@ -1,4 +1,5 @@
1
1
  {
2
+ "effortLevel": "high",
2
3
  "permissions": {
3
4
  "allow": [
4
5
  "Bash(*)",
@@ -92,6 +93,10 @@
92
93
  }
93
94
  ]
94
95
  },
96
+ "statusLine": {
97
+ "type": "command",
98
+ "command": "bash ~/.claude/scripts/statusline-command.sh"
99
+ },
95
100
  "enabledPlugins": {
96
101
  "revealjs@revealjs-skill": true,
97
102
  "ace@ace-local": true