helloagents 3.0.12 → 3.0.15-beta.1
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/marketplace.json +6 -4
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +169 -30
- package/README_CN.md +169 -30
- package/bootstrap-lite.md +27 -20
- package/bootstrap.md +30 -23
- package/cli.mjs +119 -11
- package/gemini-extension.json +1 -1
- package/install.ps1 +125 -0
- package/install.sh +118 -0
- package/package.json +23 -4
- package/scripts/advisor-state.mjs +36 -63
- package/scripts/capability-registry.mjs +3 -3
- package/scripts/cli-branch.mjs +84 -0
- package/scripts/cli-codex-config.mjs +11 -20
- package/scripts/cli-codex.mjs +32 -38
- package/scripts/cli-doctor-render.mjs +4 -0
- package/scripts/cli-doctor.mjs +40 -30
- package/scripts/cli-host-detect.mjs +0 -1
- package/scripts/cli-hosts.mjs +16 -8
- package/scripts/cli-lifecycle-hosts.mjs +92 -27
- package/scripts/cli-lifecycle.mjs +9 -7
- package/scripts/cli-messages.mjs +34 -16
- package/scripts/cli-runtime-carrier.mjs +36 -0
- package/scripts/cli-runtime-root.mjs +72 -0
- package/scripts/cli-toml.mjs +0 -79
- package/scripts/cli-utils.mjs +30 -4
- package/scripts/closeout-state.mjs +35 -62
- package/scripts/delivery-gate-messages.mjs +70 -0
- package/scripts/delivery-gate.mjs +9 -75
- package/scripts/guard-rules.mjs +42 -42
- package/scripts/guard.mjs +44 -24
- package/scripts/notify-context.mjs +19 -28
- package/scripts/notify-gates.mjs +2 -0
- package/scripts/notify-route.mjs +9 -7
- package/scripts/notify-ui.mjs +46 -33
- package/scripts/notify.mjs +60 -32
- package/scripts/project-storage.mjs +35 -66
- package/scripts/ralph-loop.mjs +36 -31
- package/scripts/replay-state.mjs +31 -128
- package/scripts/review-state.mjs +34 -61
- package/scripts/runtime-artifacts.mjs +95 -0
- package/scripts/runtime-context.mjs +35 -29
- package/scripts/runtime-scope.mjs +313 -0
- package/scripts/session-capsule.mjs +202 -0
- package/scripts/turn-state-cli.mjs +17 -0
- package/scripts/turn-state.mjs +185 -66
- package/scripts/turn-stop-gate.mjs +24 -6
- package/scripts/verify-state.mjs +34 -85
- package/scripts/visual-state.mjs +38 -65
- package/scripts/workflow-core.mjs +2 -2
- package/scripts/workflow-plan-files.mjs +1 -1
- package/scripts/workflow-recommendation.mjs +17 -13
- package/scripts/workflow-state.mjs +5 -5
- package/skills/commands/build/SKILL.md +1 -1
- package/skills/commands/commit/SKILL.md +1 -1
- package/skills/commands/help/SKILL.md +3 -3
- package/skills/commands/loop/SKILL.md +1 -1
- package/skills/commands/plan/SKILL.md +8 -6
- package/skills/commands/prd/SKILL.md +5 -3
- package/skills/commands/verify/SKILL.md +5 -5
- package/skills/hello-debug/SKILL.md +20 -3
- package/skills/hello-review/SKILL.md +2 -2
- package/skills/hello-subagent/SKILL.md +2 -2
- package/skills/hello-test/SKILL.md +6 -2
- package/skills/hello-ui/SKILL.md +4 -4
- package/skills/hello-verify/SKILL.md +10 -7
- package/skills/helloagents/SKILL.md +12 -7
- package/templates/context.md +6 -0
- package/templates/plans/plan.md +3 -0
- package/templates/plans/tasks.md +8 -3
package/scripts/visual-state.mjs
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { join } from 'node:path'
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
3
2
|
import { fileURLToPath } from 'node:url'
|
|
4
3
|
|
|
5
4
|
import { appendReplayEvent } from './replay-state.mjs'
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
import {
|
|
6
|
+
captureWorkspaceFingerprint,
|
|
7
|
+
clearRuntimeEvidence,
|
|
8
|
+
getRuntimeEvidencePath,
|
|
9
|
+
getRuntimeEvidenceRelativePath,
|
|
10
|
+
readRuntimeEvidence,
|
|
11
|
+
validateEvidenceFingerprint,
|
|
12
|
+
validateEvidenceTimestamp,
|
|
13
|
+
writeRuntimeEvidence,
|
|
14
|
+
} from './runtime-artifacts.mjs'
|
|
15
|
+
|
|
16
|
+
export const VISUAL_EVIDENCE_FILE_NAME = 'visual.json'
|
|
10
17
|
const VALID_VISUAL_STATUSES = new Set(['PASS', 'BLOCKED'])
|
|
11
18
|
|
|
12
19
|
function normalizeStringArray(values) {
|
|
@@ -24,20 +31,16 @@ function findMissingCoverage(requested = [], completed = []) {
|
|
|
24
31
|
return normalizeStringArray(requested).filter((entry) => !completedSet.has(entry))
|
|
25
32
|
}
|
|
26
33
|
|
|
27
|
-
export function getVisualEvidencePath(cwd) {
|
|
28
|
-
return
|
|
34
|
+
export function getVisualEvidencePath(cwd, options = {}) {
|
|
35
|
+
return getRuntimeEvidencePath(cwd, VISUAL_EVIDENCE_FILE_NAME, options)
|
|
29
36
|
}
|
|
30
37
|
|
|
31
|
-
export function readVisualEvidence(cwd) {
|
|
32
|
-
|
|
33
|
-
return JSON.parse(readFileSync(getVisualEvidencePath(cwd), 'utf-8'))
|
|
34
|
-
} catch {
|
|
35
|
-
return null
|
|
36
|
-
}
|
|
38
|
+
export function readVisualEvidence(cwd, options = {}) {
|
|
39
|
+
return readRuntimeEvidence(cwd, VISUAL_EVIDENCE_FILE_NAME, options)
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
export function clearVisualEvidence(cwd) {
|
|
40
|
-
|
|
42
|
+
export function clearVisualEvidence(cwd, options = {}) {
|
|
43
|
+
clearRuntimeEvidence(cwd, VISUAL_EVIDENCE_FILE_NAME, options)
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
export function normalizeVisualEvidence(input = {}) {
|
|
@@ -55,19 +58,19 @@ export function normalizeVisualEvidence(input = {}) {
|
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
|
|
58
|
-
export function writeVisualEvidence(cwd, input = {}) {
|
|
59
|
-
mkdirSync(join(cwd, '.helloagents'), { recursive: true })
|
|
61
|
+
export function writeVisualEvidence(cwd, input = {}, options = {}) {
|
|
60
62
|
const normalized = normalizeVisualEvidence(input)
|
|
61
63
|
const payload = {
|
|
62
64
|
updatedAt: new Date().toISOString(),
|
|
63
65
|
...normalized,
|
|
64
66
|
fingerprint: captureWorkspaceFingerprint(cwd),
|
|
65
67
|
}
|
|
66
|
-
|
|
68
|
+
writeRuntimeEvidence(cwd, VISUAL_EVIDENCE_FILE_NAME, payload, options)
|
|
67
69
|
appendReplayEvent(cwd, {
|
|
68
70
|
event: 'visual_evidence_written',
|
|
69
71
|
source: normalized.source,
|
|
70
72
|
skillName: normalized.originCommand,
|
|
73
|
+
payload: options.payload || {},
|
|
71
74
|
details: {
|
|
72
75
|
reason: normalized.reason,
|
|
73
76
|
tooling: normalized.tooling,
|
|
@@ -75,12 +78,12 @@ export function writeVisualEvidence(cwd, input = {}) {
|
|
|
75
78
|
statesChecked: normalized.statesChecked,
|
|
76
79
|
status: normalized.status,
|
|
77
80
|
},
|
|
78
|
-
artifacts: [
|
|
81
|
+
artifacts: [getRuntimeEvidenceRelativePath(cwd, VISUAL_EVIDENCE_FILE_NAME, options)],
|
|
79
82
|
})
|
|
80
83
|
return payload
|
|
81
84
|
}
|
|
82
85
|
|
|
83
|
-
function readRequiredVisualEvidence(cwd, required) {
|
|
86
|
+
function readRequiredVisualEvidence(cwd, required, options = {}) {
|
|
84
87
|
if (!required) {
|
|
85
88
|
return {
|
|
86
89
|
required: false,
|
|
@@ -88,53 +91,23 @@ function readRequiredVisualEvidence(cwd, required) {
|
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
const evidence = readVisualEvidence(cwd)
|
|
94
|
+
const evidence = readVisualEvidence(cwd, options)
|
|
92
95
|
if (evidence) return { evidence }
|
|
93
96
|
return {
|
|
94
97
|
error: {
|
|
95
98
|
required: true,
|
|
96
99
|
status: 'missing',
|
|
97
|
-
details: ['
|
|
100
|
+
details: ['缺少当前 UI 契约要求的视觉验收证据'],
|
|
98
101
|
},
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
104
|
|
|
102
105
|
function validateVisualTimestamp(evidence, now) {
|
|
103
|
-
|
|
104
|
-
if (!Number.isFinite(updatedAt)) {
|
|
105
|
-
return {
|
|
106
|
-
required: true,
|
|
107
|
-
status: 'invalid',
|
|
108
|
-
evidence,
|
|
109
|
-
details: ['visual validation evidence timestamp is invalid'],
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (now - updatedAt > VISUAL_EVIDENCE_MAX_AGE_MS) {
|
|
113
|
-
return {
|
|
114
|
-
required: true,
|
|
115
|
-
status: 'stale-time',
|
|
116
|
-
evidence,
|
|
117
|
-
details: ['visual validation evidence is older than 30 minutes'],
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return null
|
|
106
|
+
return validateEvidenceTimestamp(evidence, now, '视觉验收证据')
|
|
121
107
|
}
|
|
122
108
|
|
|
123
109
|
function validateVisualFingerprint(cwd, evidence) {
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
currentFingerprint.available
|
|
127
|
-
&& evidence.fingerprint?.available
|
|
128
|
-
&& currentFingerprint.combined !== evidence.fingerprint.combined
|
|
129
|
-
) {
|
|
130
|
-
return {
|
|
131
|
-
required: true,
|
|
132
|
-
status: 'stale-diff',
|
|
133
|
-
evidence,
|
|
134
|
-
details: ['workspace diff changed after the last visual validation evidence'],
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return null
|
|
110
|
+
return validateEvidenceFingerprint(cwd, evidence, '视觉验收证据')
|
|
138
111
|
}
|
|
139
112
|
|
|
140
113
|
function validateVisualContent(evidence, { screens = [], states = [] } = {}) {
|
|
@@ -144,7 +117,7 @@ function validateVisualContent(evidence, { screens = [], states = [] } = {}) {
|
|
|
144
117
|
required: true,
|
|
145
118
|
status: 'invalid',
|
|
146
119
|
evidence,
|
|
147
|
-
details: ['
|
|
120
|
+
details: ['视觉验收证据必须记录明确的 status、reason 和 summary'],
|
|
148
121
|
}
|
|
149
122
|
}
|
|
150
123
|
if (normalized.tooling.length === 0) {
|
|
@@ -152,7 +125,7 @@ function validateVisualContent(evidence, { screens = [], states = [] } = {}) {
|
|
|
152
125
|
required: true,
|
|
153
126
|
status: 'invalid',
|
|
154
127
|
evidence,
|
|
155
|
-
details: ['
|
|
128
|
+
details: ['视觉验收证据必须记录使用的检查工具'],
|
|
156
129
|
}
|
|
157
130
|
}
|
|
158
131
|
if (normalized.screensChecked.length === 0 && normalized.statesChecked.length === 0) {
|
|
@@ -160,7 +133,7 @@ function validateVisualContent(evidence, { screens = [], states = [] } = {}) {
|
|
|
160
133
|
required: true,
|
|
161
134
|
status: 'invalid',
|
|
162
135
|
evidence,
|
|
163
|
-
details: ['
|
|
136
|
+
details: ['视觉验收证据必须记录至少一个已检查视口或状态'],
|
|
164
137
|
}
|
|
165
138
|
}
|
|
166
139
|
|
|
@@ -170,7 +143,7 @@ function validateVisualContent(evidence, { screens = [], states = [] } = {}) {
|
|
|
170
143
|
required: true,
|
|
171
144
|
status: 'invalid',
|
|
172
145
|
evidence,
|
|
173
|
-
details: [
|
|
146
|
+
details: [`视觉验收证据未覆盖要求的视口:${missingScreens.join(', ')}`],
|
|
174
147
|
}
|
|
175
148
|
}
|
|
176
149
|
|
|
@@ -180,7 +153,7 @@ function validateVisualContent(evidence, { screens = [], states = [] } = {}) {
|
|
|
180
153
|
required: true,
|
|
181
154
|
status: 'invalid',
|
|
182
155
|
evidence,
|
|
183
|
-
details: [
|
|
156
|
+
details: [`视觉验收证据未覆盖要求的状态:${missingStates.join(', ')}`],
|
|
184
157
|
}
|
|
185
158
|
}
|
|
186
159
|
|
|
@@ -189,14 +162,14 @@ function validateVisualContent(evidence, { screens = [], states = [] } = {}) {
|
|
|
189
162
|
required: true,
|
|
190
163
|
status: 'blocked',
|
|
191
164
|
evidence,
|
|
192
|
-
details: ['
|
|
165
|
+
details: ['最新视觉验收证据仍记录阻塞问题'],
|
|
193
166
|
}
|
|
194
167
|
}
|
|
195
168
|
return null
|
|
196
169
|
}
|
|
197
170
|
|
|
198
|
-
export function getVisualEvidenceStatus(cwd, { required = false, screens = [], states = [], now = Date.now() } = {}) {
|
|
199
|
-
const requiredEvidence = readRequiredVisualEvidence(cwd, required)
|
|
171
|
+
export function getVisualEvidenceStatus(cwd, { required = false, screens = [], states = [], now = Date.now(), ...options } = {}) {
|
|
172
|
+
const requiredEvidence = readRequiredVisualEvidence(cwd, required, options)
|
|
200
173
|
if ('status' in requiredEvidence) return requiredEvidence
|
|
201
174
|
if (requiredEvidence.error) return requiredEvidence.error
|
|
202
175
|
|
|
@@ -231,10 +204,10 @@ function main() {
|
|
|
231
204
|
|
|
232
205
|
const input = readStdinJson()
|
|
233
206
|
const cwd = input.cwd || process.cwd()
|
|
234
|
-
const payload = writeVisualEvidence(cwd, input)
|
|
207
|
+
const payload = writeVisualEvidence(cwd, input, { payload: input })
|
|
235
208
|
process.stdout.write(JSON.stringify({
|
|
236
209
|
suppressOutput: true,
|
|
237
|
-
path: getVisualEvidencePath(cwd),
|
|
210
|
+
path: getVisualEvidencePath(cwd, { payload: input }),
|
|
238
211
|
payload,
|
|
239
212
|
}))
|
|
240
213
|
}
|
|
@@ -162,10 +162,10 @@ export function buildUiContractHint(cwd, snapshot) {
|
|
|
162
162
|
|
|
163
163
|
const extraHints = []
|
|
164
164
|
if (styleAdvisorRequired) {
|
|
165
|
-
extraHints.push('若当前 UI 契约要求 style advisor
|
|
165
|
+
extraHints.push('若当前 UI 契约要求 style advisor,收尾前需写当前会话 `artifacts/advisor.json` 留下独立复查证据')
|
|
166
166
|
}
|
|
167
167
|
if (visualValidationRequired) {
|
|
168
|
-
extraHints.push('若当前 UI
|
|
168
|
+
extraHints.push('若当前 UI 契约要求视觉验收,收尾前需写当前会话 `artifacts/visual.json` 记录关键视口、状态与结论')
|
|
169
169
|
}
|
|
170
170
|
return `UI 约束提示:如本次属于视觉/交互任务,设计决策优先级固定为:当前活跃 plan.md / prd/03-ui-design.md → ${describeProjectStoreFile(cwd, 'DESIGN.md')} → hello-ui。${extraHints.length > 0 ? ` ${extraHints.join(';')}。` : ''}`
|
|
171
171
|
}
|
|
@@ -167,7 +167,7 @@ function findTemplateIssues(fileName, filePath) {
|
|
|
167
167
|
const content = readText(filePath)
|
|
168
168
|
return (PLAN_TEMPLATE_MARKERS[fileName] || [])
|
|
169
169
|
.filter((pattern) => pattern.test(content))
|
|
170
|
-
.map(() => `${fileName}
|
|
170
|
+
.map(() => `${fileName} 仍包含模板占位内容`)
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
function comparePlanEntries(a, b) {
|
|
@@ -11,22 +11,25 @@ import {
|
|
|
11
11
|
normalizeTaskFile,
|
|
12
12
|
} from './workflow-core.mjs'
|
|
13
13
|
|
|
14
|
-
function getClosedPlanEvidenceStatus(cwd, plan) {
|
|
14
|
+
function getClosedPlanEvidenceStatus(cwd, plan, options = {}) {
|
|
15
15
|
const verifyMode = determineVerifyMode(plan)
|
|
16
16
|
const advisorRequirement = getAdvisorRequirement(plan.contract)
|
|
17
17
|
const visualRequirement = getVisualValidationRequirement(plan.contract)
|
|
18
|
-
const verificationStatus = getVerifyEvidenceStatus(cwd)
|
|
18
|
+
const verificationStatus = getVerifyEvidenceStatus(cwd, options)
|
|
19
19
|
const reviewStatus = getReviewEvidenceStatus(cwd, {
|
|
20
20
|
required: verifyMode?.mode === 'review-first',
|
|
21
|
+
...options,
|
|
21
22
|
})
|
|
22
23
|
const advisorStatus = getAdvisorEvidenceStatus(cwd, {
|
|
23
24
|
required: advisorRequirement.required,
|
|
24
25
|
focus: advisorRequirement.focus,
|
|
26
|
+
...options,
|
|
25
27
|
})
|
|
26
28
|
const visualStatus = getVisualEvidenceStatus(cwd, {
|
|
27
29
|
required: visualRequirement.required,
|
|
28
30
|
screens: visualRequirement.screens,
|
|
29
31
|
states: visualRequirement.states,
|
|
32
|
+
...options,
|
|
30
33
|
})
|
|
31
34
|
const verifyReady = !verificationStatus.required || verificationStatus.status === 'valid'
|
|
32
35
|
const reviewReady = !reviewStatus.required || reviewStatus.status === 'valid'
|
|
@@ -34,6 +37,7 @@ function getClosedPlanEvidenceStatus(cwd, plan) {
|
|
|
34
37
|
const visualReady = !visualStatus.required || visualStatus.status === 'valid'
|
|
35
38
|
const closeoutStatus = getCloseoutEvidenceStatus(cwd, {
|
|
36
39
|
required: verifyReady && reviewReady && advisorReady && visualReady,
|
|
40
|
+
...options,
|
|
37
41
|
})
|
|
38
42
|
|
|
39
43
|
return {
|
|
@@ -59,7 +63,7 @@ function buildConsolidateAction(recommendation) {
|
|
|
59
63
|
phase: 'consolidate',
|
|
60
64
|
mode: recommendation.mode,
|
|
61
65
|
routeHint: recommendation.guidance,
|
|
62
|
-
gateHint: '
|
|
66
|
+
gateHint: '交付把关:审查与验证证据已满足;先写当前会话 `artifacts/closeout.json` 记录需求覆盖与交付清单,再更新 `state_path` 并归档后才可交付。',
|
|
63
67
|
}
|
|
64
68
|
}
|
|
65
69
|
|
|
@@ -77,10 +81,10 @@ function buildVerifyAction(plan, verifyMode) {
|
|
|
77
81
|
const visualRequirement = getVisualValidationRequirement(plan.contract)
|
|
78
82
|
const extraChecks = []
|
|
79
83
|
if (advisorRequirement.required) {
|
|
80
|
-
extraChecks.push('完成独立 advisor / style advisor
|
|
84
|
+
extraChecks.push('完成独立 advisor / style advisor 复查并写入当前会话 `artifacts/advisor.json`')
|
|
81
85
|
}
|
|
82
86
|
if (visualRequirement.required) {
|
|
83
|
-
extraChecks.push('
|
|
87
|
+
extraChecks.push('完成视觉验收并写入当前会话 `artifacts/visual.json`')
|
|
84
88
|
}
|
|
85
89
|
const gateSuffix = extraChecks.length > 0 ? ` ${extraChecks.join(',')},再进入 CONSOLIDATE。` : ''
|
|
86
90
|
if (verifyMode.mode === 'review-first') {
|
|
@@ -171,8 +175,8 @@ function buildInProgressRecommendation(scopeLabel, plan, classification) {
|
|
|
171
175
|
}
|
|
172
176
|
}
|
|
173
177
|
|
|
174
|
-
function buildClosedRecommendation(scopeLabel, plan, cwd) {
|
|
175
|
-
const closedPlanEvidence = getClosedPlanEvidenceStatus(cwd, plan)
|
|
178
|
+
function buildClosedRecommendation(scopeLabel, plan, cwd, options = {}) {
|
|
179
|
+
const closedPlanEvidence = getClosedPlanEvidenceStatus(cwd, plan, options)
|
|
176
180
|
if (closedPlanEvidence.verifyMode?.mode === 'metadata-first') {
|
|
177
181
|
return {
|
|
178
182
|
scopeLabel,
|
|
@@ -198,7 +202,7 @@ function buildClosedRecommendation(scopeLabel, plan, cwd) {
|
|
|
198
202
|
nextCommand: 'verify',
|
|
199
203
|
nextPath: '~verify -> CONSOLIDATE',
|
|
200
204
|
summary: `${scopeLabel} "${plan.planName}" 的任务已闭合,但当前 UI 契约仍要求独立 advisor 复查与视觉验收。`,
|
|
201
|
-
guidance: '先在 ~verify 阶段完成独立 advisor / style advisor
|
|
205
|
+
guidance: '先在 ~verify 阶段完成独立 advisor / style advisor 复查,并写入当前会话 `artifacts/advisor.json`;再完成视觉验收并写入当前会话 `artifacts/visual.json`,记录 reason、tooling、screensChecked、statesChecked、status 与 summary;两项都通过后再进入 CONSOLIDATE。',
|
|
202
206
|
}
|
|
203
207
|
}
|
|
204
208
|
|
|
@@ -210,7 +214,7 @@ function buildClosedRecommendation(scopeLabel, plan, cwd) {
|
|
|
210
214
|
nextCommand: 'verify',
|
|
211
215
|
nextPath: '~verify -> CONSOLIDATE',
|
|
212
216
|
summary: `${scopeLabel} "${plan.planName}" 的任务已闭合,但当前契约仍要求独立 advisor 复查。`,
|
|
213
|
-
guidance: '先在 ~verify 阶段完成独立 advisor / style advisor
|
|
217
|
+
guidance: '先在 ~verify 阶段完成独立 advisor / style advisor 复查,并写入当前会话 `artifacts/advisor.json` 记录复查原因、focus、来源与结论;advisor 通过后再进入 CONSOLIDATE。',
|
|
214
218
|
}
|
|
215
219
|
}
|
|
216
220
|
|
|
@@ -222,7 +226,7 @@ function buildClosedRecommendation(scopeLabel, plan, cwd) {
|
|
|
222
226
|
nextCommand: 'verify',
|
|
223
227
|
nextPath: '~verify -> CONSOLIDATE',
|
|
224
228
|
summary: `${scopeLabel} "${plan.planName}" 的任务已闭合,但当前 UI 契约仍要求视觉验收。`,
|
|
225
|
-
guidance: '先在 ~verify
|
|
229
|
+
guidance: '先在 ~verify 阶段完成视觉验收,并写入当前会话 `artifacts/visual.json` 记录 reason、tooling、screensChecked、statesChecked、status 与 summary;视觉验收通过后再进入 CONSOLIDATE。',
|
|
226
230
|
}
|
|
227
231
|
}
|
|
228
232
|
|
|
@@ -240,7 +244,7 @@ function buildClosedRecommendation(scopeLabel, plan, cwd) {
|
|
|
240
244
|
: `${scopeLabel} "${plan.planName}" 的任务、审查与验证已闭合。`,
|
|
241
245
|
guidance: closedPlanEvidence.closeoutReady
|
|
242
246
|
? '当前进入 CONSOLIDATE:更新 `state_path`、知识文件并归档方案后即可交付;不要无故重开新的方案包或重新跑一遍无关验证。'
|
|
243
|
-
: '当前进入 CONSOLIDATE
|
|
247
|
+
: '当前进入 CONSOLIDATE:先写当前会话 `artifacts/closeout.json` 记录需求覆盖与交付清单,再更新 `state_path` 并归档后交付。',
|
|
244
248
|
}
|
|
245
249
|
}
|
|
246
250
|
|
|
@@ -255,7 +259,7 @@ function buildClosedRecommendation(scopeLabel, plan, cwd) {
|
|
|
255
259
|
}
|
|
256
260
|
}
|
|
257
261
|
|
|
258
|
-
export function buildRecommendation(snapshot, cwd = process.cwd()) {
|
|
262
|
+
export function buildRecommendation(snapshot, cwd = process.cwd(), options = {}) {
|
|
259
263
|
const plan = getTargetPlans(snapshot)[0]
|
|
260
264
|
if (!plan) return null
|
|
261
265
|
|
|
@@ -269,7 +273,7 @@ export function buildRecommendation(snapshot, cwd = process.cwd()) {
|
|
|
269
273
|
return buildInProgressRecommendation(scopeLabel, plan, classification)
|
|
270
274
|
}
|
|
271
275
|
if (classification.status === 'closed') {
|
|
272
|
-
return buildClosedRecommendation(scopeLabel, plan, cwd)
|
|
276
|
+
return buildClosedRecommendation(scopeLabel, plan, cwd, options)
|
|
273
277
|
}
|
|
274
278
|
return null
|
|
275
279
|
}
|
|
@@ -18,12 +18,12 @@ import {
|
|
|
18
18
|
|
|
19
19
|
export function getDeliveryAction(cwd, options = {}) {
|
|
20
20
|
const snapshot = getWorkflowSnapshot(cwd, options)
|
|
21
|
-
const recommendation = buildRecommendation(snapshot, cwd)
|
|
21
|
+
const recommendation = buildRecommendation(snapshot, cwd, options)
|
|
22
22
|
return buildDeliveryActionFromSnapshot(snapshot, cwd, recommendation)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export function getWorkflowRecommendation(cwd, options = {}) {
|
|
26
|
-
return buildRecommendation(getWorkflowSnapshot(cwd, options), cwd)
|
|
26
|
+
return buildRecommendation(getWorkflowSnapshot(cwd, options), cwd, options)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export function buildStateSyncHint(cwd, options = {}) {
|
|
@@ -32,12 +32,12 @@ export function buildStateSyncHint(cwd, options = {}) {
|
|
|
32
32
|
|
|
33
33
|
export function buildDeliveryGateHint(cwd, options = {}) {
|
|
34
34
|
const snapshot = getWorkflowSnapshot(cwd, options)
|
|
35
|
-
return buildDeliveryGateHintFromSnapshot(snapshot, cwd, buildRecommendation(snapshot, cwd))
|
|
35
|
+
return buildDeliveryGateHintFromSnapshot(snapshot, cwd, buildRecommendation(snapshot, cwd, options))
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export function buildWorkflowRouteHint(cwd, options = {}) {
|
|
39
39
|
const snapshot = getWorkflowSnapshot(cwd, options)
|
|
40
|
-
const recommendation = buildRecommendation(snapshot, cwd)
|
|
40
|
+
const recommendation = buildRecommendation(snapshot, cwd, options)
|
|
41
41
|
const stateSyncHint = buildStateSyncHintFromSnapshot(snapshot)
|
|
42
42
|
const stateRoleHint = buildStateRoleHintFromSnapshot(snapshot)
|
|
43
43
|
const orchestrationHint = buildOrchestrationHintFromSnapshot(snapshot, cwd, recommendation)
|
|
@@ -92,7 +92,7 @@ function buildCommandRouteMessage(skillName, recommendation, verifyModeHint) {
|
|
|
92
92
|
|
|
93
93
|
export function buildCommandRouteHint(skillName, cwd, options = {}) {
|
|
94
94
|
const snapshot = getWorkflowSnapshot(cwd, options)
|
|
95
|
-
const recommendation = buildRecommendation(snapshot, cwd)
|
|
95
|
+
const recommendation = buildRecommendation(snapshot, cwd, options)
|
|
96
96
|
const contextHints = [
|
|
97
97
|
buildStateRoleHintFromSnapshot(snapshot),
|
|
98
98
|
buildStateSyncHintFromSnapshot(snapshot),
|
|
@@ -8,7 +8,7 @@ Trigger: ~build [description]
|
|
|
8
8
|
|
|
9
9
|
`~build` 是执行实现命令。它负责读取现有需求、方案包与项目上下文,完成实现、局部验证、修复循环,并把结果交给后续验证与收尾。
|
|
10
10
|
执行 `~build` 时,通用阶段边界按当前已加载 bootstrap 执行;本 skill 负责补充实现前定位、实现约束,以及进入 `~verify` / 收尾前的实现边界。
|
|
11
|
-
`.helloagents/` 在本 skill 中统一按项目级存储路径理解:状态文件只使用 `state_path
|
|
11
|
+
`.helloagents/` 在本 skill 中统一按项目级存储路径理解:状态文件只使用 `state_path`;会话证据使用当前 `state_path` 所在目录下的 `artifacts/*.json`;若 `project_store_mode=repo-shared`,知识库、`DESIGN.md`、`verify.yaml` 与方案包按当前上下文中已注入的项目知识/方案目录解析。
|
|
12
12
|
|
|
13
13
|
## 铁律
|
|
14
14
|
- 默认先定位上下文与范围,再修改代码
|
|
@@ -15,7 +15,7 @@ Trigger: ~commit [message]
|
|
|
15
15
|
3. 生成 conventional commit message(如未提供)
|
|
16
16
|
- 格式: type(scope): description
|
|
17
17
|
- type: feat|fix|refactor|docs|test|chore|style|perf
|
|
18
|
-
4.
|
|
18
|
+
4. 先一次性解析本轮设置:优先使用当前上下文中已注入的“当前用户设置”;上下文不存在或缺少 `commit_attribution` / `kb_create_mode` 时,读取一次 `~/.helloagents/helloagents.json`
|
|
19
19
|
5. 复用上一步已解析的设置获取 `commit_attribution`:
|
|
20
20
|
- ""(空,默认)→ 不添加归属
|
|
21
21
|
- 有内容(如 "Co-Authored-By: HelloAGENTS")→ 添加该内容到 commit message
|
|
@@ -39,14 +39,14 @@ Trigger: ~help
|
|
|
39
39
|
完成时:hello-verify, hello-reflect
|
|
40
40
|
|
|
41
41
|
### 当前设置
|
|
42
|
-
|
|
42
|
+
优先使用当前上下文中已注入的“当前用户设置”显示;若上下文不存在该信息,或缺少下表任一配置项,读取一次 `~/.helloagents/helloagents.json`。
|
|
43
43
|
如果当前 CLI 存在工作区限制导致家目录不可读,则明确说明“无法直接读取配置文件,以下按已注入设置或默认值展示”,不要改用无关工具或伪造已读取结果。
|
|
44
44
|
| 配置项 | 默认值 | 作用 | 适用 CLI |
|
|
45
45
|
|--------|-------|------|---------|
|
|
46
46
|
| output_language | "" | 空=跟随用户语言/填写则指定(如 zh-CN、en) | Claude Code + Gemini CLI + Codex CLI |
|
|
47
|
-
| output_format | true | true
|
|
47
|
+
| output_format | true | true=主代理最终收尾必须使用 HelloAGENTS 格式,流式/中间输出及子代理输出保持自然;false=自然输出 | Claude Code + Gemini CLI + Codex CLI |
|
|
48
48
|
| notify_level | 0 | 0=关闭/1=桌面通知/2=声音/3=两者 | Claude Code + Gemini CLI + Codex CLI |
|
|
49
|
-
| ralph_loop_enabled | true |
|
|
49
|
+
| ralph_loop_enabled | true | 自动验证循环(显式 ~verify / ~loop 或收尾要求时触发 lint/test/build) | Claude Code + Gemini CLI + Codex CLI |
|
|
50
50
|
| guard_enabled | true | 阻断危险命令与写入后的安全扫描 | Claude Code + Gemini CLI + Codex CLI |
|
|
51
51
|
| kb_create_mode | 1 | 0=关闭/1=已激活项目或全局模式中编码自动/2=已激活项目或全局模式中始终 | Claude Code + Gemini CLI + Codex CLI |
|
|
52
52
|
| project_store_mode | "local" | "local"=知识库/方案包保留在项目本地 `.helloagents/`;"repo-shared"=本地 `.helloagents/` 仅保留激活/STATE/运行态,知识库与方案包改写到 `~/.helloagents/projects/<repo-key>/` | Claude Code + Gemini CLI + Codex CLI |
|
|
@@ -22,7 +22,7 @@ Trigger: ~loop <目标描述> [--iterations N] [--metric "命令"] [--direction
|
|
|
22
22
|
2. 确保 `.helloagents/` 目录和 `state_path` 存在;文件不存在时按 `templates/STATE.md` 创建。`~loop` 必须维护这个状态文件,不受 `kb_create_mode` 控制;“主线目标”固定写本次优化目标,避免混入其他任务
|
|
23
23
|
3. 运行指标命令获取基线值,记录到 results log
|
|
24
24
|
4. 如有守卫命令,运行确认基线通过
|
|
25
|
-
5.
|
|
25
|
+
5. 创建当前会话的 `.helloagents/sessions/{branch}/{session}/artifacts/loop-results.tsv`
|
|
26
26
|
6. 根据优化目标标记可能需要的 hello-* 质量技能(如性能优化标记 hello-perf,UI 优化标记 hello-ui)
|
|
27
27
|
7. 重写 `state_path`:记录主线目标=当前优化目标、基线指标、守卫命令、下一步设为第一轮迭代的具体动作
|
|
28
28
|
|
|
@@ -8,7 +8,7 @@ Trigger: ~plan [description]
|
|
|
8
8
|
|
|
9
9
|
`~plan` 是实现前的主规划命令。它负责需求澄清、方案设计、任务拆解与方案写入;直接显式执行 `~plan` 时,默认停在“形成可执行方案”,只有用户明确授权继续时才继续执行。
|
|
10
10
|
执行 `~plan` 时,通用阶段边界按当前已加载 bootstrap 执行;本 skill 负责补充 `~plan` 的需求澄清、方案确认、方案包写入与继续执行要求。
|
|
11
|
-
`.helloagents/` 在本 skill 中统一按项目级存储路径理解:状态文件只使用 `state_path
|
|
11
|
+
`.helloagents/` 在本 skill 中统一按项目级存储路径理解:状态文件只使用 `state_path`;会话证据使用当前 `state_path` 所在目录下的 `artifacts/*.json`;若 `project_store_mode=repo-shared`,知识库、`DESIGN.md` 与 `plans/` / `archive/` 按当前上下文中已注入的项目知识/方案目录解析。
|
|
12
12
|
|
|
13
13
|
## 铁律
|
|
14
14
|
- 在用户确认方案之前,禁止编写任何实现代码、创建任何实现文件、或执行任何实现操作
|
|
@@ -39,6 +39,7 @@ Trigger: ~plan [description]
|
|
|
39
39
|
- 先读取 5-15 个相关文件,基于代码证据形成假设
|
|
40
40
|
- 用 2-4 轮确认关键假设
|
|
41
41
|
- 低置信度假设必须明确询问
|
|
42
|
+
- 发现用户用词与 `.helloagents/context.md` 的领域语言冲突时,立即澄清并统一术语
|
|
42
43
|
|
|
43
44
|
**交互模式**(全新项目或信息不足):
|
|
44
45
|
- 每次只问一个问题,优先使用选择题
|
|
@@ -69,6 +70,7 @@ Trigger: ~plan [description]
|
|
|
69
70
|
- 数据流与错误处理
|
|
70
71
|
- 验证策略
|
|
71
72
|
- 涉及 UI 时的设计方向、状态覆盖与 `DESIGN.md` 更新点
|
|
73
|
+
- 涉及项目特有概念时,同步确认标准术语、避免用语和关键关系,必要时更新 `.helloagents/context.md` 的“领域语言”区块(按当前项目存储模式解析)
|
|
72
74
|
|
|
73
75
|
### 5. 写入方案包
|
|
74
76
|
|
|
@@ -81,7 +83,7 @@ Trigger: ~plan [description]
|
|
|
81
83
|
- `tasks.md`
|
|
82
84
|
- `contract.json`
|
|
83
85
|
- 写 `contract.json` 时,至少落成以下字段:`verifyMode`、`reviewerFocus`、`testerFocus`;涉及 UI 时再写 `ui.required`、`ui.designContract` 与 `ui.sourcePriority`
|
|
84
|
-
- 只有在 UI 方向确需先明确时,才额外写 `ui.styleAdvisor.required`、`ui.styleAdvisor.reason` 与 `ui.styleAdvisor.focus
|
|
86
|
+
- 只有在 UI 方向确需先明确时,才额外写 `ui.styleAdvisor.required`、`ui.styleAdvisor.reason` 与 `ui.styleAdvisor.focus`;它复用当前会话 `artifacts/advisor.json`,不是默认常驻步骤
|
|
85
87
|
- 只有在 UI 验收确有收益时,才额外写 `ui.visualValidation.required`、`ui.visualValidation.reason`、`ui.visualValidation.screens` 与 `ui.visualValidation.states`;不要把视觉验收扩成所有 UI 任务的固定步骤
|
|
86
88
|
- 只有在 `T3`、非 UI 的高风险审查或确需额外跨模型建议时,才写 `advisor.required`、`advisor.reason`、`advisor.focus` 与 `advisor.preferredSources`;不要把 advisor 变成默认常驻流程
|
|
87
89
|
- 使用 `scripts/plan-contract.mjs write` 写 `contract.json`,不要让后续检查脚本再从 `plan.md` 的自然语言说明里猜验证主路径
|
|
@@ -103,10 +105,10 @@ Trigger: ~plan [description]
|
|
|
103
105
|
## 方案包要求
|
|
104
106
|
|
|
105
107
|
方案包中的 `tasks.md` 必须满足:
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
-
|
|
109
|
-
-
|
|
108
|
+
- 每个任务默认是端到端垂直切片,能交付一个可验证行为;除非确有技术前置,否则不按“数据库 / API / UI / 测试”横向拆分
|
|
109
|
+
- 每个任务标注 `AFK` 或 `HITL`:`AFK` 表示代理可独立完成,`HITL` 表示需要用户决策、外部凭据、人工视觉确认或手动验收
|
|
110
|
+
- 明确文件路径、预期变更、完成标准、验证方式与依赖关系
|
|
111
|
+
- 每个任务可独立验证;厚任务必须拆成更薄的可验收切片
|
|
110
112
|
|
|
111
113
|
方案包中的 `contract.json` 必须满足:
|
|
112
114
|
- `verifyMode` 只能是 `test-first` 或 `review-first`
|
|
@@ -8,7 +8,7 @@ Trigger: ~prd [description]
|
|
|
8
8
|
|
|
9
9
|
执行 `~prd` 时,不读取 `~plan` 的 command skill;只有当前流程明确需要时,才继续读取对应的 hello-* 技能。
|
|
10
10
|
执行 `~prd` 时,通用阶段边界按当前已加载 bootstrap 执行;本 skill 负责补充规格探索、PRD 写入与继续执行要求。
|
|
11
|
-
`.helloagents/` 在本 skill 中统一按项目级存储路径理解:状态文件只使用 `state_path
|
|
11
|
+
`.helloagents/` 在本 skill 中统一按项目级存储路径理解:状态文件只使用 `state_path`;会话证据使用当前 `state_path` 所在目录下的 `artifacts/*.json`;若 `project_store_mode=repo-shared`,知识库、`DESIGN.md` 与 `plans/` / `archive/` 按当前上下文中已注入的项目知识/方案目录解析。
|
|
12
12
|
|
|
13
13
|
## 铁律
|
|
14
14
|
- 在用户确认方案之前,禁止编写任何实现代码、创建任何文件、或执行任何实现操作。
|
|
@@ -60,6 +60,7 @@ Trigger: ~prd [description]
|
|
|
60
60
|
已有项目:
|
|
61
61
|
- 按当前已加载 bootstrap 的“.helloagents/ 文件读取优先级”和“项目文件”规则恢复上下文;若当前消息明确要继续上次任务,或会话刚经历恢复 / 压缩,先读取 `state_path`,再用当前用户消息、显式命令、活跃方案包 / PRD 与代码事实确认当前任务
|
|
62
62
|
- 在进入维度探索前,至少确认 `.helloagents/context.md`、`.helloagents/guidelines.md`,并只扫描与当前产品范围直接相关的代码和配置
|
|
63
|
+
- 若 `.helloagents/context.md` 已有领域语言,PRD 中统一沿用;发现术语冲突或歧义时,先澄清再写入
|
|
63
64
|
|
|
64
65
|
全新项目(无 .helloagents/ 目录):
|
|
65
66
|
- 跳过,直接进入项目定位
|
|
@@ -88,6 +89,7 @@ c. AI 总结该维度的决策结果,进入下一个维度
|
|
|
88
89
|
- 用户说"默认" → AI 按推荐方案填充,快速过
|
|
89
90
|
- 用户说"展开" → 深入讨论该维度的子项
|
|
90
91
|
- 维度之间可以回溯:用户说"回到 03" → 重新讨论 UI/UX 设计
|
|
92
|
+
- 涉及项目特有概念时,确认标准术语、避免用语和关键关系;不要把泛化技术词写入领域语言
|
|
91
93
|
|
|
92
94
|
选项质量要求:
|
|
93
95
|
- 涉及视觉/交互/体验的问题时,选项必须体现当前前沿设计水准
|
|
@@ -100,7 +102,7 @@ c. AI 总结该维度的决策结果,进入下一个维度
|
|
|
100
102
|
- 按当前已加载 bootstrap 的 `.helloagents/` 与流程状态规则,确保最小项目状态已建立;这是方案包写入的前置操作,不受 kb_create_mode 开关控制
|
|
101
103
|
- 创建 `.helloagents/plans/YYYYMMDDHHMM_{feature}/prd/`(按当前项目存储模式解析)
|
|
102
104
|
- 按 templates/plans/prd/ 的模板格式,仅写入用户未跳过的维度文件
|
|
103
|
-
- 生成 tasks.md
|
|
105
|
+
- 生成 tasks.md(每个任务默认是端到端垂直切片,标注 AFK / HITL、依赖、具体文件路径、预期变更、完成标准与验证方式;任务独立可验证)
|
|
104
106
|
- 生成 decisions.md(贯穿全程的决策日志)
|
|
105
107
|
- 生成 `contract.json`(至少包含 `verifyMode`、`reviewerFocus`、`testerFocus`;涉及 UI 时补 `ui.required`、`ui.designContract`、`ui.sourcePriority`;仅在确需先明确审美方向时再补 `ui.styleAdvisor.required`、`ui.styleAdvisor.reason`、`ui.styleAdvisor.focus`;仅在确需视觉验收时再补 `ui.visualValidation.required`、`ui.visualValidation.reason`、`ui.visualValidation.screens`、`ui.visualValidation.states`;仅在确需独立 advisor 时,再补 `advisor.required`、`advisor.reason`、`advisor.focus`、`advisor.preferredSources`)
|
|
106
108
|
- 使用 `scripts/plan-contract.mjs write` 写 `contract.json`,不要只把验证路径留在自然语言说明里
|
|
@@ -140,7 +142,7 @@ plans/YYYYMMDDHHMM_{feature}/
|
|
|
140
142
|
│ ├── 02-functional.md
|
|
141
143
|
│ └── ...
|
|
142
144
|
├── contract.json # 机器可消费的验证 / 审查契约
|
|
143
|
-
├── tasks.md #
|
|
145
|
+
├── tasks.md # 端到端垂直切片任务
|
|
144
146
|
└── decisions.md # 决策日志
|
|
145
147
|
```
|
|
146
148
|
|
|
@@ -13,8 +13,8 @@ Trigger: ~verify [scope]
|
|
|
13
13
|
- 即使命令通过,也不能越过当前方案包边界:不完整方案包不能视为可信交付记录,未闭合方案包不能被整体报告为已完成
|
|
14
14
|
- 当推荐路径已进入 `~verify` / 收尾时,优先把本命令用于审查、验真和交付收尾
|
|
15
15
|
- 若当前存在活跃方案包,先读取 `requirements.md`、`plan.md`、`tasks.md`、`contract.json`,把它们当作本轮验证契约;不要只看命令结果
|
|
16
|
-
- 若 `contract.json` 声明 `advisor.required=true` 或 `ui.styleAdvisor.required=true
|
|
17
|
-
- 若 `contract.json` 声明 `ui.visualValidation.required=true
|
|
16
|
+
- 若 `contract.json` 声明 `advisor.required=true` 或 `ui.styleAdvisor.required=true`,则本轮还必须补齐当前会话 `artifacts/advisor.json`;advisor / style advisor 都是可选能力,不是默认常驻步骤
|
|
17
|
+
- 若 `contract.json` 声明 `ui.visualValidation.required=true`,则本轮还必须补齐当前会话 `artifacts/visual.json`;视觉验收优先用截图/浏览器工具,没有工具时才降级为结构化代码级自检
|
|
18
18
|
1. 先决定验证分流:
|
|
19
19
|
- 若当前上下文中已注入“验证分流”,先按该分流执行
|
|
20
20
|
- 用户显式使用 `~review` 时,即使本轮没有注入分流,也按审查优先起步
|
|
@@ -23,15 +23,15 @@ Trigger: ~verify [scope]
|
|
|
23
23
|
- 获取变更范围:无参数默认未提交变更;`staged` 代表暂存区;指定文件/目录则只审查对应范围
|
|
24
24
|
- 按 hello-* 技能查找路径读取 `hello-review` SKILL.md,执行逐文件审查
|
|
25
25
|
- 高风险流程除显式范围外,还要主动补查相关配置、迁移、权限、部署或安全边界文件,不能只盯住单个功能文件
|
|
26
|
-
- 审查结论确定后,立即调用 `scripts/review-state.mjs write`
|
|
26
|
+
- 审查结论确定后,立即调用 `scripts/review-state.mjs write` 写当前会话 `artifacts/review.json`;用结构化字段记录 `outcome`、`conclusion`、`findings`、`fileReferences`,不要让后续检查脚本再从自然语言消息里猜结论
|
|
27
27
|
3. 全量验证模式或审查后继续验证:
|
|
28
28
|
- 读取 `hello-verify` SKILL.md
|
|
29
29
|
- 按其“验证命令来源”优先级检测命令
|
|
30
30
|
- 逐个运行所有检测到的命令
|
|
31
31
|
- 收集每个命令的输出和退出码
|
|
32
32
|
- 对照当前契约逐项核对:requirements 是否覆盖、tasks 中每项“完成标准”是否满足、`plan.md` 中风险与设计约束是否被验证、`contract.json` 中声明的 `verifyMode` / reviewer / tester 关注边界是否已被覆盖
|
|
33
|
-
- 若 `advisor.required=true` 或 `ui.styleAdvisor.required=true`,在进入收尾前调用 `scripts/advisor-state.mjs write`
|
|
34
|
-
- 若 `ui.visualValidation.required=true`,在进入收尾前调用 `scripts/visual-state.mjs write`
|
|
33
|
+
- 若 `advisor.required=true` 或 `ui.styleAdvisor.required=true`,在进入收尾前调用 `scripts/advisor-state.mjs write` 写当前会话 `artifacts/advisor.json`;记录触发原因、focus、consultedSources、结论与建议,禁止只在自然语言里留一段 advisor 意见
|
|
34
|
+
- 若 `ui.visualValidation.required=true`,在进入收尾前调用 `scripts/visual-state.mjs write` 写当前会话 `artifacts/visual.json`;记录 `reason`、`tooling`、`screensChecked`、`statesChecked`、`status`、`summary`、`findings` 与 `recommendations`
|
|
35
35
|
4. 汇总报告:
|
|
36
36
|
- ✅ 通过的审查项 / 命令
|
|
37
37
|
- ❌ 失败的审查项 / 命令 + 错误详情
|