@tea-agent/loop-agent 0.40.0-next.7 → 0.40.0-next.9

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 (90) hide show
  1. package/CHANGELOG.md +106 -140
  2. package/dist/build-stamp.json +3 -3
  3. package/dist/executors/dag-pi-executor.js +3 -0
  4. package/dist/executors/pi-executor.js +4 -2
  5. package/dist/executors/pi-sdk-executor.js +46 -1
  6. package/dist/worker/console/chat/chat-event-store.js +13 -1
  7. package/dist/worker/console/chat/pi-runtime.js +70 -5
  8. package/dist/worker/console/chat/routes.js +99 -29
  9. package/dist/worker/console/chat/workspace-landing.js +65 -0
  10. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-DGt5TRsk.js → abnfDiagram-N423BO3Z-Bs-CDAXM.js} +1 -1
  11. package/dist/worker/console/static/assets/{arc-DKBSJsXm.js → arc-CAkA3We3.js} +1 -1
  12. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-BnhooRBs.js → architectureDiagram-T3A2C74G-DEmI_zqr.js} +1 -1
  13. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Bm9qkrJP.js → blockDiagram-VBNYF7ZC-uDHANebE.js} +1 -1
  14. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B2cFh4bO.js → c4Diagram-5PPSVZJV-Bv97b4_B.js} +1 -1
  15. package/dist/worker/console/static/assets/channel-amxUpk7o.js +1 -0
  16. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DhvWRI03.js → chunk-2GRJ4B5K-shmQKsFz.js} +1 -1
  17. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-chzTP_2w.js → chunk-2Q5K7J3B-BAraNvcN.js} +1 -1
  18. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-SdWIR12m.js → chunk-5RXB4S5H-BirhxUop.js} +1 -1
  19. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-C2-8Eo_A.js → chunk-5VM5RSS4-C9LgUJpR.js} +1 -1
  20. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DvbE1yQW.js → chunk-6Q2QTUOP-DrU-s-t7.js} +1 -1
  21. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CEenyPTz.js → chunk-GF5L2VYU-Tx-H_FA2.js} +1 -1
  22. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CcaZrq0k.js → chunk-JWPE2WC7-BjLtNFrR.js} +1 -1
  23. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-FGngOTto.js → chunk-KBJHAD2P-UNLVwSsy.js} +1 -1
  24. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-jT_yX3sf.js → chunk-RYQCIY6F-CBEUX8XD.js} +1 -1
  25. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CjE9LQOM.js → chunk-XXDRQBXY-WTL7IZOq.js} +1 -1
  26. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-bejwBVIz.js +1 -0
  27. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-bejwBVIz.js +1 -0
  28. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-GQWns1tb.js → cose-bilkent-JH36ORCC-CkHG6W3s.js} +1 -1
  29. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-CGRpxWNJ.js → cynefin-VYW2F7L2-BRzFqTaL.js} +1 -1
  30. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Cd3uFGE4.js → cynefinDiagram-MW4NZA55-2_CFp_i7.js} +1 -1
  31. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-DmDHuUW0.js → dagre-VZM6K2ZE-BJtsmdkE.js} +1 -1
  32. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-kAr--hF3.js → diagram-7IWD3JNH-DNEFFo6w.js} +1 -1
  33. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-woahL2Oh.js → diagram-B4RE2ZJO-B_IWV7eo.js} +1 -1
  34. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-7syNVaNf.js → diagram-LBJQPF4R-DvvRx2dz.js} +1 -1
  35. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BELPXiaY.js → diagram-Q27KOJAE-CsibsWLg.js} +1 -1
  36. package/dist/worker/console/static/assets/{diagram-UB23O5K3-CrPa4aXi.js → diagram-UB23O5K3-les_djBQ.js} +1 -1
  37. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-B48u2VVe.js → ebnfDiagram-BXEA7PRR-BEm2n7qJ.js} +1 -1
  38. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DhBTfwTF.js → erDiagram-JOGREHBK-BI7vHHVm.js} +1 -1
  39. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CAeZ5nDU.js → flowDiagram-UKHOOZJN-CUFCERrB.js} +1 -1
  40. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CkIFeFLN.js → ganttDiagram-PKOTCBZU-wxyLiGWt.js} +1 -1
  41. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-t0HGYDel.js → gitGraphDiagram-DS77QQ5N-Bt897K8Z.js} +1 -1
  42. package/dist/worker/console/static/assets/index-BHhUOTri.css +1 -0
  43. package/dist/worker/console/static/assets/index-DqJbO3-p.js +407 -0
  44. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-WM0HZhe4.js → infoDiagram-6WML65LV-DYNx_IPv.js} +1 -1
  45. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-CV5byHe0.js → ishikawaDiagram-WSZJBQD7-CzpLNEu6.js} +1 -1
  46. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-lIyWkgnw.js → journeyDiagram-NVQOT4AX-97f9owNU.js} +1 -1
  47. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BIH4YNRY.js → kanban-definition-27J2QSJJ-BxM9hyBn.js} +1 -1
  48. package/dist/worker/console/static/assets/{linear-lQ0ZGrWc.js → linear-ByuxcHvp.js} +1 -1
  49. package/dist/worker/console/static/assets/{mermaid.core-BYdXtke8.js → mermaid.core-DwPGvpCv.js} +5 -5
  50. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-k93vkIa4.js → mindmap-definition-FAOFIHXS-DCoqG9RT.js} +1 -1
  51. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-Bm6AqvSy.js → pegDiagram-VL7TDLO6-BLSBmBMx.js} +1 -1
  52. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DnJW6Xpf.js → pieDiagram-7S7Q4E2Y-B0t_0oJW.js} +1 -1
  53. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-CMzm4ObL.js → quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js} +1 -1
  54. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-fwFF5dFQ.js → railroadDiagram-AXF67PYL-B3jRdATC.js} +1 -1
  55. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-tzl9VDUc.js → requirementDiagram-LRYGKXZP-D-cTtXEN.js} +1 -1
  56. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B26V09DD.js → sankeyDiagram-W5VNT64P-B25igJRE.js} +1 -1
  57. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-D2npyCeP.js → sequenceDiagram-SI44F4Z6-jW_lM1_D.js} +1 -1
  58. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CTJtkRU2.js → sizeCapture-X5ZJPWSS-CrzTgsHE.js} +1 -1
  59. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-B8lk4Lzu.js → stateDiagram-OKZ733FA-B01MvlqE.js} +1 -1
  60. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BvFKEtm2.js +1 -0
  61. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-C3yP53hH.js → swimlanes-SLNWSIFB-YcF12FiU.js} +2 -2
  62. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DIB2eVg-.js +8 -0
  63. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Bck7xjhe.js → timeline-definition-Z64GVDOM-ClnRcg2s.js} +1 -1
  64. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-CCntr1w7.js → vennDiagram-T6HMQDX7-B6gr_z-q.js} +1 -1
  65. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DsCqCBZz.js → wardleyDiagram-T6FBY63Y-CvSgguGH.js} +1 -1
  66. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-Br2l90OM.js → xychartDiagram-ELKLHX3M-23OtSZCb.js} +1 -1
  67. package/dist/worker/console/static/index.html +2 -2
  68. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +33 -32
  69. package/dist/worker/console/static-src/operator-chat/compaction-message.js +79 -0
  70. package/dist/worker/console/static-src/operator-chat/spatial-overlay.js +1 -2
  71. package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +25 -0
  72. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +54 -56
  73. package/dist/worker/console/static-src/operator-chat/useChatStream.js +81 -27
  74. package/dist/worker/console/static-src/operator-chat/useChatThread.js +14 -25
  75. package/dist/worker/console/static-src/shell/workspace-route.js +7 -5
  76. package/dist/workflows/dag/backend-test-writer-completeness.js +7 -12
  77. package/dist/workflows/dag/init-hybrid.js +27 -5
  78. package/dist/workflows/dag/types.js +13 -0
  79. package/docs/templates/agent-dag.schema.json +18 -0
  80. package/docs/templates/backend-test-dag.json +22 -5
  81. package/package.json +1 -1
  82. package/dist/worker/console/static/assets/channel-DSgFX07x.js +0 -1
  83. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-unJObRls.js +0 -1
  84. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-unJObRls.js +0 -1
  85. package/dist/worker/console/static/assets/index-B4l5ag79.js +0 -407
  86. package/dist/worker/console/static/assets/index-CwVHWB71.css +0 -1
  87. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BmOcMTJE.js +0 -1
  88. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Beah-dq0.js +0 -8
  89. package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +0 -73
  90. package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +0 -59
@@ -4698,8 +4698,8 @@ async function buildBackendTestHybridDag(sources) {
4698
4698
  writePolicy: "read-only",
4699
4699
  allowedPaths: ro,
4700
4700
  forbiddenPaths: forbidden,
4701
- outputContract: "Stdout JSON {modules:[{stem}]} parsed from testcase/md/README.md using the same module-stem extractor as the Completeness Gate, so the map_agent shard set deterministically matches the Markdown module index.",
4702
- subtask_prompt: "Parse testcase/md/README.md and emit exactly one trailing JSON line {modules:[{stem}]} listing every trusted module stem (table-row testcase/md/<stem>.md mentions and canonical [label](./<stem>.md) relative links only). No file writes.",
4701
+ outputContract: "Stdout JSON {modules:[{stem,planReadPath}],planReadPath,planSha256} parsed from the run-owned Markdown plan artifact, so the pytest map shard set and every child planReadPath deterministically match the Markdown map manifest.",
4702
+ subtask_prompt: "Parse only the run-owned generate-backend-md-plan-pi/plan.md artifact and emit exactly one trailing JSON line {modules:[{stem,planReadPath}],planReadPath,planSha256}. Reuse the same plan-derived Module Index contract as the Markdown manifest; do not search for or fall back to testcase/**/README.md. No file writes.",
4703
4703
  shell: {
4704
4704
  commands: [buildBackendTestModuleManifestShellCommand(layout)],
4705
4705
  cwd: ".",
@@ -4770,6 +4770,12 @@ async function buildBackendTestHybridDag(sources) {
4770
4770
  },
4771
4771
  };
4772
4772
  const collectionAssess = shellNode("assess-backend-pytest-collection-shell", [generatePytestCasesMap.id], "markdown-collection-assess", "Resolve final Markdown-mapped scripts before any business test body execution. Run scenario-param assess/at-most-one deterministic repair first, then pytest --collect-only and a no-business-body pytest --setup-plan fixture-resolution preflight. A safe missing mapped script, generated-local syntax/import defect, or generated fixture dependency/plugin-registration defect is REPAIRABLE; dependency, third-party plugin, production-module, environment, safety and unknown failures remain blocked. Materialize hash-bound collection-v3 facts with repairPaths and fixtureResolutionStatus.", "Run-owned reports/backend-test-pytest-collection-initial.md and contracts/backend-test-pytest-collection-initial.json (collection-v3) with bounded collection/fixture diagnostics, repairPaths, asset hashes, collected item IDs and deterministic repair eligibility.", [], 120000);
4773
+ // N10 owns the deterministic scenario-param rewrite that may update mapped
4774
+ // generated test modules before collection. Declare that bounded shell write
4775
+ // authority so filesystem-only workspace control does not misclassify the
4776
+ // intentional repair as an out-of-bounds mutation.
4777
+ collectionAssess.writePolicy = "exclusive";
4778
+ collectionAssess.writeSet = [applyLayout("testcase/**/test_*.py")];
4773
4779
  const repairPytest = {
4774
4780
  id: "repair-backend-pytest-collection-pi",
4775
4781
  depends_on: [collectionAssess.id],
@@ -4779,8 +4785,24 @@ async function buildBackendTestHybridDag(sources) {
4779
4785
  toolProfile: "write",
4780
4786
  complexity: "MED",
4781
4787
  writePolicy: "exclusive",
4782
- writeSet: ["testcase/**/test_*.py"],
4783
- allowedPaths: Array.from(new Set([...ro, "testcase/**"])),
4788
+ writeSet: Array.from(new Set([
4789
+ applyLayout("testcase/**/test_*.py"),
4790
+ `${layout.testRoot}/helpers/**/*.py`,
4791
+ `${layout.testRoot}/factories/**/*.py`,
4792
+ `${layout.testRoot}/__*_helpers.py`,
4793
+ `${layout.scriptDir}/helpers/**/*.py`,
4794
+ `${layout.scriptDir}/factories/**/*.py`,
4795
+ `${layout.scriptDir}/__*_helpers.py`,
4796
+ ])),
4797
+ readSet: [
4798
+ ".harness/dag-runs/**/reports/backend-test-pytest-collection-initial.md",
4799
+ ".harness/dag-runs/**/reports/backend-test-markdown-pytest-correspondence-initial.md",
4800
+ ".harness/dag-runs/**/generate-backend-md-plan-pi/plan.md",
4801
+ `${layout.markdownDir}/**`,
4802
+ `${layout.testRoot}/**/*.py`,
4803
+ ],
4804
+ contextBudget: { maxTurns: 24, maxTokens: 80_000 },
4805
+ allowedPaths: Array.from(new Set([...ro, `${layout.testRoot}/**`])),
4784
4806
  forbiddenPaths: Array.from(new Set([
4785
4807
  ...forbidden,
4786
4808
  "testcase/md/**",
@@ -4793,7 +4815,7 @@ async function buildBackendTestHybridDag(sources) {
4793
4815
  outputContract: "First non-empty line is IMPLEMENTATION_OUTCOME: changed|blocked, followed by a concise repair summary. This node runs only for REPAIRABLE initial facts, so already-satisfied is invalid and a successful outcome requires a non-empty bounded diff. Modify only generated pytest scripts/helpers/factories and preserve every Markdown Case, Test Point, primary symbol and assertion meaning.",
4794
4816
  subtask_prompt: [
4795
4817
  "Repair the generated backend pytest asset as one bounded program using the direct upstream collection assessment. This is the only repair attempt and happens before any business test body execution. Treat any upstream line such as `Repair paths: testcase/test_x.py` as complete authoritative repairPaths evidence. Directly read and edit that testcase path; do not search for separate root-level `contracts/**`, guess a DAG run directory, or require another report artifact. If the read tool successfully returns the testcase file, the path exists—continue the bounded repair and never later claim that file is absent.",
4796
- "Initial status REPAIRABLE means at least one listed finding remains: `already-satisfied` is forbidden, and you must produce a non-empty bounded diff on repairPaths before returning `IMPLEMENTATION_OUTCOME: changed`. Fix only readiness-proven generated testcase-local defects on initial facts repairPaths: create exact safe missing mapped test_*.py paths, repair syntax/import/symbol/decorator/parameterization, close generated fixture dependencies/plugin registration, and repair initial Markdown-to-pytest correspondence findings (missing/multiple primary symbol, script mismatch, parameter ID or assertion binding). Never invent a business pytest symbol for evidence-only Markdown Cases that declare `脚本/primary symbol=无` with empty variants. For fixture defects inspect both provider and importer; fix ScopeMismatch by aligning fixture scopes or inlining request-scoped values so module fixtures never depend on function fixtures; when a shared fixture depends on sibling fixtures, register the whole provider module through an exact pytest_plugins declaration rather than importing only the outer fixture. Do not create unrelated pytest scripts.",
4818
+ "Initial status REPAIRABLE means at least one listed finding remains: `already-satisfied` is forbidden, and you must produce a non-empty bounded diff on repairPaths before returning `IMPLEMENTATION_OUTCOME: changed`. Fix only readiness-proven generated testcase-local defects on initial facts repairPaths: create exact safe missing mapped test_*.py paths, repair syntax/import/symbol/decorator/parameterization, close generated fixture dependencies/plugin registration, and repair initial Markdown-to-pytest correspondence findings. Use this deterministic repair map instead of reading analyzer implementation: findings about `Case-ID`, `Assertion-Test-Points`, or `Cross-Cutting-Test-Points` are fixed by editing the declared primary symbol docstring metadata lines; variant binding findings are fixed in the literal direct `pytest.param(..., id=\"TP-...\")` row; primary-symbol cardinality/name findings are fixed in the function name or duplicate primary symbols; script mismatch is fixed only on the authoritative assessment repairPaths; payload findings are fixed in request payload construction. Do not read controller `src/**` or inspect JS/TS analyzer code. Do not search for `testcase/**/README.md`. Never invent a business pytest symbol for evidence-only Markdown Cases that declare `脚本/primary symbol=无` with empty variants. For fixture defects inspect both provider and importer listed by repairPaths; fix ScopeMismatch by aligning fixture scopes or inlining request-scoped values so module fixtures never depend on function fixtures; when a shared fixture depends on sibling fixtures, register the whole provider module through an exact pytest_plugins declaration rather than importing only the outer fixture. Do not create unrelated pytest scripts.",
4797
4819
  "This is the single pytest incremental synchronization round. The `Findings` in `reports/backend-test-pytest-collection-initial.md` are the mandatory repair checklist: resolve every repairable listed finding on every authoritative `Repair paths` file before considering any other advisory evidence, and never substitute an unrelated scenario-param cleanup for a listed correspondence/collection defect. For every assessment-listed path, compare the effective Markdown Case/Test Points/test data and its `Payload Contract`/`Payload Required Paths`/`Payload Allowed Paths`/`Payload Enum` labels with the generated module. Incrementally add or repair only missing symbols, params, assertions and payload builders. Repair every assessment-listed missing nested path, unexpected key and enum mismatch; preserve exact DTO keys, nested shapes, enum/boundary literals, operation transport and business preconditions; remove guessed replacement keys only when the effective Markdown proves the exact contract. Keep path/query/header identifiers and scenario-control metadata separate from DTO patches and JSON bodies; an `id` used for a path target must be passed to the request path/helper, never inserted into a body patch unless `id` is explicitly listed in Payload Allowed Paths. Flatten every variant into a literal direct `pytest.param(..., id=\"TP-...\")` row; replace `_post_case`/`_put_case` or other parameter-row factories because correspondence and scenario readiness require the actual row values and IDs to be statically visible. Also repair helper call sites to match their defined return signatures; do not tuple-unpack a helper that returns one scalar value.",
4798
4820
  "Preserve final testcase/md/** semantics, every Case ID, Rule/Test Point binding, primary symbol, parameter ID, expected status/body/schema assertion, HTTP logging, redaction and truncation behavior.",
4799
4821
  "Use local edit only on assessment-listed paths; keep summaries short; never rewrite unrelated modules.",
@@ -780,6 +780,19 @@ export const dagTaskSchema = z.object({ id: z.string().regex(/^[a-z][a-z0-9-]*$/
780
780
  writeSet: z.array(z.string()).optional(),
781
781
  /** Strict repository-relative read allowlist for bounded Pi nodes. */
782
782
  readSet: z.array(z.string()).optional(),
783
+ /**
784
+ * Online per-attempt Pi context guard. Unlike run/map cost budgets, this
785
+ * aborts the active SDK session before an oversized conversation reaches
786
+ * the provider's context rejection boundary.
787
+ */
788
+ contextBudget: z
789
+ .object({
790
+ maxTurns: z.number().int().positive().optional(),
791
+ maxTokens: z.number().int().positive().optional(),
792
+ })
793
+ .strict()
794
+ .refine((value) => value.maxTurns !== undefined || value.maxTokens !== undefined, "contextBudget requires maxTurns or maxTokens")
795
+ .optional(),
783
796
  piStep: z.string().optional(),
784
797
  shell: dagShellConfigSchema.optional(),
785
798
  static: dagStaticConfigSchema.optional(),
@@ -538,6 +538,24 @@
538
538
  "type": "array",
539
539
  "items": { "type": "string", "minLength": 1 }
540
540
  },
541
+ "readSet": {
542
+ "type": "array",
543
+ "items": { "type": "string", "minLength": 1 },
544
+ "description": "Strict repository-relative read allowlist for bounded Pi nodes."
545
+ },
546
+ "contextBudget": {
547
+ "type": "object",
548
+ "additionalProperties": false,
549
+ "description": "Online per-attempt Pi SDK conversation guard. At least one threshold is required; exhaustion aborts the active session with context-budget-exhausted partial evidence.",
550
+ "properties": {
551
+ "maxTurns": { "type": "integer", "minimum": 1 },
552
+ "maxTokens": { "type": "integer", "minimum": 1 }
553
+ },
554
+ "anyOf": [
555
+ { "required": ["maxTurns"] },
556
+ { "required": ["maxTokens"] }
557
+ ]
558
+ },
541
559
  "piStep": {
542
560
  "type": "string",
543
561
  "minLength": 1
@@ -383,7 +383,7 @@
383
383
  "generate-backend-pytest-plan-pi"
384
384
  ],
385
385
  "complexity": "LOW",
386
- "subtask_prompt": "Parse testcase/md/README.md and emit exactly one trailing JSON line {modules:[{stem}]} listing every trusted module stem (table-row testcase/md/<stem>.md mentions and canonical [label](./<stem>.md) relative links only). No file writes.",
386
+ "subtask_prompt": "Parse only the run-owned generate-backend-md-plan-pi/plan.md artifact and emit exactly one trailing JSON line {modules:[{stem,planReadPath}],planReadPath,planSha256}. Reuse the same plan-derived Module Index contract as the Markdown manifest; do not search for or fall back to testcase/**/README.md. No file writes.",
387
387
  "executor": "shell",
388
388
  "role": "verifier",
389
389
  "writePolicy": "read-only",
@@ -394,7 +394,7 @@
394
394
  "timeoutMs": 60000,
395
395
  "cwd": "."
396
396
  },
397
- "outputContract": "Stdout JSON {modules:[{stem}]} parsed from testcase/md/README.md using the same module-stem extractor as the Completeness Gate, so the map_agent shard set deterministically matches the Markdown module index.",
397
+ "outputContract": "Stdout JSON {modules:[{stem,planReadPath}],planReadPath,planSha256} parsed from the run-owned Markdown plan artifact, so the pytest map shard set and every child planReadPath deterministically match the Markdown map manifest.",
398
398
  "allowedPaths": [
399
399
  "testcase/**",
400
400
  "docs/test-reports/**"
@@ -491,7 +491,10 @@
491
491
  "subtask_prompt": "Resolve final Markdown-mapped scripts before any business test body execution. Run scenario-param assess/at-most-one deterministic repair first, then pytest --collect-only and a no-business-body pytest --setup-plan fixture-resolution preflight. A safe missing mapped script, generated-local syntax/import defect, or generated fixture dependency/plugin-registration defect is REPAIRABLE; dependency, third-party plugin, production-module, environment, safety and unknown failures remain blocked. Materialize hash-bound collection-v3 facts with repairPaths and fixtureResolutionStatus.",
492
492
  "executor": "shell",
493
493
  "role": "verifier",
494
- "writePolicy": "read-only",
494
+ "writePolicy": "exclusive",
495
+ "writeSet": [
496
+ "testcase/**/test_*.py"
497
+ ],
495
498
  "shell": {
496
499
  "commands": [],
497
500
  "backendTestPipeline": "markdown-collection-assess",
@@ -516,14 +519,28 @@
516
519
  ],
517
520
  "runIf": "$.nodes['assess-backend-pytest-collection-shell'].json.repairEligible == true",
518
521
  "complexity": "MED",
519
- "subtask_prompt": "Repair the generated backend pytest asset as one bounded program using the direct upstream collection assessment. This is the only repair attempt and happens before any business test body execution. Treat any upstream line such as `Repair paths: testcase/test_x.py` as complete authoritative repairPaths evidence. Directly read and edit that testcase path; do not search for separate root-level `contracts/**`, guess a DAG run directory, or require another report artifact. If the read tool successfully returns the testcase file, the path exists—continue the bounded repair and never later claim that file is absent.\n\nInitial status REPAIRABLE means at least one listed finding remains: `already-satisfied` is forbidden, and you must produce a non-empty bounded diff on repairPaths before returning `IMPLEMENTATION_OUTCOME: changed`. Fix only readiness-proven generated testcase-local defects on initial facts repairPaths: create exact safe missing mapped test_*.py paths, repair syntax/import/symbol/decorator/parameterization, close generated fixture dependencies/plugin registration, and repair initial Markdown-to-pytest correspondence findings (missing/multiple primary symbol, script mismatch, parameter ID or assertion binding). Never invent a business pytest symbol for evidence-only Markdown Cases that declare `脚本/primary symbol=无` with empty variants. For fixture defects inspect both provider and importer; fix ScopeMismatch by aligning fixture scopes or inlining request-scoped values so module fixtures never depend on function fixtures; when a shared fixture depends on sibling fixtures, register the whole provider module through an exact pytest_plugins declaration rather than importing only the outer fixture. Do not create unrelated pytest scripts.\n\nThis is the single pytest incremental synchronization round. The `Findings` in `reports/backend-test-pytest-collection-initial.md` are the mandatory repair checklist: resolve every repairable listed finding on every authoritative `Repair paths` file before considering any other advisory evidence, and never substitute an unrelated scenario-param cleanup for a listed correspondence/collection defect. For every assessment-listed path, compare the effective Markdown Case/Test Points/test data and its `Payload Contract`/`Payload Required Paths`/`Payload Allowed Paths`/`Payload Enum` labels with the generated module. Incrementally add or repair only missing symbols, params, assertions and payload builders. Repair every assessment-listed missing nested path, unexpected key and enum mismatch; preserve exact DTO keys, nested shapes, enum/boundary literals, operation transport and business preconditions; remove guessed replacement keys only when the effective Markdown proves the exact contract. Keep path/query/header identifiers and scenario-control metadata separate from DTO patches and JSON bodies; an `id` used for a path target must be passed to the request path/helper, never inserted into a body patch unless `id` is explicitly listed in Payload Allowed Paths. Flatten every variant into a literal direct `pytest.param(..., id=\"TP-...\")` row; replace `_post_case`/`_put_case` or other parameter-row factories because correspondence and scenario readiness require the actual row values and IDs to be statically visible. Also repair helper call sites to match their defined return signatures; do not tuple-unpack a helper that returns one scalar value.\n\nPreserve final testcase/md/** semantics, every Case ID, Rule/Test Point binding, primary symbol, parameter ID, expected status/body/schema assertion, HTTP logging, redaction and truncation behavior.\n\nUse local edit only on assessment-listed paths; keep summaries short; never rewrite unrelated modules.\n\nDo not reinterpret requirements beyond the effective Markdown and bounded assessment diagnostics. Do not modify Markdown, conftest, pytest config, production code or dependencies.\n\nDo not add skip/skipif/xfail, remove tests, reduce collected items, loosen assertions, swallow exceptions, use try/except ImportError fallback, mutate sys.path/PYTHONPATH, or replace the real API with mocks.\n\nDo not execute pytest; the deterministic effective collection gate owns the final collection attempt.",
522
+ "subtask_prompt": "Repair the generated backend pytest asset as one bounded program using the direct upstream collection assessment. This is the only repair attempt and happens before any business test body execution. Treat any upstream line such as `Repair paths: testcase/test_x.py` as complete authoritative repairPaths evidence. Directly read and edit that testcase path; do not search for separate root-level `contracts/**`, guess a DAG run directory, or require another report artifact. If the read tool successfully returns the testcase file, the path exists—continue the bounded repair and never later claim that file is absent.\n\nInitial status REPAIRABLE means at least one listed finding remains: `already-satisfied` is forbidden, and you must produce a non-empty bounded diff on repairPaths before returning `IMPLEMENTATION_OUTCOME: changed`. Fix only readiness-proven generated testcase-local defects on initial facts repairPaths: create exact safe missing mapped test_*.py paths, repair syntax/import/symbol/decorator/parameterization, close generated fixture dependencies/plugin registration, and repair initial Markdown-to-pytest correspondence findings. Use this deterministic repair map instead of reading analyzer implementation: findings about `Case-ID`, `Assertion-Test-Points`, or `Cross-Cutting-Test-Points` are fixed by editing the declared primary symbol docstring metadata lines; variant binding findings are fixed in the literal direct `pytest.param(..., id=\"TP-...\")` row; primary-symbol cardinality/name findings are fixed in the function name or duplicate primary symbols; script mismatch is fixed only on the authoritative assessment repairPaths; payload findings are fixed in request payload construction. Do not read controller `src/**` or inspect JS/TS analyzer code. Do not search for `testcase/**/README.md`. Never invent a business pytest symbol for evidence-only Markdown Cases that declare `脚本/primary symbol=无` with empty variants. For fixture defects inspect both provider and importer listed by repairPaths; fix ScopeMismatch by aligning fixture scopes or inlining request-scoped values so module fixtures never depend on function fixtures; when a shared fixture depends on sibling fixtures, register the whole provider module through an exact pytest_plugins declaration rather than importing only the outer fixture. Do not create unrelated pytest scripts.\n\nThis is the single pytest incremental synchronization round. The `Findings` in `reports/backend-test-pytest-collection-initial.md` are the mandatory repair checklist: resolve every repairable listed finding on every authoritative `Repair paths` file before considering any other advisory evidence, and never substitute an unrelated scenario-param cleanup for a listed correspondence/collection defect. For every assessment-listed path, compare the effective Markdown Case/Test Points/test data and its `Payload Contract`/`Payload Required Paths`/`Payload Allowed Paths`/`Payload Enum` labels with the generated module. Incrementally add or repair only missing symbols, params, assertions and payload builders. Repair every assessment-listed missing nested path, unexpected key and enum mismatch; preserve exact DTO keys, nested shapes, enum/boundary literals, operation transport and business preconditions; remove guessed replacement keys only when the effective Markdown proves the exact contract. Keep path/query/header identifiers and scenario-control metadata separate from DTO patches and JSON bodies; an `id` used for a path target must be passed to the request path/helper, never inserted into a body patch unless `id` is explicitly listed in Payload Allowed Paths. Flatten every variant into a literal direct `pytest.param(..., id=\"TP-...\")` row; replace `_post_case`/`_put_case` or other parameter-row factories because correspondence and scenario readiness require the actual row values and IDs to be statically visible. Also repair helper call sites to match their defined return signatures; do not tuple-unpack a helper that returns one scalar value.\n\nPreserve final testcase/md/** semantics, every Case ID, Rule/Test Point binding, primary symbol, parameter ID, expected status/body/schema assertion, HTTP logging, redaction and truncation behavior.\n\nUse local edit only on assessment-listed paths; keep summaries short; never rewrite unrelated modules.\n\nDo not reinterpret requirements beyond the effective Markdown and bounded assessment diagnostics. Do not modify Markdown, conftest, pytest config, production code or dependencies.\n\nDo not add skip/skipif/xfail, remove tests, reduce collected items, loosen assertions, swallow exceptions, use try/except ImportError fallback, mutate sys.path/PYTHONPATH, or replace the real API with mocks.\n\nDo not execute pytest; the deterministic effective collection gate owns the final collection attempt.",
520
523
  "executor": "pi",
521
524
  "role": "implementer",
522
525
  "toolProfile": "write",
523
526
  "writePolicy": "exclusive",
524
527
  "writeSet": [
525
- "testcase/**/test_*.py"
528
+ "testcase/**/test_*.py",
529
+ "testcase/helpers/**/*.py",
530
+ "testcase/factories/**/*.py",
531
+ "testcase/__*_helpers.py"
526
532
  ],
533
+ "readSet": [
534
+ ".harness/dag-runs/**/reports/backend-test-pytest-collection-initial.md",
535
+ ".harness/dag-runs/**/reports/backend-test-markdown-pytest-correspondence-initial.md",
536
+ ".harness/dag-runs/**/generate-backend-md-plan-pi/plan.md",
537
+ "testcase/md/**",
538
+ "testcase/**/*.py"
539
+ ],
540
+ "contextBudget": {
541
+ "maxTurns": 24,
542
+ "maxTokens": 80000
543
+ },
527
544
  "outputContract": "First non-empty line is IMPLEMENTATION_OUTCOME: changed|blocked, followed by a concise repair summary. This node runs only for REPAIRABLE initial facts, so already-satisfied is invalid and a successful outcome requires a non-empty bounded diff. Modify only generated pytest scripts/helpers/factories and preserve every Markdown Case, Test Point, primary symbol and assertion meaning.",
528
545
  "writerOutcomePolicy": {
529
546
  "type": "implementation-outcome-v1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.40.0-next.7",
3
+ "version": "0.40.0-next.9",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",
@@ -1 +0,0 @@
1
- import{ag as o,ah as n}from"./mermaid.core-BYdXtke8.js";const t=(a,r)=>o.lang.round(n.parse(a)[r]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-CEenyPTz.js";import{_ as i}from"./mermaid.core-BYdXtke8.js";import"./chunk-5VM5RSS4-C2-8Eo_A.js";import"./chunk-XXDRQBXY-CjE9LQOM.js";import"./chunk-KBJHAD2P-FGngOTto.js";import"./chunk-2GRJ4B5K-DhvWRI03.js";import"./index-B4l5ag79.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-CEenyPTz.js";import{_ as i}from"./mermaid.core-BYdXtke8.js";import"./chunk-5VM5RSS4-C2-8Eo_A.js";import"./chunk-XXDRQBXY-CjE9LQOM.js";import"./chunk-KBJHAD2P-FGngOTto.js";import"./chunk-2GRJ4B5K-DhvWRI03.js";import"./index-B4l5ag79.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};