@tea-agent/loop-agent 0.38.2 → 0.38.3
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 +18 -0
- package/README.md +2 -0
- package/bin/loop-agent.js +7 -3
- package/dist/application/task-lifecycle/advance.js +4 -0
- package/dist/build-stamp.json +3 -3
- package/dist/commands/task-advance.js +31 -0
- package/dist/executors/dag-pi-executor.js +58 -1
- package/dist/executors/pi-event-serializer.js +42 -1
- package/dist/executors/pi-executor.js +51 -0
- package/dist/executors/pi-extension-resolver.js +233 -0
- package/dist/executors/pi-sdk-executor.js +187 -59
- package/dist/executors/shell-executor.js +56 -2
- package/dist/executors/shell-write-guard.js +7 -0
- package/dist/task/contract/constants.js +1 -0
- package/dist/task/contract/diff.js +26 -0
- package/dist/task/contract/project.js +5 -0
- package/dist/task/contract/schema.js +6 -1
- package/dist/task/source-prepare/build-draft.js +15 -0
- package/dist/worker/console/pi-readiness.js +4 -4
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4bmo3iY.js → abnfDiagram-N423BO3Z-C4kVYweA.js} +1 -1
- package/dist/worker/console/static/assets/{arc-SAD7McOS.js → arc-Bj2M8iO5.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DAVLUdK1.js → architectureDiagram-T3A2C74G-CLlXe4-6.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CPPdv4vj.js → blockDiagram-VBNYF7ZC-psEp5xH0.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-D1GRGZax.js → c4Diagram-5PPSVZJV-DeKcOCGJ.js} +1 -1
- package/dist/worker/console/static/assets/channel-CPF4N7pf.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-D_Bq2ZqK.js → chunk-2GRJ4B5K-K0C744p1.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-CPLVtamK.js → chunk-2Q5K7J3B-xbNw4J9-.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DnaZWcL3.js → chunk-5RXB4S5H-DjLaSDUO.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BRTmFgnq.js → chunk-5VM5RSS4-CtiPlKel.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BRlfYZoH.js → chunk-6Q2QTUOP-DZtolir7.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CjNybD4u.js → chunk-GF5L2VYU-CPcdNeew.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-D3e-74fG.js → chunk-JWPE2WC7-NgHc6V37.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-Br3ir6f2.js → chunk-KBJHAD2P-DQ_T-hg8.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-1NgVuRbh.js → chunk-RYQCIY6F-DgLsxcVP.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-BTYuvuWN.js → chunk-XXDRQBXY-UrVoM9z1.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C2DwA_Y1.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C2DwA_Y1.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BC6Bgosf.js → cose-bilkent-JH36ORCC-CLkYvTb3.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-DV-HypfL.js → cynefin-VYW2F7L2-BwT_xKrE.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-DhTaddO-.js → cynefinDiagram-MW4NZA55-Bi9tuzif.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BnEcOmiI.js → dagre-VZM6K2ZE-BCIqkWBV.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-xphGRVKp.js → diagram-7IWD3JNH-Dip6l9_Z.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CrdD1mRG.js → diagram-B4RE2ZJO-B-xkh_wK.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-D4YdLsaF.js → diagram-LBJQPF4R-DZO0kTt_.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-LCKyGZ5U.js → diagram-Q27KOJAE-D6ZplNbZ.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-BeiTe7t0.js → diagram-UB23O5K3-BPekbhoS.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BO2cq8GS.js → ebnfDiagram-BXEA7PRR-BtmaJpK5.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-CmWww3Nt.js → erDiagram-JOGREHBK-6DS0Xc44.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-C2kkUYg5.js → flowDiagram-UKHOOZJN-CihnROSm.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DY_JZ2iQ.js → ganttDiagram-PKOTCBZU-CZC4zOE2.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-BizhCSw9.js → gitGraphDiagram-DS77QQ5N-Dq1fhzGN.js} +1 -1
- package/dist/worker/console/static/assets/{index-BXN89VPX.js → index-DTZOKgAn.js} +142 -63
- package/dist/worker/console/static/assets/index-Ya5FE7cD.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-Dlo2eK_d.js → infoDiagram-6WML65LV-DlSl4BGx.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-3EIlIIuZ.js → ishikawaDiagram-WSZJBQD7-snnzFl_U.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DiMDe5Yh.js → journeyDiagram-NVQOT4AX-BDE7qpMx.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-sN553oIN.js → kanban-definition-27J2QSJJ-CD2Ci04G.js} +1 -1
- package/dist/worker/console/static/assets/{linear-D9Py31Ld.js → linear-DdnapKIH.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-D7Occzk_.js → mermaid.core-BVjAT9b8.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DjDRboiR.js → mindmap-definition-FAOFIHXS-D0yJk-zA.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-Cgc4qlzp.js → pegDiagram-VL7TDLO6-BVo9tFP-.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DxZj8pKd.js → pieDiagram-7S7Q4E2Y-DnOV-mZ_.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-CJ50MngR.js → quadrantDiagram-CIZ2JOQS-CzUJo58i.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BY-OD8Tr.js → railroadDiagram-AXF67PYL-Bvikrolh.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-CQFButfK.js → requirementDiagram-LRYGKXZP-DtaSVCap.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-BB_QUK_b.js → sankeyDiagram-W5VNT64P-C2c9A0wW.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-CqhXZjyx.js → sequenceDiagram-SI44F4Z6-DmXJcU7r.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-2l1U4rgJ.js → sizeCapture-X5ZJPWSS-B4GUFW92.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-BX1FbrhJ.js → stateDiagram-OKZ733FA-Dsad2MXf.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8FB_cNk.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DOSnT7hb.js → swimlanes-SLNWSIFB-DGq48Fbi.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CrZYaWfx.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-DVJQA7AN.js → timeline-definition-Z64GVDOM-CSSi6OFf.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-74uxl9gx.js → vennDiagram-T6HMQDX7-BqyzPrWv.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DsBxlcg_.js → wardleyDiagram-T6FBY63Y-DlznVb6S.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-snuW9Mjw.js → xychartDiagram-ELKLHX3M-CfBcgJ_K.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +328 -0
- package/dist/worker/observe/node-input.js +72 -3
- package/dist/worker/observe/static/dag-history-labels.js +4 -0
- package/dist/worker/observe/static/state.js +2 -2
- package/dist/worker/observe/static/views/dag-inspector.js +51 -0
- package/dist/worker/observe/static/views/session-timeline.js +18 -5
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +56 -4
- package/dist/workflows/dag/backend-test-scenario-partitions.js +73 -1
- package/dist/workflows/dag/contract-output-registry.js +15 -0
- package/dist/workflows/dag/failure-category.js +4 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +140 -39
- package/dist/workflows/dag/frontend-prewrite-gate.js +87 -135
- package/dist/workflows/dag/frontend-test-case-quality.js +5 -13
- package/dist/workflows/dag/frontend-test-environment-probe.js +227 -0
- package/dist/workflows/dag/frontend-test-markdown.js +61 -0
- package/dist/workflows/dag/frontend-test-result-contract.js +10 -18
- package/dist/workflows/dag/frontend-test-standard-scenarios.js +68 -0
- package/dist/workflows/dag/init-hybrid.js +79 -101
- package/dist/workflows/dag/node-execution.js +119 -8
- package/dist/workflows/dag/prompt.js +15 -1
- package/dist/workflows/dag/rerun-plan.js +22 -3
- package/dist/workflows/dag/structured-output-repair.js +712 -0
- package/dist/workflows/dag/types.js +23 -0
- package/dist/workflows/dag/validate.js +41 -1
- package/docs/operations/local-development-environment.md +1 -5
- package/docs/skills/vetted-skill-registry.md +14 -0
- package/docs/templates/README.md +1 -1
- package/docs/templates/agent-dag.schema.json +44 -0
- package/docs/templates/backend-test-dag.json +2 -2
- package/docs/templates/frontend-test-dag.json +8 -10
- package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +1 -1
- package/package.json +8 -4
- package/skills/analyze-product-requirements/SKILL.md +8 -5
- package/skills/analyze-product-requirements/references/acceptance-criteria.md +1 -1
- package/skills/analyze-product-requirements/references/clarification-and-knowledge.md +10 -6
- package/skills/analyze-product-requirements/references/example.md +50 -0
- package/skills/analyze-product-requirements/references/forward-test-cases.md +11 -7
- package/skills/analyze-product-requirements/references/kb-integration.md +5 -5
- package/skills/analyze-product-requirements/references/product-analysis-schema.md +8 -4
- package/skills/analyze-product-requirements/references/product-requirement-schema.md +2 -2
- package/skills/analyze-product-requirements/references/requirement-clarification-schema.md +1 -1
- package/skills/analyze-product-requirements/scripts/test-validators.mjs +11 -1
- package/skills/analyze-product-requirements/scripts/validate-product-analysis.mjs +20 -1
- package/skills/analyze-product-requirements/scripts/validate-requirement-clarification.mjs +9 -0
- package/skills/codebase-scout/SKILL.md +1 -1
- package/skills/improve-codebase-architecture/SKILL.md +81 -0
- package/skills/improve-codebase-architecture/deepening.md +37 -0
- package/skills/improve-codebase-architecture/html-report.md +123 -0
- package/skills/improve-codebase-architecture/interface-design.md +44 -0
- package/skills/improve-codebase-architecture/language.md +53 -0
- package/dist/worker/console/static/assets/channel-R6oQIDkw.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BPXlmPWI.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BPXlmPWI.js +0 -1
- package/dist/worker/console/static/assets/index-CuH5CNFu.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DJKi0Qel.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-YYe7EEm5.js +0 -8
|
@@ -10,6 +10,18 @@ export const dagNodeExecutorSchema = z.enum(["pi", "shell", "static"]);
|
|
|
10
10
|
export const CURSOR_DAG_EXECUTOR_REMOVED_ERROR = 'executor "cursor" is no longer supported; regenerate the DAG with Pi-only writers (implement-pi / repair-pi)';
|
|
11
11
|
export const CURSOR_EXECUTOR_MODELS_REMOVED_ERROR = "executorModels.cursor is no longer supported; use executorModels.pi only";
|
|
12
12
|
export const dagToolProfileSchema = z.enum(["read-only", "write"]);
|
|
13
|
+
/**
|
|
14
|
+
* Frozen Pi extension short ids for backend implementation DAGs (plan
|
|
15
|
+
* 2026-08-21 D2): the DAG carries only these ids; the executor resolves them
|
|
16
|
+
* against the Pi settings package inventory at run time. Adding a package
|
|
17
|
+
* requires changing this enum and the plan.
|
|
18
|
+
*/
|
|
19
|
+
export const dagPiExtensionIdSchema = z.enum(["pi-codegraph", "pi-lens"]);
|
|
20
|
+
/** Node-level explicit Pi extension allowlist (omitted = all off, R8.1). */
|
|
21
|
+
export const dagPiExtensionsSchema = z
|
|
22
|
+
.array(dagPiExtensionIdSchema)
|
|
23
|
+
.min(1)
|
|
24
|
+
.transform((ids) => Array.from(new Set(ids)));
|
|
13
25
|
/** Static command capabilities only; tasks cannot inject executables or shell prefixes. */
|
|
14
26
|
export const dagCommandCapabilitySchema = z.enum(["playwright-cli"]);
|
|
15
27
|
export const dagCommandPolicySchema = z.discriminatedUnion("mode", [
|
|
@@ -427,6 +439,8 @@ export const dagBackendTestPipelineSchema = z.enum([
|
|
|
427
439
|
"ingest-backend-test-gap",
|
|
428
440
|
]);
|
|
429
441
|
export const dagFrontendBrowserToolPreflightSchema = z.object({}).strict();
|
|
442
|
+
export const dagFrontendTestStandardScenariosSchema = z.object({}).strict();
|
|
443
|
+
export const dagFrontendTestEnvironmentProbeSchema = z.object({}).strict();
|
|
430
444
|
export const dagFrontendTestEvidenceValidationSchema = z.object({}).strict();
|
|
431
445
|
export const dagFrontendTestCaseChecklistSchema = z.object({}).strict();
|
|
432
446
|
export const dagFrontendTestHtmlReportSchema = z.object({}).strict();
|
|
@@ -517,6 +531,8 @@ export const dagShellConfigSchema = z.object({
|
|
|
517
531
|
frontendReviewContext: dagFrontendReviewContextSchema.optional(),
|
|
518
532
|
frontendTestCaseChecklist: dagFrontendTestCaseChecklistSchema.optional(),
|
|
519
533
|
frontendBrowserToolPreflight: dagFrontendBrowserToolPreflightSchema.optional(),
|
|
534
|
+
frontendTestStandardScenarios: dagFrontendTestStandardScenariosSchema.optional(),
|
|
535
|
+
frontendTestEnvironmentProbe: dagFrontendTestEnvironmentProbeSchema.optional(),
|
|
520
536
|
frontendTestEvidenceValidation: dagFrontendTestEvidenceValidationSchema.optional(),
|
|
521
537
|
finalWriteSetApprovalGate: dagFinalWriteSetApprovalGateSchema.optional(),
|
|
522
538
|
frontendTestL5Report: z.object({}).strict().optional(),
|
|
@@ -749,6 +765,13 @@ export const dagTaskSchema = z.object({ id: z.string().regex(/^[a-z][a-z0-9-]*$/
|
|
|
749
765
|
role: dagRoleSchema.optional(),
|
|
750
766
|
skills: z.array(z.string()).optional(),
|
|
751
767
|
toolProfile: dagToolProfileSchema.optional(),
|
|
768
|
+
/**
|
|
769
|
+
* Explicit Pi extension allowlist (backend implementation DAGs only):
|
|
770
|
+
* frozen short ids resolved at run time against the Pi settings package
|
|
771
|
+
* inventory. Omitted = extension discovery stays fully closed (R8.1).
|
|
772
|
+
* Only `executor: "pi"` nodes may declare it (validated fail-closed).
|
|
773
|
+
*/
|
|
774
|
+
piExtensions: dagPiExtensionsSchema.optional(),
|
|
752
775
|
/** Default deny: file write (toolProfile=write) does not grant command execution. */
|
|
753
776
|
commandPolicy: dagCommandPolicySchema.optional(),
|
|
754
777
|
writePolicy: dagWritePolicySchema.optional(),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_DAG_EXECUTOR_MODELS, ENV_VAR_NAME_PATTERN, dagCommandPolicyAllows, resolveDagCommandPolicy, } from "./types.js";
|
|
1
|
+
import { DEFAULT_DAG_EXECUTOR_MODELS, ENV_VAR_NAME_PATTERN, dagCommandPolicyAllows, dagPiExtensionIdSchema, resolveDagCommandPolicy, } from "./types.js";
|
|
2
2
|
import { resolveShellCommands } from "../../executors/shell-executor.js";
|
|
3
3
|
import { pathMatchesPattern } from "../../shared/git-progress.js";
|
|
4
4
|
import { resolveRepairTaskForGate } from "./repair-artifact.js";
|
|
@@ -465,6 +465,8 @@ function validateShellTaskConfig(task, spec, issues) {
|
|
|
465
465
|
!shell.backendTestPipeline &&
|
|
466
466
|
!shell.frontendPrewriteGate &&
|
|
467
467
|
!shell.frontendBrowserToolPreflight &&
|
|
468
|
+
!shell.frontendTestStandardScenarios &&
|
|
469
|
+
!shell.frontendTestEnvironmentProbe &&
|
|
468
470
|
!shell.frontendVerificationBundle &&
|
|
469
471
|
!shell.frontendReviewContext &&
|
|
470
472
|
!shell.frontendTestCaseChecklist &&
|
|
@@ -953,6 +955,7 @@ export function validateDagSpec(spec) {
|
|
|
953
955
|
validateCommandPolicyTaskConfig(task, issues);
|
|
954
956
|
validateDynamicChildCommandPolicy(task, issues);
|
|
955
957
|
validateProjectGovernanceTaskConfig(task, spec, issues);
|
|
958
|
+
validatePiExtensionsTaskConfig(task, issues);
|
|
956
959
|
validateFailureAwareDependsOn(task, spec, issues);
|
|
957
960
|
}
|
|
958
961
|
validateSameRankWriteSetConflicts(spec, ranks, issues);
|
|
@@ -963,6 +966,43 @@ export function validateDagSpec(spec) {
|
|
|
963
966
|
}
|
|
964
967
|
return issues;
|
|
965
968
|
}
|
|
969
|
+
/**
|
|
970
|
+
* Fail-closed `piExtensions` validation (plan 2026-08-21 D1/D2):
|
|
971
|
+
* - only `executor: "pi"` nodes may declare it (shell/static reject);
|
|
972
|
+
* - unknown ids outside the frozen enum are rejected at parse time by zod,
|
|
973
|
+
* and here for task objects that bypass schema parsing;
|
|
974
|
+
* - closeout nodes must stay fully closed (extension-free) — the two-bucket
|
|
975
|
+
* generator never assigns it there, so any appearance is contract drift.
|
|
976
|
+
*/
|
|
977
|
+
function validatePiExtensionsTaskConfig(task, issues) {
|
|
978
|
+
const ids = task.piExtensions;
|
|
979
|
+
if (ids === undefined)
|
|
980
|
+
return;
|
|
981
|
+
if (task.executor !== "pi") {
|
|
982
|
+
issues.push({
|
|
983
|
+
type: "invalid-pi-extensions-config",
|
|
984
|
+
message: `task ${task.id} piExtensions requires executor "pi" (found ${task.executor})`,
|
|
985
|
+
});
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
const allowed = new Set(dagPiExtensionIdSchema.options);
|
|
989
|
+
for (const id of ids) {
|
|
990
|
+
if (!allowed.has(id)) {
|
|
991
|
+
issues.push({
|
|
992
|
+
type: "invalid-pi-extensions-config",
|
|
993
|
+
message: `task ${task.id} piExtensions has unknown id "${id}"; allowed: ${[
|
|
994
|
+
...allowed,
|
|
995
|
+
].join(", ")}`,
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
if (task.id === "closeout-pi" && ids.length > 0) {
|
|
1000
|
+
issues.push({
|
|
1001
|
+
type: "invalid-pi-extensions-config",
|
|
1002
|
+
message: "closeout-pi must stay extension-free (read buckets exclude closeout)",
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
966
1006
|
function validateProjectGovernanceTaskConfig(task, spec, issues) {
|
|
967
1007
|
if (task.governanceStandardReview) {
|
|
968
1008
|
if (task.executor !== "pi" ||
|
|
@@ -29,11 +29,7 @@ Cursor Cloud VM 当前有两个需要特别注意的环境问题。
|
|
|
29
29
|
|
|
30
30
|
### Node.js 版本
|
|
31
31
|
|
|
32
|
-
VM 默认 `node`(`/exec-daemon/node`)可能是 v22.14.0
|
|
33
|
-
|
|
34
|
-
```text
|
|
35
|
-
Cannot find module '@earendil-works/...'
|
|
36
|
-
```
|
|
32
|
+
VM 默认 `node`(`/exec-daemon/node`)可能是 v22.14.0,但根包与运行时依赖 `@earendil-works/pi-ai` / `@earendil-works/pi-coding-agent` 都要求 Node.js `>=22.19.0`。版本过低时,npm 默认模式会报告 `EBADENGINE` 警告;启用 `engine-strict` 时,`npm install` / `npm ci` 会直接失败。即使默认模式完成安装,也不应在不受支持的 Node.js 版本上继续执行 typecheck、build 或 runtime 命令。
|
|
37
33
|
|
|
38
34
|
在 Cursor Cloud 中执行安装或验证前,先切换到已配置的 Node.js 22:
|
|
39
35
|
|
|
@@ -16,10 +16,22 @@ The entries below are local wrappers or existing local skills. They are not whol
|
|
|
16
16
|
| `code-review-core` | local wrapper inspired by code review practice | `skills/code-review-core/SKILL.md` | reviewer | reviewer | No external tools or network by default. |
|
|
17
17
|
| `codebase-scout` | local wrapper | `skills/codebase-scout/SKILL.md` | scout | scout | Read-only reconnaissance guidance. |
|
|
18
18
|
| `init-capability-evolution` | local wrapper | `skills/init-capability-evolution/SKILL.md` | supervisor, maintenance | optional | Used only when changes may affect target-project initialization, package surface, or init projection rules. |
|
|
19
|
+
| `frontend-implementation` | local existing (frontend hybrid DAG) | `skills/frontend-implementation/SKILL.md` | frontend plan / contract / scout / mock nodes (spec-level `skillsByRole`) | frontend-implementation DAG only | Required refs node-contracts / design-spec / code-standards; injected by `init-hybrid.ts` spec generation and `src/adapters/loop-agent.ts`; projected via init-surface manifest. Not in `DEFAULT_SKILLS_BY_ROLE`. |
|
|
20
|
+
| `frontend-review` | local existing (frontend hybrid DAG) | `skills/frontend-review/SKILL.md` | reviewer (frontend review nodes, spec-level) | frontend-implementation / repair DAGs | Consumed by `init-hybrid.ts` / `frontend-repair.ts` / `shell-executor.ts`; required ref review-findings (maxChars 2800). |
|
|
21
|
+
| `frontend-verification` | local existing (frontend hybrid DAG) | `skills/frontend-verification/SKILL.md` | verifier / closeout (frontend evidence, spec-level) | frontend DAG closeout | Consumed by `shell-executor.ts` / `frontend-repair.ts` / `frontend-review-context.ts`; required ref verification-checklist. |
|
|
22
|
+
| `frontend-design-review` | local existing (frontend hybrid DAG) | `skills/frontend-design-review/SKILL.md` | design-gate reviewer (before any writer) | frontend-implementation DAG design gate | Injected by `init-hybrid.ts`; runs before the prewrite gate authorizes writers; required ref review-checklist. |
|
|
23
|
+
| `frontend-bounded-implement` | local existing (frontend hybrid DAG) | `skills/frontend-bounded-implement/SKILL.md` | implementer (writer nodes, spec-level) | frontend writers after canonical contract gate | Injected by `init-hybrid.ts`; writers run only after the canonical contract gate accepts and only inside the frozen writeSet (ADR 0015/0016 discipline). |
|
|
19
24
|
| `grill-with-docs` | local operator skill adapted from domain grilling + ADR/glossary discipline | `skills/grill-with-docs/SKILL.md` | explicit interactive operator only | never a default DAG role | Resolves decisions via `harness.json.governanceRoot`; required refs `context-format.md` / `adr-format.md`; respects writeSet; not in `DEFAULT_SKILLS_BY_ROLE`. |
|
|
25
|
+
| `grill-me` | local interview question engine wrapper | `skills/grill-me/SKILL.md` | interview runtime dependency (not a DAG role) | never a default DAG role | Question engine lives in `src/worker/console/interview/grill-me.ts` (Console interview / operator-actions); intentionally NOT projected by init-surface manifest — runs in this repo's Console only. |
|
|
26
|
+
| `analyze-product-requirements` | local org-internal Product Analysis V4 skill | `skills/analyze-product-requirements/SKILL.md` | source-prepare dependency (not a DAG role) | never a default DAG role | Loaded by `src/task/source-prepare/prepare.ts` during 任务源 preparation; IRON-LAW freeze semantics on `product-analysis.md`; intentionally NOT projected by init-surface manifest. |
|
|
20
27
|
| `webapp-testing` | local wrapper inspired by frontend/browser testing practice | `skills/webapp-testing/SKILL.md` | verifier, reviewer | optional | Only applies when task explicitly involves browser-rendered behavior; no default Playwright/Semgrep execution. |
|
|
21
28
|
| `playwright-cli` | repo-local Playwright CLI instructions | `skills/playwright-cli/SKILL.md` | FE-test case executor | FE-test only | Direct browser commands require isolated test environments, per-case evidence paths, and explicit credential/data handling. |
|
|
22
29
|
| `playwright-cli-case-generator` | adapted from the repo-local playwright CLI case-generator contract | `skills/playwright-cli-case-generator/SKILL.md` | FE-test case generator | FE-test only | Generates Markdown cases and a compact manifest from RAG facts; does not execute browsers, create test code, or invent API/data constraints. |
|
|
30
|
+
| `analyze-product-dependencies` | local org-internal product dependency analysis | `skills/analyze-product-dependencies/SKILL.md` | explicit interactive operator only | never a default DAG role | PRD → code/API mapping analysis; read-only; no runtime references; not projected. |
|
|
31
|
+
| `browser-tools` | local operator skill (CDP automation) | `skills/browser-tools/SKILL.md` | explicit interactive operator only | never a default DAG role | Requires user-visible Chrome with remote debugging (:9222); credential/data handling reviewed per use; not projected. |
|
|
32
|
+
| `local-jacoco-coverage` | local operator orchestration skill | `skills/local-jacoco-coverage/SKILL.md` | explicit interactive operator only | never a default DAG role | Orchestrates backend-test DAGs with a JaCoCo agent — it drives DAGs, so it must never be loaded by one (no recursion); not projected. |
|
|
33
|
+
| `using-git-worktrees` | local wrapper | `skills/using-git-worktrees/SKILL.md` | explicit interactive operator only | never a default DAG role | Workspace isolation guidance only; no runtime references; not projected. |
|
|
34
|
+
| `improve-codebase-architecture` | local operator skill (copied from shared agent platform 2026-08-21) | `skills/improve-codebase-architecture/SKILL.md` | explicit interactive operator only | never a default DAG role | Interactive architecture review producing a temp HTML report; reads CONTEXT.md glossary + `docs/decisions/` ADRs; cross-directory refs `../grill-with-docs/{context,adr}-format.md` are exempt (see Vetting Rules); not projected. |
|
|
23
35
|
|
|
24
36
|
## Verification placement taxonomy
|
|
25
37
|
|
|
@@ -42,6 +54,8 @@ Authoring vocabulary for where a check or verification skill should live. Prefer
|
|
|
42
54
|
- Default role mappings may reference only repo-local skills that resolve cleanly under `dag validate --strict-skills`.
|
|
43
55
|
- `agent-worker` is explicitly outside default role mappings. Its trigger description must cover `agent-worker`, Feature Packet, TaskSpec, Task Pool, self-host/candidate and the `loop-agent` routing boundary; `scripts/check-skill-entry.sh` enforces this public entry contract.
|
|
44
56
|
- `grill-with-docs` is an explicit interactive operator skill only; it must stay outside `DEFAULT_SKILLS_BY_ROLE`.
|
|
57
|
+
- Registry ↔ disk sync: every `skills/*/SKILL.md` in the repo must have a row above. Operator-local skills are recorded with `never a default DAG role` instead of being omitted, so an audit cannot mistake them for drift.
|
|
58
|
+
- `improve-codebase-architecture` is exempt from the "references stay within the skill directory" rule: it is operator-only, never resolved by DAG skill snapshots, and reuses `grill-with-docs` context/ADR formats by relative path.
|
|
45
59
|
- Optional/security/web skills remain task- or profile-specific until their tool, network, credential, and write behavior is reviewed.
|
|
46
60
|
- This registry records source inspiration, not license clearance for vendored third-party content. Vendoring requires a separate license/security review.
|
|
47
61
|
- `SKILL.md` is the entry point. References must be declared in frontmatter and stay within the skill directory.
|
package/docs/templates/README.md
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
## Backend-test
|
|
32
32
|
|
|
33
|
-
- `backend-test-dag.json` — backend-test DAG 模板;其中 `generate-backend-md-cases-pi` 是唯一允许 `writer-empty-diff` 重试的 writer(总共两次,仅限 post-write-guard attribution 确认的空 diff
|
|
33
|
+
- `backend-test-dag.json` — backend-test DAG 模板;其中 `generate-backend-md-cases-pi` 是唯一允许 `writer-empty-diff` 重试的 writer(总共两次,仅限 post-write-guard attribution 确认的空 diff);N2/N5 合同限定 Scenario Partition 必须有源有限域。
|
|
34
34
|
- `backend-test-dag.classify.prompt.md`、`backend-test-dag.generate-pytest.prompt.md`、`backend-test-dag.review-cases.prompt.md`、`backend-test-dag.retrospect.prompt.md` — 分类、生成、审查和复盘提示。
|
|
35
35
|
- `backend-test-analysis.schema.json`、`backend-test-execution.schema.json`、`backend-test-result.schema.json`、`backend-test-case-manifest.schema.json` — 分析、执行、结果与用例清单 schema。
|
|
36
36
|
|
|
@@ -130,6 +130,18 @@
|
|
|
130
130
|
"toolProfile": {
|
|
131
131
|
"enum": ["read-only", "write"]
|
|
132
132
|
},
|
|
133
|
+
"piExtensionId": {
|
|
134
|
+
"type": "string",
|
|
135
|
+
"enum": ["pi-codegraph", "pi-lens"],
|
|
136
|
+
"description": "Frozen Pi extension short id resolved at run time against the Pi settings package inventory. Adding a package requires changing the plan and this enum."
|
|
137
|
+
},
|
|
138
|
+
"piExtensions": {
|
|
139
|
+
"type": "array",
|
|
140
|
+
"minItems": 1,
|
|
141
|
+
"uniqueItems": true,
|
|
142
|
+
"items": { "$ref": "#/$defs/piExtensionId" },
|
|
143
|
+
"description": "Node-level explicit Pi extension allowlist (backend implementation DAGs only). Omitted = extension discovery stays fully closed (R8.1). Only executor 'pi' nodes may declare it."
|
|
144
|
+
},
|
|
133
145
|
"role": {
|
|
134
146
|
"enum": ["planner", "scout", "implementer", "reviewer", "supervisor", "verifier", "closeout"]
|
|
135
147
|
},
|
|
@@ -356,6 +368,31 @@
|
|
|
356
368
|
"properties": { "schemaVersion": { "const": 1 }, "requireBaseline": { "const": true } }
|
|
357
369
|
},
|
|
358
370
|
"frontendTestCaseChecklist": { "type": "object", "additionalProperties": false },
|
|
371
|
+
"frontendBrowserToolPreflight": { "type": "object", "additionalProperties": false },
|
|
372
|
+
"frontendTestStandardScenarios": { "type": "object", "additionalProperties": false },
|
|
373
|
+
"frontendTestEnvironmentProbe": { "type": "object", "additionalProperties": false },
|
|
374
|
+
"frontendTestCaseManifest": {
|
|
375
|
+
"type": "object",
|
|
376
|
+
"additionalProperties": false,
|
|
377
|
+
"properties": {
|
|
378
|
+
"maxCases": { "type": "integer", "minimum": 1 },
|
|
379
|
+
"declaredAcIds": { "type": "array", "items": { "type": "string" } }
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
"frontendTestResultFinalize": {
|
|
383
|
+
"type": "object",
|
|
384
|
+
"additionalProperties": false,
|
|
385
|
+
"properties": {
|
|
386
|
+
"declaredAcIds": { "type": "array", "items": { "type": "string" } }
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
"frontendTestReports": {
|
|
390
|
+
"type": "object",
|
|
391
|
+
"additionalProperties": false,
|
|
392
|
+
"properties": {
|
|
393
|
+
"l5": { "type": "boolean" }
|
|
394
|
+
}
|
|
395
|
+
},
|
|
359
396
|
"frontendTestEvidenceValidation": { "type": "object", "additionalProperties": false },
|
|
360
397
|
"frontendTestHtmlReport": { "type": "object", "additionalProperties": false },
|
|
361
398
|
"backendTestPipeline": {
|
|
@@ -383,6 +420,12 @@
|
|
|
383
420
|
{ "required": ["frontendVerificationBundle"] },
|
|
384
421
|
{ "required": ["frontendReviewContext"] },
|
|
385
422
|
{ "required": ["frontendTestCaseChecklist"] },
|
|
423
|
+
{ "required": ["frontendBrowserToolPreflight"] },
|
|
424
|
+
{ "required": ["frontendTestStandardScenarios"] },
|
|
425
|
+
{ "required": ["frontendTestEnvironmentProbe"] },
|
|
426
|
+
{ "required": ["frontendTestCaseManifest"] },
|
|
427
|
+
{ "required": ["frontendTestResultFinalize"] },
|
|
428
|
+
{ "required": ["frontendTestReports"] },
|
|
386
429
|
{ "required": ["frontendTestEvidenceValidation"] },
|
|
387
430
|
{ "required": ["frontendTestHtmlReport"] },
|
|
388
431
|
{ "required": ["backendTestPipeline"] }
|
|
@@ -485,6 +528,7 @@
|
|
|
485
528
|
"items": { "type": "string", "minLength": 1 }
|
|
486
529
|
},
|
|
487
530
|
"toolProfile": { "$ref": "#/$defs/toolProfile" },
|
|
531
|
+
"piExtensions": { "$ref": "#/$defs/piExtensions" },
|
|
488
532
|
"governanceStandardReview": {
|
|
489
533
|
"type": "boolean",
|
|
490
534
|
"description": "Explicitly opts this node into writer-change-scoped AGENTS.md and repository-local code-standard review. Never inferred from node id or role."
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
]
|
|
146
146
|
},
|
|
147
147
|
"outputContract": "Write a Chinese, human-readable testcase/md/README.md as the single Markdown-first entry page with Coverage Scope, Coverage Matrix and a machine-parseable module index. Do not write module case cards here; do not execute pytest or modify production code/config.",
|
|
148
|
-
"subtask_prompt": "This is a required file-generation node. After reading the bounded inputs, immediately use write tools to create testcase/md/README.md. Do not end after analysis or planning, and do not return before a non-empty bounded diff exists. Write ONLY testcase/md/README.md in this node; module case cards are written by downstream sharded nodes.\n\nOutput budget protocol (hard, max output <=16K per turn): Never paste full Matrix, case bodies, or source text into assistant chat. README holds only Scope+Matrix+module index; never inline full case bodies. If a Completeness Gate / OUTPUT_LIMIT_RECOVERY retry is injected, continue only listed target paths.\n\nThe first non-empty response line must be exactly IMPLEMENTATION_OUTCOME: changed after the README has been written, or IMPLEMENTATION_OUTCOME: blocked when precise missing evidence prevents safe generation. already-satisfied is not valid for this node.\n\nRead the upstream environment report. Generate the Markdown-first backend test README under testcase/md/README.md.\n\nWrite human-readable content in Simplified Chinese by default. Keep English only for machine-readable IDs and technical literals such as Case/AC/REQ/BR IDs, HTTP methods, paths, field names, enum values, commands, filenames, code symbols and exact source citations.\n\nCreate testcase/md/README.md as the concise entry page: test objective, target/environment, isolation/cleanup, module summary and a linked case index table with Case ID, Chinese case name, scenario type, endpoint and expected status/result. Avoid repeating every case body in README.\n\nBefore the Coverage Matrix, write a mandatory machine-readable `## Coverage Scope` section in README using exactly `| Field | Value |`, immediately followed by the separator row `|---|---|`, and these six unique rows: `Change Classification`, `Coverage Policy`, `Affected Operations`, `Affected Rule Keys`, `Regression Floor`, `Scope Evidence`. Always set `Change Classification` to `new-operation` and `Coverage Policy` to `full-contract`; do NOT reason about whether operations are new or existing. Cover all in-scope rules from the requirement document at full depth; treat the product requirement as the coverage baseline and use API contract evidence (fields/status/enum/boundary/format) to supplement scenario dimensions. Scope is limited to operations/rules the requirement document (or its referenced API contract) explicitly describes; do not expand to unrelated operations that the requirement does not mention. List affected operations exactly as `METHOD /path`, stable rule keys separated by semicolons, and precise source pointers as Scope Evidence.\n\nCoverage depth is full over the in-scope rules: fully cover every documented status, request/response field rule, requiredness, enum, boundary, format, auth and business state of each affected operation the requirement describes, but do not re-test unrelated operations the requirement does not mention. Inspect shared validator/helper/DTO/query builder evidence and expand Affected Operations when the same affected path can affect them; unresolved impact stays visible as GAP/CONFLICT.\n\nBefore writing cases, build the mandatory machine-readable Coverage Matrix inside `testcase/md/README.md` itself. Its section heading line must be exactly `## Coverage Matrix` with no numeric prefix/suffix; never place the canonical Matrix only in a module file. Use this exact header: `| Rule Key | Priority | Source | Endpoint/Field | Dimension | Rule | Required Test Points | Case IDs | Status |`. Every data row must contain exactly 9 pipe-delimited cells and must never omit `Dimension`; use concise dimensions such as requirement, operation, response-status, requiredness, enum, boundary, format, business-state or error. Use only P0/P1/P2 and COVERED/PARTIAL/GAP/CONFLICT. Use stable `TP-<UPPERCASE-HYPHENATED-ID>` test points separated by semicolons.\n\nEach Rule Key must appear in exactly one Matrix row. Preserve each AC/REQ/BR Rule Key as one row; if one product rule spans multiple dimensions, use a concise composite Dimension in that single row instead of duplicating the key. Derive OpenAPI Rule Keys exactly as the deterministic analyzer does: operation token is `<HTTP-METHOD>-<PATH>` with braces removed and every non-alphanumeric run replaced by a hyphen, uppercase (for example POST `/api/resource-notes` → `POST-API-RESOURCE-NOTES`); response statuses use `API-<OPERATION>-RESPONSE-STATUS`; body/parameter fields use `API-<OPERATION>-<FIELD>-REQUIRED|ENUM|MIN-LENGTH|MAX-LENGTH|MINIMUM|MAXIMUM|PATTERN|FORMAT`. Do not invent aliases such as API-CREATE-FIELDS when a deterministic key applies.\n\nCoverage priority is strict inside the declared scope: P0 product requirements/task hard constraints always remain in scope; P1 exhaustively supplements documented operations, fields, business rules, statuses and errors only for Affected Operations; P2 adds bounded protocol robustness only when it is relevant to the change and does not invent product behavior. Coverage percentages describe the declared affected scope, never whole-API completeness unless every operation is explicitly listed. Conflicts or undefined expectations must stay visible as GAP/CONFLICT with precise source pointers, never guessed.\n\nFor uniqueness/lifecycle rules cover absent, active-existing, deleted-existing, create-delete-recreate, restore-then-recreate and documented scope/case-normalization states. For every enum cover every valid value plus bounded invalid equivalence classes (unknown, case variant, whitespace, empty, null/missing and wrong types as applicable). For every length/number rule cover min-1, min, nominal, max and max+1. For format rules cover each allowed class separately plus a valid mixed value, and representative forbidden classes including uppercase, internal/leading/trailing whitespace, tab/newline, unsupported punctuation, slash, emoji or control characters when the source contract supports that expectation.\n\nMandatory module index: include a `## Module Index` table in README that lists every planned module as a canonical relative link of the exact form `[label](./<stem>.md)` plus a `testcase/md/<stem>.md` path cell, so a downstream deterministic manifest can parse the module list. Group by stable business resource/domain, not by CRUD operation: one resource's list/detail/create/update/delete cases belong in one module such as `resource_notes`; split only when a single module would exceed the per-child 16K output protocol, keep the total module count at the smallest safe value, and never exceed 8 modules. Name each module file with a stable lowercase business stem such as `health` or `resource_notes`. Pure hexadecimal/hash-like opaque stems such as `a401606` or `deadbeef` are forbidden. Do not use priority-only stems `p0`, `p1` or `p2`; Priority belongs only in the Coverage Matrix and never defines module files. Do not use Case-ID-like module filenames such as `BE-HEALTH.md` or `BE-NOTES.md`. The relative link target MUST equal the on-disk filename stem the sharded writer will create. For every automatable case, `自动化映射` must name exactly `testcase/test_<module>.py`, where <module> is that Markdown filename without `.md`, lowercased, with non-alphanumeric characters replaced by underscores. Example: `testcase/md/health.md` → `testcase/test_health.py`; `testcase/md/resource_notes.md` → `testcase/test_resource_notes.py`. Never invent a different pytest path in Markdown than the module stem implies.\n\nScenario Partitions (query/filter axes): for every affected GET/list operation, declare one row per enum or classification axis used for filtering (query/path parameters such as type/status/category). Add a mandatory machine-readable `## Scenario Partitions` section after the Coverage Matrix using exactly `| Partition ID | Operation | Axis | Domain | Required Slots | Expected by Slot | Bind Rule |` with the separator row. Partition ID is a stable `SP-<OPERATION>-<AXIS>` token; Domain must copy the legal values verbatim from the bound OpenAPI enum or requirement sentence (never guess); Required Slots writes `each-value` plus `omitted` only when the parameter is optional; Expected by Slot states the documented expectation per slot kind (`domain-value`, `default-behavior`, `empty-result`/`excluded-result` when documented, or `GAP` when the source does not document the complement expectation — never invent 空列表/400). POST/PUT body field-validation enums stay in the Coverage Matrix as `TP-<FIELD>-ENUM-*` and MUST NOT get a Scenario Partition row. Do not create partitions for axes without a documented legal-value domain. Cross-axis combinations stay as ONE nominal Case; never declare a cross-axis cartesian partition.\n\nBefore finalizing README, calculate the predicted collected-item count as `sum(max(1, number of variant Test Points in each Case))`. If the task declares an item budget, the prediction must not exceed it. Reduce excess only by removing duplicate execution and converting same-request checkpoints to assertions; never drop required rules, boundaries, enums, operation-specific inputs, or business states. Record the prediction in README. Use only environment-supported fixtures/targets/isolation, record evidence gaps in Chinese, and do not emit JSON, pytest, or execute commands.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and copy `path` exactly into Markdown Source References. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails.\n\nRead only precise indexed references needed for AC/API/field/rule evidence; references remain authoritative over derived text."
|
|
148
|
+
"subtask_prompt": "This is a required file-generation node. After reading the bounded inputs, immediately use write tools to create testcase/md/README.md. Do not end after analysis or planning, and do not return before a non-empty bounded diff exists. Write ONLY testcase/md/README.md in this node; module case cards are written by downstream sharded nodes.\n\nOutput budget protocol (hard, max output <=16K per turn): Never paste full Matrix, case bodies, or source text into assistant chat. README holds only Scope+Matrix+module index; never inline full case bodies. If a Completeness Gate / OUTPUT_LIMIT_RECOVERY retry is injected, continue only listed target paths.\n\nThe first non-empty response line must be exactly IMPLEMENTATION_OUTCOME: changed after the README has been written, or IMPLEMENTATION_OUTCOME: blocked when precise missing evidence prevents safe generation. already-satisfied is not valid for this node.\n\nRead the upstream environment report. Generate the Markdown-first backend test README under testcase/md/README.md.\n\nWrite human-readable content in Simplified Chinese by default. Keep English only for machine-readable IDs and technical literals such as Case/AC/REQ/BR IDs, HTTP methods, paths, field names, enum values, commands, filenames, code symbols and exact source citations.\n\nCreate testcase/md/README.md as the concise entry page: test objective, target/environment, isolation/cleanup, module summary and a linked case index table with Case ID, Chinese case name, scenario type, endpoint and expected status/result. Avoid repeating every case body in README.\n\nBefore the Coverage Matrix, write a mandatory machine-readable `## Coverage Scope` section in README using exactly `| Field | Value |`, immediately followed by the separator row `|---|---|`, and these six unique rows: `Change Classification`, `Coverage Policy`, `Affected Operations`, `Affected Rule Keys`, `Regression Floor`, `Scope Evidence`. Always set `Change Classification` to `new-operation` and `Coverage Policy` to `full-contract`; do NOT reason about whether operations are new or existing. Cover all in-scope rules from the requirement document at full depth; treat the product requirement as the coverage baseline and use API contract evidence (fields/status/enum/boundary/format) to supplement scenario dimensions. Scope is limited to operations/rules the requirement document (or its referenced API contract) explicitly describes; do not expand to unrelated operations that the requirement does not mention. List affected operations exactly as `METHOD /path`, stable rule keys separated by semicolons, and precise source pointers as Scope Evidence.\n\nCoverage depth is full over the in-scope rules: fully cover every documented status, request/response field rule, requiredness, enum, boundary, format, auth and business state of each affected operation the requirement describes, but do not re-test unrelated operations the requirement does not mention. Inspect shared validator/helper/DTO/query builder evidence and expand Affected Operations when the same affected path can affect them; unresolved impact stays visible as GAP/CONFLICT.\n\nBefore writing cases, build the mandatory machine-readable Coverage Matrix inside `testcase/md/README.md` itself. Its section heading line must be exactly `## Coverage Matrix` with no numeric prefix/suffix; never place the canonical Matrix only in a module file. Use this exact header: `| Rule Key | Priority | Source | Endpoint/Field | Dimension | Rule | Required Test Points | Case IDs | Status |`. Every data row must contain exactly 9 pipe-delimited cells and must never omit `Dimension`; use concise dimensions such as requirement, operation, response-status, requiredness, enum, boundary, format, business-state or error. Use only P0/P1/P2 and COVERED/PARTIAL/GAP/CONFLICT. Use stable `TP-<UPPERCASE-HYPHENATED-ID>` test points separated by semicolons.\n\nEach Rule Key must appear in exactly one Matrix row. Preserve each AC/REQ/BR Rule Key as one row; if one product rule spans multiple dimensions, use a concise composite Dimension in that single row instead of duplicating the key. Derive OpenAPI Rule Keys exactly as the deterministic analyzer does: operation token is `<HTTP-METHOD>-<PATH>` with braces removed and every non-alphanumeric run replaced by a hyphen, uppercase (for example POST `/api/resource-notes` → `POST-API-RESOURCE-NOTES`); response statuses use `API-<OPERATION>-RESPONSE-STATUS`; body/parameter fields use `API-<OPERATION>-<FIELD>-REQUIRED|ENUM|MIN-LENGTH|MAX-LENGTH|MINIMUM|MAXIMUM|PATTERN|FORMAT`. Do not invent aliases such as API-CREATE-FIELDS when a deterministic key applies.\n\nCoverage priority is strict inside the declared scope: P0 product requirements/task hard constraints always remain in scope; P1 exhaustively supplements documented operations, fields, business rules, statuses and errors only for Affected Operations; P2 adds bounded protocol robustness only when it is relevant to the change and does not invent product behavior. Coverage percentages describe the declared affected scope, never whole-API completeness unless every operation is explicitly listed. Conflicts or undefined expectations must stay visible as GAP/CONFLICT with precise source pointers, never guessed.\n\nFor uniqueness/lifecycle rules cover absent, active-existing, deleted-existing, create-delete-recreate, restore-then-recreate and documented scope/case-normalization states. For every enum cover every valid value plus bounded invalid equivalence classes (unknown, case variant, whitespace, empty, null/missing and wrong types as applicable). For every length/number rule cover min-1, min, nominal, max and max+1. For format rules cover each allowed class separately plus a valid mixed value, and representative forbidden classes including uppercase, internal/leading/trailing whitespace, tab/newline, unsupported punctuation, slash, emoji or control characters when the source contract supports that expectation.\n\nMandatory module index: include a `## Module Index` table in README that lists every planned module as a canonical relative link of the exact form `[label](./<stem>.md)` plus a `testcase/md/<stem>.md` path cell, so a downstream deterministic manifest can parse the module list. Group by stable business resource/domain, not by CRUD operation: one resource's list/detail/create/update/delete cases belong in one module such as `resource_notes`; split only when a single module would exceed the per-child 16K output protocol, keep the total module count at the smallest safe value, and never exceed 8 modules. Name each module file with a stable lowercase business stem such as `health` or `resource_notes`. Pure hexadecimal/hash-like opaque stems such as `a401606` or `deadbeef` are forbidden. Do not use priority-only stems `p0`, `p1` or `p2`; Priority belongs only in the Coverage Matrix and never defines module files. Do not use Case-ID-like module filenames such as `BE-HEALTH.md` or `BE-NOTES.md`. The relative link target MUST equal the on-disk filename stem the sharded writer will create. For every automatable case, `自动化映射` must name exactly `testcase/test_<module>.py`, where <module> is that Markdown filename without `.md`, lowercased, with non-alphanumeric characters replaced by underscores. Example: `testcase/md/health.md` → `testcase/test_health.py`; `testcase/md/resource_notes.md` → `testcase/test_resource_notes.py`. Never invent a different pytest path in Markdown than the module stem implies.\n\nScenario Partitions (query/filter axes): for every affected GET/list operation, declare one row per enum or classification axis used for filtering (query/path parameters such as type/status/category). Add a mandatory machine-readable `## Scenario Partitions` section after the Coverage Matrix using exactly `| Partition ID | Operation | Axis | Domain | Required Slots | Expected by Slot | Bind Rule |` with the separator row. Partition ID is a stable `SP-<OPERATION>-<AXIS>` token; Domain must copy the legal values verbatim from the bound OpenAPI enum or requirement sentence (never guess); Required Slots writes `each-value` plus `omitted` only when the parameter is optional; Expected by Slot states the documented expectation per slot kind (`domain-value`, `default-behavior`, `empty-result`/`excluded-result` when documented, or `GAP` when the source does not document the complement expectation — never invent 空列表/400). POST/PUT body field-validation enums stay in the Coverage Matrix as `TP-<FIELD>-ENUM-*` and MUST NOT get a Scenario Partition row. Do not create partitions for axes without a documented legal-value domain. Only GET/list query or path parameters whose bound source documents a finite enum or classification set may become a Scenario Partition. Do not create partitions for free-form strings, primary keys, required-or-optional-only parameters, or boundary/format-only axes. If an axis has no finite legal-value domain, do not declare a Partition row and do not invent NOT-IN-SET cases. Cross-axis combinations stay as ONE nominal Case; never declare a cross-axis cartesian partition.\n\nBefore finalizing README, calculate the predicted collected-item count as `sum(max(1, number of variant Test Points in each Case))`. If the task declares an item budget, the prediction must not exceed it. Reduce excess only by removing duplicate execution and converting same-request checkpoints to assertions; never drop required rules, boundaries, enums, operation-specific inputs, or business states. Record the prediction in README. Use only environment-supported fixtures/targets/isolation, record evidence gaps in Chinese, and do not emit JSON, pytest, or execute commands.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and copy `path` exactly into Markdown Source References. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails.\n\nRead only precise indexed references needed for AC/API/field/rule evidence; references remain authoritative over derived text."
|
|
149
149
|
},
|
|
150
150
|
{
|
|
151
151
|
"id": "materialize-backend-md-module-manifest-shell",
|
|
@@ -274,7 +274,7 @@
|
|
|
274
274
|
"type": "implementation-outcome-v1"
|
|
275
275
|
},
|
|
276
276
|
"outputContract": "First non-empty line is IMPLEMENTATION_OUTCOME: changed|already-satisfied|blocked. Perform exactly one bounded incremental synchronization of testcase/md/** against all bound source references; preserve valid Cases and report a concise summary.",
|
|
277
|
-
"subtask_prompt": "Perform one gap-targeted synchronization, not a full-suite rewrite or stylistic review. Start from explicit bound source IDs/error codes/DTO fields/normative quoted rules and the README Matrix; open and edit only modules that own a missing or conflicting rule. Preserve unrelated valid modules byte-for-byte and avoid optional wording cleanup.\n\nOutput budget protocol: never dump full Matrix/case bodies into assistant chat. Inspect README first, build a concise target list, then read/write only target modules one file per tool call. Do not traverse every module when the Matrix and source token inventory show no gap; return `already-satisfied`. When adding omitted in-scope cases, keep every required section. Do not bulk-delete in-scope cases to save tokens.\n\nFor every variant Test Point, ensure the Markdown scenario intent is machine-checkable and located inside that same Case body/自动化映射, never in a file-level appendix, implementation-details block, or another Case. Use an exact transport target: `场景意图: <TP-ID>; operation=<METHOD /path>; target=<body.field|query.field|path.field|header.field|request>; intent=<empty|missing|null|min-1|min|max|max+1|pattern-invalid|enum-invalid|wrong-type|nominal-operation|custom-literal:V>; bound=<n optional>; example=<optional>; expectedCode=<optional>`. Never use vague targets such as field=resource/health. Keep pytest params aligned to the exact target. For intent=missing/empty/default-omit, pytest may use `_OMIT` or delete the key; for intent=enum-invalid use a concrete invalid enum literal (for example `UNKNOWN_STATUS`), never `_OMIT`/missing-key; for trim/padded samples use `custom-literal:trim` or a real padded string, not a bare token like `filter-active` when the intent is `custom-literal:ACTIVE`.\n\nTreat the requirement document as the coverage baseline; scope is limited to operations/rules it (or its referenced API contract) describes, and API contract evidence supplements scenario dimensions. For every in-scope operation, check applicable lifecycle/uniqueness states (including deleted-existing when in scope), valid enum values, bounded invalid classes, min-1/min/nominal/max/max+1, allowed/forbidden format classes, required/null/missing/wrong-type semantics, status/error codes, auth and state transitions. Inspect shared validator/helper/DTO/query builder evidence and expand Affected Operations when the same affected path can affect them; unresolved impact stays visible as GAP/CONFLICT. Directly add in-scope omissions; reject scope expansion to operations absent from the requirement document; undefined impact remains GAP/CONFLICT rather than invented behavior.\n\nCheck AC completeness/meaning, endpoint, fields/shape, status/error codes, rules, states, documented boundaries/auth, positive/negative coverage, executable steps and assertable results. Require the exact `## Coverage Scope` Field/Value table with the `|---|---|` separator row, a valid classification-policy pair, non-empty Affected Operations/Rule Keys/Scope Evidence, and the classification-specific Regression Floor. Require the exact unnumbered `## Coverage Matrix` heading in `testcase/md/README.md`, exact headers, exactly 9 cells in every data row (including a non-empty Dimension), deterministic OpenAPI Rule Keys for every in-scope affected operation, exactly one Matrix row per Rule Key (merge multi-dimension product rows), and bidirectional Matrix Rule/Test Point ↔ Case bindings. Never describe affected-scope coverage as whole-API completeness. Every explicit AC ID must appear in at least one Case `验收标准`; every explicit in-scope AC/REQ/BR Rule Key cited by a Case must have exactly one Coverage Matrix row, and no Case may cite a source Rule Key omitted from the Matrix. Every Matrix Case ID must share at least one of that row's Required Test Points and the Case must cite that Rule Key. Perform an explicit execution-redundancy review: merge checkpoint-only parameter rows, repeated default/read-back assertions, DELETE status/body/follow-up-read checks, response schema/Content-Type checks, PUT full-update/timestamp checks, repeated list setup and identical null/empty inputs when endpoint, input partition, precondition state and expected outcome are the same. Preserve separate POST/PUT, boundary, enum, wrong-type, role/tenant and distinct business-state variants. Directly repair malformed headings/rows/keys and binding modes rather than merely commenting on them. Reject avoidable English prose, duplicated bilingual wording, repeated boilerplate, oversized unstructured sections, a `### 操作步骤` section that contains only a table without any numbered executable line, vague results such as ‘符合预期’, Case-ID-like module filenames (for example `BE-HEALTH.md`), dropped exact `### 操作步骤`/`### 预期结果` headings, and missing or drifted script/function mapping where it can be derived.\n\nCorrect testcase/md/** directly: add documented omissions, remove unsupported cases, rename module files to stable lowercase stems when needed, normalize every Case ID to hyphen-separated module segments plus exactly three zero-padded digits (`BE-RESOURCE_NOTES-01` → `BE-RESOURCE-NOTES-001`; `BE-RN-011A` must be renumbered or merged) consistently across headings/index/mappings, fix automation mappings so each automatable case points at `testcase/test_<module>.py` derived from that module filename and declares exactly one primary symbol (evidence-only meta cases may keep `脚本/primary symbol=无` with empty variants), assign every Test Point exactly one of `变体测试点`/`场景断言测试点`/`横切证据测试点`, then perform an exact-set check: each Case's `### 测试点` set must equal (not merely contain) the union of those three binding lists; delete stale/legacy aliases and ensure every binding-list Test Point is present, expand every variant parameter row into its own atomic TP ID, make every non-cross-cutting TP Case-specific and owned by exactly one Case, require every primary symbol to start with the canonical Case prefix, ensure every explicit AC ID appears in an applicable Case `验收标准`, merge execution duplicates, improve navigation/tables/Chinese wording, or record gaps in Chinese. Remove every credential/header value, placeholder, fake token and anti-example from Markdown. Sensitive key names may remain only as a plain list; values must be described as runtime-only and omitted, with no colon/value pair or literal example anywhere, including details blocks and explanatory text. Keep Case IDs, AC/REQ/BR IDs, HTTP methods, paths, fields, enum values, filenames, code symbols and source citations as exact machine-readable identifiers; only normalize Case ID separator/sequence formatting as specified above. Recalculate predicted collected items as `sum(max(1, variant count per Case))`; when the task declares a budget, directly merge redundant journeys/reclassify same-request checkpoints until the prediction is within budget, while preserving all required coverage. The validator accepts Chinese and legacy English section aliases; retain or converge to the Chinese human-readable headings without losing structure.\n\nThis is the single Markdown incremental synchronization round. Read every authoritative reference index entry whose role hints include acceptance-criteria, api-contract, data-contract or business-rule; do not rely on the derived PRD as a complete inventory. Preserve every explicit AC/REQ/BR ID, every documented HTTP/business error code, every DTO/JSON field, enum value, boundary, format, nested shape, transaction/state/idempotency/uniqueness/auth/tenant/cross-field rule. For each natural-language normative business rule preserved as required scope, include its exact source sentence without paraphrase together with source path and line/heading anchor so the deterministic ledger can verify quote/hash provenance. Ensure every Case declares exactly `Payload Contract: none` or the three labels `Payload Required Paths`, `Payload Allowed Paths`, and `Payload Enum`; every label must occupy its own machine-readable list line, and a Case must never concatenate target/setup operations or multiple `Payload Contract` tokens onto one line, and explanatory prose/details must not repeat any `Payload Contract:` token; never infer missing keys or enum values. A target GET/DELETE operation with no request body must remain `Payload Contract: none` even when its setup journey performs POST/PUT with a DTO; setup payloads never redefine the target Case payload contract. Add only missing Matrix rows/Test Points/Cases/assertions or repair exact drift; do not rewrite already-valid unrelated modules. Work gap-targeted: inspect source anchors and affected modules first, leave unrelated valid modules byte-stable, and return `already-satisfied` without restating the full suite when no gap exists.\n\nFor affected API fields, use one valid nominal payload plus atomic required/missing/null/empty/wrong-type, every documented enum value plus bounded invalid classes, documented min-1/min/nominal/max/max+1, formats and nested object/array constraints. Do not generate a Cartesian product or invent undocumented constraints. Do not invent a concrete identifier type when the source only requires presence; for a missing-resource 404 path with unspecified identifier syntax/type, synchronize the Case to a create-delete-derived valid identifier journey rather than an arbitrary UUID/text placeholder.\n\nScenario Partitions synchronization: when README declares `## Scenario Partitions`, verify each declared partition's slots are fully materialized as variant Test Points with exact `TP-<Partition ID>-...` IDs (each-value per Domain value, OMITTED only for optional axes, exactly one NOT-IN-SET with intent=enum-invalid). Directly add missing slot rows/Cases; never delete a declared partition or drop its complement slot to force coverage green. When the bound source does not document the complement expectation, keep the slot with GAP expected instead of guessing. Body-field validation enums (`TP-<FIELD>-ENUM-*`) are NOT partitions — do not add partition rows for them.\n\nBefore returning, verify that every explicit source AC/REQ/BR, error code and strong DTO field token appears in README or an applicable module Case. If a fact cannot be safely automated, retain it as GAP/CONFLICT with its exact source pointer instead of dropping it. Return already-satisfied only when no target file needs an incremental edit.\n\nRead only indexed source paths. Do not scan the repository, modify source/**, generate pytest, execute tests, or emit JSON.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and keep `path` as the exact Markdown Source References citation. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails.",
|
|
277
|
+
"subtask_prompt": "Perform one gap-targeted synchronization, not a full-suite rewrite or stylistic review. Start from explicit bound source IDs/error codes/DTO fields/normative quoted rules and the README Matrix; open and edit only modules that own a missing or conflicting rule. Preserve unrelated valid modules byte-for-byte and avoid optional wording cleanup.\n\nOutput budget protocol: never dump full Matrix/case bodies into assistant chat. Inspect README first, build a concise target list, then read/write only target modules one file per tool call. Do not traverse every module when the Matrix and source token inventory show no gap; return `already-satisfied`. When adding omitted in-scope cases, keep every required section. Do not bulk-delete in-scope cases to save tokens.\n\nFor every variant Test Point, ensure the Markdown scenario intent is machine-checkable and located inside that same Case body/自动化映射, never in a file-level appendix, implementation-details block, or another Case. Use an exact transport target: `场景意图: <TP-ID>; operation=<METHOD /path>; target=<body.field|query.field|path.field|header.field|request>; intent=<empty|missing|null|min-1|min|max|max+1|pattern-invalid|enum-invalid|wrong-type|nominal-operation|custom-literal:V>; bound=<n optional>; example=<optional>; expectedCode=<optional>`. Never use vague targets such as field=resource/health. Keep pytest params aligned to the exact target. For intent=missing/empty/default-omit, pytest may use `_OMIT` or delete the key; for intent=enum-invalid use a concrete invalid enum literal (for example `UNKNOWN_STATUS`), never `_OMIT`/missing-key; for trim/padded samples use `custom-literal:trim` or a real padded string, not a bare token like `filter-active` when the intent is `custom-literal:ACTIVE`.\n\nTreat the requirement document as the coverage baseline; scope is limited to operations/rules it (or its referenced API contract) describes, and API contract evidence supplements scenario dimensions. For every in-scope operation, check applicable lifecycle/uniqueness states (including deleted-existing when in scope), valid enum values, bounded invalid classes, min-1/min/nominal/max/max+1, allowed/forbidden format classes, required/null/missing/wrong-type semantics, status/error codes, auth and state transitions. Inspect shared validator/helper/DTO/query builder evidence and expand Affected Operations when the same affected path can affect them; unresolved impact stays visible as GAP/CONFLICT. Directly add in-scope omissions; reject scope expansion to operations absent from the requirement document; undefined impact remains GAP/CONFLICT rather than invented behavior.\n\nCheck AC completeness/meaning, endpoint, fields/shape, status/error codes, rules, states, documented boundaries/auth, positive/negative coverage, executable steps and assertable results. Require the exact `## Coverage Scope` Field/Value table with the `|---|---|` separator row, a valid classification-policy pair, non-empty Affected Operations/Rule Keys/Scope Evidence, and the classification-specific Regression Floor. Require the exact unnumbered `## Coverage Matrix` heading in `testcase/md/README.md`, exact headers, exactly 9 cells in every data row (including a non-empty Dimension), deterministic OpenAPI Rule Keys for every in-scope affected operation, exactly one Matrix row per Rule Key (merge multi-dimension product rows), and bidirectional Matrix Rule/Test Point ↔ Case bindings. Never describe affected-scope coverage as whole-API completeness. Every explicit AC ID must appear in at least one Case `验收标准`; every explicit in-scope AC/REQ/BR Rule Key cited by a Case must have exactly one Coverage Matrix row, and no Case may cite a source Rule Key omitted from the Matrix. Every Matrix Case ID must share at least one of that row's Required Test Points and the Case must cite that Rule Key. Perform an explicit execution-redundancy review: merge checkpoint-only parameter rows, repeated default/read-back assertions, DELETE status/body/follow-up-read checks, response schema/Content-Type checks, PUT full-update/timestamp checks, repeated list setup and identical null/empty inputs when endpoint, input partition, precondition state and expected outcome are the same. Preserve separate POST/PUT, boundary, enum, wrong-type, role/tenant and distinct business-state variants. Directly repair malformed headings/rows/keys and binding modes rather than merely commenting on them. Reject avoidable English prose, duplicated bilingual wording, repeated boilerplate, oversized unstructured sections, a `### 操作步骤` section that contains only a table without any numbered executable line, vague results such as ‘符合预期’, Case-ID-like module filenames (for example `BE-HEALTH.md`), dropped exact `### 操作步骤`/`### 预期结果` headings, and missing or drifted script/function mapping where it can be derived.\n\nCorrect testcase/md/** directly: add documented omissions, remove unsupported cases, rename module files to stable lowercase stems when needed, normalize every Case ID to hyphen-separated module segments plus exactly three zero-padded digits (`BE-RESOURCE_NOTES-01` → `BE-RESOURCE-NOTES-001`; `BE-RN-011A` must be renumbered or merged) consistently across headings/index/mappings, fix automation mappings so each automatable case points at `testcase/test_<module>.py` derived from that module filename and declares exactly one primary symbol (evidence-only meta cases may keep `脚本/primary symbol=无` with empty variants), assign every Test Point exactly one of `变体测试点`/`场景断言测试点`/`横切证据测试点`, then perform an exact-set check: each Case's `### 测试点` set must equal (not merely contain) the union of those three binding lists; delete stale/legacy aliases and ensure every binding-list Test Point is present, expand every variant parameter row into its own atomic TP ID, make every non-cross-cutting TP Case-specific and owned by exactly one Case, require every primary symbol to start with the canonical Case prefix, ensure every explicit AC ID appears in an applicable Case `验收标准`, merge execution duplicates, improve navigation/tables/Chinese wording, or record gaps in Chinese. Remove every credential/header value, placeholder, fake token and anti-example from Markdown. Sensitive key names may remain only as a plain list; values must be described as runtime-only and omitted, with no colon/value pair or literal example anywhere, including details blocks and explanatory text. Keep Case IDs, AC/REQ/BR IDs, HTTP methods, paths, fields, enum values, filenames, code symbols and source citations as exact machine-readable identifiers; only normalize Case ID separator/sequence formatting as specified above. Recalculate predicted collected items as `sum(max(1, variant count per Case))`; when the task declares a budget, directly merge redundant journeys/reclassify same-request checkpoints until the prediction is within budget, while preserving all required coverage. The validator accepts Chinese and legacy English section aliases; retain or converge to the Chinese human-readable headings without losing structure.\n\nThis is the single Markdown incremental synchronization round. Read every authoritative reference index entry whose role hints include acceptance-criteria, api-contract, data-contract or business-rule; do not rely on the derived PRD as a complete inventory. Preserve every explicit AC/REQ/BR ID, every documented HTTP/business error code, every DTO/JSON field, enum value, boundary, format, nested shape, transaction/state/idempotency/uniqueness/auth/tenant/cross-field rule. For each natural-language normative business rule preserved as required scope, include its exact source sentence without paraphrase together with source path and line/heading anchor so the deterministic ledger can verify quote/hash provenance. Ensure every Case declares exactly `Payload Contract: none` or the three labels `Payload Required Paths`, `Payload Allowed Paths`, and `Payload Enum`; every label must occupy its own machine-readable list line, and a Case must never concatenate target/setup operations or multiple `Payload Contract` tokens onto one line, and explanatory prose/details must not repeat any `Payload Contract:` token; never infer missing keys or enum values. A target GET/DELETE operation with no request body must remain `Payload Contract: none` even when its setup journey performs POST/PUT with a DTO; setup payloads never redefine the target Case payload contract. Add only missing Matrix rows/Test Points/Cases/assertions or repair exact drift; do not rewrite already-valid unrelated modules. Work gap-targeted: inspect source anchors and affected modules first, leave unrelated valid modules byte-stable, and return `already-satisfied` without restating the full suite when no gap exists.\n\nFor affected API fields, use one valid nominal payload plus atomic required/missing/null/empty/wrong-type, every documented enum value plus bounded invalid classes, documented min-1/min/nominal/max/max+1, formats and nested object/array constraints. Do not generate a Cartesian product or invent undocumented constraints. Do not invent a concrete identifier type when the source only requires presence; for a missing-resource 404 path with unspecified identifier syntax/type, synchronize the Case to a create-delete-derived valid identifier journey rather than an arbitrary UUID/text placeholder.\n\nScenario Partitions synchronization: when README declares `## Scenario Partitions`, verify each declared partition's slots are fully materialized as variant Test Points with exact `TP-<Partition ID>-...` IDs (each-value per Domain value, OMITTED only for optional axes, exactly one NOT-IN-SET with intent=enum-invalid). Directly add missing slot rows/Cases. You may delete an illegal Partition row that has no source-backed finite domain, together with its derived `TP-SP-*` slots/Cases. Never delete a legal source-backed partition or drop its complement slot to force coverage green. When the bound source does not document the complement expectation, keep the slot with GAP expected instead of guessing. Body-field validation enums (`TP-<FIELD>-ENUM-*`) are NOT partitions — do not add partition rows for them.\n\nBefore returning, verify that every explicit source AC/REQ/BR, error code and strong DTO field token appears in README or an applicable module Case. If a fact cannot be safely automated, retain it as GAP/CONFLICT with its exact source pointer instead of dropping it. Return already-satisfied only when no target file needs an incremental edit.\n\nRead only indexed source paths. Do not scan the repository, modify source/**, generate pytest, execute tests, or emit JSON.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and keep `path` as the exact Markdown Source References citation. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails.",
|
|
278
278
|
"retryPolicy": {
|
|
279
279
|
"maxAttempts": 2,
|
|
280
280
|
"backoff": "exponential",
|
|
@@ -66,12 +66,11 @@
|
|
|
66
66
|
".harness/**",
|
|
67
67
|
"artifacts/**"
|
|
68
68
|
],
|
|
69
|
-
"outputContract": "Write testcase/frontend/rag/standard-scenarios.v1.json for generate-time standard scenario coverage.",
|
|
70
|
-
"subtask_prompt": "
|
|
69
|
+
"outputContract": "Write testcase/frontend/rag/standard-scenarios.v1.json for generate-time standard scenario coverage. Copy docs/templates or harness.json governanceRoot templates (including ai_workspace/loop-agent/templates) when present; otherwise write the minimal STD-FE-SMOKE-ENTRY fallback.",
|
|
70
|
+
"subtask_prompt": "Prepare frontend-test package: materialize standard-scenarios.v1.json into the RAG package from docs/templates, governanceRoot/templates, or the init-projected ai_workspace/loop-agent/templates path.",
|
|
71
71
|
"shell": {
|
|
72
|
-
"commands": [
|
|
73
|
-
|
|
74
|
-
],
|
|
72
|
+
"commands": [],
|
|
73
|
+
"frontendTestStandardScenarios": {},
|
|
75
74
|
"cwd": ".",
|
|
76
75
|
"timeoutMs": 60000
|
|
77
76
|
}
|
|
@@ -120,12 +119,11 @@
|
|
|
120
119
|
".harness/**",
|
|
121
120
|
"artifacts/**"
|
|
122
121
|
],
|
|
123
|
-
"outputContract": "Fail-closed environment preflight: absolute non-production baseUrl + curl HTTP reachability; writes environmentProbe facts; unreachable => blockedReason frontend-base-url-unreachable (
|
|
124
|
-
"subtask_prompt": "Parse the concrete baseUrl selected by retrieve-frontend-test-context-pi from testcase/frontend/rag/context.md. Reject production, non-http(s), credentials, query and fragment. Probe with curl (HEAD then GET fallback; connect/max-time; no auth/cookie). 2xx/3xx => reachable and continue. 4xx/5xx/DNS/timeout/
|
|
122
|
+
"outputContract": "Fail-closed environment preflight: absolute non-production baseUrl + curl HTTP reachability; writes environmentProbe facts; unreachable => blockedReason frontend-base-url-unreachable with errorClass (connection-refused / dns-unresolved / connect-timeout / http-N). Node ERROR so generate/map do not run. Does not start the app.",
|
|
123
|
+
"subtask_prompt": "Parse the concrete baseUrl selected by retrieve-frontend-test-context-pi from testcase/frontend/rag/context.md. Reject production, non-http(s), credentials, query and fragment. Probe with curl (HEAD then GET fallback; connect/max-time; no auth/cookie). 2xx/3xx => reachable and continue. Connection refused records errorClass=connection-refused and tells the operator to start the local app then rerun from this node. 4xx/5xx/DNS/timeout/TLS => blockedReason frontend-base-url-unreachable. Missing curl => blockedReason curl-unavailable. Do not start the app.",
|
|
125
124
|
"shell": {
|
|
126
|
-
"commands": [
|
|
127
|
-
|
|
128
|
-
],
|
|
125
|
+
"commands": [],
|
|
126
|
+
"frontendTestEnvironmentProbe": {},
|
|
129
127
|
"cwd": ".",
|
|
130
128
|
"timeoutMs": 60000
|
|
131
129
|
}
|
|
@@ -17,5 +17,5 @@ Do not claim the environment is reachable until preflight completes. Preflight d
|
|
|
17
17
|
|
|
18
18
|
## Standard scenario coverage
|
|
19
19
|
|
|
20
|
-
- Copy or reference `docs/templates/frontend-test-standard-scenarios.v1.json` into `testcase/frontend/rag/standard-scenarios.v1.json` when available.
|
|
20
|
+
- Copy or reference `docs/templates/frontend-test-standard-scenarios.v1.json`, `harness.json` `governanceRoot`/templates, or the init-projected `ai_workspace/loop-agent/templates/frontend-test-standard-scenarios.v1.json` into `testcase/frontend/rag/standard-scenarios.v1.json` when available.
|
|
21
21
|
- Add `## Standard scenario coverage` to coverage-map.md with planned/n/a for each must scenario.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tea-agent/loop-agent",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"loop-agent": "bin/loop-agent.js",
|
|
@@ -39,6 +39,9 @@
|
|
|
39
39
|
"publishConfig": {
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=22.19.0"
|
|
44
|
+
},
|
|
42
45
|
"scripts": {
|
|
43
46
|
"dev": "node --import tsx/esm src/cli.ts",
|
|
44
47
|
"cursor": "node --import tsx/esm src/cli.ts cursor-prompt",
|
|
@@ -64,6 +67,8 @@
|
|
|
64
67
|
"verify:tree": "node scripts/pre-push-verify.mjs --verify-current-tree"
|
|
65
68
|
},
|
|
66
69
|
"dependencies": {
|
|
70
|
+
"@earendil-works/pi-ai": "0.83.0",
|
|
71
|
+
"@earendil-works/pi-coding-agent": "0.83.0",
|
|
67
72
|
"commander": "^12.1.0",
|
|
68
73
|
"katex": "^0.16.47",
|
|
69
74
|
"mermaid": "^11.16.1",
|
|
@@ -71,13 +76,12 @@
|
|
|
71
76
|
"rehype-katex": "^7.0.1",
|
|
72
77
|
"remark-math": "^6.0.0",
|
|
73
78
|
"semver": "^7.8.5",
|
|
79
|
+
"typebox": "1.3.7",
|
|
74
80
|
"yaml": "^2.9.0",
|
|
75
81
|
"zod": "^3.25.76"
|
|
76
82
|
},
|
|
77
83
|
"optionalDependencies": {
|
|
78
|
-
"@cursor/sdk": "^1.0.7"
|
|
79
|
-
"@earendil-works/pi-ai": "0.80.10",
|
|
80
|
-
"@earendil-works/pi-coding-agent": "0.80.10"
|
|
84
|
+
"@cursor/sdk": "^1.0.7"
|
|
81
85
|
},
|
|
82
86
|
"devDependencies": {
|
|
83
87
|
"@remixicon/react": "^4.9.0",
|
|
@@ -48,8 +48,9 @@ IRON LAW:`product-analysis.md` 必须先写入正式路径,再对该正式
|
|
|
48
48
|
- [ ] 知识库状态为 `executed-hit` 或 `executed-no-match`,或 `unavailable` 后用户明确确认跳过,才允许进入项目资料预扫描与常规代码探索;其余情况保持阻断。
|
|
49
49
|
- [ ] 知识库门禁通过后,依次预扫描 `<project-root>/ai_workspace/project-how-to`、`code-specification`、`project-business`:先枚举文件,再读取入口文档及与当前需求直接相关的内容;缺失目录记录 `not-found` 并继续,不做无边界加载。
|
|
50
50
|
- [ ] 然后读取并执行 `references/clarification-and-knowledge.md` 第 1 节,按需求问题和知识库结论定向探索代码库。当前宿主支持隔离的只读代码侦察 agent 时,优先委派限定范围的代码探索;不支持时由当前 agent 执行同等范围的定向搜索并只保留精简结果,不得阻断或扩大搜索范围。知识库结论不得替代代码落点证据。
|
|
51
|
+
- [ ] 执行「输入↔规范一致性核对」:将原始需求的每条明确声明与有效规范证据(`KB-FACT-*`、ai_workspace 项目资料、仓库规范文档)及代码现状事实(`CODE-FACT-*`)逐条比对,分类为 一致 / 规范补充 / 冲突 / 无规则。分类为"冲突"的条目必须逐条进入待确认问题,标注"输入声明 vs 规范/代码声明"与冲突来源,用户裁决前不选边。该核对是强制步骤,任何"输入明确"都不构成豁免;规范补充仅适用于规范类事实,代码现状在输入未说明时按 unknown 分流,不得静默填补。
|
|
51
52
|
- [ ] 汇总原始需求、`KB-FACT-*`、项目资料与 `CODE-FACT-*`,识别可查明事实、冲突、unknown 和必须由用户选择的目标行为;完成以上顺序后才生成待确认问题并进入 Step 2。
|
|
52
|
-
- [ ] 区分明确需求、推断需求和待确认问题。推断需求一律视为未确认产品内容;每一项推断需求以及任何含糊、缺失、冲突或存在多种合理解释的产品问题,都必须进入 Step 2
|
|
53
|
+
- [ ] 区分明确需求、推断需求和待确认问题。推断需求一律视为未确认产品内容;每一项推断需求以及任何含糊、缺失、冲突或存在多种合理解释的产品问题,都必须进入 Step 2 逐题向用户澄清,不得因模型认为推荐答案合理而跳过。与有效规范或代码现状冲突的行为不属于"明确需求",不得按 `source-requirement` 直接合并;冲突按 unknown 同款边界分流:影响范围、权限、业务规则、用户可感知输出/状态/边界或验收结果的冲突必须澄清,纯实现/技术细节冲突只记录事实、不生成问题。
|
|
53
54
|
- [ ] scope 包含 backend 且需求涉及接口/API 时,必须确认实现范围为 Web、Remote 或 Web + Remote;只写笼统“接口/API”视为待确认问题。不得依据知识库或代码现状替用户选择。
|
|
54
55
|
- [ ] 仅按 target 生成精简故事骨架和逐故事初步输出规范:`frontend` 只生成 `FE-US-*`,`backend` 只生成 `BE-US-*`,`both` 才生成两端。
|
|
55
56
|
- [ ] Product Analysis 只记录验收关注点,不创建正式 `AC-*` 或完整 Given/When/Then。每个前端故事的同 ID 初步输出规范必须包含“页面路由”:独立页面写以 `/` 开头的目标 URL;组件、弹窗或抽屉无独立路由时写“`不适用;嵌入 /目标路径 页面`”(`/目标路径` 替换为真实路径)。
|
|
@@ -74,23 +75,23 @@ IRON LAW:`product-analysis.md` 必须先写入正式路径,再对该正式
|
|
|
74
75
|
- [ ] 澄清进行中:每次合成后重写 `pending` Product Requirement,并保留“未决事项”;不得标为 `complete`。
|
|
75
76
|
- [ ] pending Clarification 与 pending Product Requirement 写入后,使用 `--allow-pending` 运行二者校验器;两者状态必须一致。`--allow-pending` 仅用于内部中间产物校验,不得用于最终交付或下游消费。
|
|
76
77
|
- [ ] 共同理解已确认后:生成 `complete` Product Requirement;Clarification 同步为 `complete`。
|
|
77
|
-
- [ ]
|
|
78
|
+
- [ ] 优先级(仅用于「输入↔规范一致性核对」与冲突澄清完成、用户裁决后的合成默认,不构成跳过澄清的依据):用户确认决策 > 原始明确需求 > 当前有效的知识库项目规范 > 模型推断;知识库/代码事实只用于理解项目规范与现状、发现冲突和辅助澄清,不得发明产品意图。
|
|
78
79
|
- [ ] 不得把 `KB-FACT-*`、`CODE-FACT-*`、知识库/仓库路径或代码符号原样写入 Product Requirement。
|
|
79
80
|
- [ ] 用户故事只描述角色/使用方、目标/能力、价值、入口/触发方式和 AC 引用;详细产品行为只写在同 ID 输出规范中,正式 AC 嵌入该输出规范。
|
|
80
81
|
- [ ] 逐个检查每个 `FE-US-*` 的同 ID 输出规范并写入“页面路由”,不得因多个故事共享页面而省略或合并该字段。独立页面写以 `/` 开头的目标 URL;组件、弹窗或抽屉无独立路由时写“`不适用;嵌入 /目标路径 页面`”(`/目标路径` 替换为真实路径)。
|
|
81
82
|
- [ ] target 为 `backend` 或 `both` 时,后端故事只定义 API 的业务能力、输入输出语义、权限和规则;触发方式写 `API(Web)`、`API(Remote)` 或 `API(Web + Remote)`。Web + Remote 表示同一能力需要两个接口;具体 Method+Path 及 DTO 留给依赖 skill。
|
|
82
|
-
- [ ]
|
|
83
|
+
- [ ] 后端分页:每页条数允许值与其他规则同等参与「输入↔规范一致性核对」。输入与有效分页规范冲突(含允许值集合的差异、子集或超集)时必须进入待确认问题澄清,用户裁决后以确认值为准;无冲突时按”用户确认 > 原始需求 > 有效知识库分页规范 > 默认集合 `10`、`20`、`50`、`100`”确定。参数名、必填性、默认值和其他契约不得从知识库 API 文档自动带入。
|
|
83
84
|
- [ ] Step 5:验证并交付 ⛔ BLOCKING
|
|
84
85
|
- [ ] 再次以只读方式向已冻结 Product Analysis 和 Product Requirement 校验器传入归一化 target,只运行三个当前产物校验器;Product Analysis 在 Step 1 已通过正式文件校验,本步不得因任何原因修改它。交付路径不得使用 `--allow-pending`。
|
|
85
86
|
- [ ] Requirement Clarification 校验器核对 Product Analysis/Clarification 的原始需求身份,以及三个产物的 requirement ID、analysis scope 和状态;冻结不做脚本校验。
|
|
86
87
|
- [ ] 只有所有命令返回 0 才能声明完成。本步只交付 complete V4 Product Requirement;下游 `analyze-product-dependencies` 首选消费该产物,其 `--target` 可为本次 `analysis_scope` 的子集。
|
|
87
88
|
- [ ] `test-validators.mjs` 仅在修改本 skill 的输出契约、schema、validator、artifact version、示例、forward-test contract,或发布/安装/回归验证时运行;普通需求分析不运行 validator matrix。
|
|
88
89
|
|
|
89
|
-
完整格式示例按需读取 `references/example.md
|
|
90
|
+
完整格式示例按需读取 `references/example.md`(含无需澄清与输入↔规范冲突澄清两条路径);维护或 forward-test 时读取 `references/forward-test-cases.md`。不要为了执行校验而阅读脚本,直接运行。
|
|
90
91
|
|
|
91
92
|
## 完成规则
|
|
92
93
|
|
|
93
|
-
- `no-clarification-required`
|
|
94
|
+
- `no-clarification-required` 仍生成三个产物,但只适用于”推断需求”为 `- 无未确认的推断需求。` 且”待确认问题”为 `- 无待确认问题。` 的场景,且必须完成「输入↔规范一致性核对」并在待确认问题记录 `- 一致性核对:…未发现冲突条目。`;Clarification 使用”澄清结论、来源、合并结果”三章精简结构,并记录 `- 内容补充:用户已确认无需补充`;不得仅凭模型判断需求足够明确就自动完成。
|
|
94
95
|
- 需要澄清的 `complete` Clarification:全部分支 resolved,所有实际 `Q-*` 为 `confirmed/user`,决策索引含 `- 共同理解:已确认`,每个 `DEC-Q-*` 进入 Product Requirement 决策追溯。
|
|
95
96
|
- Product Requirement 必须自包含;只描述目标产品行为,不得出现 `KB-FACT-*`、`CODE-FACT-*`、知识库/仓库文件路径、代码级类/函数/组件符号、模块调用关系、数据表名、证据位置或实现算法。
|
|
96
97
|
- 不得生成独立用户角色、验收标准汇总、前后端契约、Open Questions、测试建议或独立边界 case 章节。
|
|
@@ -110,6 +111,8 @@ IRON LAW:`product-analysis.md` 必须先写入正式路径,再对该正式
|
|
|
110
111
|
- 在 Product Analysis 写正式 `AC-*` 或 Given/When/Then。
|
|
111
112
|
- 任何前端故事的同 ID Product Analysis 或 Product Requirement 输出规范缺少“页面路由”,或因共享页面而只在其中一个故事中填写。
|
|
112
113
|
- 输入已给出分页允许值时,用知识库规范或默认 `10/20/50/100` 覆盖;或从知识库/API 文档自动带入路径、方法、参数名、必填性、默认值、响应、错误码或 DTO。
|
|
114
|
+
- 输入与有效规范(知识库、ai_workspace、仓库规范)或代码现状冲突时,按"原始需求优先"静默采用输入而不进入澄清;分页允许值冲突也不例外。
|
|
115
|
+
- 「输入↔规范一致性核对」漏掉任一证据通道,或把"规范补充"误判为"冲突"、把"冲突"静默当作"规范补充"处理,或用代码现状填补输入未说明的产品行为。
|
|
113
116
|
- 生成独立用户角色、验收标准汇总、前后端契约、Open Questions、测试建议或边界 case 章节。
|
|
114
117
|
|
|
115
118
|
## 交付前自检
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
每条验收标准必须独立可执行、结果可观察,并使用 Given/When/Then。一个用户故事存在多个关键流程时,拆成多个 AC,不要把互不相关的行为塞入一条 AC。
|
|
6
6
|
|
|
7
|
-
涉及状态变量、空数据、loading、error、disabled、错误提示或恢复入口时,Then
|
|
7
|
+
涉及状态变量、空数据、loading、error、disabled、错误提示或恢复入口时,Then 与异常场景必须使用已查明的项目枚举、共享组件、文案和交互规范;不得用通用占位状态替代项目规范。明确需求与项目规范或代码现状冲突时先澄清目标行为。
|
|
8
8
|
|
|
9
9
|
每条 AC 必须说明:
|
|
10
10
|
|
|
@@ -6,21 +6,21 @@
|
|
|
6
6
|
|
|
7
7
|
项目资料预扫描的时机与顺序按 `kb-integration.md` 执行;命中内容不得替代真实代码证据。
|
|
8
8
|
|
|
9
|
-
有效知识结果使用 `KB-FACT
|
|
9
|
+
有效知识结果使用 `KB-FACT-*`,包含规范事实、来源文档及定位、版本/生效状态、适用范围、需求影响、置信度和与输入关系(一致 | 补充 | 冲突)。知识库用于说明项目要求,代码库用于说明当前实现;知识库命中不能把代码文件、符号或调用关系标记为 confirmed。
|
|
10
10
|
|
|
11
|
-
提供代码仓库且当前宿主支持隔离的只读代码侦察 agent 时,优先将定向事实搜索交给该 agent:认证、权限、状态枚举、相似能力、字段类型、统一错误结构、设计系统、空数据及 loading/error 展示。委派内容仅包含待查问题、允许搜索的范围和适用的知识库规范结论,当前会话只保留结论、证据位置、置信度和未定位项。当前宿主不支持该能力时,由当前 agent 先限定故事、问题、目录或关键词,再沿直接相关引用定向搜索,不做无边界扫描;不得因此阻断流程或扩大搜索范围。文件搜索优先使用 `rg --files` 和 `rg`,没有 `rg` 时使用宿主提供的等价只读搜索能力,不得降低证据标准。事实使用 `CODE-FACT
|
|
11
|
+
提供代码仓库且当前宿主支持隔离的只读代码侦察 agent 时,优先将定向事实搜索交给该 agent:认证、权限、状态枚举、相似能力、字段类型、统一错误结构、设计系统、空数据及 loading/error 展示。委派内容仅包含待查问题、允许搜索的范围和适用的知识库规范结论,当前会话只保留结论、证据位置、置信度和未定位项。当前宿主不支持该能力时,由当前 agent 先限定故事、问题、目录或关键词,再沿直接相关引用定向搜索,不做无边界扫描;不得因此阻断流程或扩大搜索范围。文件搜索优先使用 `rg --files` 和 `rg`,没有 `rg` 时使用宿主提供的等价只读搜索能力,不得降低证据标准。事实使用 `CODE-FACT-*`,包含事实、证据位置、需求影响、证据类别(项目规范 | 代码现状)和与输入关系(一致 | 补充 | 冲突)。ai_workspace 项目资料与仓库规范文档统一记录为 `CODE-FACT-*` 并标注证据类别:项目规范;代码现状标注证据类别:代码现状。代码只能回答现状,不能替代用户决定目标需求。
|
|
12
12
|
|
|
13
|
-
scope 包含 backend
|
|
13
|
+
scope 包含 backend 且涉及分页时:每页条数允许值与其他明确声明一样参与「输入↔规范一致性核对」。输入与有效分页规范冲突(含允许值集合的差异、子集或超集)时必须进入澄清,用户裁决后以确认值为准;输入未说明时优先采用 `kb-design-assist` 返回的当前有效分页规范,仍未查明才使用默认集合 `10`、`20`、`50`、`100`。不得把知识库/API 文档的路径、方法、参数名、必填性、默认值、响应、错误码或 DTO 自动合并为产品需求。分析状态变量、空数据、loading、error、disabled 或兜底行为时,优先以当前有效知识库规范为项目规范来源,再核验仓库级指令、设计系统、共享组件和同类实现;未查明时写 unknown,不得用通用惯例冒充项目规范。
|
|
14
14
|
|
|
15
15
|
unknown 按影响分流:会改变范围、权限、业务规则、用户可感知输出/状态/边界或验收结果时,提炼成目标行为的产品决策并进入澄清;只涉及代码位置、符号、实现方式、技术复用或证据缺失时,保留为 `CODE-FACT-*` unknown 并交给依赖分析,不向用户提问,也不进入 Product Requirement。不得询问用户“代码在哪里”;应询问用户希望产品表现为何。
|
|
16
16
|
|
|
17
17
|
scope 包含 backend 且需求涉及接口/API 时,Web、Remote 或 Web + Remote 属于必须由用户确认的产品范围。只写笼统“接口/API”时生成一个澄清问题;确认结果写入现有“触发方式”,不得新增接口形态字段。Web + Remote 表示同一能力需要两个 HTTP 接口。
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
执行「输入↔规范一致性核对」:将原始需求的每条明确声明与有效规范证据(`KB-FACT-*`、ai_workspace 项目资料、仓库规范文档,统一以 `KB-FACT-*`/`CODE-FACT-*` 记录并标注与输入关系)及代码现状事实(`CODE-FACT-*`)逐条比对,分类为 一致 / 规范补充 / 冲突 / 无规则。分类为"冲突"的条目必须进入待确认问题,保留双方声明与来源证据,用户裁决前不选边;"输入明确"不构成豁免。规范补充仅适用于规范类事实(`KB-FACT-*` 及"证据类别:项目规范"的 `CODE-FACT-*`),输入未说明时直接并入、不生成问题;代码现状不得静默填补产品行为。冲突按 unknown 同款边界分流:影响范围、权限、业务规则、用户可感知输出/状态/边界或验收结果的冲突必须逐条澄清;纯实现/技术细节冲突只标"与输入关系:冲突"、不生成问题,留待依赖分析。过期、适用范围不明、互相冲突或无来源定位的知识结果按 unknown 处理。
|
|
20
20
|
|
|
21
21
|
## 2. 决策树式访谈
|
|
22
22
|
|
|
23
|
-
1. 从 Product Analysis 的全部推断需求、待确认问题和输出规范中的未确认产品内容提取顶层 `BR-*` 分支;每一项推断、含糊、缺失、冲突、多种合理解释或目标行为 unknown
|
|
23
|
+
1. 从 Product Analysis 的全部推断需求、待确认问题和输出规范中的未确认产品内容提取顶层 `BR-*` 分支;每一项推断、含糊、缺失、冲突、多种合理解释或目标行为 unknown 都必须进入决策树,覆盖完整分支,不为满足数量制造分支。原始需求已明确、与有效规范及代码现状核对一致且不存在歧义的行为直接作为 `source-requirement` 事实,不创建分支或问题;与有效规范或代码现状冲突的行为视为存在歧义,必须进入决策树。
|
|
24
24
|
2. 标注分支依赖,从范围、权限、核心流程、数据语义等基础决策开始。
|
|
25
25
|
3. 每轮只处理一个决策问题:先给推荐答案和理由,再提问并等待回答。任何两个待决子项都不得合并为一次提问。
|
|
26
26
|
4. 收到回答后重新识别剩余推断、模糊点、缺失项、冲突和新引入的未定义产品内容;只要仍存在未确认产品问题或需求,就开启下一轮。
|
|
@@ -32,7 +32,7 @@ scope 包含 backend 且需求涉及接口/API 时,Web、Remote 或 Web + Remo
|
|
|
32
32
|
|
|
33
33
|
### 回答复核
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
收到用户回答后,先判断它是否直接覆盖当前问题的关键决策点、是否只有一种合理的产品解释、是否足以写成明确的范围/规则/输出行为/验收结果、是否与原始明确需求、已有决策、有效规范或代码现状冲突,以及是否引入新的未定义概念、例外条件或依赖关系。全部满足时才形成最终决策并标记为 confirmed。
|
|
36
36
|
|
|
37
37
|
任一条件不满足时:
|
|
38
38
|
|
|
@@ -43,6 +43,10 @@ scope 包含 backend 且需求涉及接口/API 时,Web、Remote 或 Web + Remo
|
|
|
43
43
|
|
|
44
44
|
当前问题明确后,再扫描全部推断需求、其他未解决问题和本次回答新引入的模糊点。只要内容属于产品需求或目标行为且尚未确认,就必须继续澄清;纯措辞、代码位置、符号、实现方式、技术复用和其他不构成产品需求的下游技术细节不消耗澄清轮次。
|
|
45
45
|
|
|
46
|
+
### 澄清轮中的规范冲突
|
|
47
|
+
|
|
48
|
+
Product Analysis 冻结后,回答复核、用户回答或新证据暴露"用户回答或新增内容与有效规范/代码现状冲突"时:不得标记 confirmed;下一轮继续当前分支,把冲突双方声明与来源(`KB-FACT-*`/`CODE-FACT-*`)并列呈现,并在 Q-* 的"推荐理由"中成对写明,`最终决策` 记录用户裁决结果。已冻结的 Product Analysis 不回写。
|
|
49
|
+
|
|
46
50
|
问题等级:
|
|
47
51
|
|
|
48
52
|
- P0:改变范围、权限、关键流程、数据语义或验收结果;必须由用户明确确认。
|