@tea-agent/loop-agent 0.12.0 → 0.13.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/AGENTS.md +155 -153
  2. package/CHANGELOG.md +338 -265
  3. package/README.md +345 -298
  4. package/bin/agent-worker.js +22 -22
  5. package/bin/loop-agent.js +21 -21
  6. package/dist/application/dag/generate-task-dag.js +28 -28
  7. package/dist/application/evaluation/candidate-hash.js +75 -0
  8. package/dist/application/evaluation/candidate.js +52 -0
  9. package/dist/application/evaluation/replay.js +289 -0
  10. package/dist/application/evaluation/types.js +130 -0
  11. package/dist/cli/command-definitions.js +27 -7
  12. package/dist/cli/program.js +8 -4
  13. package/dist/commands/cursor-prompt.js +6 -6
  14. package/dist/commands/eval.js +235 -0
  15. package/dist/commands/init.js +544 -506
  16. package/dist/commands/knowledge.js +129 -31
  17. package/dist/commands/loop-benchmark.js +11 -11
  18. package/dist/commands/pi-reuse-benchmark.js +16 -16
  19. package/dist/executors/pi-sdk-executor.js +38 -24
  20. package/dist/executors/shell-executor.js +34 -2
  21. package/dist/executors/shell-presets.js +20 -0
  22. package/dist/executors/shell-verification.js +7 -0
  23. package/dist/governance/manifest-types.js +4 -0
  24. package/dist/infrastructure/evaluation/candidate-store.js +435 -0
  25. package/dist/infrastructure/evaluation/store.js +40 -0
  26. package/dist/sidecars/cursor-prompt/executor.js +1 -1
  27. package/dist/task/config-types.js +28 -1
  28. package/dist/task/runtime.js +27 -27
  29. package/dist/worker/cli.js +96 -1
  30. package/dist/worker/delivery/package.js +3 -3
  31. package/dist/worker/feature/decision-loader.js +37 -6
  32. package/dist/worker/feature/next-action.js +10 -2
  33. package/dist/worker/feature/ready-plan-projection.js +81 -0
  34. package/dist/worker/feature/reducer.js +2 -1
  35. package/dist/worker/feature/review.js +19 -2
  36. package/dist/worker/feature/run.js +27 -2
  37. package/dist/worker/follow-up/approve.js +5 -2
  38. package/dist/worker/follow-up/factory.js +1 -1
  39. package/dist/worker/observability/read-model.js +246 -41
  40. package/dist/worker/observe/routes.js +173 -15
  41. package/dist/worker/observe/spec-evidence.js +281 -0
  42. package/dist/worker/observe/static/api.js +46 -27
  43. package/dist/worker/observe/static/app.js +150 -150
  44. package/dist/worker/observe/static/constants.js +148 -148
  45. package/dist/worker/observe/static/copy.js +67 -67
  46. package/dist/worker/observe/static/dag-helpers.js +172 -172
  47. package/dist/worker/observe/static/dag-layout.d.ts +31 -31
  48. package/dist/worker/observe/static/dag-layout.js +83 -83
  49. package/dist/worker/observe/static/dag-model.js +72 -72
  50. package/dist/worker/observe/static/dom.js +61 -61
  51. package/dist/worker/observe/static/format-pool.js +67 -67
  52. package/dist/worker/observe/static/format.js +292 -292
  53. package/dist/worker/observe/static/index.html +308 -308
  54. package/dist/worker/observe/static/kpi.js +94 -94
  55. package/dist/worker/observe/static/relations.js +133 -128
  56. package/dist/worker/observe/static/router.js +93 -85
  57. package/dist/worker/observe/static/run-processing.js +148 -148
  58. package/dist/worker/observe/static/shell-chrome.js +68 -68
  59. package/dist/worker/observe/static/state.js +253 -253
  60. package/dist/worker/observe/static/styles.css +1902 -1890
  61. package/dist/worker/observe/static/views/batch.js +227 -226
  62. package/dist/worker/observe/static/views/dag-graph.js +172 -172
  63. package/dist/worker/observe/static/views/dag-inspector.js +607 -477
  64. package/dist/worker/observe/static/views/dag.js +362 -362
  65. package/dist/worker/observe/static/views/dashboard.js +445 -442
  66. package/dist/worker/observe/static/views/failures.js +143 -143
  67. package/dist/worker/observe/static/views/feature.js +492 -453
  68. package/dist/worker/observe/static/views/pool.js +350 -347
  69. package/dist/worker/observe/static/views/run.js +453 -453
  70. package/dist/worker/observe/static/views/session-timeline.js +205 -205
  71. package/dist/worker/observe/static/views/shell.js +7 -7
  72. package/dist/worker/observe/static/views/task.js +314 -260
  73. package/dist/worker/observe/static/views/timeline.js +163 -163
  74. package/dist/worker/pool/doctor.js +165 -0
  75. package/dist/worker/pool/migrate-state.js +303 -0
  76. package/dist/worker/pool/run-store.js +205 -17
  77. package/dist/worker/pool/types.js +17 -1
  78. package/dist/worker/pool/validation.js +100 -15
  79. package/dist/worker/report/morning-report.js +12 -2
  80. package/dist/worker/runner/run-ready.js +41 -26
  81. package/dist/worker/task-graph/ready-planner.js +136 -0
  82. package/dist/workflows/dag/backend-test-analysis-contract.js +120 -0
  83. package/dist/workflows/dag/canvas-observer.js +275 -275
  84. package/dist/workflows/dag/convergence/controller.js +16 -8
  85. package/dist/workflows/dag/dynamic-runtime/map.js +90 -2
  86. package/dist/workflows/dag/failure-routing.js +12 -1
  87. package/dist/workflows/dag/init-hybrid.js +2404 -360
  88. package/dist/workflows/dag/node-execution.js +9 -0
  89. package/dist/workflows/dag/prompt.js +9 -0
  90. package/dist/workflows/dag/report.js +35 -1
  91. package/dist/workflows/dag/runner.js +28 -2
  92. package/dist/workflows/dag/task-demand-routing.js +383 -0
  93. package/dist/workflows/dag/types.js +51 -13
  94. package/dist/workflows/dag/upstream-artifacts.js +1 -0
  95. package/dist/workflows/dag/validate.js +59 -1
  96. package/docs/README.md +106 -104
  97. package/docs/agent-dag-recovery-playbook.md +195 -184
  98. package/docs/agent-dag-runner.md +67 -67
  99. package/docs/architecture/README.md +26 -26
  100. package/docs/architecture/dag-execution.md +140 -140
  101. package/docs/architecture/evolution.md +54 -53
  102. package/docs/architecture/facts-and-state.md +71 -58
  103. package/docs/architecture/runtime-boundaries.md +191 -191
  104. package/docs/architecture/system-overview.md +93 -93
  105. package/docs/architecture/worker-and-feature.md +85 -81
  106. package/docs/cursor-prompt-sidecar.md +36 -36
  107. package/docs/decisions/README.md +18 -15
  108. package/docs/design/README.md +167 -77
  109. package/docs/development-principles.md +73 -73
  110. package/docs/exec-plans/README.md +6 -6
  111. package/docs/exec-plans/active/README.md +15 -9
  112. package/docs/exec-plans/completed/README.md +85 -73
  113. package/docs/feature-workflow.md +389 -261
  114. package/docs/harness-methodology-debugging.md +153 -153
  115. package/docs/harness-methodology-tdd.md +130 -130
  116. package/docs/harness-methodology-verification.md +27 -27
  117. package/docs/init-surface.manifest.json +289 -280
  118. package/docs/loop-agent-harness.md +142 -130
  119. package/docs/production-readiness.md +96 -96
  120. package/docs/progress/README.md +64 -54
  121. package/docs/reports/README.md +117 -94
  122. package/docs/skills/README.md +7 -7
  123. package/docs/skills/vetted-skill-registry.md +29 -27
  124. package/docs/templates/adr.md +60 -60
  125. package/docs/templates/agent-dag-authority-surface-audit.prompt.md +94 -94
  126. package/docs/templates/agent-dag-decision-envelope.schema.json +213 -213
  127. package/docs/templates/agent-dag-decision-gate-dogfood-report.md +117 -117
  128. package/docs/templates/agent-dag-decision-gate.prompt.md +246 -246
  129. package/docs/templates/agent-dag-process-supervisor.prompt.md +98 -98
  130. package/docs/templates/agent-dag-report.schema.json +473 -473
  131. package/docs/templates/agent-dag-review-verdict.prompt.md +68 -68
  132. package/docs/templates/agent-dag.base.json +190 -190
  133. package/docs/templates/agent-dag.final-verification.json +185 -185
  134. package/docs/templates/agent-dag.schema.json +411 -383
  135. package/docs/templates/agent-dag.supervised-implementation.json +501 -501
  136. package/docs/templates/backend-test-analysis.schema.json +44 -0
  137. package/docs/templates/backend-test-dag.generate-pytest.prompt.md +202 -139
  138. package/docs/templates/backend-test-dag.json +311 -276
  139. package/docs/templates/backend-test-dag.retrospect.prompt.md +125 -125
  140. package/docs/templates/backend-test-dag.review-cases.prompt.md +81 -81
  141. package/docs/templates/exec-plan.md +64 -64
  142. package/docs/templates/feature-spec.md +53 -53
  143. package/docs/templates/frontend-design-contract.md +42 -33
  144. package/docs/templates/frontend-task-constraints.md +35 -25
  145. package/docs/templates/frontend-task-requirement.md +70 -61
  146. package/docs/templates/frontend-test-dag.generate-cases.prompt.md +5 -0
  147. package/docs/templates/frontend-test-dag.json +23 -0
  148. package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +3 -0
  149. package/docs/templates/frontend-test-dag.retrospect.prompt.md +3 -0
  150. package/docs/templates/frontend-test-dag.review-cases.prompt.md +3 -0
  151. package/docs/templates/frontend-test-dag.review-execution.prompt.md +3 -0
  152. package/docs/templates/harness.schema.json +221 -221
  153. package/docs/templates/hybrid-dag.json +188 -188
  154. package/docs/templates/init-evolution-review.md +35 -35
  155. package/docs/templates/interactive-ui-round2-experiment.md +66 -66
  156. package/docs/templates/knowledge-graph-bootstrap-dag.json +118 -0
  157. package/docs/templates/knowledge-sync-dag.json +178 -0
  158. package/docs/templates/knowledge-sync-draft.schema.json +71 -0
  159. package/docs/templates/product-line/AGENTS.md +8 -8
  160. package/docs/templates/product-line/README.md +9 -9
  161. package/docs/templates/product-line/acceptance.yaml +14 -14
  162. package/docs/templates/product-line/closeout.yaml +9 -9
  163. package/docs/templates/product-line/design.md +13 -13
  164. package/docs/templates/product-line/links.md +10 -10
  165. package/docs/templates/product-line/requirement.md +17 -17
  166. package/docs/templates/product-line/task-graph.yaml +15 -15
  167. package/docs/templates/product-line/task.yaml +64 -64
  168. package/docs/templates/product-line/test-plan.md +7 -7
  169. package/docs/templates/production-readiness-checklist.md +57 -57
  170. package/docs/templates/progress-log.md +17 -17
  171. package/docs/templates/project-start-checklist.md +9 -9
  172. package/docs/templates/qa-report.md +48 -48
  173. package/docs/templates/sprint-contract.md +29 -29
  174. package/docs/templates/worker-dogfood-evidence.md +80 -80
  175. package/docs/templates/worker-dogfood-setup.md +68 -68
  176. package/docs/verification-matrix.md +70 -66
  177. package/examples/decision-gate-agent-dag.json +177 -177
  178. package/examples/example-dag.json +46 -46
  179. package/examples/hybrid-loop-agent-dag.json +189 -189
  180. package/harness.json +66 -66
  181. package/package.json +88 -46
  182. package/scripts/check-product-line-docs.sh +29 -29
  183. package/scripts/check-task-pool-root.sh +32 -32
  184. package/scripts/kb-bootstrap-init-skeleton.sh +240 -0
  185. package/scripts/kb-graph-incremental-prepare.mjs +386 -0
  186. package/scripts/kb-graph-incremental-prepare.sh +5 -0
  187. package/scripts/kb-graph-materialize.mjs +105 -0
  188. package/scripts/kb-graph-materialize.sh +4 -0
  189. package/scripts/kb-graph-promote.mjs +164 -0
  190. package/scripts/kb-graph-promote.sh +4 -0
  191. package/scripts/kb-query.mjs +554 -0
  192. package/scripts/kb-query.sh +5 -0
  193. package/skills/agent-worker/SKILL.md +39 -37
  194. package/skills/agent-worker/references/agent-worker-operator.md +60 -43
  195. package/skills/ai-engineering-context/SKILL.md +48 -48
  196. package/skills/analyze-product-dependencies/SKILL.md +67 -0
  197. package/skills/analyze-product-dependencies/agents/openai.yaml +4 -0
  198. package/skills/analyze-product-dependencies/references/api-documentation-schema.md +30 -0
  199. package/skills/analyze-product-dependencies/references/dependency-analysis-schema.md +28 -0
  200. package/skills/analyze-product-dependencies/references/example.md +76 -0
  201. package/skills/analyze-product-dependencies/references/forward-test-cases.md +35 -0
  202. package/skills/analyze-product-dependencies/references/input-contract.md +11 -0
  203. package/skills/analyze-product-dependencies/references/scouting-rules.md +61 -0
  204. package/skills/analyze-product-dependencies/scripts/test-validators.mjs +267 -0
  205. package/skills/analyze-product-dependencies/scripts/validate-api-documentation.mjs +101 -0
  206. package/skills/analyze-product-dependencies/scripts/validate-dependency-analysis.mjs +142 -0
  207. package/skills/analyze-product-dependencies/scripts/validate-product-requirement-input.mjs +76 -0
  208. package/skills/analyze-product-dependencies/scripts/validation-helpers.mjs +146 -0
  209. package/skills/analyze-product-requirements/SKILL.md +90 -0
  210. package/skills/analyze-product-requirements/agents/openai.yaml +4 -0
  211. package/skills/analyze-product-requirements/references/acceptance-criteria.md +91 -0
  212. package/skills/analyze-product-requirements/references/clarification-and-knowledge.md +56 -0
  213. package/skills/analyze-product-requirements/references/example.md +86 -0
  214. package/skills/analyze-product-requirements/references/forward-test-cases.md +66 -0
  215. package/skills/analyze-product-requirements/references/product-analysis-schema.md +32 -0
  216. package/skills/analyze-product-requirements/references/product-requirement-schema.md +33 -0
  217. package/skills/analyze-product-requirements/references/requirement-clarification-schema.md +35 -0
  218. package/skills/analyze-product-requirements/scripts/test-validators.mjs +193 -0
  219. package/skills/analyze-product-requirements/scripts/validate-product-analysis.mjs +69 -0
  220. package/skills/analyze-product-requirements/scripts/validate-product-requirement.mjs +97 -0
  221. package/skills/analyze-product-requirements/scripts/validate-requirement-clarification.mjs +98 -0
  222. package/skills/analyze-product-requirements/scripts/validation-helpers.mjs +156 -0
  223. package/skills/code-review-core/SKILL.md +20 -20
  224. package/skills/codebase-scout/SKILL.md +19 -19
  225. package/skills/frontend-design-review/SKILL.md +66 -59
  226. package/skills/frontend-design-review/references/review-checklist.md +58 -37
  227. package/skills/frontend-implementation/SKILL.md +47 -51
  228. package/skills/frontend-implementation/references/code-standards.md +32 -34
  229. package/skills/frontend-implementation/references/design-spec.md +46 -46
  230. package/skills/frontend-implementation/references/node-contracts.md +76 -32
  231. package/skills/frontend-review/SKILL.md +59 -53
  232. package/skills/frontend-review/references/review-findings.md +47 -42
  233. package/skills/frontend-verification/SKILL.md +53 -40
  234. package/skills/frontend-verification/references/verification-checklist.md +68 -56
  235. package/skills/grill-me/SKILL.md +10 -10
  236. package/skills/grill-with-docs/SKILL.md +88 -88
  237. package/skills/grill-with-docs/adr-format.md +47 -47
  238. package/skills/grill-with-docs/context-format.md +60 -60
  239. package/skills/init-capability-evolution/SKILL.md +70 -70
  240. package/skills/loop-agent/SKILL.md +151 -151
  241. package/skills/loop-agent/references/README.md +67 -67
  242. package/skills/loop-agent/references/command-reference.md +505 -452
  243. package/skills/loop-agent/references/docs-converge.md +126 -126
  244. package/skills/loop-agent/references/harness-policy.md +263 -263
  245. package/skills/loop-agent/references/hybrid-dag.md +238 -233
  246. package/skills/loop-agent/references/learned/README.md +21 -21
  247. package/skills/loop-agent/references/long-running-loop.md +57 -57
  248. package/skills/loop-agent/references/model-routing.md +36 -36
  249. package/skills/loop-agent/references/multi-worktree.md +54 -54
  250. package/skills/loop-agent/references/one-shot-runs.md +85 -85
  251. package/skills/loop-agent/references/orchestrator-and-interventions.md +169 -169
  252. package/skills/loop-agent/references/pi-prompt.md +23 -23
  253. package/skills/loop-agent/references/pi-subagent-assisted-mode.md +84 -84
  254. package/skills/loop-agent/references/post-implementation-and-patterns.md +44 -44
  255. package/skills/loop-agent/references/task-workflow.md +89 -89
  256. package/skills/loop-agent/references/verification-and-failure-handling.md +139 -139
  257. package/skills/playwright-cli/SKILL.md +420 -0
  258. package/skills/playwright-cli/references/element-attributes.md +23 -0
  259. package/skills/playwright-cli/references/playwright-tests.md +39 -0
  260. package/skills/playwright-cli/references/request-mocking.md +87 -0
  261. package/skills/playwright-cli/references/running-code.md +241 -0
  262. package/skills/playwright-cli/references/session-management.md +225 -0
  263. package/skills/playwright-cli/references/storage-state.md +275 -0
  264. package/skills/playwright-cli/references/test-generation.md +433 -0
  265. package/skills/playwright-cli/references/tracing.md +139 -0
  266. package/skills/playwright-cli/references/video-recording.md +143 -0
  267. package/skills/playwright-cli-case-generator/SKILL.md +74 -0
  268. package/skills/requesting-code-review/SKILL.md +101 -101
  269. package/skills/requesting-code-review/code-reviewer.md +168 -168
  270. package/skills/systematic-debugging/CREATION-LOG.md +119 -119
  271. package/skills/systematic-debugging/SKILL.md +296 -296
  272. package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -158
  273. package/skills/systematic-debugging/condition-based-waiting.md +115 -115
  274. package/skills/systematic-debugging/defense-in-depth.md +122 -122
  275. package/skills/systematic-debugging/find-polluter.sh +63 -63
  276. package/skills/systematic-debugging/root-cause-tracing.md +169 -169
  277. package/skills/systematic-debugging/test-academic.md +14 -14
  278. package/skills/systematic-debugging/test-pressure-1.md +58 -58
  279. package/skills/systematic-debugging/test-pressure-2.md +68 -68
  280. package/skills/systematic-debugging/test-pressure-3.md +69 -69
  281. package/skills/test-driven-development/SKILL.md +20 -20
  282. package/skills/using-git-worktrees/SKILL.md +215 -215
  283. package/skills/verification-before-completion/SKILL.md +154 -154
  284. package/skills/webapp-testing/SKILL.md +19 -19
@@ -1,383 +1,411 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://loop-agent.local/schemas/agent-dag.schema.json",
4
- "title": "Agent DAG Spec",
5
- "type": "object",
6
- "additionalProperties": false,
7
- "required": ["version", "title", "tasks"],
8
- "allOf": [
9
- {
10
- "if": { "properties": { "version": { "const": 3 } }, "required": ["version"] },
11
- "then": { "required": ["runtimeContract"] }
12
- },
13
- {
14
- "if": { "required": ["runtimeContract"] },
15
- "then": { "properties": { "version": { "const": 3 } } }
16
- }
17
- ],
18
- "properties": {
19
- "$schema": {
20
- "type": "string"
21
- },
22
- "version": {
23
- "enum": [1, 2, 3],
24
- "default": 1
25
- },
26
- "title": {
27
- "type": "string",
28
- "minLength": 1
29
- },
30
- "runtimeContract": { "$ref": "#/$defs/runtimeContract" },
31
- "objective": {
32
- "type": "string"
33
- },
34
- "successCriteria": {
35
- "type": "array",
36
- "items": { "type": "string", "minLength": 1 }
37
- },
38
- "globalConstraints": {
39
- "type": "array",
40
- "items": { "type": "string", "minLength": 1 }
41
- },
42
- "verifyStrategy": { "$ref": "#/$defs/verifyStrategy" },
43
- "defaults": {
44
- "type": "object",
45
- "additionalProperties": false,
46
- "properties": {
47
- "executor": { "$ref": "#/$defs/executor" },
48
- "model": { "type": "string" },
49
- "piBackend": {
50
- "enum": ["sdk-first", "cli-only"],
51
- "description": "Accepted metadata only. Runtime Pi backend selection is controlled by CODE_AGENT_PI_BACKEND."
52
- },
53
- "contextProfile": { "type": "string" },
54
- "skills": {
55
- "type": "array",
56
- "items": { "type": "string", "minLength": 1 }
57
- },
58
- "writePolicy": { "$ref": "#/$defs/writePolicy" }
59
- }
60
- },
61
- "skillsByRole": {
62
- "type": "object",
63
- "additionalProperties": {
64
- "type": "array",
65
- "items": { "type": "string", "minLength": 1 }
66
- }
67
- },
68
- "executorModels": {
69
- "type": "object",
70
- "description": "Executor-owned model routing template keyed by executor then complexity. Do not use legacy top-level models or defaults.model.",
71
- "additionalProperties": false,
72
- "properties": {
73
- "pi": { "$ref": "#/$defs/complexityModelMap" }
74
- }
75
- },
76
- "tasks": {
77
- "type": "array",
78
- "minItems": 1,
79
- "items": { "$ref": "#/$defs/task" }
80
- }
81
- },
82
- "not": {
83
- "required": ["models"]
84
- },
85
- "$defs": {
86
- "runtimeContract": {
87
- "type": "object",
88
- "additionalProperties": false,
89
- "required": ["schemaVersion", "agentRuntime", "repairWriterProtocol"],
90
- "description": "DagSpec v3 controller capability handshake. Compatibility is decided by capability fields first; minimumControllerVersion is enforced when present. Legacy v1/v2 DAGs may omit this block.",
91
- "properties": {
92
- "schemaVersion": { "const": 1 },
93
- "agentRuntime": { "const": "pi-only" },
94
- "repairWriterProtocol": { "const": "explicit-node-v1" },
95
- "minimumControllerVersion": {
96
- "type": "string",
97
- "pattern": "^\\d+\\.\\d+\\.\\d+([-+].+)?$"
98
- }
99
- }
100
- },
101
- "complexity": {
102
- "enum": ["LOW", "MED", "HIGH"]
103
- },
104
- "executor": {
105
- "enum": ["pi", "shell", "static"]
106
- },
107
- "toolProfile": {
108
- "enum": ["read-only", "write"]
109
- },
110
- "role": {
111
- "enum": ["planner", "scout", "implementer", "reviewer", "supervisor", "verifier", "closeout"]
112
- },
113
- "writePolicy": {
114
- "enum": ["read-only", "docs-only", "exclusive", "none"]
115
- },
116
- "complexityModelMap": {
117
- "type": "object",
118
- "additionalProperties": false,
119
- "properties": {
120
- "LOW": { "type": "string", "minLength": 1 },
121
- "MED": { "type": "string", "minLength": 1 },
122
- "HIGH": { "type": "string", "minLength": 1 }
123
- }
124
- },
125
- "verifyQuota": {
126
- "enum": ["1", "3", "full"]
127
- },
128
- "verifyStrategy": {
129
- "type": "object",
130
- "additionalProperties": false,
131
- "properties": {
132
- "intermediateQuota": { "$ref": "#/$defs/verifyQuota" },
133
- "finalQuota": {
134
- "const": "full",
135
- "default": "full",
136
- "description": "Final completion verification cannot be quota-reduced."
137
- },
138
- "focusedCommandSource": {
139
- "const": "adapter",
140
- "default": "adapter"
141
- }
142
- }
143
- },
144
- "shellVerifyEvidence": {
145
- "type": "object",
146
- "additionalProperties": false,
147
- "required": ["phase", "quota", "commandSource", "commandCount"],
148
- "properties": {
149
- "phase": { "enum": ["intermediate", "final"] },
150
- "quota": { "$ref": "#/$defs/verifyQuota" },
151
- "commandSource": { "enum": ["adapter", "inline"] },
152
- "commandCount": { "type": "integer", "minimum": 0 },
153
- "commandLabels": {
154
- "type": "array",
155
- "items": { "type": "string" },
156
- "default": []
157
- },
158
- "finalFullRequired": { "type": "boolean" }
159
- }
160
- },
161
- "repairArtifactGate": {
162
- "type": "object",
163
- "additionalProperties": false,
164
- "required": ["fromNodeId"],
165
- "properties": {
166
- "fromNodeId": {
167
- "type": "string",
168
- "pattern": "^[a-z][a-z0-9-]*$"
169
- },
170
- "repairNodeId": {
171
- "type": "string",
172
- "pattern": "^[a-z][a-z0-9-]*$",
173
- "description": "Explicit governed Pi repair writer this gate feeds (executor=pi, toolProfile=write, writePolicy=exclusive, non-empty allowedPaths+writeSet, depends_on the gate). New DAGs must set this; legacy DAGs are only accepted when a unique safe downstream Pi writer can be derived."
174
- }
175
- }
176
- },
177
- "shellConfig": {
178
- "type": "object",
179
- "additionalProperties": false,
180
- "properties": {
181
- "commands": {
182
- "type": "array",
183
- "items": { "type": "string", "minLength": 1 },
184
- "default": []
185
- },
186
- "preset": {
187
- "enum": ["loop-agent-standard-verify"]
188
- },
189
- "verdictGate": {
190
- "type": "object",
191
- "additionalProperties": false,
192
- "required": ["fromNodeId", "accept"],
193
- "properties": {
194
- "fromNodeId": {
195
- "type": "string",
196
- "pattern": "^[a-z][a-z0-9-]*$",
197
- "description": "Upstream node id whose canonical JSON output in the runner-injected current run directory ($HARNESS_DAG_RUN_DIR/<fromNodeId>.json) supplies the verdict line."
198
- },
199
- "accept": {
200
- "type": "array",
201
- "minItems": 1,
202
- "items": { "type": "string", "minLength": 1 },
203
- "description": "Exact assistantText/stdout verdict lines that pass the gate."
204
- },
205
- "label": {
206
- "type": "string",
207
- "minLength": 1,
208
- "description": "Optional human-readable gate label for error messages."
209
- },
210
- "lineMode": {
211
- "type": "string",
212
- "enum": ["first-non-empty", "first-verdict-line"],
213
- "default": "first-non-empty",
214
- "description": "Selects how verdict gates parse assistant output: first non-empty line (legacy) or first normalized line starting with 'VERDICT:' (common whole-line Markdown emphasis is normalized before exact accept matching)."
215
- }
216
- }
217
- },
218
- "verifyEvidence": { "$ref": "#/$defs/shellVerifyEvidence" },
219
- "repairArtifactGate": { "$ref": "#/$defs/repairArtifactGate" },
220
- "envAllowlist": {
221
- "type": "array",
222
- "items": {
223
- "type": "string",
224
- "pattern": "^[A-Z_][A-Z0-9_]*$"
225
- }
226
- },
227
- "timeoutMs": { "type": "number" },
228
- "cwd": { "type": "string", "minLength": 1 }
229
- },
230
- "anyOf": [
231
- { "required": ["commands"], "properties": { "commands": { "minItems": 1 } } },
232
- { "required": ["preset"] },
233
- { "required": ["verdictGate"] }
234
- ]
235
- },
236
- "staticConfig": {
237
- "type": "object",
238
- "additionalProperties": false,
239
- "required": ["resultMarkdown"],
240
- "properties": {
241
- "resultMarkdown": { "type": "string", "minLength": 1 },
242
- "status": { "enum": ["success", "error"] }
243
- }
244
- },
245
- "retryPolicy": {
246
- "type": "object",
247
- "additionalProperties": false,
248
- "required": ["maxAttempts"],
249
- "description": "Retry policy for safe read-only planner/scout/reviewer/verifier/closeout Pi nodes. Total attempts include the first try and are capped at five. Supervisors, implementers, and side-effecting nodes are ineligible. Only the categories listed in retryCategories are retried; quota/auth/invalid-output/write-guard are never retried.",
250
- "properties": {
251
- "maxAttempts": {
252
- "type": "integer",
253
- "minimum": 1,
254
- "maximum": 5,
255
- "description": "Total attempts including the first try. 1 disables retry."
256
- },
257
- "backoff": { "const": "exponential", "default": "exponential" },
258
- "initialDelayMs": {
259
- "type": "integer",
260
- "minimum": 0,
261
- "default": 2000
262
- },
263
- "maxDelayMs": {
264
- "type": "integer",
265
- "minimum": 0,
266
- "default": 30000
267
- },
268
- "retryCategories": {
269
- "type": "array",
270
- "items": {
271
- "enum": ["timeout", "network", "rate-limit", "unavailable"]
272
- },
273
- "default": ["timeout", "network", "rate-limit", "unavailable"],
274
- "description": "Failure categories eligible for retry. quota is never eligible."
275
- }
276
- }
277
- },
278
- "promptSource": {
279
- "type": "object",
280
- "additionalProperties": false,
281
- "required": ["type", "path", "sha256"],
282
- "properties": {
283
- "type": { "const": "markdown" },
284
- "path": { "type": "string", "minLength": 1 },
285
- "sha256": { "type": "string", "minLength": 1 }
286
- }
287
- },
288
- "task": {
289
- "type": "object",
290
- "additionalProperties": false,
291
- "required": ["id", "depends_on", "complexity"],
292
- "properties": {
293
- "id": {
294
- "type": "string",
295
- "pattern": "^[a-z][a-z0-9-]*$"
296
- },
297
- "depends_on": {
298
- "type": "array",
299
- "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
300
- "default": []
301
- },
302
- "complexity": { "$ref": "#/$defs/complexity" },
303
- "subtask_prompt": {
304
- "type": "string",
305
- "minLength": 1
306
- },
307
- "subtask_prompt_markdown": {
308
- "type": "string",
309
- "minLength": 1
310
- },
311
- "subtask_prompt_source": { "$ref": "#/$defs/promptSource" },
312
- "executor": {
313
- "$ref": "#/$defs/executor",
314
- "default": "pi"
315
- },
316
- "role": { "$ref": "#/$defs/role" },
317
- "skills": {
318
- "type": "array",
319
- "items": { "type": "string", "minLength": 1 }
320
- },
321
- "toolProfile": { "$ref": "#/$defs/toolProfile" },
322
- "writePolicy": { "$ref": "#/$defs/writePolicy" },
323
- "writeSet": {
324
- "type": "array",
325
- "items": { "type": "string", "minLength": 1 }
326
- },
327
- "piStep": {
328
- "type": "string",
329
- "minLength": 1
330
- },
331
- "shell": {
332
- "$ref": "#/$defs/shellConfig"
333
- },
334
- "static": {
335
- "$ref": "#/$defs/staticConfig"
336
- },
337
- "outputContract": {
338
- "type": "string",
339
- "minLength": 1
340
- },
341
- "allowedPaths": {
342
- "type": "array",
343
- "items": { "type": "string", "minLength": 1 },
344
- "default": []
345
- },
346
- "forbiddenPaths": {
347
- "type": "array",
348
- "items": { "type": "string", "minLength": 1 },
349
- "default": []
350
- },
351
- "decisionGate": {
352
- "type": "object",
353
- "additionalProperties": false,
354
- "required": ["enabled"],
355
- "properties": {
356
- "enabled": { "type": "boolean" },
357
- "schemaVersion": { "const": 1 },
358
- "mode": {
359
- "enum": ["record-only", "pause-on-human"],
360
- "default": "record-only"
361
- }
362
- }
363
- },
364
- "retryPolicy": {
365
- "$ref": "#/$defs/retryPolicy",
366
- "description": "Opt-in retry policy. Allowed only on safe read-only planner/scout/reviewer/verifier/closeout non-dynamic Pi nodes; validation rejects it on supervisors, implementers, writers, dynamic, shell, static, docs-only, and decision-gate nodes. Generated DAGs declare the default policy on eligible nodes automatically."
367
- }
368
- },
369
- "oneOf": [
370
- {
371
- "description": "Inline prompt only; subtask_prompt_markdown must be absent.",
372
- "required": ["subtask_prompt"],
373
- "not": { "required": ["subtask_prompt_markdown"] }
374
- },
375
- {
376
- "description": "Markdown-backed prompt only; subtask_prompt must be absent until file loader resolves it.",
377
- "required": ["subtask_prompt_markdown"],
378
- "not": { "required": ["subtask_prompt"] }
379
- }
380
- ]
381
- }
382
- }
383
- }
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://loop-agent.local/schemas/agent-dag.schema.json",
4
+ "title": "Agent DAG Spec",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["version", "title", "tasks"],
8
+ "allOf": [
9
+ {
10
+ "if": { "properties": { "version": { "const": 3 } }, "required": ["version"] },
11
+ "then": { "required": ["runtimeContract"] }
12
+ },
13
+ {
14
+ "if": { "required": ["runtimeContract"] },
15
+ "then": { "properties": { "version": { "const": 3 } } }
16
+ }
17
+ ],
18
+ "properties": {
19
+ "$schema": {
20
+ "type": "string"
21
+ },
22
+ "version": {
23
+ "enum": [1, 2, 3],
24
+ "default": 1
25
+ },
26
+ "title": {
27
+ "type": "string",
28
+ "minLength": 1
29
+ },
30
+ "runtimeContract": { "$ref": "#/$defs/runtimeContract" },
31
+ "sourceBinding": { "$ref": "#/$defs/sourceBinding" },
32
+ "objective": {
33
+ "type": "string"
34
+ },
35
+ "successCriteria": {
36
+ "type": "array",
37
+ "items": { "type": "string", "minLength": 1 }
38
+ },
39
+ "globalConstraints": {
40
+ "type": "array",
41
+ "items": { "type": "string", "minLength": 1 }
42
+ },
43
+ "verifyStrategy": { "$ref": "#/$defs/verifyStrategy" },
44
+ "defaults": {
45
+ "type": "object",
46
+ "additionalProperties": false,
47
+ "properties": {
48
+ "executor": { "$ref": "#/$defs/executor" },
49
+ "model": { "type": "string" },
50
+ "piBackend": {
51
+ "enum": ["sdk-first", "cli-only"],
52
+ "description": "Accepted metadata only. Runtime Pi backend selection is controlled by CODE_AGENT_PI_BACKEND."
53
+ },
54
+ "contextProfile": { "type": "string" },
55
+ "skills": {
56
+ "type": "array",
57
+ "items": { "type": "string", "minLength": 1 }
58
+ },
59
+ "writePolicy": { "$ref": "#/$defs/writePolicy" }
60
+ }
61
+ },
62
+ "skillsByRole": {
63
+ "type": "object",
64
+ "additionalProperties": {
65
+ "type": "array",
66
+ "items": { "type": "string", "minLength": 1 }
67
+ }
68
+ },
69
+ "executorModels": {
70
+ "type": "object",
71
+ "description": "Executor-owned model routing template keyed by executor then complexity. Do not use legacy top-level models or defaults.model.",
72
+ "additionalProperties": false,
73
+ "properties": {
74
+ "pi": { "$ref": "#/$defs/complexityModelMap" }
75
+ }
76
+ },
77
+ "tasks": {
78
+ "type": "array",
79
+ "minItems": 1,
80
+ "items": { "$ref": "#/$defs/task" }
81
+ }
82
+ },
83
+ "not": {
84
+ "required": ["models"]
85
+ },
86
+ "$defs": {
87
+ "runtimeContract": {
88
+ "type": "object",
89
+ "additionalProperties": false,
90
+ "required": ["schemaVersion", "agentRuntime", "repairWriterProtocol"],
91
+ "description": "DagSpec v3 controller capability handshake. Compatibility is decided by capability fields first; minimumControllerVersion is enforced when present. Legacy v1/v2 DAGs may omit this block.",
92
+ "properties": {
93
+ "schemaVersion": { "const": 1 },
94
+ "agentRuntime": { "const": "pi-only" },
95
+ "repairWriterProtocol": { "const": "explicit-node-v1" },
96
+ "minimumControllerVersion": {
97
+ "type": "string",
98
+ "pattern": "^\\d+\\.\\d+\\.\\d+([-+].+)?$"
99
+ }
100
+ }
101
+ },
102
+ "sourceBinding": {
103
+ "type": "object", "additionalProperties": false,
104
+ "required": ["schemaVersion", "taskId", "sources", "requirementIds"],
105
+ "properties": {
106
+ "schemaVersion": { "const": 1 },
107
+ "taskId": { "type": "string", "minLength": 1 },
108
+ "sources": { "type": "array", "minItems": 1, "items": {
109
+ "type": "object", "additionalProperties": false, "required": ["kind", "path", "sha256"],
110
+ "properties": {
111
+ "kind": { "enum": ["requirement", "constraint", "reference"] },
112
+ "path": { "type": "string", "minLength": 1 },
113
+ "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" }
114
+ }
115
+ } },
116
+ "requirementIds": { "type": "array", "items": { "type": "string", "pattern": "^(?:REQ|BR|AC)-[A-Z0-9]+(?:-[A-Z0-9]+)*$" } }
117
+ }
118
+ },
119
+ "complexity": {
120
+ "enum": ["LOW", "MED", "HIGH"]
121
+ },
122
+ "executor": {
123
+ "enum": ["pi", "shell", "static"]
124
+ },
125
+ "toolProfile": {
126
+ "enum": ["read-only", "write"]
127
+ },
128
+ "role": {
129
+ "enum": ["planner", "scout", "implementer", "reviewer", "supervisor", "verifier", "closeout"]
130
+ },
131
+ "writePolicy": {
132
+ "enum": ["read-only", "docs-only", "exclusive", "none"]
133
+ },
134
+ "complexityModelMap": {
135
+ "type": "object",
136
+ "additionalProperties": false,
137
+ "properties": {
138
+ "LOW": { "type": "string", "minLength": 1 },
139
+ "MED": { "type": "string", "minLength": 1 },
140
+ "HIGH": { "type": "string", "minLength": 1 }
141
+ }
142
+ },
143
+ "verifyQuota": {
144
+ "enum": ["1", "3", "full"]
145
+ },
146
+ "verifyStrategy": {
147
+ "type": "object",
148
+ "additionalProperties": false,
149
+ "properties": {
150
+ "intermediateQuota": { "$ref": "#/$defs/verifyQuota" },
151
+ "finalQuota": {
152
+ "const": "full",
153
+ "default": "full",
154
+ "description": "Final completion verification cannot be quota-reduced."
155
+ },
156
+ "focusedCommandSource": {
157
+ "const": "adapter",
158
+ "default": "adapter"
159
+ }
160
+ }
161
+ },
162
+ "shellVerifyEvidence": {
163
+ "type": "object",
164
+ "additionalProperties": false,
165
+ "required": ["phase", "quota", "commandSource", "commandCount"],
166
+ "properties": {
167
+ "phase": { "enum": ["intermediate", "final"] },
168
+ "quota": { "$ref": "#/$defs/verifyQuota" },
169
+ "commandSource": { "enum": ["adapter", "inline"] },
170
+ "commandCount": { "type": "integer", "minimum": 0 },
171
+ "commandLabels": {
172
+ "type": "array",
173
+ "items": { "type": "string" },
174
+ "default": []
175
+ },
176
+ "finalFullRequired": { "type": "boolean" }
177
+ }
178
+ },
179
+ "repairArtifactGate": {
180
+ "type": "object",
181
+ "additionalProperties": false,
182
+ "required": ["fromNodeId"],
183
+ "properties": {
184
+ "fromNodeId": {
185
+ "type": "string",
186
+ "pattern": "^[a-z][a-z0-9-]*$"
187
+ },
188
+ "repairNodeId": {
189
+ "type": "string",
190
+ "pattern": "^[a-z][a-z0-9-]*$",
191
+ "description": "Explicit governed Pi repair writer this gate feeds (executor=pi, toolProfile=write, writePolicy=exclusive, non-empty allowedPaths+writeSet, depends_on the gate). New DAGs must set this; legacy DAGs are only accepted when a unique safe downstream Pi writer can be derived."
192
+ }
193
+ }
194
+ },
195
+ "shellConfig": {
196
+ "type": "object",
197
+ "additionalProperties": false,
198
+ "properties": {
199
+ "commands": {
200
+ "type": "array",
201
+ "items": { "type": "string", "minLength": 1 },
202
+ "default": []
203
+ },
204
+ "preset": {
205
+ "enum": ["loop-agent-standard-verify"]
206
+ },
207
+ "verdictGate": {
208
+ "type": "object",
209
+ "additionalProperties": false,
210
+ "required": ["fromNodeId", "accept"],
211
+ "properties": {
212
+ "fromNodeId": {
213
+ "type": "string",
214
+ "pattern": "^[a-z][a-z0-9-]*$",
215
+ "description": "Upstream node id whose canonical JSON output in the runner-injected current run directory ($HARNESS_DAG_RUN_DIR/<fromNodeId>.json) supplies the verdict line."
216
+ },
217
+ "accept": {
218
+ "type": "array",
219
+ "minItems": 1,
220
+ "items": { "type": "string", "minLength": 1 },
221
+ "description": "Exact assistantText/stdout verdict lines that pass the gate."
222
+ },
223
+ "label": {
224
+ "type": "string",
225
+ "minLength": 1,
226
+ "description": "Optional human-readable gate label for error messages."
227
+ },
228
+ "lineMode": {
229
+ "type": "string",
230
+ "enum": ["first-non-empty", "first-verdict-line"],
231
+ "default": "first-non-empty",
232
+ "description": "Selects how verdict gates parse assistant output: first non-empty line (legacy) or first normalized line starting with 'VERDICT:' (common whole-line Markdown emphasis is normalized before exact accept matching)."
233
+ }
234
+ }
235
+ },
236
+ "requirementCoverageGate": {
237
+ "type": "object", "additionalProperties": false,
238
+ "required": ["fromNodeIds", "requiredIds"],
239
+ "properties": {
240
+ "fromNodeIds": { "type": "array", "minItems": 1, "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" } },
241
+ "requiredIds": { "type": "array", "minItems": 1, "items": { "type": "string", "pattern": "^(?:REQ|BR|AC)-[A-Z0-9]+(?:-[A-Z0-9]+)*$" } },
242
+ "label": { "type": "string", "minLength": 1 }
243
+ }
244
+ },
245
+ "verifyEvidence": { "$ref": "#/$defs/shellVerifyEvidence" },
246
+ "repairArtifactGate": { "$ref": "#/$defs/repairArtifactGate" },
247
+ "envAllowlist": {
248
+ "type": "array",
249
+ "items": {
250
+ "type": "string",
251
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
252
+ }
253
+ },
254
+ "timeoutMs": { "type": "number" },
255
+ "cwd": { "type": "string", "minLength": 1 }
256
+ },
257
+ "anyOf": [
258
+ { "required": ["commands"], "properties": { "commands": { "minItems": 1 } } },
259
+ { "required": ["preset"] },
260
+ { "required": ["verdictGate"] },
261
+ { "required": ["requirementCoverageGate"] }
262
+ ]
263
+ },
264
+ "staticConfig": {
265
+ "type": "object",
266
+ "additionalProperties": false,
267
+ "required": ["resultMarkdown"],
268
+ "properties": {
269
+ "resultMarkdown": { "type": "string", "minLength": 1 },
270
+ "status": { "enum": ["success", "error"] }
271
+ }
272
+ },
273
+ "retryPolicy": {
274
+ "type": "object",
275
+ "additionalProperties": false,
276
+ "required": ["maxAttempts"],
277
+ "description": "Retry policy for safe read-only planner/scout/reviewer/verifier/closeout Pi nodes. Total attempts include the first try and are capped at five. Supervisors, implementers, and side-effecting nodes are ineligible. Only the categories listed in retryCategories are retried; quota/auth/invalid-output/write-guard are never retried.",
278
+ "properties": {
279
+ "maxAttempts": {
280
+ "type": "integer",
281
+ "minimum": 1,
282
+ "maximum": 5,
283
+ "description": "Total attempts including the first try. 1 disables retry."
284
+ },
285
+ "backoff": { "const": "exponential", "default": "exponential" },
286
+ "initialDelayMs": {
287
+ "type": "integer",
288
+ "minimum": 0,
289
+ "default": 2000
290
+ },
291
+ "maxDelayMs": {
292
+ "type": "integer",
293
+ "minimum": 0,
294
+ "default": 30000
295
+ },
296
+ "retryCategories": {
297
+ "type": "array",
298
+ "items": {
299
+ "enum": ["timeout", "network", "rate-limit", "unavailable"]
300
+ },
301
+ "default": ["timeout", "network", "rate-limit", "unavailable"],
302
+ "description": "Failure categories eligible for retry. quota is never eligible."
303
+ }
304
+ }
305
+ },
306
+ "promptSource": {
307
+ "type": "object",
308
+ "additionalProperties": false,
309
+ "required": ["type", "path", "sha256"],
310
+ "properties": {
311
+ "type": { "const": "markdown" },
312
+ "path": { "type": "string", "minLength": 1 },
313
+ "sha256": { "type": "string", "minLength": 1 }
314
+ }
315
+ },
316
+ "task": {
317
+ "type": "object",
318
+ "additionalProperties": false,
319
+ "required": ["id", "depends_on", "complexity"],
320
+ "properties": {
321
+ "id": {
322
+ "type": "string",
323
+ "pattern": "^[a-z][a-z0-9-]*$"
324
+ },
325
+ "depends_on": {
326
+ "type": "array",
327
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
328
+ "default": []
329
+ },
330
+ "complexity": { "$ref": "#/$defs/complexity" },
331
+ "subtask_prompt": {
332
+ "type": "string",
333
+ "minLength": 1
334
+ },
335
+ "subtask_prompt_markdown": {
336
+ "type": "string",
337
+ "minLength": 1
338
+ },
339
+ "subtask_prompt_source": { "$ref": "#/$defs/promptSource" },
340
+ "executor": {
341
+ "$ref": "#/$defs/executor",
342
+ "default": "pi"
343
+ },
344
+ "role": { "$ref": "#/$defs/role" },
345
+ "skills": {
346
+ "type": "array",
347
+ "items": { "type": "string", "minLength": 1 }
348
+ },
349
+ "toolProfile": { "$ref": "#/$defs/toolProfile" },
350
+ "writePolicy": { "$ref": "#/$defs/writePolicy" },
351
+ "writeSet": {
352
+ "type": "array",
353
+ "items": { "type": "string", "minLength": 1 }
354
+ },
355
+ "piStep": {
356
+ "type": "string",
357
+ "minLength": 1
358
+ },
359
+ "shell": {
360
+ "$ref": "#/$defs/shellConfig"
361
+ },
362
+ "static": {
363
+ "$ref": "#/$defs/staticConfig"
364
+ },
365
+ "outputContract": {
366
+ "type": "string",
367
+ "minLength": 1
368
+ },
369
+ "allowedPaths": {
370
+ "type": "array",
371
+ "items": { "type": "string", "minLength": 1 },
372
+ "default": []
373
+ },
374
+ "forbiddenPaths": {
375
+ "type": "array",
376
+ "items": { "type": "string", "minLength": 1 },
377
+ "default": []
378
+ },
379
+ "decisionGate": {
380
+ "type": "object",
381
+ "additionalProperties": false,
382
+ "required": ["enabled"],
383
+ "properties": {
384
+ "enabled": { "type": "boolean" },
385
+ "schemaVersion": { "const": 1 },
386
+ "mode": {
387
+ "enum": ["record-only", "pause-on-human"],
388
+ "default": "record-only"
389
+ }
390
+ }
391
+ },
392
+ "retryPolicy": {
393
+ "$ref": "#/$defs/retryPolicy",
394
+ "description": "Opt-in retry policy. Allowed only on safe read-only planner/scout/reviewer/verifier/closeout non-dynamic Pi nodes; validation rejects it on supervisors, implementers, writers, dynamic, shell, static, docs-only, and decision-gate nodes. Generated DAGs declare the default policy on eligible nodes automatically."
395
+ }
396
+ },
397
+ "oneOf": [
398
+ {
399
+ "description": "Inline prompt only; subtask_prompt_markdown must be absent.",
400
+ "required": ["subtask_prompt"],
401
+ "not": { "required": ["subtask_prompt_markdown"] }
402
+ },
403
+ {
404
+ "description": "Markdown-backed prompt only; subtask_prompt must be absent until file loader resolves it.",
405
+ "required": ["subtask_prompt_markdown"],
406
+ "not": { "required": ["subtask_prompt"] }
407
+ }
408
+ ]
409
+ }
410
+ }
411
+ }