@tea-agent/loop-agent 0.39.0-next.21 → 0.39.0-next.23

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 (79) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/application/task-lifecycle/advance.js +4 -0
  3. package/dist/build-stamp.json +2 -2
  4. package/dist/commands/task-advance.js +31 -0
  5. package/dist/executors/shell-executor.js +1 -1
  6. package/dist/task/contract/constants.js +1 -0
  7. package/dist/task/contract/diff.js +26 -0
  8. package/dist/task/contract/project.js +5 -0
  9. package/dist/task/contract/schema.js +6 -1
  10. package/dist/task/source-prepare/build-draft.js +15 -0
  11. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4bmo3iY.js → abnfDiagram-N423BO3Z-tnlecWET.js} +1 -1
  12. package/dist/worker/console/static/assets/{arc-SAD7McOS.js → arc-LVmtsShq.js} +1 -1
  13. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DAVLUdK1.js → architectureDiagram-T3A2C74G-Bot2nhjX.js} +1 -1
  14. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CPPdv4vj.js → blockDiagram-VBNYF7ZC-B8wcEMRC.js} +1 -1
  15. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-D1GRGZax.js → c4Diagram-5PPSVZJV-Cj4_jsBk.js} +1 -1
  16. package/dist/worker/console/static/assets/channel-Bor-DZxZ.js +1 -0
  17. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-D_Bq2ZqK.js → chunk-2GRJ4B5K-indAMcNl.js} +1 -1
  18. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-CPLVtamK.js → chunk-2Q5K7J3B-BoVy7yeK.js} +1 -1
  19. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DnaZWcL3.js → chunk-5RXB4S5H-BluRngmE.js} +1 -1
  20. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BRTmFgnq.js → chunk-5VM5RSS4-DyBfxRXh.js} +1 -1
  21. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BRlfYZoH.js → chunk-6Q2QTUOP-DEQqTXL2.js} +1 -1
  22. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CjNybD4u.js → chunk-GF5L2VYU-KUGA4ndX.js} +1 -1
  23. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-D3e-74fG.js → chunk-JWPE2WC7-DfXKSh2I.js} +1 -1
  24. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-Br3ir6f2.js → chunk-KBJHAD2P-BSnwJm3J.js} +1 -1
  25. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-1NgVuRbh.js → chunk-RYQCIY6F-DeEfgdtO.js} +1 -1
  26. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-BTYuvuWN.js → chunk-XXDRQBXY-avXbO4RW.js} +1 -1
  27. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Cztq0Lcf.js +1 -0
  28. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Cztq0Lcf.js +1 -0
  29. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BC6Bgosf.js → cose-bilkent-JH36ORCC-CpfsIlv4.js} +1 -1
  30. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-DV-HypfL.js → cynefin-VYW2F7L2-Bspf3ng8.js} +1 -1
  31. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-DhTaddO-.js → cynefinDiagram-MW4NZA55-BJGfcaVQ.js} +1 -1
  32. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BnEcOmiI.js → dagre-VZM6K2ZE-DvBTZtam.js} +1 -1
  33. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-xphGRVKp.js → diagram-7IWD3JNH-BUJCj_7u.js} +1 -1
  34. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CrdD1mRG.js → diagram-B4RE2ZJO-CrpLm_RP.js} +1 -1
  35. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-D4YdLsaF.js → diagram-LBJQPF4R-Dt5sd0fM.js} +1 -1
  36. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-LCKyGZ5U.js → diagram-Q27KOJAE-FE0WGVt3.js} +1 -1
  37. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BeiTe7t0.js → diagram-UB23O5K3-C22W8Vsw.js} +1 -1
  38. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BO2cq8GS.js → ebnfDiagram-BXEA7PRR-Dug0ybod.js} +1 -1
  39. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-CmWww3Nt.js → erDiagram-JOGREHBK-Muy74GVP.js} +1 -1
  40. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-C2kkUYg5.js → flowDiagram-UKHOOZJN-Dg7DfZPD.js} +1 -1
  41. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DY_JZ2iQ.js → ganttDiagram-PKOTCBZU-BgDMbjEX.js} +1 -1
  42. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-BizhCSw9.js → gitGraphDiagram-DS77QQ5N-CCwz0FDR.js} +1 -1
  43. package/dist/worker/console/static/assets/{index-BXN89VPX.js → index-CnJwuIKx.js} +142 -63
  44. package/dist/worker/console/static/assets/index-Ya5FE7cD.css +1 -0
  45. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-Dlo2eK_d.js → infoDiagram-6WML65LV-DQfSRCnK.js} +1 -1
  46. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-3EIlIIuZ.js → ishikawaDiagram-WSZJBQD7-DbP56Q0A.js} +1 -1
  47. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DiMDe5Yh.js → journeyDiagram-NVQOT4AX-DnU6-oGf.js} +1 -1
  48. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-sN553oIN.js → kanban-definition-27J2QSJJ-D20nWOTw.js} +1 -1
  49. package/dist/worker/console/static/assets/{linear-D9Py31Ld.js → linear-BF_t08wv.js} +1 -1
  50. package/dist/worker/console/static/assets/{mermaid.core-D7Occzk_.js → mermaid.core-DTwZdcUQ.js} +5 -5
  51. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DjDRboiR.js → mindmap-definition-FAOFIHXS-CgABKTml.js} +1 -1
  52. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-Cgc4qlzp.js → pegDiagram-VL7TDLO6-KF8xVdyI.js} +1 -1
  53. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DxZj8pKd.js → pieDiagram-7S7Q4E2Y-kdvBlmug.js} +1 -1
  54. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-CJ50MngR.js → quadrantDiagram-CIZ2JOQS-Dz_5Gx-J.js} +1 -1
  55. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BY-OD8Tr.js → railroadDiagram-AXF67PYL-CoUkUsjS.js} +1 -1
  56. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-CQFButfK.js → requirementDiagram-LRYGKXZP-Cp0SKNOb.js} +1 -1
  57. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-BB_QUK_b.js → sankeyDiagram-W5VNT64P-nvgfxhl4.js} +1 -1
  58. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-CqhXZjyx.js → sequenceDiagram-SI44F4Z6-DUyqpiIH.js} +1 -1
  59. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-2l1U4rgJ.js → sizeCapture-X5ZJPWSS-FCodLTFq.js} +1 -1
  60. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-BX1FbrhJ.js → stateDiagram-OKZ733FA-NVAbafR9.js} +1 -1
  61. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-j9D1xnHc.js +1 -0
  62. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DOSnT7hb.js → swimlanes-SLNWSIFB-H29rigTf.js} +2 -2
  63. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DQ4huT5W.js +8 -0
  64. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-DVJQA7AN.js → timeline-definition-Z64GVDOM-CNFQjoyV.js} +1 -1
  65. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-74uxl9gx.js → vennDiagram-T6HMQDX7-BWf8nCZL.js} +1 -1
  66. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DsBxlcg_.js → wardleyDiagram-T6FBY63Y-D58QQyvD.js} +1 -1
  67. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-snuW9Mjw.js → xychartDiagram-ELKLHX3M-DjF1qJhp.js} +1 -1
  68. package/dist/worker/console/static/index.html +2 -2
  69. package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +328 -0
  70. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +2 -2
  71. package/dist/workflows/dag/frontend-prewrite-gate.js +6 -3
  72. package/dist/workflows/dag/init-hybrid.js +25 -5
  73. package/package.json +1 -1
  74. package/dist/worker/console/static/assets/channel-R6oQIDkw.js +0 -1
  75. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BPXlmPWI.js +0 -1
  76. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BPXlmPWI.js +0 -1
  77. package/dist/worker/console/static/assets/index-CuH5CNFu.css +0 -1
  78. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DJKi0Qel.js +0 -1
  79. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-YYe7EEm5.js +0 -8
package/CHANGELOG.md CHANGED
@@ -8,6 +8,8 @@
8
8
 
9
9
  ### 新增
10
10
 
11
+ - `backendTest` 布局配置纳入 Task Contract managed 注入面:`task advance` 新增 `--backend-test <json>`,可在公共任务生命周期内把 `testRoot`/`markdownRel`/`scriptRel`/`sharedSetupDoc`/`mode`/`gapDoc`/`executeScope` 写进 `task.json`,不再需要手工编辑(手工编辑会让任务漂移成 `externally-modified` 并拒绝 `--approve-gate`)。给出即整体替换、省略即保留既有配置(历史手写配置因此自愈)、`'{}'` 为显式清空回默认布局;重复 advance 幂等,契约保持 `managed`。`task contract diff` 把值变更标 routine `BACKEND_TEST_CONFIG_CHANGED`、丢键/清空额外标 elevated `BACKEND_TEST_CONFIG_WEAKENED`。
12
+ - Operator Chat 文件预览抽屉新增图标「新窗口打开」:用当前已加载内容在独立浏览器窗口打开全页阅读视图,窗口内可切换「预览 / 查看原文」(带宽高的 `window.open` popup,Markdown 排版、HTML 铺满视口的空 sandbox iframe、JSON pretty-print / 其它文本等宽滚动);打开成功后断开 `opener` 且不立刻 revoke Blob,避免空白页;弹窗被拦截时 header 附近报错且不关闭抽屉
11
13
  - backend-test 适配 A–D:可配置 `backendTest` 布局(`testRoot`/`markdownRel`/`scriptRel`)、用户公共前置文档引用与模块顶部 `user_shared_setup`(不写 conftest)、查询轴 Scenario Partitions 确定性展开与 fail-closed 门禁、`mode=gap-fill` 13 节点增量 DAG。Slot ID 以声明的 Partition ID 为真源(`TP-<Partition ID>-...`)。
12
14
  - 前端 plan 唯一机器契约化(JSON-only):`frontend-plan-pi` / `frontend-plan-revision-pi` 输出收敛为「一行导语 + 唯一 fenced `json` 契约 + 唯一 `openspec-citations` 引用块」,彻底移除「可选 Markdown 说明」;plan.md(`contracts/frontend-plan.md`)改由 prewrite gate 用纯函数 `renderFrontendPlanMarkdown` 确定性渲染(不新增 DAG 节点/不新增 Pi 调用)
13
15
  - 契约 schema 新增 5 个可选字段(`implementationSteps` / `stylingStrategy` / `dependencyPolicy` / `residualRisks` / `realIntegrationGap`),`schemaVersion` 保持 1;`docs/templates/frontend-implementation-contract.schema.json` 同步
@@ -38,6 +38,7 @@ function hasEngineeringBoundary(input) {
38
38
  return Boolean((input.allowedPaths && input.allowedPaths.length > 0) ||
39
39
  (input.forbiddenPaths && input.forbiddenPaths.length > 0) ||
40
40
  (input.verifyCommands && input.verifyCommands.length > 0) ||
41
+ input.backendTest !== undefined ||
41
42
  input.fromText ||
42
43
  input.fromDraftPath);
43
44
  }
@@ -632,6 +633,7 @@ export async function advanceTaskLifecycle(input) {
632
633
  allowedPaths: effectiveInput.allowedPaths,
633
634
  forbiddenPaths: input.forbiddenPaths,
634
635
  verifyCommands: effectiveInput.verifyCommands,
636
+ backendTest: input.backendTest,
635
637
  },
636
638
  });
637
639
  if (!prepareResult.ok) {
@@ -687,6 +689,7 @@ export async function advanceTaskLifecycle(input) {
687
689
  allowedPaths: effectiveInput.allowedPaths,
688
690
  forbiddenPaths: input.forbiddenPaths,
689
691
  verifyCommands: effectiveInput.verifyCommands,
692
+ backendTest: input.backendTest,
690
693
  },
691
694
  });
692
695
  if (semantic.ok) {
@@ -707,6 +710,7 @@ export async function advanceTaskLifecycle(input) {
707
710
  allowedPaths: effectiveInput.allowedPaths,
708
711
  forbiddenPaths: input.forbiddenPaths,
709
712
  verifyCommands: effectiveInput.verifyCommands,
713
+ backendTest: input.backendTest,
710
714
  },
711
715
  });
712
716
  if (retry.ok) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "version": "0.37.0",
4
- "gitSha": "8512d440d297980cf2bcb7f4d77f3520950ee051",
5
- "builtAt": "2026-08-19T17:24:57.980Z"
4
+ "gitSha": "6f966ef01852a18f0ca1dd0a2f9a69ae45844b28",
5
+ "builtAt": "2026-08-20T09:15:26.353Z"
6
6
  }
@@ -1,4 +1,5 @@
1
1
  import { advanceTaskLifecycle, } from "../application/task-lifecycle/index.js";
2
+ import { backendTestConfigSchema, } from "../task/config-types.js";
2
3
  import { buildOperatorResult, operatorFailed, processExitCodeForOutcome, writeOperatorJson, } from "../shared/operator/index.js";
3
4
  import { createRunDagProgressObserver, validateRunDagProgressIntervalMs, } from "./run-dag-progress.js";
4
5
  const COMMAND = "task advance";
@@ -14,6 +15,7 @@ const USAGE = `usage:
14
15
  [--forbidden-path <glob>]...
15
16
  [--verify <label:command>]...
16
17
  [--verify-timeout <label:timeoutMs>]...
18
+ [--backend-test <json>]
17
19
  [--accept-recommendations <digest>]
18
20
  [--approve-gate <gate-id:digest>]
19
21
  [--reject-gate <gate-id:digest> --reason <text>]
@@ -52,6 +54,30 @@ function parseVerifyTimeout(flag) {
52
54
  }
53
55
  return { label: flag.slice(0, idx), timeoutMs };
54
56
  }
57
+ /**
58
+ * Parse `--backend-test <json>` into a validated managed backendTest config.
59
+ * `{}` is legal (explicit clear back to the default layout).
60
+ */
61
+ function parseBackendTestFlag(raw) {
62
+ let parsed;
63
+ try {
64
+ parsed = JSON.parse(raw);
65
+ }
66
+ catch {
67
+ throw new Error(`invalid --backend-test ${raw}; expected an inline JSON object`);
68
+ }
69
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
70
+ throw new Error(`invalid --backend-test ${raw}; expected an inline JSON object`);
71
+ }
72
+ const result = backendTestConfigSchema.safeParse(parsed);
73
+ if (!result.success) {
74
+ const summary = result.error.issues
75
+ .map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`)
76
+ .join("; ");
77
+ throw new Error(`invalid --backend-test: ${summary}`);
78
+ }
79
+ return result.data ?? {};
80
+ }
55
81
  export function parseTaskAdvanceArgs(args) {
56
82
  const options = {};
57
83
  const positional = [];
@@ -113,6 +139,10 @@ export function parseTaskAdvanceArgs(args) {
113
139
  options.verifyTimeout = pushList(options.verifyTimeout, next());
114
140
  continue;
115
141
  }
142
+ if (token === "--backend-test") {
143
+ options.backendTest = parseBackendTestFlag(next());
144
+ continue;
145
+ }
116
146
  if (token === "--accept-recommendations") {
117
147
  options.acceptRecommendations = next();
118
148
  continue;
@@ -273,6 +303,7 @@ export function toUseCaseInput(repoRoot, taskId, options, observer) {
273
303
  allowedPaths: options.allowedPaths,
274
304
  forbiddenPaths: options.forbiddenPaths,
275
305
  verifyCommands: verifyCommands.length > 0 ? verifyCommands : undefined,
306
+ backendTest: options.backendTest,
276
307
  approveGateToken: options.approveGate,
277
308
  rejectGateToken: options.rejectGate,
278
309
  rejectReason: options.reason,
@@ -877,7 +877,7 @@ async function executeBackendTestPipeline(input, meta) {
877
877
  });
878
878
  }
879
879
  else if (initial.status === "REPAIRABLE") {
880
- const mappedScripts = await collectBackendTestMappedPytestScripts(input.cwd);
880
+ const mappedScripts = await collectBackendTestMappedPytestScripts(input.cwd, backendLayout);
881
881
  const scenario = await runBackendScenarioParamPreflight({
882
882
  workspaceRoot: input.cwd,
883
883
  runDir: meta.runDir,
@@ -17,6 +17,7 @@ export const MANAGED_TASK_CONFIG_FIELDS = [
17
17
  "forbiddenPaths",
18
18
  "hardConstraints",
19
19
  "verifyCommands",
20
+ "backendTest",
20
21
  ];
21
22
  export const CONTRACT_FILE_NAME = "contract.json";
22
23
  export const TRANSACTIONS_DIR_NAME = ".transactions";
@@ -1,3 +1,4 @@
1
+ import { canonicalizeJsonValue } from "./canonicalize.js";
1
2
  import { MANAGED_TASK_CONFIG_FIELDS } from "./constants.js";
2
3
  function maxRisk(a, b) {
3
4
  const order = ["routine", "elevated", "blocking"];
@@ -139,6 +140,31 @@ export function diffDraftAgainstCurrent(input) {
139
140
  path: "task.json#featureId",
140
141
  });
141
142
  }
143
+ // backendTest is managed whole-object: an absent draft value means
144
+ // "keep existing" and never diffs; declared values compare canonically.
145
+ if (input.draft.backendTest !== undefined) {
146
+ const before = cfg.backendTest ?? {};
147
+ const after = input.draft.backendTest;
148
+ if (canonicalizeJsonValue(before) !== canonicalizeJsonValue(after)) {
149
+ changedManagedFields.push("backendTest");
150
+ risks.push({
151
+ code: "BACKEND_TEST_CONFIG_CHANGED",
152
+ level: "routine",
153
+ message: "backendTest configuration changed",
154
+ path: "task.json#backendTest",
155
+ });
156
+ const afterKeys = new Set(Object.keys(after));
157
+ const droppedKeys = Object.keys(before).filter((key) => !afterKeys.has(key));
158
+ if (droppedKeys.length > 0) {
159
+ risks.push({
160
+ code: "BACKEND_TEST_CONFIG_WEAKENED",
161
+ level: "elevated",
162
+ message: `drop backendTest keys: ${droppedKeys.sort().join(", ")}`,
163
+ path: "task.json#backendTest",
164
+ });
165
+ }
166
+ }
167
+ }
142
168
  }
143
169
  else {
144
170
  for (const field of MANAGED_TASK_CONFIG_FIELDS) {
@@ -174,6 +174,11 @@ export function mergeManagedTaskConfigFields(existing, draft) {
174
174
  if (draft.featureId !== undefined) {
175
175
  next.featureId = draft.featureId;
176
176
  }
177
+ // backendTest is whole-object replace when the draft declares it (`{}` is a
178
+ // legal explicit clear back to the default layout); absent keeps existing.
179
+ if (draft.backendTest !== undefined) {
180
+ next.backendTest = draft.backendTest;
181
+ }
177
182
  return next;
178
183
  }
179
184
  /**
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { taskKindSchema, taskVerifyCommandSchema } from "../config-types.js";
2
+ import { backendTestConfigSchema, taskKindSchema, taskVerifyCommandSchema, } from "../config-types.js";
3
3
  import { TASK_CONFIG_SCHEMA_VERSION, TASK_CONTRACT_CANONICALIZER_VERSION, TASK_CONTRACT_DRAFT_SCHEMA_VERSION, TASK_CONTRACT_PROJECTION_VERSION, TASK_CONTRACT_REF_SCHEMA_VERSION, } from "./constants.js";
4
4
  const sha256Schema = z
5
5
  .string()
@@ -62,6 +62,11 @@ export const taskContractDraftSchema = z
62
62
  requirement: taskContractDraftRequirementSchema,
63
63
  constraints: taskContractDraftConstraintsSchema,
64
64
  verification: taskContractDraftVerificationSchema,
65
+ /**
66
+ * Managed backend-test layout / pipeline configuration projected into
67
+ * task.json#backendTest. Optional: absent means "keep existing".
68
+ */
69
+ backendTest: backendTestConfigSchema,
65
70
  references: z.array(taskContractDraftReferenceSchema).optional(),
66
71
  sourceResolutions: z
67
72
  .array(taskContractDraftSourceResolutionSchema)
@@ -22,6 +22,18 @@ function resolveTaskKindExplicit(flags, baseDraft) {
22
22
  return flags.taskKindExplicit;
23
23
  return baseDraft?.taskKindExplicit ?? false;
24
24
  }
25
+ /**
26
+ * Resolve managed backend-test layout config.
27
+ * Precedence: explicit CLI flags > --from-draft base > existing task.json
28
+ * (the last tier self-heals tasks whose backendTest was hand-written).
29
+ */
30
+ function resolveBackendTest(flags, baseDraft, existing) {
31
+ if (flags.backendTest !== undefined)
32
+ return flags.backendTest;
33
+ if (baseDraft?.backendTest !== undefined)
34
+ return baseDraft.backendTest;
35
+ return existing?.backendTest ?? undefined;
36
+ }
25
37
  function resolveTitle(taskId, flags, facts, baseDraft, existing) {
26
38
  return (trimNonEmpty(flags.title) ??
27
39
  trimNonEmpty(baseDraft?.title) ??
@@ -205,6 +217,9 @@ export function buildPrepareDraft(input) {
205
217
  };
206
218
  if (featureId)
207
219
  draft.featureId = featureId;
220
+ const backendTest = resolveBackendTest(flags, baseDraft, existingTaskConfig);
221
+ if (backendTest !== undefined)
222
+ draft.backendTest = backendTest;
208
223
  if (references && references.length > 0) {
209
224
  draft.references = references.map((ref) => ({
210
225
  role: ref.role,
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-BRlfYZoH.js";import{p as f}from"./chunk-JWPE2WC7-D3e-74fG.js";import{_ as n,l as o}from"./mermaid.core-D7Occzk_.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-DV-HypfL.js";import"./index-BXN89VPX.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-DEQqTXL2.js";import{p as f}from"./chunk-JWPE2WC7-DfXKSh2I.js";import{_ as n,l as o}from"./mermaid.core-DTwZdcUQ.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-Bspf3ng8.js";import"./index-CnJwuIKx.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-D7Occzk_.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-DTwZdcUQ.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};