@tea-agent/loop-agent 0.39.0-beta.5 → 0.39.0-beta.7

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.
Files changed (130) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/dist/build-stamp.json +3 -3
  3. package/dist/commands/client-recovery.js +3 -0
  4. package/dist/commands/task-advance.js +19 -0
  5. package/dist/executors/dag-pi-executor.js +138 -36
  6. package/dist/executors/pi-executor.js +7 -0
  7. package/dist/executors/pi-playwright-cli-tool.js +23 -16
  8. package/dist/executors/shell-executor.js +26 -9
  9. package/dist/shared/dag-failure-category.js +150 -0
  10. package/dist/task/config-types.js +6 -0
  11. package/dist/task/frontend-project-capability.js +19 -0
  12. package/dist/task/source-references.js +22 -1
  13. package/dist/worker/console/chat/operation-card.js +8 -1
  14. package/dist/worker/console/chat/routes.js +5 -3
  15. package/dist/worker/console/inspect-split.js +18 -0
  16. package/dist/worker/console/operation-run-facts.js +19 -3
  17. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-zsNyvGaH.js → abnfDiagram-N423BO3Z-bPer1waP.js} +1 -1
  18. package/dist/worker/console/static/assets/{arc-BDjZ5kE1.js → arc-BLdkwucW.js} +1 -1
  19. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-BkgaujnN.js → architectureDiagram-T3A2C74G-Bw4wo4I1.js} +1 -1
  20. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CqxOJi0j.js → blockDiagram-VBNYF7ZC-DUUkc0gr.js} +1 -1
  21. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-C2JHLdRi.js → c4Diagram-5PPSVZJV-BC3O0nob.js} +1 -1
  22. package/dist/worker/console/static/assets/channel-AbFtVnFm.js +1 -0
  23. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DF_YSvOS.js → chunk-2GRJ4B5K-Dd4g2nti.js} +1 -1
  24. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-D3Ort5Vo.js → chunk-2Q5K7J3B-s2EDm7-n.js} +1 -1
  25. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-XfAfZeUC.js → chunk-5RXB4S5H-GqtHM2yQ.js} +1 -1
  26. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-SLBibhf5.js → chunk-5VM5RSS4-BzRFrN8j.js} +1 -1
  27. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-Dz29Ye_f.js → chunk-6Q2QTUOP-Bw9nFjCJ.js} +1 -1
  28. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-DB2G4H8V.js → chunk-GF5L2VYU-B4n-03Qm.js} +1 -1
  29. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CIoGkxdu.js → chunk-JWPE2WC7-Dt75ZdBD.js} +1 -1
  30. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-CG78FGkn.js → chunk-KBJHAD2P-B_afMhHB.js} +1 -1
  31. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-ZDHAvXPd.js → chunk-RYQCIY6F-Bd8Rqqg9.js} +1 -1
  32. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-BKkkC4VA.js → chunk-XXDRQBXY-9boOMji4.js} +1 -1
  33. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-n1yf2Jcv.js +1 -0
  34. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-n1yf2Jcv.js +1 -0
  35. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-SposUZsO.js → cose-bilkent-JH36ORCC-BtCycfCc.js} +1 -1
  36. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BSCtQpD7.js → cynefin-VYW2F7L2-eTOts9L1.js} +1 -1
  37. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-DgFHrw9l.js → cynefinDiagram-MW4NZA55-Cibd2mjg.js} +1 -1
  38. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BVBasYbj.js → dagre-VZM6K2ZE-CDjDZtDV.js} +1 -1
  39. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-6r_4rN_c.js → diagram-7IWD3JNH-Btexn-JJ.js} +1 -1
  40. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-JmuaB41P.js → diagram-B4RE2ZJO-Cyl8sdpM.js} +1 -1
  41. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-xXvAY3sk.js → diagram-LBJQPF4R-Ev-83E1t.js} +1 -1
  42. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-D2B3lY2o.js → diagram-Q27KOJAE-41LqE0Mc.js} +1 -1
  43. package/dist/worker/console/static/assets/{diagram-UB23O5K3-tK54tMEX.js → diagram-UB23O5K3-BC39T5R3.js} +1 -1
  44. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-CNtELzV-.js → ebnfDiagram-BXEA7PRR-DzcNRuri.js} +1 -1
  45. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-C1xKMKcW.js → erDiagram-JOGREHBK-B5Frvvnz.js} +1 -1
  46. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CZ7dlPMz.js → flowDiagram-UKHOOZJN-BapxROIM.js} +1 -1
  47. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-BqGb42Xe.js → ganttDiagram-PKOTCBZU-Cd4d4wQ0.js} +1 -1
  48. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-D_BlXEtt.js → gitGraphDiagram-DS77QQ5N-CrL6buFW.js} +1 -1
  49. package/dist/worker/console/static/assets/index-DBh_x_Ek.js +406 -0
  50. package/dist/worker/console/static/assets/index-DwOGauxU.css +1 -0
  51. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-Vce2vmIe.js → infoDiagram-6WML65LV-BrSiNxyd.js} +1 -1
  52. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-DDwVBAvI.js → ishikawaDiagram-WSZJBQD7-gvlvY-n9.js} +1 -1
  53. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-y_Ew-wv4.js → journeyDiagram-NVQOT4AX-D-YaPzRQ.js} +1 -1
  54. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-CjXJFp1K.js → kanban-definition-27J2QSJJ-BsmDv9E_.js} +1 -1
  55. package/dist/worker/console/static/assets/{linear-1itMst1Q.js → linear-UWaoDN3h.js} +1 -1
  56. package/dist/worker/console/static/assets/{mermaid.core-C-D3ZRUa.js → mermaid.core-BlvpGVG8.js} +5 -5
  57. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-BiYywmZc.js → mindmap-definition-FAOFIHXS-CUCIP5CP.js} +1 -1
  58. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-l2fydNWA.js → pegDiagram-VL7TDLO6-CB1aQUAK.js} +1 -1
  59. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-Dz0hNbYW.js → pieDiagram-7S7Q4E2Y-BwehHxhf.js} +1 -1
  60. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-BujI_mLZ.js → quadrantDiagram-CIZ2JOQS-CFz30APB.js} +1 -1
  61. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-pWe84beb.js → railroadDiagram-AXF67PYL-BwNmw1i6.js} +1 -1
  62. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-ByYu2frg.js → requirementDiagram-LRYGKXZP-jg-tPXlI.js} +1 -1
  63. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-CoPnilFP.js → sankeyDiagram-W5VNT64P-BlyReDKl.js} +1 -1
  64. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-1Md2LnS0.js → sequenceDiagram-SI44F4Z6-DBUzW1f3.js} +1 -1
  65. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-DqqqAoSH.js → sizeCapture-X5ZJPWSS-BYcI2RAr.js} +1 -1
  66. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-C4sGkf--.js → stateDiagram-OKZ733FA-D7AiyJdo.js} +1 -1
  67. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BBSH5c8m.js +1 -0
  68. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-ByxJrUzW.js → swimlanes-SLNWSIFB-BHGt7Kkv.js} +2 -2
  69. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-D2F7-U4H.js +8 -0
  70. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-D8MLgM0O.js → timeline-definition-Z64GVDOM-OPjooWcX.js} +1 -1
  71. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-DnBis-wZ.js → vennDiagram-T6HMQDX7-ggsWDvrO.js} +1 -1
  72. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-uuyYT7UO.js → wardleyDiagram-T6FBY63Y-DjNe-BjZ.js} +1 -1
  73. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-BjgabhwK.js → xychartDiagram-ELKLHX3M-Byp63Hei.js} +1 -1
  74. package/dist/worker/console/static/index.html +2 -2
  75. package/dist/worker/console/static-src/app/useRecoveryConsole.js +38 -2
  76. package/dist/worker/console/static-src/app/useRunProgress.js +46 -0
  77. package/dist/worker/console/static-src/operator-chat/cards/failure-category-advice.js +25 -0
  78. package/dist/worker/console/static-src/operator-chat/input-history.js +76 -0
  79. package/dist/worker/console/static-src/operator-chat/turn-submission.js +13 -1
  80. package/dist/worker/console/static-src/operator-chat/useChatStream.js +29 -9
  81. package/dist/worker/console/static-src/operator-chat/useComposer.js +32 -0
  82. package/dist/worker/console/static-src/pages/tasks/run-id-resolution.js +79 -0
  83. package/dist/worker/console/static-src/pages/tasks/run-ownership-verify.js +23 -0
  84. package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +110 -0
  85. package/dist/worker/materialize/harness-task-lineage.js +5 -2
  86. package/dist/worker/observability/read-model.js +22 -0
  87. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +29 -1
  88. package/dist/workflows/dag/backend-test-markdown-workflow.js +176 -1
  89. package/dist/workflows/dag/backend-test-pytest-collection.js +87 -4
  90. package/dist/workflows/dag/backend-test-writer-completeness.js +10 -5
  91. package/dist/workflows/dag/dynamic-runtime/loop-until.js +1 -1
  92. package/dist/workflows/dag/dynamic-runtime/map.js +1 -1
  93. package/dist/workflows/dag/failure-category.js +7 -128
  94. package/dist/workflows/dag/frontend-design-policy.js +31 -7
  95. package/dist/workflows/dag/frontend-implementation-contract.js +78 -3
  96. package/dist/workflows/dag/frontend-review-findings.js +238 -0
  97. package/dist/workflows/dag/frontend-shadow-dual-write.js +24 -10
  98. package/dist/workflows/dag/frontend-shape.js +5 -3
  99. package/dist/workflows/dag/frontend-test-case-checklist.js +4 -2
  100. package/dist/workflows/dag/frontend-test-case-manifest.js +6 -4
  101. package/dist/workflows/dag/frontend-test-case-quality.js +6 -3
  102. package/dist/workflows/dag/frontend-test-environment-probe.js +10 -7
  103. package/dist/workflows/dag/frontend-test-html-report.js +3 -1
  104. package/dist/workflows/dag/frontend-test-l5-report.js +3 -1
  105. package/dist/workflows/dag/frontend-test-layout.js +159 -0
  106. package/dist/workflows/dag/frontend-test-result-contract.js +28 -14
  107. package/dist/workflows/dag/frontend-test-standard-scenarios.js +3 -1
  108. package/dist/workflows/dag/init-hybrid.js +149 -15
  109. package/dist/workflows/dag/node-execution.js +18 -1
  110. package/dist/workflows/dag/report.js +37 -1
  111. package/dist/workflows/dag/rerun-feedback.js +101 -1
  112. package/dist/workflows/dag/retry-policy.js +31 -3
  113. package/dist/workflows/dag/runner.js +46 -1
  114. package/dist/workflows/dag/types.js +12 -0
  115. package/dist/workflows/dag/validate.js +32 -22
  116. package/docs/templates/agent-dag-report.schema.json +8 -2
  117. package/docs/templates/agent-dag.schema.json +1 -1
  118. package/docs/templates/frontend-test-case-checklist.md +2 -2
  119. package/package.json +1 -1
  120. package/skills/fe-test-ui-scout/SKILL.md +4 -4
  121. package/skills/fe-test-ui-scout/references/ledger-schema.md +1 -1
  122. package/skills/playwright-cli/SKILL.md +1 -1
  123. package/skills/playwright-cli-case-generator/SKILL.md +10 -8
  124. package/dist/worker/console/static/assets/channel-BuqaGKAT.js +0 -1
  125. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DNdSHjH9.js +0 -1
  126. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DNdSHjH9.js +0 -1
  127. package/dist/worker/console/static/assets/index-D5zGX6fG.js +0 -404
  128. package/dist/worker/console/static/assets/index-DBbhESQ_.css +0 -1
  129. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8rmop_9.js +0 -1
  130. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-B0ky-kBM.js +0 -8
@@ -39,6 +39,7 @@ import { materializeFrontendLintAssessment, materializeFrontendLintBaseline, } f
39
39
  import { formatTraceabilityGateStdout, materializeBackendTestCaseManifest, runBackendTestTraceabilityGate, } from "../workflows/dag/backend-test-case-manifest.js";
40
40
  import { materializeBackendTestExecutionContract } from "../workflows/dag/backend-test-execution-contract.js";
41
41
  import { resolveBackendTestLayout } from "../workflows/dag/backend-test-layout.js";
42
+ import { frontendTestLayoutFromSpec, } from "../workflows/dag/frontend-test-layout.js";
42
43
  import { backendTestGapDocSchema, ingestBackendTestGap, } from "../workflows/dag/backend-test-gap-fill.js";
43
44
  import { analyzeBackendTestCaseCoverage, analyzeBackendTestMarkdownPytestCorrespondence, materializeBackendTestCaseManifestFromFacts, } from "../workflows/dag/backend-test-case-coverage-analysis.js";
44
45
  import { materializeBackendTestResultFromPytestHtml, materializeBackendTestResultFromRunDir, parsePytestHtmlReport, } from "../workflows/dag/backend-test-result-contract.js";
@@ -1067,7 +1068,7 @@ async function executeBackendTestPipeline(input, meta) {
1067
1068
  else if (pipeline === "markdown-traceability") {
1068
1069
  let report;
1069
1070
  try {
1070
- report = await validateBackendMarkdownTraceability(input.cwd);
1071
+ report = await validateBackendMarkdownTraceability(input.cwd, backendLayout);
1071
1072
  }
1072
1073
  catch (error) {
1073
1074
  report = `# Backend Test Traceability\n\n## Status\n\nFAIL\n\n## Findings\n\n- Traceability validation could not complete: ${error instanceof Error ? error.message : String(error)}\n`;
@@ -2800,10 +2801,12 @@ async function executeFrontendCloseout(input, meta) {
2800
2801
  async function executeFrontendTestCaseChecklist(input, meta) {
2801
2802
  const started = Date.now();
2802
2803
  try {
2804
+ const layout = frontendTestLayoutFromSpec(meta.spec);
2803
2805
  const declaredAcIds = (meta.spec.sourceBinding?.requirementIds ?? []).filter((id) => /^AC(?:-[A-Z0-9]+)+$/i.test(id));
2804
2806
  const result = await validateFrontendCaseChecklist({
2805
2807
  workspaceRoot: input.cwd,
2806
2808
  declaredAcIds,
2809
+ layout,
2807
2810
  });
2808
2811
  if (result.issues.length) {
2809
2812
  return {
@@ -2838,6 +2841,7 @@ async function executeFrontendTestL5Report(input, meta) {
2838
2841
  const output = await renderFrontendTestL5Report({
2839
2842
  workspaceRoot: input.cwd,
2840
2843
  runDir: meta.runDir,
2844
+ layout: frontendTestLayoutFromSpec(meta.spec),
2841
2845
  });
2842
2846
  return {
2843
2847
  ok: true,
@@ -2863,6 +2867,7 @@ async function executeFrontendTestHtmlReport(input, meta) {
2863
2867
  const output = await renderFrontendTestHtmlReport({
2864
2868
  workspaceRoot: input.cwd,
2865
2869
  runDir: meta.runDir,
2870
+ layout: frontendTestLayoutFromSpec(meta.spec),
2866
2871
  });
2867
2872
  return {
2868
2873
  ok: true,
@@ -2882,11 +2887,12 @@ async function executeFrontendTestHtmlReport(input, meta) {
2882
2887
  };
2883
2888
  }
2884
2889
  }
2885
- async function executeFrontendTestStandardScenarios(input) {
2890
+ async function executeFrontendTestStandardScenarios(input, meta) {
2886
2891
  const started = Date.now();
2887
2892
  try {
2888
2893
  const result = await copyFrontendTestStandardScenarios({
2889
2894
  workspaceRoot: input.cwd,
2895
+ layout: frontendTestLayoutFromSpec(meta.spec),
2890
2896
  });
2891
2897
  return {
2892
2898
  ok: true,
@@ -2906,10 +2912,11 @@ async function executeFrontendTestStandardScenarios(input) {
2906
2912
  };
2907
2913
  }
2908
2914
  }
2909
- async function executeFrontendTestEnvironmentProbe(input) {
2915
+ async function executeFrontendTestEnvironmentProbe(input, meta) {
2910
2916
  const started = Date.now();
2911
2917
  const result = await probeFrontendTestEnvironment({
2912
2918
  workspaceRoot: input.cwd,
2919
+ layout: frontendTestLayoutFromSpec(meta.spec),
2913
2920
  });
2914
2921
  if (result.ok) {
2915
2922
  return {
@@ -2928,11 +2935,12 @@ async function executeFrontendTestEnvironmentProbe(input) {
2928
2935
  durationMs: Date.now() - started,
2929
2936
  };
2930
2937
  }
2931
- async function executeFrontendTestEvidenceValidation(input) {
2938
+ async function executeFrontendTestEvidenceValidation(input, meta) {
2932
2939
  const started = Date.now();
2933
2940
  try {
2934
2941
  const result = await validateFrontendCaseEvidence({
2935
2942
  workspaceRoot: input.cwd,
2943
+ layout: frontendTestLayoutFromSpec(meta.spec),
2936
2944
  });
2937
2945
  const output = `frontend case evidence validation cases=${result.cases} findings=${result.issues.length}${result.issues.length ? ` issues=${JSON.stringify(result.issues)}` : ""}`;
2938
2946
  if (result.hardFail) {
@@ -2971,6 +2979,7 @@ async function executeFrontendTestCaseManifest(input, meta) {
2971
2979
  const checklist = await validateFrontendCaseChecklist({
2972
2980
  workspaceRoot: input.cwd,
2973
2981
  declaredAcIds,
2982
+ layout: frontendTestLayoutFromSpec(meta.spec),
2974
2983
  });
2975
2984
  if (checklist.issues.length) {
2976
2985
  return {
@@ -2985,6 +2994,7 @@ async function executeFrontendTestCaseManifest(input, meta) {
2985
2994
  workspaceRoot: input.cwd,
2986
2995
  maxCases: gate.maxCases,
2987
2996
  declaredAcIds,
2997
+ layout: frontendTestLayoutFromSpec(meta.spec),
2988
2998
  });
2989
2999
  return {
2990
3000
  ok: true,
@@ -3023,6 +3033,7 @@ async function executeFrontendTestResultFinalize(input, meta) {
3023
3033
  try {
3024
3034
  const evidence = await validateFrontendCaseEvidence({
3025
3035
  workspaceRoot: input.cwd,
3036
+ layout: frontendTestLayoutFromSpec(meta.spec),
3026
3037
  });
3027
3038
  advisoryStdout = `frontend case evidence validation cases=${evidence.cases} findings=${evidence.issues.length}${evidence.issues.length ? ` issues=${JSON.stringify(evidence.issues)}` : ""}`;
3028
3039
  // Advisory findings must not block materialize; only hardFail (path escape) does.
@@ -3041,6 +3052,7 @@ async function executeFrontendTestResultFinalize(input, meta) {
3041
3052
  artifactName: "frontend-test-result.json",
3042
3053
  outputDir: "contracts",
3043
3054
  sourceBinding: meta.spec.sourceBinding,
3055
+ layout: frontendTestLayoutFromSpec(meta.spec),
3044
3056
  });
3045
3057
  return {
3046
3058
  ok: true,
@@ -3079,12 +3091,14 @@ async function executeFrontendTestReports(input, meta) {
3079
3091
  const l5 = await renderFrontendTestL5Report({
3080
3092
  workspaceRoot: input.cwd,
3081
3093
  runDir: meta.runDir,
3094
+ layout: frontendTestLayoutFromSpec(meta.spec),
3082
3095
  });
3083
3096
  lines.push(`Frontend L-5 report: ${l5.htmlPath}\nMarkdown: ${l5.markdownPath}\nStatus: ${l5.metrics.status}`);
3084
3097
  }
3085
3098
  const report = await renderFrontendTestHtmlReport({
3086
3099
  workspaceRoot: input.cwd,
3087
3100
  runDir: meta.runDir,
3101
+ layout: frontendTestLayoutFromSpec(meta.spec),
3088
3102
  });
3089
3103
  lines.push(`Frontend test report: ${report.htmlPath}\nMarkdown: ${report.markdownPath}\nOutcome: ${report.outcome}\nCases: ${report.caseCount}`);
3090
3104
  return {
@@ -3214,10 +3228,10 @@ async function executeDagShellNodeInner(input, meta) {
3214
3228
  }
3215
3229
  }
3216
3230
  if (shell?.frontendTestStandardScenarios) {
3217
- return executeFrontendTestStandardScenarios(input);
3231
+ return executeFrontendTestStandardScenarios(input, meta);
3218
3232
  }
3219
3233
  if (shell?.frontendTestEnvironmentProbe) {
3220
- return executeFrontendTestEnvironmentProbe(input);
3234
+ return executeFrontendTestEnvironmentProbe(input, meta);
3221
3235
  }
3222
3236
  if (shell?.frontendBrowserToolPreflight) {
3223
3237
  const started = Date.now();
@@ -3273,14 +3287,16 @@ async function executeDagShellNodeInner(input, meta) {
3273
3287
  label: "Pi SDK custom-tool 能力",
3274
3288
  ok: true,
3275
3289
  });
3290
+ const layout = frontendTestLayoutFromSpec(meta.spec);
3276
3291
  const toolProbe = await createPlaywrightCliTool({
3277
3292
  repoRoot: input.cwd,
3278
3293
  runDir: meta.runDir,
3279
3294
  nodeId: input.task.id,
3280
3295
  caseId: "frontend-browser-preflight",
3281
- evidenceDir: "testcase/frontend/evidence/frontend-browser-preflight",
3296
+ evidenceDir: `${layout.evidenceDir}/frontend-browser-preflight`,
3282
3297
  baseUrl: "http://localhost:5173/",
3283
- inputRoot: "testcase/frontend/fixtures",
3298
+ inputRoot: layout.fixturesDir,
3299
+ layout,
3284
3300
  });
3285
3301
  if (toolProbe.name !== "playwright_cli") {
3286
3302
  steps.push({
@@ -3431,7 +3447,7 @@ async function executeDagShellNodeInner(input, meta) {
3431
3447
  return executeFrontendTestCaseManifest(input, meta);
3432
3448
  }
3433
3449
  if (shell?.frontendTestEvidenceValidation) {
3434
- return executeFrontendTestEvidenceValidation(input);
3450
+ return executeFrontendTestEvidenceValidation(input, meta);
3435
3451
  }
3436
3452
  if (shell?.frontendTestResultFinalize) {
3437
3453
  return executeFrontendTestResultFinalize(input, meta);
@@ -3538,6 +3554,7 @@ async function executeDagShellNodeInner(input, meta) {
3538
3554
  artifactName: gate.artifactName,
3539
3555
  outputDir: gate.outputDir,
3540
3556
  sourceBinding: meta.spec.sourceBinding,
3557
+ layout: frontendTestLayoutFromSpec(meta.spec),
3541
3558
  });
3542
3559
  break;
3543
3560
  default:
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Pure DAG failure-category classification shared by the workflows kernel and
3
+ * the Operator Console projection (console sources may not import
4
+ * src/workflows — security-and-tools boundary test).
5
+ *
6
+ * No runtime imports: this module is a leaf safe for both the CLI kernel and
7
+ * the browser bundle.
8
+ */
9
+ export const DAG_NORMALIZED_FAILURE_CATEGORY_VALUES = [
10
+ "success",
11
+ "validation",
12
+ "executor",
13
+ "write-guard",
14
+ "timeout",
15
+ "auth",
16
+ "human-required",
17
+ "human-rejected",
18
+ "shell-command",
19
+ "static-error",
20
+ "decision-envelope",
21
+ "skipped",
22
+ "unknown",
23
+ ];
24
+ const RAW_TO_NORMALIZED = {
25
+ success: "success",
26
+ "write-guard": "write-guard",
27
+ timeout: "timeout",
28
+ // Clean implementer stall with zero writes — still a timeout class for report,
29
+ // but retryable under WRITER_TRANSPORT_RETRY_POLICY.
30
+ "writer-clean-timeout": "timeout",
31
+ "missing-api-key": "auth",
32
+ auth: "auth",
33
+ "human-rejected": "human-rejected",
34
+ "human-required": "human-required",
35
+ "decision-envelope-invalid": "decision-envelope",
36
+ "nonzero-exit": "shell-command",
37
+ "spawn-error": "shell-command",
38
+ "test-timeout": "timeout",
39
+ "static-error": "static-error",
40
+ "invalid-output": "validation",
41
+ "structured-output-truncated": "validation",
42
+ "output-too-large": "validation",
43
+ "structured-repair-exhausted": "validation",
44
+ "governance-blocked": "validation",
45
+ "path-violation": "validation",
46
+ "empty-output": "validation",
47
+ "verify-failure": "validation",
48
+ "test-failure": "validation",
49
+ "verification-plan-stale": "validation",
50
+ "read-burst": "validation",
51
+ // Writer persisted real file changes but the final provider call hit a
52
+ // context overflow; verification never ran. Distinct from empty-output so
53
+ // the report shows partial success instead of a spec issue.
54
+ "partial-success-with-context-overflow": "validation",
55
+ // Writer burned an excessive token budget (unconverged read-edit-test loop)
56
+ // and still failed; distinct from empty-output for accurate reporting.
57
+ "writer-budget-exhausted": "validation",
58
+ network: "executor",
59
+ quota: "executor",
60
+ "rate-limit": "executor",
61
+ unavailable: "executor",
62
+ // Context window overflow (400 request-too-large): the session needs
63
+ // compaction / fresh context before retrying — an executor-side
64
+ // environment condition, not a plan-quality defect.
65
+ "context-overflow": "executor",
66
+ // Deterministic capability/policy refusal: missing verified launcher JS
67
+ // entry, capability allowlist rejection, or missing bounded write tool
68
+ // profile. These are environment/config defects the operator repairs
69
+ // before rerunning; classify as executor so recovery recommends
70
+ // rerun-after-fix WITHOUT forcing a human-decision gate on
71
+ // standaloneTaskRerun (run-failed same-task rerun).
72
+ "tool-policy": "executor",
73
+ unknown: "unknown",
74
+ };
75
+ /** Status inputs are deliberately `string`: projection layers pass bounded
76
+ * text from CLI JSON; unmatched values simply fall through to unknown. */
77
+ function isFinishedStatus(status) {
78
+ return status === "FINISHED" || status === "finished";
79
+ }
80
+ function isInProgressStatus(status) {
81
+ return (status === "PENDING" ||
82
+ status === "RUNNING" ||
83
+ status === "pending" ||
84
+ status === "running");
85
+ }
86
+ function isFailureStatus(status) {
87
+ return (status === "ERROR" ||
88
+ status === "failed" ||
89
+ status === "partial_failed");
90
+ }
91
+ function mapRawCategory(raw) {
92
+ const direct = RAW_TO_NORMALIZED[raw];
93
+ if (direct)
94
+ return direct;
95
+ const lower = raw.toLowerCase();
96
+ if (lower.includes("timeout"))
97
+ return "timeout";
98
+ if (lower.includes("validation") ||
99
+ lower.includes("invalid") ||
100
+ lower.includes("verification-plan-stale") ||
101
+ lower.includes("plan-stale"))
102
+ return "validation";
103
+ if (lower.includes("auth") || lower.includes("api-key"))
104
+ return "auth";
105
+ if (lower.includes("write-guard") || lower.includes("write_guard"))
106
+ return "write-guard";
107
+ if (lower.includes("decision-envelope") || lower.includes("decision_envelope"))
108
+ return "decision-envelope";
109
+ if (lower.includes("human-rejected"))
110
+ return "human-rejected";
111
+ if (lower.includes("human-required"))
112
+ return "human-required";
113
+ if (lower.includes("static-error"))
114
+ return "static-error";
115
+ if (lower.includes("nonzero-exit") ||
116
+ lower.includes("spawn-error") ||
117
+ lower.includes("shell"))
118
+ return "shell-command";
119
+ return undefined;
120
+ }
121
+ export function isDagFailureCategory(value) {
122
+ return DAG_NORMALIZED_FAILURE_CATEGORY_VALUES.includes(value);
123
+ }
124
+ export function normalizeDagFailureCategory(raw, status) {
125
+ if (status === "SKIPPED") {
126
+ return "skipped";
127
+ }
128
+ if (raw !== undefined) {
129
+ const mapped = mapRawCategory(raw);
130
+ if (mapped) {
131
+ if (mapped === "success") {
132
+ return isFinishedStatus(status) ? "success" : "unknown";
133
+ }
134
+ return mapped;
135
+ }
136
+ }
137
+ if (raw === undefined && isFinishedStatus(status)) {
138
+ return "success";
139
+ }
140
+ if (isInProgressStatus(status)) {
141
+ return "unknown";
142
+ }
143
+ if (isFailureStatus(status)) {
144
+ return "unknown";
145
+ }
146
+ if (raw === "success" && isFinishedStatus(status)) {
147
+ return "success";
148
+ }
149
+ return "unknown";
150
+ }
@@ -101,6 +101,12 @@ export const frontendOpenspecConfigSchema = z.object({
101
101
  /** Batch limits and gate profile for the browser-driven frontend test DAG.
102
102
  * Token fields are post-case stop thresholds, not model-provider hard caps. */
103
103
  export const frontendTestConfigSchema = z.object({
104
+ /**
105
+ * Repository-relative frontend-test artifact root.
106
+ * Default "testcase/frontend". Semantic validation lives in
107
+ * resolveFrontendTestLayout (fail-closed), not in this schema.
108
+ */
109
+ testRoot: z.string().min(1).optional(),
104
110
  maxCasesPerBatch: z.number().int().min(1).max(50).optional(),
105
111
  maxTokensPerCase: z.number().int().positive().optional(),
106
112
  maxTotalTokens: z.number().int().positive().optional(),
@@ -133,9 +133,28 @@ export async function listOpenspecDiscovery(repoRoot, options = {}) {
133
133
  .filter(Boolean);
134
134
  const collected = [];
135
135
  let excludedGovernanceCount = 0;
136
+ // Metadata / bookkeeping directories that are not normative design specs:
137
+ // changelogs, ADR/history archives, proposals under review, and scratch
138
+ // state. Reading them inflates the candidate list (and the plan prompt)
139
+ // with files no component selection should cite. A task that genuinely
140
+ // needs one can still reference it explicitly — the prewrite gate
141
+ // candidates come from this discovery, but explicit task-source citations
142
+ // flow through openspecMandatoryPaths independently.
143
+ const DEFAULT_EXCLUDED_SPEC_PREFIXES = [
144
+ "openspec/changes",
145
+ "openspec/project-specs/changes",
146
+ "openspec/project-specs/changelog",
147
+ "openspec/project-specs/history",
148
+ "openspec/project-specs/archive",
149
+ "openspec/project-specs/decisions",
150
+ "openspec/project-specs/proposals",
151
+ ];
136
152
  const isExcluded = (rel) => {
137
153
  if (isGovernanceSubtreePath(rel, governanceRoot))
138
154
  return true;
155
+ if (DEFAULT_EXCLUDED_SPEC_PREFIXES.some((prefix) => rel === prefix || rel.startsWith(prefix + "/"))) {
156
+ return true;
157
+ }
139
158
  return extraExcludedPrefixes.some((prefix) => rel === prefix || rel.startsWith(prefix + "/"));
140
159
  };
141
160
  for (const specDir of options.specRoots ?? [...OPENSPEC_SPEC_DIRS]) {
@@ -22,6 +22,18 @@ function slugifyName(value) {
22
22
  .replace(/-{2,}/g, "-");
23
23
  return slug || "requirement";
24
24
  }
25
+ /** Stable identity of a manifest document for change detection. Timestamps and
26
+ * byte sizes are excluded: identical content re-imported later must not appear
27
+ * "changed" (the canonical hash includes manifest bytes). */
28
+ function documentIdentity(doc) {
29
+ return `${doc.role}|${doc.name}|${doc.materializedPath}|${doc.sha256}`;
30
+ }
31
+ function sameDocumentSet(left, right) {
32
+ if (left.length !== right.length)
33
+ return false;
34
+ const rightIds = new Set(right.map(documentIdentity));
35
+ return left.every((doc) => rightIds.has(documentIdentity(doc)));
36
+ }
25
37
  function ensureUniqueReferenceName(existing, baseName, extension) {
26
38
  const used = new Set(existing);
27
39
  const candidate = `${baseName}${extension}`;
@@ -149,10 +161,19 @@ export async function importPrdDocument(input) {
149
161
  const documents = [...(existingManifest?.documents ?? [])].filter((entry) => entry.materializedPath !== materializedRelativePath);
150
162
  documents.push(document);
151
163
  documents.sort((left, right) => left.materializedPath.localeCompare(right.materializedPath));
164
+ // Keep `updatedAt` stable across re-imports of the same content: the
165
+ // canonical contract hash includes the manifest bytes, so a fresh
166
+ // timestamp on every identical re-import would make the observed
167
+ // canonical hash drift and fail task verification. Only bump it when the
168
+ // document set actually changed (a new/changed materialized file).
169
+ const documentSetChanged = !existingManifest ||
170
+ !sameDocumentSet(existingManifest.documents, documents);
152
171
  const manifest = {
153
172
  schemaVersion: 1,
154
173
  taskId: input.taskId,
155
- updatedAt: importedAt,
174
+ updatedAt: documentSetChanged
175
+ ? importedAt
176
+ : (existingManifest?.updatedAt ?? importedAt),
156
177
  documents,
157
178
  };
158
179
  await writeSourceManifest(paths.sourceDir, manifest);
@@ -64,7 +64,14 @@ function safeRunSummary(value) {
64
64
  const status = String(node.status ?? "");
65
65
  if (!id || !status)
66
66
  return [];
67
- return [{ id, status }];
67
+ const failureCategory = String(node.failureCategory ?? "");
68
+ return [
69
+ {
70
+ id,
71
+ status,
72
+ ...(failureCategory ? { failureCategory } : {}),
73
+ },
74
+ ];
68
75
  })
69
76
  .slice(0, 20);
70
77
  }
@@ -728,13 +728,15 @@ export async function handlePutDeferredTurn(req, res, deps, sessionId) {
728
728
  return;
729
729
  }
730
730
  const active = deps.events.getActiveTurn(sessionId);
731
- if (!active || !active.abortRequestedAt || active.turnId !== blockedByTurnId) {
731
+ // Queueing binds to the active Turn (running OR stopping); the durable
732
+ // follow-up auto-dispatches when that Turn reaches a terminal state.
733
+ if (!active || active.turnId !== blockedByTurnId) {
732
734
  sendJson(res, 409, {
733
735
  ok: false,
734
736
  accepted: false,
735
737
  error: {
736
- code: "TURN_NOT_STOPPING",
737
- message: "只有仍在停止中的当前 Turn 可以保存停止后发送消息",
738
+ code: "TURN_NOT_ACTIVE",
739
+ message: "没有匹配的运行中 Turn,无法保存待发送消息",
738
740
  },
739
741
  activeTurn: active ? turnSummary(active) : null,
740
742
  });
@@ -80,3 +80,21 @@ export function pickInspectNode(nodes, preferredNodeId) {
80
80
  });
81
81
  return running ?? nodes[0];
82
82
  }
83
+ /**
84
+ * Terminal DagRun effective/status values (mirrors observe read-model
85
+ * TERMINAL_RUN_STATUSES). A run that reached one of these states no longer
86
+ * needs live polling in the console split panel.
87
+ */
88
+ export const TERMINAL_DAG_RUN_STATUSES = new Set([
89
+ "finished",
90
+ "failed",
91
+ "partial_failed",
92
+ "superseded",
93
+ "abandoned",
94
+ ]);
95
+ export function isTerminalDagRun(dag) {
96
+ if (!dag)
97
+ return false;
98
+ const status = String(dag.effectiveStatus ?? dag.status ?? "").toLowerCase();
99
+ return TERMINAL_DAG_RUN_STATUSES.has(status);
100
+ }
@@ -13,6 +13,7 @@
13
13
  * - A run summary is a projection only: it can never change the terminal
14
14
  * operation state decided by the command envelope/exit facts.
15
15
  */
16
+ import { normalizeDagFailureCategory } from "../../shared/dag-failure-category.js";
16
17
  import { scrubSecrets } from "./chat/explore-tools.js";
17
18
  const RUN_SUMMARY_MAX_NODES = 20;
18
19
  const RUN_SUMMARY_MAX_TEXT_CHARS = 600;
@@ -72,7 +73,13 @@ function safeNode(value) {
72
73
  const status = boundedRedactedText(rec.status, 100);
73
74
  if (!id || !status)
74
75
  return undefined;
75
- return { id, status };
76
+ const rawCategory = boundedRedactedText(rec.failureCategory, 200);
77
+ if (!rawCategory)
78
+ return { id, status };
79
+ const category = normalizeDagFailureCategory(rawCategory, status);
80
+ if (category === "success" || category === "skipped")
81
+ return { id, status };
82
+ return { id, status, failureCategory: category };
76
83
  }
77
84
  /** Independent allowlist projection of a structured run summary. */
78
85
  export function safeRunSummaryForProjection(value) {
@@ -117,13 +124,22 @@ export function safeRunSummaryForProjection(value) {
117
124
  }
118
125
  }
119
126
  const verdict = boundedRedactedText(rec.verdict);
120
- const failureCategory = boundedRedactedText(rec.failureCategory);
127
+ const rawFailureCategory = boundedRedactedText(rec.failureCategory, 200);
128
+ // Normalize the run-level category too (2026-08-23): raw codes like
129
+ // missing-api-key / nonzero-exit never matched the browser advice table.
130
+ const failureCategory = rawFailureCategory !== undefined
131
+ ? normalizeDagFailureCategory(rawFailureCategory, status)
132
+ : undefined;
121
133
  return {
122
134
  runId,
123
135
  status,
124
136
  nodes,
125
137
  ...(verdict !== undefined ? { verdict } : {}),
126
- ...(failureCategory !== undefined ? { failureCategory } : {}),
138
+ ...(failureCategory !== undefined &&
139
+ failureCategory !== "success" &&
140
+ failureCategory !== "skipped"
141
+ ? { failureCategory }
142
+ : {}),
127
143
  ...(outOfBounds.length > 0 ? { outOfBounds } : {}),
128
144
  ...(next ? { next } : {}),
129
145
  };
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-Dz29Ye_f.js";import{p as f}from"./chunk-JWPE2WC7-CIoGkxdu.js";import{_ as n,l as o}from"./mermaid.core-C-D3ZRUa.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BSCtQpD7.js";import"./index-D5zGX6fG.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
1
+ import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-Bw9nFjCJ.js";import{p as f}from"./chunk-JWPE2WC7-Dt75ZdBD.js";import{_ as n,l as o}from"./mermaid.core-BlvpGVG8.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-eTOts9L1.js";import"./index-DBh_x_Ek.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
@@ -1 +1 @@
1
- import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-C-D3ZRUa.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
1
+ import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-BlvpGVG8.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};