@tea-agent/loop-agent 0.21.0 → 0.22.0
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/CHANGELOG.md +46 -0
- package/bin/agent-worker.js +0 -0
- package/dist/adapters/loop-agent.js +52 -0
- package/dist/commands/init.js +97 -0
- package/dist/executors/dag-pi-executor.js +2 -0
- package/dist/executors/shell-executor.js +162 -19
- package/dist/shared/openspec-spec.js +49 -0
- package/dist/worker/observability/read-model.js +21 -1
- package/dist/worker/observe/spec-evidence.js +12 -15
- package/dist/worker/observe/static/dag-helpers.js +22 -0
- package/dist/worker/observe/static/views/dag.js +5 -0
- package/dist/workflows/dag/backend-test-markdown-workflow.js +37 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +141 -32
- package/dist/workflows/dag/frontend-lint-baseline.js +471 -0
- package/dist/workflows/dag/frontend-prewrite-gate.js +79 -16
- package/dist/workflows/dag/frontend-project-capability.js +11 -8
- package/dist/workflows/dag/frontend-repair.js +6 -4
- package/dist/workflows/dag/frontend-review-context.js +67 -0
- package/dist/workflows/dag/frontend-test-case-quality.js +105 -0
- package/dist/workflows/dag/frontend-test-result-contract.js +71 -66
- package/dist/workflows/dag/frontend-verification-trace.js +31 -1
- package/dist/workflows/dag/frontend-worktree-diff.js +81 -6
- package/dist/workflows/dag/init-hybrid.js +344 -64
- package/dist/workflows/dag/types.js +62 -1
- package/docs/templates/agent-dag.schema.json +15 -5
- package/docs/templates/backend-test-dag.json +1 -1
- package/docs/templates/frontend-implementation-contract.schema.json +4 -3
- package/docs/templates/frontend-test-case-checklist.md +6 -2
- package/docs/templates/frontend-test-dag.json +2 -2
- package/package.json +1 -1
- package/skills/frontend-design-review/SKILL.md +12 -10
- package/skills/frontend-design-review/references/review-checklist.md +4 -4
- package/skills/frontend-implementation/SKILL.md +2 -2
- package/skills/frontend-implementation/references/code-standards.md +4 -3
- package/skills/frontend-implementation/references/design-spec.md +19 -14
- package/skills/frontend-implementation/references/node-contracts.md +2 -2
- package/skills/frontend-review/SKILL.md +15 -28
- package/skills/frontend-review/references/review-findings.md +16 -18
- package/skills/frontend-verification/SKILL.md +16 -13
- package/skills/frontend-verification/references/verification-checklist.md +18 -30
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { isOpenspecSpecFilePath } from "../../shared/openspec-spec.js";
|
|
2
3
|
import { campaignBudgetSchema, } from "../../application/evaluation/budget.js";
|
|
3
4
|
import { assertDagPromptSourceRule } from "./prompt-source.js";
|
|
4
5
|
import { dagRetryPolicySchema } from "./retry-policy.js";
|
|
@@ -25,6 +26,7 @@ export const dagShellVerifyEvidenceSchema = z.object({
|
|
|
25
26
|
commandSource: z.enum(["adapter", "inline"]),
|
|
26
27
|
commandCount: z.number().int().nonnegative(),
|
|
27
28
|
commandLabels: z.array(z.string()).default([]),
|
|
29
|
+
commandTexts: z.array(z.string()).default([]),
|
|
28
30
|
finalFullRequired: z.boolean().optional(),
|
|
29
31
|
});
|
|
30
32
|
export const dagRepairArtifactGateSchema = z.object({
|
|
@@ -128,22 +130,80 @@ export const dagFrontendPrewriteGateSchema = z.object({
|
|
|
128
130
|
allowedMockStrategies: z.array(z.enum(["native", "browser-intercept", "request-adapter", "not-needed"])).min(1),
|
|
129
131
|
artifactName: z.string().regex(/^[a-z0-9][a-z0-9._-]*\.json$/),
|
|
130
132
|
outputDir: z.string().regex(/^[a-z0-9][a-z0-9._-]*$/),
|
|
133
|
+
requireSourceFreshness: z.literal(true),
|
|
134
|
+
implementationWriteSet: z.array(z.string().min(1)).min(1).optional(),
|
|
131
135
|
openspecCandidatePaths: z
|
|
132
|
-
.array(z.string().
|
|
136
|
+
.array(z.string().refine((candidate) => !candidate.includes("\\") &&
|
|
137
|
+
isOpenspecSpecFilePath(candidate), "openspec candidate must be a repo-relative supported file under openspec/schemas/ or openspec/project-specs/"))
|
|
133
138
|
.default([]),
|
|
134
139
|
});
|
|
140
|
+
export const dagFrontendLintBaselineSchema = z
|
|
141
|
+
.object({
|
|
142
|
+
schemaVersion: z.literal(1),
|
|
143
|
+
lintCommands: z.array(z.string().min(1)).min(1),
|
|
144
|
+
lintEvidence: dagShellVerifyEvidenceSchema,
|
|
145
|
+
})
|
|
146
|
+
.strict();
|
|
135
147
|
export const dagFrontendVerificationBundleSchema = z.object({
|
|
136
148
|
schemaVersion: z.literal(1),
|
|
137
149
|
mockCommands: z.array(z.string()).default([]),
|
|
150
|
+
lintCommands: z.array(z.string().min(1)).optional(),
|
|
138
151
|
staticCommands: z.array(z.string()).min(1),
|
|
139
152
|
behaviorCommands: z.array(z.string()).min(1),
|
|
140
153
|
mockEvidence: dagShellVerifyEvidenceSchema.optional(),
|
|
154
|
+
lintEvidence: dagShellVerifyEvidenceSchema.optional(),
|
|
141
155
|
staticEvidence: dagShellVerifyEvidenceSchema,
|
|
142
156
|
behaviorEvidence: dagShellVerifyEvidenceSchema,
|
|
157
|
+
lintBaselineNodeId: dagFrontendNodeIdSchema.optional(),
|
|
158
|
+
writerNodeIds: z.array(dagFrontendNodeIdSchema).optional(),
|
|
143
159
|
mode: z.enum(["initial", "repair"]),
|
|
160
|
+
}).superRefine((bundle, context) => {
|
|
161
|
+
const groups = [
|
|
162
|
+
["mock", bundle.mockCommands, bundle.mockEvidence],
|
|
163
|
+
["lint", bundle.lintCommands ?? [], bundle.lintEvidence],
|
|
164
|
+
["static", bundle.staticCommands, bundle.staticEvidence],
|
|
165
|
+
["behavior", bundle.behaviorCommands, bundle.behaviorEvidence],
|
|
166
|
+
];
|
|
167
|
+
for (const [name, commands, evidence] of groups) {
|
|
168
|
+
if ((name === "mock" || name === "lint") && commands.length === 0 && !evidence)
|
|
169
|
+
continue;
|
|
170
|
+
if (!evidence) {
|
|
171
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: [`${name}Evidence`], message: `${name} evidence is required when commands are configured` });
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
if (evidence.commandCount !== commands.length) {
|
|
175
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: [`${name}Evidence`, "commandCount"], message: `${name} commandCount must match commands` });
|
|
176
|
+
}
|
|
177
|
+
if (evidence.commandLabels.length !== commands.length) {
|
|
178
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: [`${name}Evidence`, "commandLabels"], message: `${name} commandLabels must match commands` });
|
|
179
|
+
}
|
|
180
|
+
if (evidence.commandTexts.length !== commands.length || evidence.commandTexts.some((command, index) => command !== commands[index])) {
|
|
181
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: [`${name}Evidence`, "commandTexts"], message: `${name} commandTexts must exactly match commands` });
|
|
182
|
+
}
|
|
183
|
+
if (new Set(evidence.commandLabels).size !== evidence.commandLabels.length || evidence.commandLabels.some((label) => !label.trim())) {
|
|
184
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: [`${name}Evidence`, "commandLabels"], message: `${name} commandLabels must be non-empty and unique` });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if ((bundle.lintCommands?.length ?? 0) > 0) {
|
|
188
|
+
if (!bundle.lintBaselineNodeId) {
|
|
189
|
+
context.addIssue({
|
|
190
|
+
code: z.ZodIssueCode.custom,
|
|
191
|
+
path: ["lintBaselineNodeId"],
|
|
192
|
+
message: "lintBaselineNodeId is required when lintCommands are present",
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
if (!bundle.writerNodeIds || bundle.writerNodeIds.length === 0) {
|
|
196
|
+
context.addIssue({
|
|
197
|
+
code: z.ZodIssueCode.custom,
|
|
198
|
+
path: ["writerNodeIds"],
|
|
199
|
+
message: "writerNodeIds are required when lintCommands are present",
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
144
203
|
});
|
|
145
204
|
export const dagFrontendReviewContextSchema = z.object({
|
|
146
205
|
schemaVersion: z.literal(1),
|
|
206
|
+
requireBaseline: z.literal(true),
|
|
147
207
|
});
|
|
148
208
|
export const ENV_VAR_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
|
|
149
209
|
export const dagVersionSchema = z
|
|
@@ -226,6 +286,7 @@ export const dagShellConfigSchema = z.object({
|
|
|
226
286
|
requirementCoverageGate: dagRequirementCoverageGateSchema.optional(),
|
|
227
287
|
jsonArtifactGate: dagJsonArtifactGateSchema.optional(),
|
|
228
288
|
frontendPrewriteGate: dagFrontendPrewriteGateSchema.optional(),
|
|
289
|
+
frontendLintBaseline: dagFrontendLintBaselineSchema.optional(),
|
|
229
290
|
frontendVerificationBundle: dagFrontendVerificationBundleSchema.optional(),
|
|
230
291
|
frontendReviewContext: dagFrontendReviewContextSchema.optional(),
|
|
231
292
|
backendTestPipeline: dagBackendTestPipelineSchema.optional(),
|
|
@@ -173,6 +173,11 @@
|
|
|
173
173
|
"items": { "type": "string" },
|
|
174
174
|
"default": []
|
|
175
175
|
},
|
|
176
|
+
"commandTexts": {
|
|
177
|
+
"type": "array",
|
|
178
|
+
"items": { "type": "string" },
|
|
179
|
+
"default": []
|
|
180
|
+
},
|
|
176
181
|
"finalFullRequired": { "type": "boolean" }
|
|
177
182
|
}
|
|
178
183
|
},
|
|
@@ -306,7 +311,7 @@
|
|
|
306
311
|
"frontendPrewriteGate": {
|
|
307
312
|
"type": "object",
|
|
308
313
|
"additionalProperties": false,
|
|
309
|
-
"required": ["schemaVersion", "planFromNodeId", "reviewFromNodeId", "allowedMockStrategies", "artifactName", "outputDir"],
|
|
314
|
+
"required": ["schemaVersion", "planFromNodeId", "reviewFromNodeId", "allowedMockStrategies", "artifactName", "outputDir", "requireSourceFreshness"],
|
|
310
315
|
"properties": {
|
|
311
316
|
"schemaVersion": { "const": 1 },
|
|
312
317
|
"planFromNodeId": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
|
|
@@ -316,7 +321,9 @@
|
|
|
316
321
|
"requiredRequirementIds": { "type": "array", "items": { "type": "string", "pattern": "^(?:REQ|BR|AC)-[A-Z0-9]+(?:-[A-Z0-9]+)*$" } },
|
|
317
322
|
"allowedMockStrategies": { "type": "array", "minItems": 1, "items": { "enum": ["native", "browser-intercept", "request-adapter", "not-needed"] } },
|
|
318
323
|
"artifactName": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*\\.json$" },
|
|
319
|
-
"outputDir": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" }
|
|
324
|
+
"outputDir": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
|
|
325
|
+
"requireSourceFreshness": { "const": true },
|
|
326
|
+
"implementationWriteSet": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } }
|
|
320
327
|
}
|
|
321
328
|
},
|
|
322
329
|
"frontendVerificationBundle": {
|
|
@@ -332,13 +339,16 @@
|
|
|
332
339
|
"staticEvidence": { "$ref": "#/$defs/shellVerifyEvidence" },
|
|
333
340
|
"behaviorEvidence": { "$ref": "#/$defs/shellVerifyEvidence" },
|
|
334
341
|
"mode": { "enum": ["initial", "repair"] }
|
|
335
|
-
}
|
|
342
|
+
},
|
|
343
|
+
"allOf": [
|
|
344
|
+
{ "properties": { "staticEvidence": { "required": ["commandTexts"], "properties": { "commandTexts": { "minItems": 1 } } }, "behaviorEvidence": { "required": ["commandTexts"], "properties": { "commandTexts": { "minItems": 1 } } } } }
|
|
345
|
+
]
|
|
336
346
|
},
|
|
337
347
|
"frontendReviewContext": {
|
|
338
348
|
"type": "object",
|
|
339
349
|
"additionalProperties": false,
|
|
340
|
-
"required": ["schemaVersion"],
|
|
341
|
-
"properties": { "schemaVersion": { "const": 1 } }
|
|
350
|
+
"required": ["schemaVersion", "requireBaseline"],
|
|
351
|
+
"properties": { "schemaVersion": { "const": 1 }, "requireBaseline": { "const": true } }
|
|
342
352
|
},
|
|
343
353
|
"backendTestPipeline": {
|
|
344
354
|
"enum": ["contracts", "semantic-initial", "execute-parse-initial", "classification-result-context"]
|
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
".harness/dag-runs/**",
|
|
251
251
|
"artifacts/**"
|
|
252
252
|
],
|
|
253
|
-
"outputContract": "One scoped pytest execution over Markdown-mapped scripts producing valid JUnit with per-case captured output, self-contained HTML and reports/backend-test-facts.md; exit 0/1 with valid evidence continues.",
|
|
253
|
+
"outputContract": "One scoped pytest execution over Markdown-mapped scripts producing valid JUnit with per-case captured output, self-contained HTML, reports/backend-test.md and reports/backend-test-facts.md; exit 0/1 with valid evidence continues.",
|
|
254
254
|
"subtask_prompt": "Resolve the final Markdown Automation Notes/自动化映射 to a unique, safe set of testcase/**/test_*.py targets and execute only those scripts exactly once. Validate JUnit, then render the primary self-contained Chinese HTML report from the same JUnit plus final Markdown case metadata without rerun. Keep 测试结论, quality status, failure overview, and a polished per-case result card with concise scenario, automation test name, result, duration, and redacted bounded HTTP request parameters/response results for both passed and failed cases. Do not render a technical/execution evidence section in HTML; retain auditable paths and hashes in facts.",
|
|
255
255
|
"shell": {
|
|
256
256
|
"commands": [
|
|
@@ -10,14 +10,15 @@
|
|
|
10
10
|
"sourceBinding": { "$ref": "#/$defs/sourceBinding" },
|
|
11
11
|
"riskLevel": { "enum": ["small", "standard", "high-risk"] },
|
|
12
12
|
"targets": { "type": "object", "additionalProperties": false, "required": ["files"], "properties": { "files": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/path" } }, "routes": { "type": "array", "items": { "type": "string", "pattern": "^/" } }, "publicApiChanges": { "type": "array", "items": { "type": "string", "minLength": 1 } } } },
|
|
13
|
-
"requirements": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["id", "implementationTargets", "verificationTargetIds"], "properties": { "id": { "$ref": "#/$defs/requirementId" }, "implementationTargets": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "verificationTargetIds": { "type": "array", "items": { "type": "string", "minLength": 1 } }, "evidenceGap": { "$ref": "#/$defs/gap" } } } },
|
|
14
|
-
"uiStates": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["name", "applicable"], "properties": { "name": { "type": "string", "minLength": 1 }, "applicable": { "type": "boolean" }, "expectedBehavior": { "type": "string", "minLength": 1 }, "implementationTargets": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "verificationTargetIds": { "type": "array", "items": { "type": "string", "minLength": 1 } }, "notApplicableReason": { "type": "string", "minLength": 1 } } } },
|
|
13
|
+
"requirements": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["id", "implementationTargets", "verificationTargetIds"], "properties": { "id": { "$ref": "#/$defs/requirementId" }, "implementationTargets": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "verificationTargetIds": { "type": "array", "items": { "type": "string", "minLength": 1 } }, "evidenceGap": { "$ref": "#/$defs/gap" } } } },
|
|
14
|
+
"uiStates": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["name", "applicable"], "properties": { "name": { "type": "string", "minLength": 1 }, "applicable": { "type": "boolean" }, "expectedBehavior": { "type": "string", "minLength": 1 }, "implementationTargets": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "verificationTargetIds": { "type": "array", "items": { "type": "string", "minLength": 1 } }, "notApplicableReason": { "type": "string", "minLength": 1 } } } },
|
|
15
15
|
"interactions": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["name", "implementationTargets", "verificationTargetIds"], "properties": { "name": { "type": "string", "minLength": 1 }, "implementationTargets": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "verificationTargetIds": { "type": "array", "items": { "type": "string" } } } } },
|
|
16
16
|
"mockApi": { "type": "object", "additionalProperties": false, "required": ["strategy", "productionDefaultOff", "activation", "endpoints"], "properties": { "strategy": { "enum": ["native", "browser-intercept", "request-adapter", "not-needed"] }, "productionDefaultOff": { "const": true }, "activation": { "type": "string", "minLength": 1 }, "endpoints": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["method", "path"], "properties": { "method": { "enum": ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"] }, "path": { "type": "string", "pattern": "^/" }, "fixture": { "$ref": "#/$defs/path" }, "consumer": { "$ref": "#/$defs/path" } } } } } },
|
|
17
17
|
"designEvidence": { "type": "object", "additionalProperties": false, "required": ["source", "paths", "conflicts"], "properties": { "source": { "type": "string", "minLength": 1 }, "paths": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "conflicts": { "type": "array", "items": { "type": "string", "minLength": 1 } } } },
|
|
18
|
-
"verificationTargets": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["id", "type", "commandLabel", "file", "requirementIds", "uiStates"], "properties": { "id": { "type": "string", "minLength": 1 }, "type": { "enum": ["static", "unit", "component", "integration", "mock"] }, "commandLabel": { "type": "string", "minLength": 1 }, "file": { "$ref": "#/$defs/path" }, "symbol": { "type": "string", "minLength": 1 }, "requirementIds": { "type": "array", "items": { "$ref": "#/$defs/requirementId" } }, "uiStates": { "type": "array", "items": { "type": "string", "minLength": 1 } } } } },
|
|
18
|
+
"verificationTargets": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["id", "type", "commandLabel", "file", "requirementIds", "uiStates"], "properties": { "id": { "type": "string", "minLength": 1 }, "type": { "enum": ["static", "unit", "component", "integration", "mock"] }, "commandLabel": { "type": "string", "minLength": 1 }, "file": { "$ref": "#/$defs/path" }, "symbol": { "type": "string", "minLength": 1 }, "requirementIds": { "type": "array", "items": { "$ref": "#/$defs/requirementId" } }, "uiStates": { "type": "array", "items": { "type": "string", "minLength": 1 } } } } },
|
|
19
19
|
"evidenceGaps": { "type": "array", "items": { "$ref": "#/$defs/gap" } }
|
|
20
20
|
},
|
|
21
|
+
"allOf": [{ "if": { "properties": { "mockApi": { "properties": { "strategy": { "enum": ["native", "browser-intercept", "request-adapter"] } } } } }, "then": { "properties": { "mockApi": { "properties": { "endpoints": { "minItems": 1, "items": { "required": ["method", "path", "fixture", "consumer"] } } } } } } }],
|
|
21
22
|
"$defs": {
|
|
22
23
|
"path": { "type": "string", "minLength": 1, "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\\\).+$" },
|
|
23
24
|
"requirementId": { "type": "string", "pattern": "^(?:REQ|BR|AC)-[A-Z0-9]+(?:-[A-Z0-9]+)*$" },
|
|
@@ -17,8 +17,12 @@ LLM review (when `frontendTest.reviewMode=blocking`) must not invent blocking ru
|
|
|
17
17
|
| `case-id-is-ac` | Do not use acceptance id as `caseId` / filename |
|
|
18
18
|
| `case-path-mismatch` | `casePath === testcase/frontend/cases/{caseId}.md` |
|
|
19
19
|
| `case-file-missing` | `casePath` exists |
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
|
|
21
|
+
## Tool guidance (non-blocking)
|
|
22
|
+
|
|
23
|
+
- Browser execution should **strongly prefer `playwright-cli`** and the standard start command documented above.
|
|
24
|
+
- The fourth node does not scan for or block executable commands from other tools, including `pytest`, bare/native Playwright, `npx playwright`, `playwright test`, `@playwright/test`, or Node Playwright APIs.
|
|
25
|
+
- Tool-choice findings belong in later advisory/reporting stages rather than this structural hard gate.
|
|
22
26
|
|
|
23
27
|
### ID 对照(避免混用)
|
|
24
28
|
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
".harness/**",
|
|
94
94
|
"artifacts/**"
|
|
95
95
|
],
|
|
96
|
-
"outputContract": "Markdown cases, index.md and manifest.json schemaVersion 1; no test source code.",
|
|
96
|
+
"outputContract": "Markdown cases, index.md and manifest.draft.json schemaVersion 1; materialize promotes the validated draft to manifest.json; no test source code.",
|
|
97
97
|
"subtask_prompt_markdown": "./frontend-test-dag.generate-cases.prompt.md"
|
|
98
98
|
},
|
|
99
99
|
{
|
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
".harness/**",
|
|
251
251
|
"artifacts/**"
|
|
252
252
|
],
|
|
253
|
-
"outputContract": "Mechanical checklist:
|
|
253
|
+
"outputContract": "Mechanical checklist: manifest/case paths, Case ID, non-production playwright-cli open prefix, and AC mapping; strongly recommend playwright-cli without blocking alternative executable tool commands.",
|
|
254
254
|
"subtask_prompt": "Scan generated cases/manifest against the shared blocking checklist. Runtime hybrid embeds the authoritative script.",
|
|
255
255
|
"shell": {
|
|
256
256
|
"commands": [
|
package/package.json
CHANGED
|
@@ -11,10 +11,10 @@ references:
|
|
|
11
11
|
|
|
12
12
|
For frontend design review nodes. Read the checklist; audit contract, scout, Mock
|
|
13
13
|
strategy, effective plan, task bounds, and traceable design evidence.
|
|
14
|
-
Knowledge base and `
|
|
15
|
-
knowledge-base connector when available;
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
Knowledge base, OpenSpec, and `ai_workspace/` are parallel sources. Query the
|
|
15
|
+
knowledge-base connector when available; always search/read `openspec/schemas/**`,
|
|
16
|
+
`openspec/project-specs/**`, and `ai_workspace/**` before accepting conventions.
|
|
17
|
+
Connector format is TODO: never invent results.
|
|
18
18
|
|
|
19
19
|
## Verdict Contract
|
|
20
20
|
|
|
@@ -39,16 +39,17 @@ output fails closed.
|
|
|
39
39
|
|
|
40
40
|
- Any criterion lacks implementation/verification; UI states lack reasons; a
|
|
41
41
|
dependency lacks permission; confirmed primitives/rules are ignored; design claims
|
|
42
|
-
lack knowledge-base or required
|
|
43
|
-
commands are missing/non-deterministic; or
|
|
44
|
-
data, or failure behavior requires guessing.
|
|
42
|
+
lack knowledge-base or required openspec specification evidence; paths cross
|
|
43
|
+
write bounds; commands are missing/non-deterministic; or
|
|
44
|
+
interaction, responsive, accessibility, data, or failure behavior requires guessing.
|
|
45
45
|
- `MOCK_STRATEGY: blocked`; missing permitted target paths, endpoint/schema-to-fixture
|
|
46
46
|
mapping, fixed verification, or dev/test-only activation; a second Mock framework;
|
|
47
47
|
inline fake data; commented real requests; Mock-on production defaults; test-only
|
|
48
48
|
production imports; or Mock evidence reported as real integration.
|
|
49
49
|
|
|
50
|
-
Knowledge-base absence is advisory if relevant
|
|
51
|
-
applied. Block skipped fallback, unresolved
|
|
50
|
+
Knowledge-base absence is advisory if relevant rules from either openspec
|
|
51
|
+
specification directory were read and applied. Block skipped fallback, unresolved
|
|
52
|
+
conflict, or unresolved UI decisions.
|
|
52
53
|
|
|
53
54
|
## Method And Output
|
|
54
55
|
|
|
@@ -59,7 +60,8 @@ or Advisory, and never edit files.
|
|
|
59
60
|
|
|
60
61
|
Run `grep`/`find`, then explicit `read` calls for applicable specs/checklist. Only
|
|
61
62
|
successful paired reads count as “已读取规范文件”; summaries do not. List each path/
|
|
62
|
-
section in `Checked Items`; search/read
|
|
63
|
+
section in `Checked Items`; search/read both openspec specification directories
|
|
64
|
+
before accepting conventions.
|
|
63
65
|
|
|
64
66
|
```markdown
|
|
65
67
|
VERDICT: pass
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
## Project Fit
|
|
10
10
|
|
|
11
11
|
- Reuse components, hooks, API helpers, mocks, schemas, router patterns, tokens, and theme rules.
|
|
12
|
-
- Cite knowledge base and `
|
|
13
|
-
knowledge queries must still search `<repoRoot>/openspec
|
|
12
|
+
- Cite knowledge base, `openspec/schemas/`, `openspec/project-specs/`, and `ai_workspace/` as parallel sources; failed or empty
|
|
13
|
+
knowledge queries must still search `<repoRoot>/openspec/schemas/`, `<repoRoot>/openspec/project-specs/`, and `<repoRoot>/ai_workspace/`.
|
|
14
14
|
- Record source status, query terms, paths/headings, conflicts, authorized deps, and allowed paths for both.
|
|
15
15
|
|
|
16
16
|
## Interaction / Quality
|
|
@@ -36,6 +36,6 @@
|
|
|
36
36
|
|
|
37
37
|
## Verdict Matrix
|
|
38
38
|
|
|
39
|
-
- Request revision for coverage gaps, unsafe scope, unauthorized deps, unresolved required interaction, missing required verification, skipped `openspec/`
|
|
40
|
-
- Knowledge-base unavailable but relevant `
|
|
39
|
+
- Request revision for coverage gaps, unsafe scope, unauthorized deps, unresolved required interaction, missing required verification, skipped local specification fallback (`openspec/schemas/`, `openspec/project-specs/`, or `ai_workspace/`), unsafe/missing Mock strategy, or Mock evidence presented as real integration.
|
|
40
|
+
- Knowledge-base unavailable but relevant OpenSpec or `ai_workspace/` rules applied is advisory only.
|
|
41
41
|
- Optional cleanup that cannot affect acceptance is advisory.
|
|
@@ -23,8 +23,8 @@ Read all required references before running any listed frontend node.
|
|
|
23
23
|
## Source And Evidence Rules
|
|
24
24
|
|
|
25
25
|
Use task sources/references, constraints, then `task.json`. Follow `design-spec.md`:
|
|
26
|
-
knowledge base
|
|
27
|
-
evidence. Cite tight paths/symbols,
|
|
26
|
+
query the knowledge base when available and always inspect `openspec/schemas/`,
|
|
27
|
+
`openspec/project-specs/`, and `ai_workspace/`; then use repo evidence. Cite tight paths/symbols, and never invent APIs,
|
|
28
28
|
rules, commands, or retrievals. Scout/planners locate and explicitly read applicable
|
|
29
29
|
specs; only successful paired reads count. Lockfile-only, fixture-only, or unread
|
|
30
30
|
search hits do not prove a reusable Mock service.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# Frontend Code Standards
|
|
2
2
|
|
|
3
3
|
Discover rules from task constraints, `design-spec.md` source order, config, code,
|
|
4
|
-
tests, manifests, and generated types.
|
|
5
|
-
|
|
6
|
-
not override installed APIs without an
|
|
4
|
+
tests, manifests, and generated types. Regardless of knowledge-base results,
|
|
5
|
+
applicable `openspec/schemas/`, `openspec/project-specs/`, and `ai_workspace/` rules are normative.
|
|
6
|
+
Preferences are not rules, and docs do not override installed APIs without an
|
|
7
|
+
explicit compatibility decision.
|
|
7
8
|
|
|
8
9
|
## Discover And Cite
|
|
9
10
|
|
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Required Source Sequence
|
|
4
4
|
|
|
5
|
-
Knowledge base and `
|
|
5
|
+
Knowledge base, OpenSpec, and `ai_workspace/` are parallel specification sources:
|
|
6
6
|
|
|
7
7
|
1. Attempt the configured component/design knowledge-base query first when a
|
|
8
8
|
connector is available in the execution environment.
|
|
9
9
|
2. Regardless of knowledge-base success, failure, timeout, no match, or no
|
|
10
|
-
configuration, also recursively search
|
|
11
|
-
|
|
10
|
+
configuration, also recursively search `openspec/schemas/`,
|
|
11
|
+
`openspec/project-specs/`, and `ai_workspace/` for index files and relevant content.
|
|
12
12
|
3. Treat relevant matches from both sources as the current project's
|
|
13
13
|
specification for this run.
|
|
14
14
|
4. Only then use component source, tokens, stories, tests, and pages as
|
|
15
15
|
non-normative repository fallback.
|
|
16
16
|
|
|
17
|
-
Never skip `
|
|
18
|
-
knowledge-base query returned results. Report source
|
|
19
|
-
combining them. Explicit task requirements remain the
|
|
20
|
-
with knowledge-base or
|
|
17
|
+
Never skip local OpenSpec or `ai_workspace/` sources for neighboring-code
|
|
18
|
+
conventions, even when a knowledge-base query returned results. Report source
|
|
19
|
+
conflicts instead of combining them. Explicit task requirements remain the
|
|
20
|
+
contract; flag conflicts with knowledge-base or openspec specification rules.
|
|
21
21
|
|
|
22
22
|
## Knowledge Base Connection — TODO
|
|
23
23
|
|
|
@@ -25,15 +25,19 @@ Request format is undecided. TODO: define connector/owner, namespaces, secret-fr
|
|
|
25
25
|
auth, query fields, result identity/version/time, and failure behavior.
|
|
26
26
|
|
|
27
27
|
Attempt only a connector actually available in the execution environment. Otherwise
|
|
28
|
-
record `not-configured` and run the
|
|
28
|
+
record `not-configured` and run the openspec fallback; never invent a connection.
|
|
29
29
|
|
|
30
|
-
##
|
|
30
|
+
## openspec Fallback Procedure
|
|
31
31
|
|
|
32
|
-
-
|
|
33
|
-
|
|
32
|
+
- Inspect `<repoRoot>/openspec/schemas/`, `<repoRoot>/openspec/project-specs/`,
|
|
33
|
+
and `<repoRoot>/ai_workspace/` when present; enumerate supported files recursively.
|
|
34
|
+
- Read indexes first, then search names/content using task, route, component,
|
|
35
|
+
interaction, theme, token, and state terms.
|
|
34
36
|
- Read relevant matches in context; do not treat a filename-only hit as a rule.
|
|
35
|
-
- Record search terms, inspected/matched paths, headings or tight line ranges,
|
|
36
|
-
|
|
37
|
+
- Record search terms, inspected/matched paths, headings or tight line ranges,
|
|
38
|
+
applied rules, and conflicts.
|
|
39
|
+
- If both directories or relevant rules are absent, record that fact before using
|
|
40
|
+
repository fallback.
|
|
37
41
|
|
|
38
42
|
## Retrieval Evidence
|
|
39
43
|
|
|
@@ -50,5 +54,6 @@ and conflicts. `openspec fallback` includes terms, paths/headings/lines, rules,
|
|
|
50
54
|
|
|
51
55
|
- Reuse confirmed primitives unless a new pattern is authorized.
|
|
52
56
|
- Define applicable states and responsive behavior before implementation.
|
|
53
|
-
- Cite knowledge-base or
|
|
57
|
+
- Cite knowledge-base or openspec specification evidence for component/token
|
|
58
|
+
choices; label weaker repository fallback.
|
|
54
59
|
- Make deviations and unresolved gaps explicit.
|
|
@@ -5,7 +5,7 @@ Pre-write nodes are read-only. Preserve IDs, labels, commands, language, require
|
|
|
5
5
|
## Core nodes
|
|
6
6
|
|
|
7
7
|
- **`frontend-contract-pi`**: `Scope`, `Non-goals`, `Acceptance Criteria`, `UI States`, `Target Runtime Environment`, `Risks`, `Verification Expectations`. No guessed requirements.
|
|
8
|
-
- **`frontend-scout-pi`**: routes, components, tokens, data/API/Mock, scripts, tests, assets. Fact vs inference vs gap.
|
|
8
|
+
- **`frontend-scout-pi`**: routes, components, tokens, data/API/Mock, scripts, tests, assets. Fact vs inference vs gap. Query the knowledge base when available and always search+read `openspec/schemas/`, `openspec/project-specs/`, and `ai_workspace/` before repo fallback. Output stack, routes, components, styling, conventions, state/data, test entry points, reuse, risks.
|
|
9
9
|
- **`frontend-plan-pi` + conditional design loop**: AC → steps, in-bound files, UI states, reuse, deps, Mock/API strategy, activation/rollback, frozen verify entrypoints, real-integration gap, and exactly one `frontend-implementation-contract-v1` JSON object. Prefer native Mock; browser intercept only with existing e2e; request-adapter only for a reversible seam. `auto` may select `not-needed` when no project Mock capability exists, while keeping real requests default and recording the gap; `required` cannot. Initial design pass uses the original plan; only exact `request-revision` runs read-only revision plus final review. Small-risk runs one design review only.
|
|
10
10
|
- **`frontend-prewrite-gate-shell`**: the sole write authorization. Resolve effective plan/review, require exact pass, retain every REQ/BR/AC id, enforce Mock policy, validate schema/source binding, and materialize `contracts/frontend-implementation-contract.json`. Fallback is allowed only when a conditional primary is absent; an existing malformed primary fails closed. Generation-time blocked Mock produces one deterministic blocking shell node and no writer.
|
|
11
11
|
- **`frontend-implement-pi`**: sole exclusive writer. Stay in `writeSet`; real requests default-on; Mock reversible, dev/test-only, production-off. Atomic handler/intercept/adapter with consumer+tests. Stop on forbidden paths or guesses. Output changed files, behavior, UI states, styling notes, verification attempted, residual risks. Optional mock-verify when frozen; static+behavior always; behavior must prove page consumption. Skipped-Mock `not-needed` keeps real integration pending unless the real backend path has fresh evidence.
|
|
@@ -22,4 +22,4 @@ Only `eligible=true` runs `frontend-repair-pi` (same writeSet as implement; no r
|
|
|
22
22
|
|
|
23
23
|
## Risk & capability (M4–M6)
|
|
24
24
|
|
|
25
|
-
Deterministic risk (no model); high-risk beats small; supervised never small. Standard/high-risk contain 15 top-level nodes; small contains 13 by omitting revision and final review. Capability seed injects adapters; openspec
|
|
25
|
+
Deterministic risk (no model); high-risk beats small; supervised never small. Standard/high-risk contain 15 top-level nodes; small contains 13 by omitting revision and final review. Capability seed injects adapters; openspec specs and task sources outrank adapter guidance. A11y: static/component tools only when present; Browser a11y always not-run.
|
|
@@ -12,9 +12,8 @@ references:
|
|
|
12
12
|
Use for `frontend-review-pi`; read the findings guide first. Required inputs are
|
|
13
13
|
original task/reference material, effective plan/design branch, implementation summary,
|
|
14
14
|
and `contracts/frontend-review-context.json`. That canonical context binds the validated
|
|
15
|
-
implementation contract, effective
|
|
16
|
-
assessment
|
|
17
|
-
diff from an implementation summary alone.
|
|
15
|
+
implementation contract, effective verification trace, repair assessment, optional
|
|
16
|
+
`frontend-lint-assessment-v1`, and run-owned diff. The diff is authoritative.
|
|
18
17
|
|
|
19
18
|
## Verdict Contract
|
|
20
19
|
|
|
@@ -27,42 +26,30 @@ required check, forbidden write, or unmet acceptance criterion forces revision.
|
|
|
27
26
|
- Compare intent, contract, plan, diff, and evidence; report altered requirements.
|
|
28
27
|
- Inspect every changed file against allowed, forbidden, and approved write scope.
|
|
29
28
|
- Map criteria to behavior, applicable UI states, tests, and shell evidence.
|
|
30
|
-
- Review state/data flow, validation, async/error behavior,
|
|
29
|
+
- Review state/data flow, validation, async/error behavior, design, responsive/a11y,
|
|
30
|
+
dependencies, maintenance, and regression risk when applicable.
|
|
31
31
|
- Inspect static, behavior, and available Mock-specific artifacts directly. For Mock
|
|
32
32
|
strategies, compare the endpoint matrix, handler/fixture/adapter and consumer diff;
|
|
33
33
|
require the real request as default, contract-aligned fixtures, production isolation,
|
|
34
34
|
and no false real-integration claim. `not-needed` needs applicable real/no-remote
|
|
35
35
|
evidence, or an explicit default-auto skipped-Mock rationale with the Real
|
|
36
36
|
Integration Gap preserved when no project Mock capability is confirmed.
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
- Inspect lint assessment directly. `baseline-debt` requires intact evidence, only
|
|
38
|
+
baseline-matched diagnostics on unchanged files, and none on writer-changed files.
|
|
39
|
+
Report debt, never `lint passed`; `failed`/`unavailable` blocks. Typecheck, build,
|
|
40
|
+
and test still require successful final exits.
|
|
41
|
+
- Component/design claims need both knowledge-base and local openspec evidence. Query
|
|
42
|
+
the connector when available and always read task-relevant files under
|
|
43
|
+
`<repoRoot>/openspec/schemas/`, `<repoRoot>/openspec/project-specs/`, and `<repoRoot>/ai_workspace/`.
|
|
44
|
+
Connector format is TODO; never invent evidence. Only successful `read` calls are
|
|
45
|
+
observable as "已读取规范文件".
|
|
44
46
|
- Treat shell exit status as authoritative. Do not edit files.
|
|
45
47
|
|
|
46
48
|
## Evidence And Output
|
|
47
49
|
|
|
48
50
|
Findings cite a tight file location, exact command/result, or named DAG artifact.
|
|
49
|
-
Separate confirmed defects, missing evidence, and residual risks
|
|
50
|
-
|
|
51
|
-
```markdown
|
|
52
|
-
VERDICT: request-revision
|
|
53
|
-
|
|
54
|
-
## Findings
|
|
55
|
-
- [Important] `path:line` — issue, impact, and required correction.
|
|
56
|
-
|
|
57
|
-
## Verification Assessment
|
|
58
|
-
- ...
|
|
59
|
-
|
|
60
|
-
## UX Assessment
|
|
61
|
-
- ...
|
|
62
|
-
|
|
63
|
-
## Residual Risks
|
|
64
|
-
- ...
|
|
65
|
-
```
|
|
51
|
+
Separate confirmed defects, missing evidence, and residual risks using Findings,
|
|
52
|
+
Verification Assessment, UX Assessment, and Residual Risks headings.
|
|
66
53
|
|
|
67
54
|
A pass requires no Critical/Important findings and all required shell checks passed.
|
|
68
55
|
Still report knowledge-source status and optional browser/manual gaps.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
4
|
|
|
5
|
-
- **Critical**: blocks primary flow, corrupts data, violates security/privacy, writes forbidden paths,
|
|
5
|
+
- **Critical**: blocks primary flow, corrupts data, violates security/privacy, writes forbidden paths, bypasses required verification.
|
|
6
6
|
- **Important**: acceptance/state/validation gap, material convention drift, missing behavior tests, unauthorized dependency, unsafe mock activation/import, mock-contract drift, misleading real-integration claim, or failed/missing required verification.
|
|
7
7
|
- **Minor**: non-blocking maintainability, copy, layout, or cleanup issue.
|
|
8
8
|
|
|
@@ -10,43 +10,41 @@
|
|
|
10
10
|
|
|
11
11
|
- Cite tight file locations, exact commands/results, or named DAG artifacts.
|
|
12
12
|
- Never invent evidence; name the missing check. An implementation summary is not the actual diff.
|
|
13
|
-
- Failed required static/behavior verification is at least Important
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
- Failed required static/behavior verification is at least Important. Lint may be
|
|
14
|
+
`baseline-debt` only with a valid `frontend-lint-assessment-v1`; this is not a
|
|
15
|
+
passed lint result. A changed-file lint diagnostic, new unmatched diagnostic,
|
|
16
|
+
command drift, missing baseline, timeout, or unparseable output is Important.
|
|
17
|
+
- Treat knowledge base, `openspec/schemas/`, `openspec/project-specs/`, and `ai_workspace/` as
|
|
18
|
+
parallel sources. Record connector/query/source/time plus openspec search terms and
|
|
19
|
+
matched paths/headings; label fallback or unavailable accurately.
|
|
19
20
|
|
|
20
21
|
## Review Sequence
|
|
21
22
|
|
|
22
23
|
1. Establish changed-file inventory and write boundaries.
|
|
23
24
|
2. Compare original requirement with derived contract/constraints.
|
|
24
25
|
3. Map each criterion to code, states, tests, and evidence.
|
|
25
|
-
4. Inspect interactions, state/data/API behavior, failure paths, and
|
|
26
|
+
4. Inspect interactions, state/data/API behavior, failure paths, and regressions.
|
|
26
27
|
5. Check mock selection, contract-to-fixture mapping, activation/default path,
|
|
27
|
-
handler/fixture/adapter and consumer diff,
|
|
28
|
-
|
|
29
|
-
6. Check
|
|
28
|
+
handler/fixture/adapter and consumer diff, verification, production imports, and
|
|
29
|
+
the real-integration gap.
|
|
30
|
+
6. Check design evidence, responsive/a11y behavior, dependencies, and maintenance.
|
|
30
31
|
7. Classify findings and derive the verdict mechanically.
|
|
31
32
|
|
|
32
|
-
Skipping
|
|
33
|
-
when component/design compliance affects acceptance or implementation choices.
|
|
34
|
-
|
|
35
|
-
Use one issue per finding:
|
|
33
|
+
Skipping either directory is Important when design compliance affects acceptance.
|
|
36
34
|
|
|
37
35
|
```text
|
|
38
36
|
- [Critical|Important|Minor] path:line — Problem; impact; required correction; evidence.
|
|
39
37
|
```
|
|
40
38
|
|
|
41
|
-
Avoid vague advice. When no source location exists, cite the command or artifact.
|
|
42
|
-
|
|
43
39
|
## Pass Rules
|
|
44
40
|
|
|
45
41
|
- No Critical or Important findings remain.
|
|
46
42
|
- Required static and behavior nodes ran and passed.
|
|
43
|
+
- Lint is `passed` or evidence-backed `baseline-debt`; typecheck, build, and test are
|
|
44
|
+
passed. Any debt count and affected unchanged files remain disclosed.
|
|
47
45
|
- Changed files are authorized.
|
|
48
46
|
- Criteria and applicable states have implementation and evidence.
|
|
49
47
|
- Required Mock-backed behavior passed; any generated Mock-specific verification also
|
|
50
48
|
passed; Mock is not enabled by default in production. For default-auto skipped
|
|
51
49
|
Mock, the real request remains default and the Real Integration Gap is preserved.
|
|
52
|
-
- Optional unavailable knowledge
|
|
50
|
+
- Optional unavailable knowledge/browser/visual/manual checks remain explicit risks.
|