helloagents 3.0.30 → 3.0.32
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +7 -19
- package/README_CN.md +8 -20
- package/bootstrap-lite.md +18 -18
- package/bootstrap.md +18 -18
- package/gemini-extension.json +1 -1
- package/install.ps1 +3 -3
- package/install.sh +3 -3
- package/package.json +1 -1
- package/scripts/advisor-state.mjs +1 -1
- package/scripts/cli-config.mjs +8 -0
- package/scripts/cli-doctor.mjs +2 -76
- package/scripts/cli-host-detect.mjs +0 -29
- package/scripts/cli-hosts.mjs +0 -8
- package/scripts/cli-lifecycle-hosts.mjs +1 -22
- package/scripts/cli-lifecycle.mjs +17 -3
- package/scripts/cli-messages.mjs +12 -24
- package/scripts/guard.mjs +1 -1
- package/scripts/notify-context.mjs +7 -2
- package/scripts/notify-events.mjs +0 -5
- package/scripts/notify-route.mjs +1 -1
- package/scripts/notify-source.mjs +0 -1
- package/scripts/plan-contract.mjs +1 -1
- package/scripts/ralph-loop.mjs +35 -0
- package/scripts/runtime-scope.mjs +1 -1
- package/scripts/turn-stop-gate.mjs +5 -5
- package/skills/commands/auto/SKILL.md +2 -2
- package/skills/commands/build/SKILL.md +3 -3
- package/skills/commands/global/SKILL.md +1 -1
- package/skills/commands/help/SKILL.md +11 -11
- package/skills/commands/loop/SKILL.md +1 -1
- package/skills/commands/plan/SKILL.md +1 -1
- package/skills/commands/prd/SKILL.md +1 -1
- package/skills/commands/test/SKILL.md +1 -1
- package/skills/commands/verify/SKILL.md +5 -5
- package/skills/hello-review/SKILL.md +1 -1
- package/skills/hello-subagent/SKILL.md +2 -2
- package/skills/hello-ui/SKILL.md +1 -1
- package/skills/hello-verify/SKILL.md +7 -7
- package/skills/helloagents/SKILL.md +7 -7
- package/scripts/cli-deepseek.mjs +0 -131
package/scripts/cli-doctor.mjs
CHANGED
|
@@ -3,10 +3,9 @@ import { join } from 'node:path'
|
|
|
3
3
|
|
|
4
4
|
import { DEFAULTS } from './cli-config.mjs'
|
|
5
5
|
import { inspectCodexDoctor as inspectCodexDoctorImpl } from './cli-doctor-codex.mjs'
|
|
6
|
-
import { inspectNativeDeepseekDoctor } from './cli-deepseek.mjs'
|
|
7
6
|
import { printDoctorText } from './cli-doctor-render.mjs'
|
|
8
7
|
import { buildRuntimeCarrier } from './cli-runtime-carrier.mjs'
|
|
9
|
-
import {
|
|
8
|
+
import { loadHooksWithCliEntry, safeJson, safeRead } from './cli-utils.mjs'
|
|
10
9
|
|
|
11
10
|
const runtime = {
|
|
12
11
|
home: '',
|
|
@@ -219,78 +218,6 @@ function inspectGeminiDoctor(settings) {
|
|
|
219
218
|
return { host, label: runtime.getHostLabel(host), trackedMode, detectedMode, status, checks, issues, notes, suggestedFix: suggestDoctorFix(host, status, trackedMode) }
|
|
220
219
|
}
|
|
221
220
|
|
|
222
|
-
function inspectDeepseekDoctor(settings) {
|
|
223
|
-
const host = 'deepseek'
|
|
224
|
-
const trackedMode = normalizeDoctorMode(runtime.getTrackedHostMode(settings, host))
|
|
225
|
-
const detectedMode = normalizeDoctorMode(runtime.detectHostMode(host))
|
|
226
|
-
const deepseekDir = join(runtime.home, '.deepseek')
|
|
227
|
-
const carrierPath = join(deepseekDir, 'AGENTS.md')
|
|
228
|
-
const expectedCarrierFile = (detectedMode === 'global' || (detectedMode === 'none' && trackedMode === 'global'))
|
|
229
|
-
? 'bootstrap.md'
|
|
230
|
-
: 'bootstrap-lite.md'
|
|
231
|
-
const checks = {
|
|
232
|
-
carrierMarker: (safeRead(carrierPath) || '').includes('HELLOAGENTS_START'),
|
|
233
|
-
carrierContentMatch: extractManagedCarrierContent(carrierPath)
|
|
234
|
-
=== readExpectedCarrierContent(
|
|
235
|
-
expectedCarrierFile,
|
|
236
|
-
settings,
|
|
237
|
-
expectedCarrierFile === 'bootstrap.md' ? { profile: 'full' } : {},
|
|
238
|
-
),
|
|
239
|
-
homeLink: safeRealTarget(join(deepseekDir, 'helloagents')) === runtime.pkgRoot,
|
|
240
|
-
fullProfile: (safeRead(carrierPath) || '').includes(FULL_CARRIER_PROFILE_MARKER),
|
|
241
|
-
}
|
|
242
|
-
const nativeDoctor = inspectNativeDeepseekDoctor()
|
|
243
|
-
const issues = []
|
|
244
|
-
const notes = []
|
|
245
|
-
|
|
246
|
-
if (trackedMode !== 'none' && detectedMode !== 'none' && trackedMode !== detectedMode) {
|
|
247
|
-
issues.push(buildDoctorIssue('tracked-mode-mismatch', '记录模式与检测模式不一致', 'Tracked mode does not match detected mode'))
|
|
248
|
-
}
|
|
249
|
-
if (detectedMode === 'standby') {
|
|
250
|
-
if (!checks.carrierMarker) issues.push(buildDoctorIssue('standby-carrier-missing', 'standby `~/.deepseek/AGENTS.md` 缺少 HelloAGENTS 标记', 'Standby `~/.deepseek/AGENTS.md` is missing the HELLOAGENTS marker'))
|
|
251
|
-
if (checks.carrierMarker && !checks.carrierContentMatch) issues.push(buildDoctorIssue('standby-carrier-drift', 'standby `~/.deepseek/AGENTS.md` 与当前标准模式规则不一致', 'Standby `~/.deepseek/AGENTS.md` differs from the current standby rules'))
|
|
252
|
-
if (!checks.homeLink) issues.push(buildDoctorIssue('standby-link-missing', 'standby `~/.deepseek/helloagents` 链接缺失或未指向稳定运行根目录', 'Standby `~/.deepseek/helloagents` link is missing or points to a different runtime root'))
|
|
253
|
-
if (checks.fullProfile) issues.push(buildDoctorIssue('standby-full-profile-residue', 'standby 模式下不应保留 full 标记', 'Standby mode should not keep the full profile marker'))
|
|
254
|
-
}
|
|
255
|
-
if (detectedMode === 'global') {
|
|
256
|
-
if (!checks.carrierMarker) issues.push(buildDoctorIssue('global-carrier-missing', 'global `~/.deepseek/AGENTS.md` 缺少 HelloAGENTS 标记', 'Global `~/.deepseek/AGENTS.md` is missing the HELLOAGENTS marker'))
|
|
257
|
-
if (checks.carrierMarker && !checks.carrierContentMatch) issues.push(buildDoctorIssue('global-carrier-drift', 'global `~/.deepseek/AGENTS.md` 与当前全局模式规则不一致', 'Global `~/.deepseek/AGENTS.md` differs from the current global rules'))
|
|
258
|
-
if (!checks.homeLink) issues.push(buildDoctorIssue('global-link-missing', 'global `~/.deepseek/helloagents` 链接缺失或未指向稳定运行根目录', 'Global `~/.deepseek/helloagents` link is missing or points to a different runtime root'))
|
|
259
|
-
if (!checks.fullProfile) issues.push(buildDoctorIssue('global-full-profile-missing', 'global 模式缺少 full 标记', 'Global mode is missing the full profile marker'))
|
|
260
|
-
}
|
|
261
|
-
if (trackedMode === 'none' && detectedMode !== 'none') {
|
|
262
|
-
issues.push(buildDoctorIssue('untracked-managed-state', '检测到受管状态,但配置中未记录该 CLI 模式', 'Managed state detected but this CLI mode is not tracked in config'))
|
|
263
|
-
}
|
|
264
|
-
if (trackedMode !== 'none' && detectedMode === 'none') {
|
|
265
|
-
issues.push(buildDoctorIssue('tracked-state-missing', '配置记录该 CLI 已安装,但未检测到对应的受管文件或配置', 'Config says this CLI is installed, but no managed artifacts were detected'))
|
|
266
|
-
}
|
|
267
|
-
if (!nativeDoctor.available) {
|
|
268
|
-
notes.push(runtime.msg(
|
|
269
|
-
'未找到 deepseek 命令;已跳过 DeepSeek 原生 doctor。',
|
|
270
|
-
'The deepseek command was not found; DeepSeek native doctor was skipped.',
|
|
271
|
-
))
|
|
272
|
-
} else if (!nativeDoctor.ok) {
|
|
273
|
-
issues.push(buildDoctorIssue('native-doctor-failed', 'DeepSeek 原生 doctor 返回非零状态', 'DeepSeek native doctor returned a non-zero status'))
|
|
274
|
-
}
|
|
275
|
-
if (nativeDoctor.available && nativeDoctor.parseError) {
|
|
276
|
-
issues.push(buildDoctorIssue('native-doctor-invalid-json', 'DeepSeek 原生 doctor 输出不是可解析的 JSON', 'DeepSeek native doctor output was not valid JSON'))
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const status = summarizeDoctorStatus(issues, { host, trackedMode, detectedMode })
|
|
280
|
-
return {
|
|
281
|
-
host,
|
|
282
|
-
label: runtime.getHostLabel(host),
|
|
283
|
-
trackedMode,
|
|
284
|
-
detectedMode,
|
|
285
|
-
status,
|
|
286
|
-
checks,
|
|
287
|
-
issues,
|
|
288
|
-
notes,
|
|
289
|
-
nativeDoctor,
|
|
290
|
-
suggestedFix: suggestDoctorFix(host, status, trackedMode),
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
221
|
function parseDoctorArgs(args) {
|
|
295
222
|
const wantsJson = args.includes('--json')
|
|
296
223
|
const unknownFlags = args.filter((arg) => arg.startsWith('--') && arg !== '--json' && arg !== '--all')
|
|
@@ -311,13 +238,12 @@ function parseDoctorArgs(args) {
|
|
|
311
238
|
function inspectDoctorHost(host, settings) {
|
|
312
239
|
if (host === 'claude') return inspectClaudeDoctor(settings)
|
|
313
240
|
if (host === 'gemini') return inspectGeminiDoctor(settings)
|
|
314
|
-
if (host === 'deepseek') return inspectDeepseekDoctor(settings)
|
|
315
241
|
return inspectCodexDoctorImpl(runtime, settings)
|
|
316
242
|
}
|
|
317
243
|
|
|
318
244
|
function buildDoctorReport(host) {
|
|
319
245
|
const settings = runtime.readSettings(true)
|
|
320
|
-
const hosts = host === 'all' ? ['claude', 'gemini', 'codex'
|
|
246
|
+
const hosts = host === 'all' ? ['claude', 'gemini', 'codex'] : [host]
|
|
321
247
|
const reports = hosts.map((target) => inspectDoctorHost(target, settings))
|
|
322
248
|
const summary = reports.reduce((acc, report) => {
|
|
323
249
|
acc[report.status] = (acc[report.status] || 0) + 1
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
CODEX_PLUGIN_NAME,
|
|
8
8
|
} from './cli-codex.mjs'
|
|
9
9
|
import { getStableRuntimeRoot } from './cli-runtime-root.mjs'
|
|
10
|
-
import { FULL_CARRIER_PROFILE_MARKER } from './cli-utils.mjs'
|
|
11
10
|
import { safeJson, safeRead } from './cli-utils.mjs'
|
|
12
11
|
|
|
13
12
|
const HOST_ALIASES = new Map([
|
|
@@ -19,8 +18,6 @@ const HOST_ALIASES = new Map([
|
|
|
19
18
|
['gemini-cli', 'gemini'],
|
|
20
19
|
['codex', 'codex'],
|
|
21
20
|
['codex-cli', 'codex'],
|
|
22
|
-
['deepseek', 'deepseek'],
|
|
23
|
-
['deepseek-tui', 'deepseek'],
|
|
24
21
|
])
|
|
25
22
|
|
|
26
23
|
function hasHelloagentsMarker(filePath) {
|
|
@@ -31,10 +28,6 @@ function hasHelloagentsSettings(filePath) {
|
|
|
31
28
|
return JSON.stringify(safeJson(filePath) || {}).includes('helloagents')
|
|
32
29
|
}
|
|
33
30
|
|
|
34
|
-
function hasFullCarrierProfile(filePath) {
|
|
35
|
-
return (safeRead(filePath) || '').includes(FULL_CARRIER_PROFILE_MARKER)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
31
|
function normalizePath(value = '') {
|
|
39
32
|
return String(value || '').replace(/\\/g, '/').toLowerCase()
|
|
40
33
|
}
|
|
@@ -97,26 +90,6 @@ function detectCodexMode(home) {
|
|
|
97
90
|
return ''
|
|
98
91
|
}
|
|
99
92
|
|
|
100
|
-
function detectDeepseekMode(home) {
|
|
101
|
-
const deepseekDir = join(home, '.deepseek')
|
|
102
|
-
const carrierPath = join(deepseekDir, 'AGENTS.md')
|
|
103
|
-
const runtimeRoot = normalizePath(getStableRuntimeRoot(home))
|
|
104
|
-
const homeLinkTarget = safeRealTarget(join(deepseekDir, 'helloagents'))
|
|
105
|
-
if (
|
|
106
|
-
(hasHelloagentsMarker(carrierPath) || (existsSync(join(deepseekDir, 'helloagents')) && homeLinkTarget === runtimeRoot))
|
|
107
|
-
&& hasFullCarrierProfile(carrierPath)
|
|
108
|
-
) {
|
|
109
|
-
return 'global'
|
|
110
|
-
}
|
|
111
|
-
if (
|
|
112
|
-
(existsSync(join(deepseekDir, 'helloagents')) && homeLinkTarget === runtimeRoot)
|
|
113
|
-
|| hasHelloagentsMarker(carrierPath)
|
|
114
|
-
) {
|
|
115
|
-
return 'standby'
|
|
116
|
-
}
|
|
117
|
-
return ''
|
|
118
|
-
}
|
|
119
|
-
|
|
120
93
|
export function normalizeHost(value = '') {
|
|
121
94
|
return HOST_ALIASES.get(String(value || '').toLowerCase()) || ''
|
|
122
95
|
}
|
|
@@ -125,7 +98,6 @@ export function getHostLabel(host) {
|
|
|
125
98
|
if (host === 'claude') return 'Claude Code'
|
|
126
99
|
if (host === 'gemini') return 'Gemini CLI'
|
|
127
100
|
if (host === 'codex') return 'Codex CLI'
|
|
128
|
-
if (host === 'deepseek') return 'DeepSeek TUI'
|
|
129
101
|
return 'All CLIs'
|
|
130
102
|
}
|
|
131
103
|
|
|
@@ -133,6 +105,5 @@ export function detectHostMode(host, runtime) {
|
|
|
133
105
|
if (host === 'claude') return detectClaudeMode(runtime.home)
|
|
134
106
|
if (host === 'gemini') return detectGeminiMode(runtime.home)
|
|
135
107
|
if (host === 'codex') return detectCodexMode(runtime.home)
|
|
136
|
-
if (host === 'deepseek') return detectDeepseekMode(runtime.home)
|
|
137
108
|
return ''
|
|
138
109
|
}
|
package/scripts/cli-hosts.mjs
CHANGED
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
loadHooksWithCliEntry,
|
|
13
13
|
} from './cli-utils.mjs';
|
|
14
14
|
import { buildRuntimeCarrier, readCarrierSettings } from './cli-runtime-carrier.mjs';
|
|
15
|
-
import { installDeepseekGlobal, installDeepseekStandby, uninstallDeepseekGlobal, uninstallDeepseekStandby } from './cli-deepseek.mjs'
|
|
16
15
|
|
|
17
16
|
export function installClaudeStandby(home, pkgRoot) {
|
|
18
17
|
const claudeDir = join(home, '.claude');
|
|
@@ -82,10 +81,3 @@ export function uninstallGeminiStandby(home) {
|
|
|
82
81
|
|
|
83
82
|
return true;
|
|
84
83
|
}
|
|
85
|
-
|
|
86
|
-
export {
|
|
87
|
-
installDeepseekGlobal,
|
|
88
|
-
installDeepseekStandby,
|
|
89
|
-
uninstallDeepseekGlobal,
|
|
90
|
-
uninstallDeepseekStandby,
|
|
91
|
-
}
|
|
@@ -2,12 +2,8 @@ import { spawnSync } from 'node:child_process'
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
installClaudeStandby,
|
|
5
|
-
installDeepseekGlobal,
|
|
6
|
-
installDeepseekStandby,
|
|
7
5
|
installGeminiStandby,
|
|
8
6
|
uninstallClaudeStandby,
|
|
9
|
-
uninstallDeepseekGlobal,
|
|
10
|
-
uninstallDeepseekStandby,
|
|
11
7
|
uninstallGeminiStandby,
|
|
12
8
|
} from './cli-hosts.mjs'
|
|
13
9
|
import {
|
|
@@ -100,10 +96,6 @@ function installHostStandby(runtime, host) {
|
|
|
100
96
|
installGeminiStandby(runtime.home, runtime.pkgRoot)
|
|
101
97
|
return {}
|
|
102
98
|
}
|
|
103
|
-
if (host === 'deepseek') {
|
|
104
|
-
installDeepseekStandby(runtime.home, runtime.pkgRoot)
|
|
105
|
-
return {}
|
|
106
|
-
}
|
|
107
99
|
if (!installCodexStandby(runtime.home, runtime.pkgRoot)) return { skipped: true }
|
|
108
100
|
cleanupCodexGlobalResidueForStandby(runtime.home)
|
|
109
101
|
return {}
|
|
@@ -130,10 +122,6 @@ function installHostGlobal(runtime, host) {
|
|
|
130
122
|
'Gemini CLI extension auto-install failed. Run manually: gemini extensions install https://github.com/hellowind777/helloagents',
|
|
131
123
|
)
|
|
132
124
|
}
|
|
133
|
-
if (host === 'deepseek') {
|
|
134
|
-
installDeepseekGlobal(runtime.home, runtime.pkgRoot)
|
|
135
|
-
return {}
|
|
136
|
-
}
|
|
137
125
|
uninstallCodexStandby(runtime.home)
|
|
138
126
|
return installCodexGlobal(runtime.home, runtime.pkgRoot) ? {} : { skipped: true }
|
|
139
127
|
}
|
|
@@ -141,7 +129,6 @@ function installHostGlobal(runtime, host) {
|
|
|
141
129
|
function cleanupHostStandby(runtime, host) {
|
|
142
130
|
if (host === 'claude') return { skipped: !uninstallClaudeStandby(runtime.home) }
|
|
143
131
|
if (host === 'gemini') return { skipped: !uninstallGeminiStandby(runtime.home) }
|
|
144
|
-
if (host === 'deepseek') return { skipped: !uninstallDeepseekStandby(runtime.home) }
|
|
145
132
|
const standbyCleaned = uninstallCodexStandby(runtime.home)
|
|
146
133
|
const globalResidueCleaned = uninstallCodexGlobal(runtime.home)
|
|
147
134
|
return { skipped: !(standbyCleaned || globalResidueCleaned) }
|
|
@@ -168,7 +155,6 @@ function cleanupHostGlobal(runtime, host) {
|
|
|
168
155
|
'Gemini CLI extension auto-remove failed. Run manually: gemini extensions uninstall helloagents',
|
|
169
156
|
)
|
|
170
157
|
}
|
|
171
|
-
if (host === 'deepseek') return { skipped: !uninstallDeepseekGlobal(runtime.home) }
|
|
172
158
|
return { skipped: !uninstallCodexGlobal(runtime.home) }
|
|
173
159
|
}
|
|
174
160
|
|
|
@@ -194,18 +180,12 @@ function installStandby(runtime) {
|
|
|
194
180
|
console.log(runtime.msg(' - Codex CLI 未检测到,跳过', ' - Codex CLI not detected, skipped'))
|
|
195
181
|
results.codex = { skipped: true }
|
|
196
182
|
}
|
|
197
|
-
if (installDeepseekStandby(runtime.home, runtime.pkgRoot)) {
|
|
198
|
-
runtime.ok(runtime.msg('DeepSeek TUI 已配置(standby 模式)', 'DeepSeek TUI configured (standby mode)'))
|
|
199
|
-
results.deepseek = {}
|
|
200
|
-
} else {
|
|
201
|
-
results.deepseek = { skipped: true }
|
|
202
|
-
}
|
|
203
183
|
return results
|
|
204
184
|
}
|
|
205
185
|
|
|
206
186
|
function installGlobal(runtime) {
|
|
207
187
|
const results = {}
|
|
208
|
-
for (const host of ['claude', 'gemini', 'codex'
|
|
188
|
+
for (const host of ['claude', 'gemini', 'codex']) {
|
|
209
189
|
const result = installHostGlobal(runtime, host)
|
|
210
190
|
reportHostAction(runtime, 'install', host, 'global', result)
|
|
211
191
|
results[host] = result
|
|
@@ -223,7 +203,6 @@ export function uninstallAllHosts(runtime) {
|
|
|
223
203
|
cleanupHostGlobal(runtime, 'gemini')
|
|
224
204
|
uninstallCodexStandby(runtime.home)
|
|
225
205
|
uninstallCodexGlobal(runtime.home)
|
|
226
|
-
uninstallDeepseekStandby(runtime.home)
|
|
227
206
|
}
|
|
228
207
|
|
|
229
208
|
export function runHostLifecycle(runtime, action, host, mode) {
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import { installAllHosts, runHostLifecycle, uninstallAllHosts } from './cli-lifecycle-hosts.mjs'
|
|
11
11
|
import { ensureDir, safeJson, safeWrite } from './cli-utils.mjs'
|
|
12
12
|
|
|
13
|
-
export const HOSTS = ['claude', 'gemini', 'codex'
|
|
13
|
+
export const HOSTS = ['claude', 'gemini', 'codex']
|
|
14
14
|
|
|
15
15
|
const runtime = {
|
|
16
16
|
home: '',
|
|
@@ -28,14 +28,28 @@ export function initCliLifecycle(options) {
|
|
|
28
28
|
Object.assign(runtime, options)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
function sanitizeSettings(settings = {}) {
|
|
32
|
+
const next = settings && typeof settings === 'object' ? { ...settings } : {}
|
|
33
|
+
const tracked = next.host_install_modes
|
|
34
|
+
if (!tracked || typeof tracked !== 'object' || Array.isArray(tracked)) {
|
|
35
|
+
next.host_install_modes = {}
|
|
36
|
+
return next
|
|
37
|
+
}
|
|
38
|
+
next.host_install_modes = Object.fromEntries(
|
|
39
|
+
Object.entries(tracked).filter(([host, mode]) => HOSTS.includes(host) && typeof mode === 'string' && mode),
|
|
40
|
+
)
|
|
41
|
+
return next
|
|
42
|
+
}
|
|
43
|
+
|
|
31
44
|
export function readSettings(shouldEnsure = false) {
|
|
32
45
|
if (shouldEnsure) ensureConfig(runtime.helloagentsHome, runtime.configFile, safeJson, ensureDir)
|
|
33
|
-
return safeJson(runtime.configFile) || {}
|
|
46
|
+
return sanitizeSettings(safeJson(runtime.configFile) || {})
|
|
34
47
|
}
|
|
35
48
|
|
|
36
49
|
function writeSettings(settings) {
|
|
50
|
+
const sanitized = sanitizeSettings(settings)
|
|
37
51
|
ensureDir(runtime.helloagentsHome)
|
|
38
|
-
writeFileSync(runtime.configFile, JSON.stringify(
|
|
52
|
+
writeFileSync(runtime.configFile, JSON.stringify(sanitized, null, 2), 'utf-8')
|
|
39
53
|
}
|
|
40
54
|
|
|
41
55
|
function hasTrackedHostModes(settings) {
|
package/scripts/cli-messages.mjs
CHANGED
|
@@ -19,18 +19,6 @@ function codexGlobalStatus({ home, msg }) {
|
|
|
19
19
|
: msg('安装 Codex CLI 后重新运行 npm install -g helloagents', 'Install Codex CLI then re-run npm install -g helloagents')
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function deepseekStandbyStatus({ home, msg }) {
|
|
23
|
-
return existsSync(join(home, '.deepseek'))
|
|
24
|
-
? msg('已自动配置(~/.deepseek/AGENTS.md)', 'Auto-configured (~/.deepseek/AGENTS.md)')
|
|
25
|
-
: msg('安装 DeepSeek TUI 后重新运行 npm install -g helloagents', 'Install DeepSeek TUI then re-run npm install -g helloagents')
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function deepseekGlobalStatus({ home, msg }) {
|
|
29
|
-
return existsSync(join(home, '.deepseek'))
|
|
30
|
-
? msg('已自动切到受管全局载体(~/.deepseek/AGENTS.md)', 'Managed global carrier applied (~/.deepseek/AGENTS.md)')
|
|
31
|
-
: msg('安装 DeepSeek TUI 后重新运行 npm install -g helloagents', 'Install DeepSeek TUI then re-run npm install -g helloagents')
|
|
32
|
-
}
|
|
33
|
-
|
|
34
22
|
function pluginCommands() {
|
|
35
23
|
return [
|
|
36
24
|
' Claude Code: /plugin marketplace add hellowind777/helloagents',
|
|
@@ -61,24 +49,24 @@ function renderInstallMessage(context, mode, state) {
|
|
|
61
49
|
if (mode === 'global') {
|
|
62
50
|
if (install) {
|
|
63
51
|
return msg(
|
|
64
|
-
`\n ✅ HelloAGENTS 已安装(global 模式)!\n\n Claude Code / Gemini CLI: 已自动尝试宿主原生插件/扩展安装\n Codex: ${codexGlobalStatus(context)}(~/.agents/plugins/marketplace.json + ~/plugins/helloagents)\n
|
|
65
|
-
`\n ✅ HelloAGENTS installed (global mode)!\n\n Claude Code / Gemini CLI: native plugin/extension install attempted automatically\n Codex: ${codexGlobalStatus(context)} (~/.agents/plugins/marketplace.json + ~/plugins/helloagents)\n
|
|
52
|
+
`\n ✅ HelloAGENTS 已安装(global 模式)!\n\n Claude Code / Gemini CLI: 已自动尝试宿主原生插件/扩展安装\n Codex: ${codexGlobalStatus(context)}(~/.agents/plugins/marketplace.json + ~/plugins/helloagents)\n\n ${restartHint(msg)}\n\n 若宿主命令不可用,请手动执行:\n${pluginCommands()}\n\n 切换模式:\n helloagents --standby 标准模式(默认,非插件安装)`,
|
|
53
|
+
`\n ✅ HelloAGENTS installed (global mode)!\n\n Claude Code / Gemini CLI: native plugin/extension install attempted automatically\n Codex: ${codexGlobalStatus(context)} (~/.agents/plugins/marketplace.json + ~/plugins/helloagents)\n\n ${restartHint(msg)}\n\n If a host command is unavailable, run manually:\n${pluginCommands()}\n\n Switch modes:\n helloagents --standby Standby mode (default, non-plugin install)`,
|
|
66
54
|
)
|
|
67
55
|
}
|
|
68
56
|
return msg(
|
|
69
57
|
refresh
|
|
70
|
-
? ` global 模式已刷新。\n Claude Code / Gemini 已自动尝试刷新宿主插件/扩展;Codex
|
|
71
|
-
: ` 所有项目将自动启用完整 HelloAGENTS 规则。\n Claude Code / Gemini 已自动尝试安装宿主插件/扩展;Codex
|
|
58
|
+
? ` global 模式已刷新。\n Claude Code / Gemini 已自动尝试刷新宿主插件/扩展;Codex 原生本地插件已重装并同步最新文件。\n ${restartHint(msg)}`
|
|
59
|
+
: ` 所有项目将自动启用完整 HelloAGENTS 规则。\n Claude Code / Gemini 已自动尝试安装宿主插件/扩展;Codex 已自动安装原生本地插件。\n ${restartHint(msg)}\n\n若宿主命令不可用,请手动执行:\n${pluginCommands()}`,
|
|
72
60
|
refresh
|
|
73
|
-
? ` Global mode refreshed.\n Claude Code / Gemini native plugin/extension refresh was attempted automatically; Codex native local-plugin files were reinstalled and synced
|
|
74
|
-
: ` All projects will use full HelloAGENTS rules.\n Claude Code / Gemini native plugin/extension install was attempted automatically; Codex now uses the native local-plugin path automatically
|
|
61
|
+
? ` Global mode refreshed.\n Claude Code / Gemini native plugin/extension refresh was attempted automatically; Codex native local-plugin files were reinstalled and synced.\n ${restartHint(msg)}`
|
|
62
|
+
: ` All projects will use full HelloAGENTS rules.\n Claude Code / Gemini native plugin/extension install was attempted automatically; Codex now uses the native local-plugin path automatically.\n ${restartHint(msg)}\n\nIf a host command is unavailable, run manually:\n${pluginCommands()}`,
|
|
75
63
|
)
|
|
76
64
|
}
|
|
77
65
|
|
|
78
66
|
if (install) {
|
|
79
67
|
return msg(
|
|
80
|
-
`\n ✅ HelloAGENTS 已安装(standby 模式)!\n\n Claude Code: 已自动配置(~/.claude/CLAUDE.md + hooks)\n Gemini CLI: 已自动配置(~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n
|
|
81
|
-
`\n ✅ HelloAGENTS installed (standby mode)!\n\n Claude Code: Auto-configured (~/.claude/CLAUDE.md + hooks)\n Gemini CLI: Auto-configured (~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n
|
|
68
|
+
`\n ✅ HelloAGENTS 已安装(standby 模式)!\n\n Claude Code: 已自动配置(~/.claude/CLAUDE.md + hooks)\n Gemini CLI: 已自动配置(~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n\n ${restartHint(msg)}\n\n standby 模式下,hello-* 技能不会自动触发。\n 在项目中使用 ~wiki 或 ~init 仅创建/同步知识库;用 ~global 初始化项目级全局模式;也可用 ~command 按需调用。\n\n 切换模式:\n helloagents --global 项目级全局模式(自动尝试 Claude/Gemini 插件或扩展;Codex 自动装原生本地插件)`,
|
|
69
|
+
`\n ✅ HelloAGENTS installed (standby mode)!\n\n Claude Code: Auto-configured (~/.claude/CLAUDE.md + hooks)\n Gemini CLI: Auto-configured (~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n\n ${restartHint(msg)}\n\n In standby mode, hello-* skills won't auto-trigger.\n Use ~wiki or ~init to create or sync the KB only; use ~global to initialize project-level global mode; ~command stays available on demand.\n\n Switch modes:\n helloagents --global Project-level global mode (auto-attempts Claude/Gemini plugins or extensions; native local plugin auto-install for Codex)`,
|
|
82
70
|
)
|
|
83
71
|
}
|
|
84
72
|
|
|
@@ -102,17 +90,17 @@ HelloAGENTS v${pkgVersion} — The orchestration kernel for AI CLIs
|
|
|
102
90
|
helloagents-js ${msg('(受管宿主配置的跨平台稳定入口)', '(cross-platform stable entrypoint for managed host configs)')}
|
|
103
91
|
|
|
104
92
|
${msg('模式切换', 'Mode switching')}:
|
|
105
|
-
helloagents --global ${msg('项目级全局模式(自动尝试 Claude/Gemini 插件或扩展;Codex
|
|
93
|
+
helloagents --global ${msg('项目级全局模式(自动尝试 Claude/Gemini 插件或扩展;Codex 自动装原生本地插件)', 'Project-level global mode (auto-attempts Claude/Gemini plugins or extensions; native local plugin auto-install for Codex)')}
|
|
106
94
|
helloagents --standby ${msg('标准模式(非插件安装,hello-* 不自动触发,默认)', "Standby mode (non-plugin install, hello-* won't auto-trigger, default)")}
|
|
107
95
|
|
|
108
96
|
${msg('单 CLI 管理', 'Scoped CLI management')}:
|
|
109
97
|
helloagents install codex --standby
|
|
110
|
-
helloagents install
|
|
98
|
+
helloagents install gemini --standby
|
|
111
99
|
helloagents install --all --global
|
|
112
100
|
helloagents update codex
|
|
113
101
|
helloagents cleanup claude --global
|
|
114
102
|
helloagents uninstall gemini
|
|
115
|
-
${msg('支持: claude | gemini | codex |
|
|
103
|
+
${msg('支持: claude | gemini | codex | --all;省略模式时优先沿用该 CLI 已记录/已检测的模式,否则回退 standby', 'Hosts: claude | gemini | codex | --all; omit mode to reuse the tracked/detected mode for that CLI, then fall back to standby')}
|
|
116
104
|
|
|
117
105
|
${msg('分支切换', 'Branch switching')}:
|
|
118
106
|
helloagents switch-branch beta
|
|
@@ -123,7 +111,7 @@ ${msg('分支切换', 'Branch switching')}:
|
|
|
123
111
|
${msg('诊断', 'Diagnostics')}:
|
|
124
112
|
helloagents doctor
|
|
125
113
|
helloagents doctor codex --json
|
|
126
|
-
${msg('检查 carrier、链接、hooks、配置注入、Codex
|
|
114
|
+
${msg('检查 carrier、链接、hooks、配置注入、Codex 插件安装、受管 model_instructions_file 指向、Codex hook trust 本机状态与版本漂移', 'Checks carriers, links, hooks, config injections, Codex plugin installation, managed model_instructions_file targeting, machine-local Codex hook trust state, and version drift')}
|
|
127
115
|
|
|
128
116
|
${msg('Codex /goal', 'Codex /goal')}:
|
|
129
117
|
helloagents codex goals status
|
package/scripts/guard.mjs
CHANGED
|
@@ -133,7 +133,7 @@ function buildPostWriteWarnings(data) {
|
|
|
133
133
|
const filePath = data.tool_input?.file_path || ''
|
|
134
134
|
return [
|
|
135
135
|
...(detectIdeaBoundaryContext(data)?.zeroSideEffect
|
|
136
|
-
? ['~idea
|
|
136
|
+
? ['~idea 当前任务要求只读探索;检测到写入文件的工具调用,请回到探索输出,或升级到 ~plan / ~build / ~prd / ~auto 后再修改文件']
|
|
137
137
|
: []),
|
|
138
138
|
...scanUnrequestedFiles(filePath, data.tool_name),
|
|
139
139
|
...(content ? [...scanForSecrets(content), ...scanDangerousPackages(content, filePath)] : []),
|
|
@@ -34,7 +34,7 @@ function buildReadRootBlock(readRoot) {
|
|
|
34
34
|
turnStateCommand: 'helloagents-turn-state write --kind complete --role main',
|
|
35
35
|
turnStateUsage: '仅在运行时需要识别完成、等待或阻塞时调用;普通问答不调用',
|
|
36
36
|
};
|
|
37
|
-
return `##
|
|
37
|
+
return `## 当前对话 HelloAGENTS 读取根目录\n\`\`\`json\n${JSON.stringify(block, null, 2)}\n\`\`\``;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export function resolveCanonicalCommandSkill(skillName) {
|
|
@@ -54,6 +54,10 @@ function buildAliasRouteNote(skillName) {
|
|
|
54
54
|
return '';
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
function buildDelegatedTaskHint() {
|
|
58
|
+
return '若当前输入明显来自上级代理、控制器或多代理协作上下文,且本次输出会交回上级代理继续汇总、决策或复述,而不是直接交付给最终用户,则按子代理处理:直接完成局部任务并返回结果、证据或阻塞项,不使用 HelloAGENTS 外层输出格式,不写 turn-state,不做面向最终用户的收尾。'
|
|
59
|
+
}
|
|
60
|
+
|
|
57
61
|
export function buildCompactionContext({ payload, pkgRoot, settings, bootstrapFile, host }) {
|
|
58
62
|
const summaryParts = [];
|
|
59
63
|
summaryParts.push('## HelloAGENTS 压缩摘要');
|
|
@@ -148,7 +152,7 @@ export function buildRouteInstruction({ skillName, extraRules = '', cwd, pkgRoot
|
|
|
148
152
|
const commandHint = buildCommandRouteHint(canonicalSkillName, cwd, workflowOptions);
|
|
149
153
|
const capabilityHint = buildCapabilityHint({ cwd, skillName: canonicalSkillName, options: workflowOptions });
|
|
150
154
|
const projectStorageHint = buildProjectStorageHint(cwd, workflowOptions);
|
|
151
|
-
return `用户使用了 ~${skillName} 命令。当前命令技能文件已解析为:${skillPath}。请直接读取这个 SKILL.md;不要再探测其他 helloagents
|
|
155
|
+
return `用户使用了 ~${skillName} 命令。当前命令技能文件已解析为:${skillPath}。请直接读取这个 SKILL.md;不要再探测其他 helloagents 路径。 ${buildDelegatedTaskHint()}${aliasNote ? ` ${aliasNote}` : ''}${projectStorageHint ? ` ${projectStorageHint}` : ''}${commandHint ? ` ${commandHint}` : ''}${capabilityHint ? ` ${capabilityHint}` : ''}${extraRules}`;
|
|
152
156
|
}
|
|
153
157
|
|
|
154
158
|
export function buildSemanticRouteInstruction(cwd, payload = {}) {
|
|
@@ -159,6 +163,7 @@ export function buildSemanticRouteInstruction(cwd, payload = {}) {
|
|
|
159
163
|
return [
|
|
160
164
|
'当前消息未使用 ~command。',
|
|
161
165
|
'请根据用户请求的真实意图选路,不依赖关键词表。',
|
|
166
|
+
buildDelegatedTaskHint(),
|
|
162
167
|
'Delivery Tier: T0=探索/比较;T1=低风险小改动或显式验证;T2=多文件功能/新项目/需要结构化产物;T3=高风险或不可逆操作。',
|
|
163
168
|
'路由映射:~idea=只读探索,不创建文件;~build=明确实现;~verify=审查/验证;~plan=结构化规划;~prd=重型规格;~auto=自动选择并继续执行后续阶段。',
|
|
164
169
|
'若判定为 T3,默认先走 ~plan / ~prd;纯审查/验证请求才优先 ~verify。',
|
|
@@ -4,14 +4,9 @@ export function shouldIgnoreCodexNotifyClient(client) {
|
|
|
4
4
|
return normalized !== 'codex' && !normalized.startsWith('codex-');
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export function shouldIgnoreFormattedSubagent(lastMsg, outputFormatEnabled) {
|
|
8
|
-
return outputFormatEnabled && !lastMsg.includes('【HelloAGENTS】');
|
|
9
|
-
}
|
|
10
|
-
|
|
11
7
|
export function resolveNotifyHost(argv = []) {
|
|
12
8
|
const args = Array.from(argv, (value) => String(value || ''));
|
|
13
9
|
const command = args[2] || args[0] || '';
|
|
14
|
-
if (args.includes('--deepseek')) return 'deepseek';
|
|
15
10
|
if (args.includes('--gemini')) return 'gemini';
|
|
16
11
|
if (args.includes('--codex') || command === 'codex-notify') return 'codex';
|
|
17
12
|
return 'claude';
|
package/scripts/notify-route.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { resolveProjectPlanDir } from './project-storage.mjs'
|
|
|
5
5
|
|
|
6
6
|
export const PLAN_CONTRACT_FILE_NAME = 'contract.json'
|
|
7
7
|
const VALID_VERIFY_MODES = new Set(['test-first', 'review-first'])
|
|
8
|
-
const VALID_ADVISOR_SOURCES = new Set(['claude', 'codex', 'gemini'
|
|
8
|
+
const VALID_ADVISOR_SOURCES = new Set(['claude', 'codex', 'gemini'])
|
|
9
9
|
|
|
10
10
|
function normalizeStringArray(values) {
|
|
11
11
|
if (!Array.isArray(values)) return []
|
package/scripts/ralph-loop.mjs
CHANGED
|
@@ -89,6 +89,30 @@ function runVerify(commands, cwd) {
|
|
|
89
89
|
return failures;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
function getLastAssistantMessage(data = {}) {
|
|
93
|
+
return String(
|
|
94
|
+
data.lastAssistantMessage
|
|
95
|
+
|| data.last_assistant_message
|
|
96
|
+
|| data['last-assistant-message']
|
|
97
|
+
|| '',
|
|
98
|
+
).trim();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function hasHelloagentsWrapper(message = '') {
|
|
102
|
+
if (!message.includes('【HelloAGENTS】')) return false;
|
|
103
|
+
const firstNonEmptyLine = message
|
|
104
|
+
.split(/\r?\n/)
|
|
105
|
+
.map((line) => line.trim())
|
|
106
|
+
.find(Boolean);
|
|
107
|
+
return /^[💡⚡🔵✅❓⚠️❌]【HelloAGENTS】- /.test(firstNonEmptyLine || '') || message.includes('【HelloAGENTS】');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function validateSubagentOutput(data = {}) {
|
|
111
|
+
const message = getLastAssistantMessage(data);
|
|
112
|
+
if (!message || !hasHelloagentsWrapper(message)) return '';
|
|
113
|
+
return '[HelloAGENTS Runtime] 子代理输出不应使用 HelloAGENTS 外层格式。当前回复不是直接面向最终用户的终局交付,请改为自然输出,只返回结果、证据或阻塞项。';
|
|
114
|
+
}
|
|
115
|
+
|
|
92
116
|
/** Filter commands to fast checks only for subagent mode. Returns null if no fast commands found. */
|
|
93
117
|
function filterSubagentCommands(commands) {
|
|
94
118
|
const fast = commands.filter(cmd =>
|
|
@@ -117,6 +141,17 @@ export function evaluateRalphLoop(data = {}, runtime = {}) {
|
|
|
117
141
|
const isSubagent = runtime.isSubagent ?? IS_SUBAGENT;
|
|
118
142
|
const hookEventName = runtime.hookEventName || HOOK_EVENT;
|
|
119
143
|
|
|
144
|
+
if (isSubagent) {
|
|
145
|
+
const formatReason = validateSubagentOutput(data);
|
|
146
|
+
if (formatReason) {
|
|
147
|
+
return {
|
|
148
|
+
decision: 'block',
|
|
149
|
+
reason: formatReason,
|
|
150
|
+
suppressOutput: true,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
120
155
|
let commands = detectCommands(cwd);
|
|
121
156
|
if (!commands?.length) {
|
|
122
157
|
return { suppressOutput: true };
|
|
@@ -146,7 +146,7 @@ export function getProjectRoot(cwd) {
|
|
|
146
146
|
|
|
147
147
|
function getCarrierPathForRoot(root, host = '') {
|
|
148
148
|
if (!root) return ''
|
|
149
|
-
if (host === 'codex'
|
|
149
|
+
if (host === 'codex') return join(root, 'AGENTS.md')
|
|
150
150
|
if (host === 'gemini') return join(root, '.gemini', 'GEMINI.md')
|
|
151
151
|
return join(root, 'CLAUDE.md')
|
|
152
152
|
}
|
|
@@ -39,7 +39,7 @@ function buildBlockReason(routeContext, detail, cwd) {
|
|
|
39
39
|
const commandLabel = `~${routeContext.skillName}`
|
|
40
40
|
const workflowHint = buildWorkflowHint(cwd)
|
|
41
41
|
return [
|
|
42
|
-
`[HelloAGENTS Runtime] 显式 ${commandLabel}
|
|
42
|
+
`[HelloAGENTS Runtime] 显式 ${commandLabel} 当前对话不应直接停下。`,
|
|
43
43
|
detail,
|
|
44
44
|
workflowHint,
|
|
45
45
|
'若无真实阻塞,请继续沿当前路径执行。',
|
|
@@ -74,7 +74,7 @@ function validateFormattedCloseoutMessage(routeContext, payload, cwd) {
|
|
|
74
74
|
if (!firstNonEmptyLine || !/^[💡⚡🔵✅❓⚠️❌]【HelloAGENTS】- /.test(firstNonEmptyLine)) {
|
|
75
75
|
return buildBlockReason(
|
|
76
76
|
routeContext,
|
|
77
|
-
'
|
|
77
|
+
'最终回复使用了 HelloAGENTS 外层格式,但首个非空行不是规范标题行。',
|
|
78
78
|
cwd,
|
|
79
79
|
)
|
|
80
80
|
}
|
|
@@ -82,7 +82,7 @@ function validateFormattedCloseoutMessage(routeContext, payload, cwd) {
|
|
|
82
82
|
if (countMatches(message, /[💡⚡🔵✅❓⚠️❌]【HelloAGENTS】-/g) > 1) {
|
|
83
83
|
return buildBlockReason(
|
|
84
84
|
routeContext,
|
|
85
|
-
'
|
|
85
|
+
'最终回复重复输出了 HelloAGENTS 标题;请把所有内容合并到同一个外层块内。',
|
|
86
86
|
cwd,
|
|
87
87
|
)
|
|
88
88
|
}
|
|
@@ -90,7 +90,7 @@ function validateFormattedCloseoutMessage(routeContext, payload, cwd) {
|
|
|
90
90
|
if (countMatches(message, /^🔄 下一步:/gm) > 1) {
|
|
91
91
|
return buildBlockReason(
|
|
92
92
|
routeContext,
|
|
93
|
-
'
|
|
93
|
+
'最终回复重复输出了 `🔄 下一步`;请只保留一个真实下一步。',
|
|
94
94
|
cwd,
|
|
95
95
|
)
|
|
96
96
|
}
|
|
@@ -140,7 +140,7 @@ function validateTurnState(routeContext, turnState, cwd, payload = {}) {
|
|
|
140
140
|
cwd,
|
|
141
141
|
)
|
|
142
142
|
}
|
|
143
|
-
return buildBlockReason(routeContext, `当前 turn-state 为 \`${turnState.kind}
|
|
143
|
+
return buildBlockReason(routeContext, `当前 turn-state 为 \`${turnState.kind}\`,不能作为当前对话结束状态。`, cwd)
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
export function evaluateTurnStopGate(payload = {}) {
|
|
@@ -15,7 +15,7 @@ Trigger: ~auto <任务描述>
|
|
|
15
15
|
- `T3` 高风险或不可逆操作默认不直接进入 `~build`;优先先走 `~plan` 或 `~prd`,纯审查/纯验证请求才可先进入 `~verify`
|
|
16
16
|
- 主路径一旦确定,立即读取对应 command skill,并在阶段完成后继续执行后续阶段,避免同一任务重复探索或重复等待
|
|
17
17
|
- 选路不替代授权;涉及外部副作用或高风险不可逆操作时,仍遵守 HelloAGENTS 阻塞判定与确认规则
|
|
18
|
-
- 用户显式使用 `~auto
|
|
18
|
+
- 用户显式使用 `~auto`,表示已授权在当前任务边界内沿选定主路径持续执行;若当前运行在 Codex `/goal` 下,`/goal` 只提供长程续跑与预算,`~auto` 仍按方案包、`state_path` 与验证契约推进;`~plan` / `~prd` 作为中间阶段时,不再额外询问“是否开始执行”,除非仍有真实阻塞;不得把 `🔄 下一步` 当作阶段交接或继续执行占位
|
|
19
19
|
- 优先消费当前上下文中已注入的 ROUTE / TIER、当前工作流约束与项目状态;不要在 `~auto` 内另建一套关键词路由表
|
|
20
20
|
|
|
21
21
|
## 流程
|
|
@@ -33,7 +33,7 @@ Trigger: ~auto <任务描述>
|
|
|
33
33
|
### 1. 选路
|
|
34
34
|
|
|
35
35
|
- 先按当前上下文里已注入的 ROUTE / TIER 语义约束判断,不依赖关键词命中做机械分流
|
|
36
|
-
-
|
|
36
|
+
- 若当前上下文没有足够的注入约束,再结合以下信号补足判断:影响范围、风险等级、是否需要结构化产物、是否已有活跃方案包、用户是否只想先比较方向
|
|
37
37
|
- 选路优先级:
|
|
38
38
|
- 纯探索 / 点子 / 方向比较 → `~idea`
|
|
39
39
|
- 明确要求验证 / 审查 / 跑检查 → `~verify`
|
|
@@ -20,15 +20,15 @@ Trigger: ~build [description]
|
|
|
20
20
|
|
|
21
21
|
### 1. 恢复与定位
|
|
22
22
|
|
|
23
|
-
- 优先按当前已加载的 HelloAGENTS 规则恢复当前任务,并遵循“.helloagents/ 文件读取优先级”;若当前消息明确要继续上次任务、会话刚经历恢复 /
|
|
23
|
+
- 优先按当前已加载的 HelloAGENTS 规则恢复当前任务,并遵循“.helloagents/ 文件读取优先级”;若当前消息明确要继续上次任务、会话刚经历恢复 / 压缩,或当前运行在 Codex active goal 下,先读取 `state_path`,再用当前用户消息、活跃方案包 / PRD 与代码事实确认当前任务
|
|
24
24
|
- 若存在最近的活跃方案包,读取对应的:
|
|
25
25
|
- `requirements.md`
|
|
26
26
|
- `plan.md`
|
|
27
27
|
- `tasks.md`
|
|
28
28
|
- `contract.json`
|
|
29
|
-
- 实现时优先把 `tasks.md`
|
|
29
|
+
- 实现时优先把 `tasks.md` 中每个任务的“完成标准”当作本次实现约束,不要只按任务标题猜测范围
|
|
30
30
|
- `contract.json` 存在时,优先按其中的 `verifyMode`、`reviewerFocus`、`testerFocus` 理解后续验证边界
|
|
31
|
-
-
|
|
31
|
+
- 若当前运行在 Codex active goal 下,按 `tasks.md` 未完成项、`contract.json` 与 `state_path` 恢复实现位置;不要自动创建新 goal,也不要把 goal 目标原文替代方案包
|
|
32
32
|
- 若当前上下文中已注入“当前工作流约束”或“当前推荐下一命令”,先服从它;只有推荐仍为 `~build`,或用户明确提出新增实现范围时,才继续 `~build`
|
|
33
33
|
- 其余项目知识库与相关代码文件,按 HelloAGENTS 项目上下文要求读取
|
|
34
34
|
- 若任务涉及 UI,按以下优先级读取并遵循:当前活跃 `plan.md` / PRD 中的 UI 决策 > 逻辑 `.helloagents/DESIGN.md`(实际路径按当前项目存储模式解析) > 已读取的 `hello-ui` 规则;同时所有 UI 任务都必须满足 UI 质量基线
|