create-agdf 0.30.0 → 0.31.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 (341) hide show
  1. package/generated/.agdf/control/README.md +5 -0
  2. package/generated/.agdf/control/templates/BRAND.md +28 -0
  3. package/generated/.agdf/control/templates/artefacts/PRD.md +11 -0
  4. package/generated/.agdf/control/templates/artefacts/SD.md +4 -0
  5. package/generated/.agdf/control/templates/artefacts/UX_INTENT_DEFINITION.md +1 -1
  6. package/generated/.opencode/agdf-interaction-locales.json +292 -2
  7. package/generated/.opencode/contracts/gate-artifact-preparation.md +9 -3
  8. package/generated/.opencode/contracts/interaction.md +10 -4
  9. package/generated/.opencode/contracts/modes.md +5 -0
  10. package/generated/.opencode/contracts/prd-definition.md +40 -1
  11. package/generated/.opencode/contracts/quality.md +35 -0
  12. package/generated/.opencode/contracts/request-activation.md +6 -3
  13. package/generated/.opencode/contracts/sd-definition.md +46 -0
  14. package/generated/.opencode/contracts/tp-definition.md +8 -0
  15. package/generated/.opencode/contracts/ur-definition.md +9 -5
  16. package/generated/.opencode/skills/agdf-ux-intent-definition/SKILL.md +31 -2
  17. package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
  18. package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
  19. package/generated/plugins/agdf/companion/events.mjs +117 -0
  20. package/generated/plugins/agdf/companion/figure.mjs +6 -6
  21. package/generated/plugins/agdf/companion/gate-bar.mjs +10 -28
  22. package/generated/plugins/agdf/companion/localization.mjs +10 -32
  23. package/generated/plugins/agdf/companion/notice.mjs +10 -8
  24. package/generated/plugins/agdf/companion/register.mjs +229 -43
  25. package/generated/plugins/agdf/companion/run-state.mjs +77 -90
  26. package/generated/plugins/agdf/companion/state.mjs +6 -32
  27. package/generated/plugins/agdf/companion/view.mjs +57 -12
  28. package/generated/plugins/agdf/control/README.md +5 -0
  29. package/generated/plugins/agdf/control/templates/BRAND.md +28 -0
  30. package/generated/plugins/agdf/control/templates/artefacts/PRD.md +11 -0
  31. package/generated/plugins/agdf/control/templates/artefacts/SD.md +4 -0
  32. package/generated/plugins/agdf/control/templates/artefacts/UX_INTENT_DEFINITION.md +1 -1
  33. package/generated/plugins/agdf/mcp/server/README.md +26 -2
  34. package/generated/plugins/agdf/mcp/server/package.json +3 -3
  35. package/generated/plugins/agdf/mcp/server/src/generation-runtime.js +11 -2
  36. package/generated/plugins/agdf/mcp/server/src/main.js +1 -0
  37. package/generated/plugins/agdf/mcp/server/src/next-action.js +227 -0
  38. package/generated/plugins/agdf/mcp/server/src/prepared-call-transport.js +306 -0
  39. package/generated/plugins/agdf/mcp/server/src/safe-read-continuation.js +62 -0
  40. package/generated/plugins/agdf/mcp/server/src/server.js +139 -35
  41. package/generated/plugins/agdf/mcp/server/ui/cockpit.html +2 -2
  42. package/generated/plugins/agdf/mcp/server/ui/decision-manifest.json +3 -3
  43. package/generated/plugins/agdf/mcp/server/ui/decision.html +2 -2
  44. package/generated/plugins/agdf/mcp/server/ui/manifest.json +3 -3
  45. package/generated/plugins/agdf/meta/agdf-interaction-locales.json +292 -2
  46. package/generated/plugins/agdf/meta/agdf-mcp-capability.json +1 -1
  47. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  48. package/generated/plugins/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
  49. package/generated/plugins/agdf/meta/contracts/interaction.md +10 -4
  50. package/generated/plugins/agdf/meta/contracts/modes.md +5 -0
  51. package/generated/plugins/agdf/meta/contracts/prd-definition.md +40 -1
  52. package/generated/plugins/agdf/meta/contracts/quality.md +35 -0
  53. package/generated/plugins/agdf/meta/contracts/request-activation.md +6 -3
  54. package/generated/plugins/agdf/meta/contracts/sd-definition.md +46 -0
  55. package/generated/plugins/agdf/meta/contracts/tp-definition.md +8 -0
  56. package/generated/plugins/agdf/meta/contracts/ur-definition.md +9 -5
  57. package/generated/plugins/agdf/meta/copilot-payload-baseline.json +3 -3
  58. package/generated/plugins/agdf/meta/distribution-profile-history.json +7 -0
  59. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +292 -2
  60. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  61. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
  62. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/interaction.md +10 -4
  63. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/modes.md +5 -0
  64. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/prd-definition.md +40 -1
  65. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/quality.md +35 -0
  66. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/request-activation.md +6 -3
  67. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/sd-definition.md +46 -0
  68. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/tp-definition.md +8 -0
  69. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/ur-definition.md +9 -5
  70. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +2 -1
  71. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/parse-args.js +7 -4
  72. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/project-read-command.js +29 -0
  73. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +2 -1
  74. package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-dispatch-runtime.js +32 -6
  75. package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-lifecycle/package.js +7 -0
  76. package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-lifecycle/plugin-runtime.js +34 -6
  77. package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-lifecycle/prepared-call-journal.js +269 -0
  78. package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-worker-runtime.js +86 -83
  79. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/validator-application.js +2 -2
  80. package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
  81. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/events.js +154 -0
  82. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/figure-state.js +36 -0
  83. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/journal.js +180 -0
  84. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/run-view.js +184 -0
  85. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/acceptance-criteria.js +2 -0
  86. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/closeout-readiness.js +24 -6
  87. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-check.js +44 -6
  88. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-inputs.js +2 -0
  89. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-pure.js +7 -3
  90. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/prd-readiness.js +7 -2
  91. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/report-decision.js +9 -0
  92. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/traceability-readiness.js +57 -8
  93. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/ur-readiness.js +15 -2
  94. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/artifact-readiness.js +5 -3
  95. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/authoring-inputs.js +107 -22
  96. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/cockpit.js +4 -20
  97. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/contract.js +64 -24
  98. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/material-recording-calls.js +54 -0
  99. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/project-state.js +2 -1
  100. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/run-classification.js +31 -0
  101. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/selection.js +6 -0
  102. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/service.js +32 -5
  103. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/authoring-text-handoff.js +3 -0
  104. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/input-resolution.js +7 -5
  105. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/material-limits.js +4 -0
  106. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/prepared-control-calls.js +137 -0
  107. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/presentation-delivery.js +4 -1
  108. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-contract.js +10 -4
  109. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-schema.js +9 -3
  110. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-service.js +35 -11
  111. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-identity.js +2 -0
  112. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-inventory-reader.js +5 -3
  113. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-material.js +25 -7
  114. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-presentation-render.js +84 -28
  115. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-revision.js +38 -20
  116. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-source-revisions.js +37 -17
  117. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-state-reader.js +10 -3
  118. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-steps.js +8 -5
  119. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/index.js +3 -1
  120. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog-validation.js +6 -1
  121. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog.js +8 -0
  122. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/interaction-presentation.js +26 -1
  123. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/mcp-input-hints.js +30 -1
  124. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/mcp-tool-errors.js +5 -3
  125. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/resources/canonical-init-plan.js +1 -1
  126. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/runtime/plugin-provenance.js +9 -2
  127. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/contract.js +6 -4
  128. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/delivery-intake.js +3 -1
  129. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/mcp-continuation.js +25 -2
  130. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/prd-definition.js +3 -2
  131. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/readiness-findings.js +7 -0
  132. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/sd-definition.js +4 -2
  133. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/service.js +17 -4
  134. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/tp-definition.js +4 -2
  135. package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
  136. package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +4 -3
  137. package/generated/plugins/agdf/skills/ux-intent-definition/SKILL.md +31 -2
  138. package/generated/plugins/agdf/skills/ux-intent-definition/help.md +8 -1
  139. package/generated/plugins/agdf/submission/openai/availability.md +1 -1
  140. package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
  141. package/generated/plugins/agdf/submission/openai/release-notes.md +8 -8
  142. package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
  143. package/generated/plugins/agdf-planning/.codex-plugin/plugin.json +1 -1
  144. package/generated/plugins/agdf-planning/plugin.json +1 -1
  145. package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +332 -195
  146. package/generated/plugins/copilot/agdf/control/README.md +5 -0
  147. package/generated/plugins/copilot/agdf/control/templates/BRAND.md +28 -0
  148. package/generated/plugins/copilot/agdf/control/templates/artefacts/PRD.md +11 -0
  149. package/generated/plugins/copilot/agdf/control/templates/artefacts/SD.md +4 -0
  150. package/generated/plugins/copilot/agdf/control/templates/artefacts/UX_INTENT_DEFINITION.md +1 -1
  151. package/generated/plugins/copilot/agdf/mcp/server/README.md +26 -2
  152. package/generated/plugins/copilot/agdf/mcp/server/package.json +3 -3
  153. package/generated/plugins/copilot/agdf/mcp/server/src/generation-runtime.js +11 -2
  154. package/generated/plugins/copilot/agdf/mcp/server/src/main.js +1 -0
  155. package/generated/plugins/copilot/agdf/mcp/server/src/next-action.js +227 -0
  156. package/generated/plugins/copilot/agdf/mcp/server/src/prepared-call-transport.js +306 -0
  157. package/generated/plugins/copilot/agdf/mcp/server/src/safe-read-continuation.js +62 -0
  158. package/generated/plugins/copilot/agdf/mcp/server/src/server.js +139 -35
  159. package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +1 -1
  160. package/generated/plugins/copilot/agdf/meta/distribution-profile-history.json +7 -0
  161. package/generated/plugins/copilot/agdf/plugin.json +1 -1
  162. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +292 -2
  163. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  164. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
  165. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/interaction.md +10 -4
  166. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/modes.md +5 -0
  167. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/prd-definition.md +40 -1
  168. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/quality.md +35 -0
  169. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/request-activation.md +6 -3
  170. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/sd-definition.md +46 -0
  171. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/tp-definition.md +8 -0
  172. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/ur-definition.md +9 -5
  173. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +2 -1
  174. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +7 -4
  175. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/project-read-command.js +29 -0
  176. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +2 -1
  177. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-dispatch-runtime.js +32 -6
  178. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-lifecycle/package.js +7 -0
  179. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-lifecycle/plugin-runtime.js +34 -6
  180. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-lifecycle/prepared-call-journal.js +269 -0
  181. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-worker-runtime.js +81 -78
  182. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/validator-application.js +2 -2
  183. package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +1 -1
  184. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/events.js +154 -0
  185. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/figure-state.js +36 -0
  186. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/journal.js +180 -0
  187. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/run-view.js +184 -0
  188. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/acceptance-criteria.js +2 -0
  189. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/closeout-readiness.js +24 -6
  190. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-check.js +44 -6
  191. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-inputs.js +2 -0
  192. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-pure.js +7 -3
  193. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/prd-readiness.js +7 -2
  194. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/report-decision.js +9 -0
  195. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/traceability-readiness.js +57 -8
  196. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/ur-readiness.js +15 -2
  197. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/artifact-readiness.js +5 -3
  198. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/authoring-inputs.js +107 -22
  199. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/contract.js +64 -24
  200. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/material-recording-calls.js +54 -0
  201. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/project-state.js +2 -1
  202. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/run-classification.js +31 -0
  203. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/selection.js +6 -0
  204. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/service.js +32 -5
  205. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/authoring-text-handoff.js +3 -0
  206. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/input-resolution.js +7 -5
  207. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/material-limits.js +4 -0
  208. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/prepared-control-calls.js +137 -0
  209. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/presentation-delivery.js +4 -1
  210. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-contract.js +10 -4
  211. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-schema.js +9 -3
  212. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-service.js +35 -11
  213. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-identity.js +2 -0
  214. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-inventory-reader.js +5 -3
  215. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-material.js +25 -7
  216. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-presentation-render.js +84 -28
  217. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-revision.js +38 -20
  218. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-source-revisions.js +37 -17
  219. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-state-reader.js +10 -3
  220. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-steps.js +8 -5
  221. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/index.js +3 -1
  222. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog-validation.js +6 -1
  223. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog.js +8 -0
  224. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/interaction-presentation.js +26 -1
  225. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/mcp-input-hints.js +30 -1
  226. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/mcp-tool-errors.js +5 -3
  227. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/resources/canonical-init-plan.js +1 -1
  228. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/runtime/plugin-provenance.js +9 -2
  229. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/contract.js +6 -4
  230. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/delivery-intake.js +3 -1
  231. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/mcp-continuation.js +25 -2
  232. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/prd-definition.js +3 -2
  233. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/readiness-findings.js +7 -0
  234. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/sd-definition.js +4 -2
  235. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/service.js +17 -4
  236. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/tp-definition.js +4 -2
  237. package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +2 -2
  238. package/generated/plugins/copilot/agdf/skills/agdf-interaction-locales.json +1 -1
  239. package/generated/plugins/copilot/agdf/skills/agdf-ux-intent-definition/SKILL.md +31 -2
  240. package/generated/plugins/copilot/agdf/skills/contracts/gate-artifact-preparation.md +9 -3
  241. package/generated/plugins/copilot/agdf/skills/contracts/interaction.md +10 -4
  242. package/generated/plugins/copilot/agdf/skills/contracts/modes.md +5 -0
  243. package/generated/plugins/copilot/agdf/skills/contracts/prd-definition.md +40 -1
  244. package/generated/plugins/copilot/agdf/skills/contracts/quality.md +35 -0
  245. package/generated/plugins/copilot/agdf/skills/contracts/request-activation.md +6 -3
  246. package/generated/plugins/copilot/agdf/skills/contracts/sd-definition.md +46 -0
  247. package/generated/plugins/copilot/agdf/skills/contracts/tp-definition.md +8 -0
  248. package/generated/plugins/copilot/agdf/skills/contracts/ur-definition.md +9 -5
  249. package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
  250. package/generated/submissions/openai/agdf/meta/agdf-interaction-locales.json +292 -2
  251. package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +1 -1
  252. package/generated/submissions/openai/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
  253. package/generated/submissions/openai/agdf/meta/contracts/interaction.md +10 -4
  254. package/generated/submissions/openai/agdf/meta/contracts/modes.md +5 -0
  255. package/generated/submissions/openai/agdf/meta/contracts/prd-definition.md +40 -1
  256. package/generated/submissions/openai/agdf/meta/contracts/quality.md +35 -0
  257. package/generated/submissions/openai/agdf/meta/contracts/request-activation.md +6 -3
  258. package/generated/submissions/openai/agdf/meta/contracts/sd-definition.md +46 -0
  259. package/generated/submissions/openai/agdf/meta/contracts/tp-definition.md +8 -0
  260. package/generated/submissions/openai/agdf/meta/contracts/ur-definition.md +9 -5
  261. package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +3 -3
  262. package/generated/submissions/openai/agdf/meta/distribution-profile-history.json +7 -0
  263. package/generated/submissions/openai/agdf/plugin.json +1 -1
  264. package/generated/submissions/openai/agdf/skills/ux-intent-definition/SKILL.md +31 -2
  265. package/generated/submissions/openai/agdf/skills/ux-intent-definition/help.md +8 -1
  266. package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
  267. package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
  268. package/generated/submissions/openai/agdf/submission/openai/inventory.json +24 -24
  269. package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
  270. package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
  271. package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
  272. package/generated/submissions/openai/agdf/submission/openai/release-notes.md +8 -8
  273. package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
  274. package/lib/cli/command-registry.js +2 -1
  275. package/lib/cli/parse-args.js +7 -4
  276. package/lib/cli/project-read-command.js +29 -0
  277. package/lib/cli/validation-handlers.js +2 -1
  278. package/lib/mcp-dispatch-runtime.js +32 -6
  279. package/lib/mcp-lifecycle/package.js +7 -0
  280. package/lib/mcp-lifecycle/plugin-runtime.js +34 -6
  281. package/lib/mcp-lifecycle/prepared-call-journal.js +269 -0
  282. package/lib/mcp-worker-runtime.js +86 -83
  283. package/lib/runtime/validator-application.js +2 -2
  284. package/lib/scaffold/plan.js +2 -0
  285. package/package.json +1 -1
  286. package/runtime/core/lib/companion/events.js +154 -0
  287. package/runtime/core/lib/companion/figure-state.js +36 -0
  288. package/runtime/core/lib/companion/journal.js +180 -0
  289. package/runtime/core/lib/companion/run-view.js +184 -0
  290. package/runtime/core/lib/control-evaluation/acceptance-criteria.js +2 -0
  291. package/runtime/core/lib/control-evaluation/closeout-readiness.js +24 -6
  292. package/runtime/core/lib/control-evaluation/gate-check.js +44 -6
  293. package/runtime/core/lib/control-evaluation/gate-policy-inputs.js +2 -0
  294. package/runtime/core/lib/control-evaluation/gate-policy-pure.js +7 -3
  295. package/runtime/core/lib/control-evaluation/prd-readiness.js +7 -2
  296. package/runtime/core/lib/control-evaluation/report-decision.js +9 -0
  297. package/runtime/core/lib/control-evaluation/traceability-readiness.js +57 -8
  298. package/runtime/core/lib/control-evaluation/ur-readiness.js +15 -2
  299. package/runtime/core/lib/control-inspect/artifact-readiness.js +5 -3
  300. package/runtime/core/lib/control-inspect/authoring-inputs.js +107 -22
  301. package/runtime/core/lib/control-inspect/cockpit.js +4 -20
  302. package/runtime/core/lib/control-inspect/contract.js +64 -24
  303. package/runtime/core/lib/control-inspect/material-recording-calls.js +54 -0
  304. package/runtime/core/lib/control-inspect/project-state.js +2 -1
  305. package/runtime/core/lib/control-inspect/run-classification.js +31 -0
  306. package/runtime/core/lib/control-inspect/selection.js +6 -0
  307. package/runtime/core/lib/control-inspect/service.js +32 -5
  308. package/runtime/core/lib/control-state/authoring-text-handoff.js +3 -0
  309. package/runtime/core/lib/control-state/input-resolution.js +7 -5
  310. package/runtime/core/lib/control-state/material-limits.js +4 -0
  311. package/runtime/core/lib/control-state/prepared-control-calls.js +137 -0
  312. package/runtime/core/lib/control-state/presentation-delivery.js +4 -1
  313. package/runtime/core/lib/control-state/run-command-contract.js +10 -4
  314. package/runtime/core/lib/control-state/run-command-schema.js +9 -3
  315. package/runtime/core/lib/control-state/run-command-service.js +35 -11
  316. package/runtime/core/lib/control-state/run-identity.js +2 -0
  317. package/runtime/core/lib/control-state/run-inventory-reader.js +5 -3
  318. package/runtime/core/lib/control-state/run-material.js +25 -7
  319. package/runtime/core/lib/control-state/run-presentation-render.js +84 -28
  320. package/runtime/core/lib/control-state/run-revision.js +38 -20
  321. package/runtime/core/lib/control-state/run-source-revisions.js +37 -17
  322. package/runtime/core/lib/control-state/run-state-reader.js +10 -3
  323. package/runtime/core/lib/control-state/run-steps.js +8 -5
  324. package/runtime/core/lib/index.js +3 -1
  325. package/runtime/core/lib/interaction-catalog-validation.js +6 -1
  326. package/runtime/core/lib/interaction-catalog.js +8 -0
  327. package/runtime/core/lib/interaction-presentation.js +26 -1
  328. package/runtime/core/lib/mcp-input-hints.js +30 -1
  329. package/runtime/core/lib/mcp-tool-errors.js +5 -3
  330. package/runtime/core/lib/resources/canonical-init-plan.js +1 -1
  331. package/runtime/core/lib/runtime/plugin-provenance.js +9 -2
  332. package/runtime/core/lib/skill-dispatch/contract.js +6 -4
  333. package/runtime/core/lib/skill-dispatch/delivery-intake.js +3 -1
  334. package/runtime/core/lib/skill-dispatch/mcp-continuation.js +25 -2
  335. package/runtime/core/lib/skill-dispatch/prd-definition.js +3 -2
  336. package/runtime/core/lib/skill-dispatch/readiness-findings.js +7 -0
  337. package/runtime/core/lib/skill-dispatch/sd-definition.js +4 -2
  338. package/runtime/core/lib/skill-dispatch/service.js +17 -4
  339. package/runtime/core/lib/skill-dispatch/tp-definition.js +4 -2
  340. package/generated/plugins/agdf/companion/core.mjs +0 -16
  341. package/generated/plugins/agdf/companion/locales.json +0 -200
@@ -0,0 +1,227 @@
1
+ const writeTools = new Set(['agdf_project', 'agdf_run', 'agdf_prepare', 'agdf_record', 'agdf_approve', 'agdf_revise', 'agdf_closeout']);
2
+ const knownTools = new Set([...writeTools, 'agdf_inspect', 'agdf_dispatch']);
3
+ const clone = value => structuredClone(value);
4
+ const object = value => value && typeof value === 'object' && !Array.isArray(value);
5
+ const canonical = value => JSON.stringify(stable(value));
6
+ function stable(value) {
7
+ if (Array.isArray(value)) return value.map(stable);
8
+ return object(value) ? Object.fromEntries(Object.keys(value).sort().map(key => [key, stable(value[key])])) : value;
9
+ }
10
+ function callValue(value) {
11
+ return object(value) && knownTools.has(value.tool) && object(value.arguments)
12
+ ? { tool: value.tool, arguments: clone(value.arguments) } : null;
13
+ }
14
+ function formValue(value) {
15
+ if (!object(value)) return null;
16
+ const call = callValue(value.call ?? value);
17
+ if (!call) return null;
18
+ // A normal mutating action must already be the transport's bound form. Never
19
+ // promote its Raw recovery branch or reconstruct one from operation metadata.
20
+ if (writeTools.has(call.tool) && (!Object.hasOwn(call.arguments, 'prepared_call_id')
21
+ || typeof call.arguments.prepared_call_id !== 'string' || !call.arguments.prepared_call_id
22
+ || !object(call.arguments.inputs) || Object.keys(call.arguments).some(key => !['prepared_call_id', 'inputs'].includes(key)))) return null;
23
+ if (value.required_inputs !== undefined && (!Array.isArray(value.required_inputs)
24
+ || value.required_inputs.some(field => typeof field !== 'string' || !field))) return null;
25
+ const source = clone(value);
26
+ delete source.tool; delete source.arguments;
27
+ return { ...source, call, required_inputs: Array.isArray(value.required_inputs) ? clone(value.required_inputs) : [] };
28
+ }
29
+ function uniqueForms(values) {
30
+ const forms = new Map();
31
+ for (const value of values.filter(Boolean)) {
32
+ const form = formValue(value);
33
+ if (!form) return null;
34
+ const key = canonical({ call: form.call, required_inputs: form.required_inputs });
35
+ if (!forms.has(key)) forms.set(key, form);
36
+ }
37
+ return [...forms.values()];
38
+ }
39
+ function base(state, instruction, source, extra = {}) {
40
+ return { state, call: null, required_inputs: [], instruction, source, ...extra, authorizes: false };
41
+ }
42
+ function terminal(result, source) {
43
+ return base('terminal', 'Respect this result\'s terminal host_action and stop; no next tool call is selected.', source,
44
+ result.host_action ? { host_action: clone(result.host_action) } : {});
45
+ }
46
+ function selectForms(values, source, { forceReply = false, readOnly = false } = {}) {
47
+ const forms = uniqueForms(values);
48
+ if (!forms?.length) return base('requires_source', 'No complete normal action was supplied. Read the canonical source or use its explicit recovery instructions; do not construct a replacement call.', source);
49
+ if (forms.length !== 1) return base('requires_selection', 'Several distinct actions were supplied. Preserve the current binding and obtain the authoritative selection; do not pick the first action.', source);
50
+ const form = forms[0];
51
+ if (readOnly && form.call.tool !== 'agdf_inspect') return base('requires_source', 'The supplied continuation is not a read-only page call; no action is selected.', source);
52
+ const reply = forceReply || form.call.tool === 'agdf_approve' || form.operation?.kind === 'approval.record';
53
+ if (reply) {
54
+ // The contract's approval_value is syntax, never a response. A producer that
55
+ // filled a reply in an offered form cannot establish new human intent here.
56
+ if (Object.values(form.call.arguments.inputs ?? {}).some(value => value !== '' && value !== undefined))
57
+ return base('requires_new_reply', 'Obtain a fresh blank approval form and a NEW deliberate reply for its exact presentation. No reply or approval is inferred.', source);
58
+ return { ...form, state: 'requires_new_reply', source, authorizes: false,
59
+ instruction: 'Deliver the current presentation before waiting for a NEW deliberate reply. Fill only the supplied reply field from that response; never copy approval_value as a decision. ' + (form.instruction ?? '') };
60
+ }
61
+ return { ...form, state: form.required_inputs.length ? 'form' : 'ready', source, authorizes: false,
62
+ instruction: 'Use this one exact call. Supply only its named required inputs from actual authored content or review; do not rebuild IDs, bindings or a Raw envelope. ' + (form.instruction ?? '') };
63
+ }
64
+ function authoringKey(result, report) {
65
+ if (report.format !== 'document_bundle_v2' || !/^sha256:[0-9a-f]{64}$/u.test(report.manifest_digest ?? '')) return null;
66
+ return canonical({ manifest: report.manifest_digest,
67
+ target_id: result.target?.target_id ?? result.binding?.target_id ?? report.target_id ?? null,
68
+ target: result.target?.governance_target ?? result.target?.display_path ?? null,
69
+ run_id: report.run_id ?? null, revision_id: report.revision_id ?? null, planning: report.planning ?? null,
70
+ owner: report.authoring_owner ?? null, artifact_language: report.artifact_language ?? null,
71
+ presentation_language: report.presentation_language ?? null });
72
+ }
73
+ function authoringRevision(key) {
74
+ const { manifest, ...binding } = JSON.parse(key);
75
+ return canonical(binding);
76
+ }
77
+ function authoringScope(key) {
78
+ const { manifest, revision_id, ...scope } = JSON.parse(key);
79
+ return canonical(scope);
80
+ }
81
+
82
+ // A connection-local projection of supplied actions, not an executor, permission
83
+ // decision or proof that the model has read/reviewed all source pages.
84
+ export function createNextActionProjection({ maxEntries = 32, isAvailable = () => true } = {}) {
85
+ if (!Number.isSafeInteger(maxEntries) || maxEntries < 1 || maxEntries > 32) throw Error('next_action_cache_limit_invalid');
86
+ if (typeof isAvailable !== 'function') throw Error('next_action_availability_invalid');
87
+ const forms = new Map(), superseded = new Set();
88
+ function available(form) {
89
+ const normal = formValue(form);
90
+ if (!normal) return false;
91
+ try { return isAvailable(clone(normal.call)) === true; } catch { return false; }
92
+ }
93
+ function remember(key, form) {
94
+ if (!key) return;
95
+ const revision = authoringRevision(key);
96
+ if (superseded.has(revision)) return;
97
+ if (!available(form)) { forms.delete(key); return; }
98
+ // A newly supplied first-page form for this exact authoring scope replaces
99
+ // cached forms from its earlier revision. Never refresh their bindings, or
100
+ // let a later old page revive them. Other targets/Runs/owners stay intact.
101
+ const scope = authoringScope(key);
102
+ for (const prior of forms.keys()) if (authoringScope(prior) === scope && authoringRevision(prior) !== revision) {
103
+ forms.delete(prior); superseded.add(authoringRevision(prior));
104
+ }
105
+ while (superseded.size > maxEntries) superseded.delete(superseded.values().next().value);
106
+ forms.delete(key); forms.set(key, clone(form));
107
+ while (forms.size > maxEntries) forms.delete(forms.keys().next().value);
108
+ }
109
+ function rememberAuthoring(result) {
110
+ if (result?.terminal === true || result?.outcome !== 'inspect_result' || result.operation !== 'authoring-inputs') return;
111
+ const report = result.report;
112
+ if (!object(report) || report.available === false || !report.material_call
113
+ || report.page_index !== undefined && report.page_index !== 0) return;
114
+ for (const owner of [result, result.continuation, result.navigation, report, result.family_result].filter(object))
115
+ if (owner.next_calls !== undefined && owner.next_calls !== null && !Array.isArray(owner.next_calls)
116
+ || owner.recording_calls !== undefined && owner.recording_calls !== null && !Array.isArray(owner.recording_calls)) return;
117
+ remember(authoringKey(result, report), report.material_call);
118
+ }
119
+ function fromContext(result, source) {
120
+ if (result.terminal === true) return terminal(result, source);
121
+ if (['rejected', 'recovery_required', 'effect_unknown', 'invalid_input', 'evaluator_error', 'target_unresolved'].includes(result.outcome))
122
+ return base('requires_source', 'This operation did not establish a successful normal continuation. Preserve its original receipt and recovery instructions; no write form is selected.', source);
123
+ const report = object(result.report) ? result.report : null;
124
+ for (const owner of [result, result.continuation, result.navigation, report, result.family_result].filter(object))
125
+ if (owner.next_calls !== undefined && owner.next_calls !== null && !Array.isArray(owner.next_calls)
126
+ || owner.recording_calls !== undefined && owner.recording_calls !== null && !Array.isArray(owner.recording_calls))
127
+ return base('requires_source', 'The supplied action list is malformed. Preserve the existing outcome and obtain the canonical action source.', source);
128
+ if (Object.hasOwn(result, 'material_call')) {
129
+ const material = formValue(result.material_call);
130
+ // This is an explicit correction after accepted private staging, not a
131
+ // ready write or permission to bypass the source's recording decision.
132
+ if (result.outcome !== 'accepted' || result.historical_effect === true || result.source_validation?.recordable !== false
133
+ || report?.available === false || report?.complete === false
134
+ || !material || material.call.tool !== 'agdf_record' || material.operation?.kind !== 'material.stage'
135
+ || material.state === 'transport_unavailable' || material.transport_reason
136
+ || !material.required_inputs.length || new Set(material.required_inputs).size !== material.required_inputs.length
137
+ || Object.keys(material.call.arguments.inputs).length || !available(material))
138
+ return base('requires_source', 'No complete authored correction form was supplied. Preserve the source validation and receipt; obtain the canonical correction source without constructing a new call.', source + '.material_call');
139
+ const competing = [...(result.recording_calls ?? []), ...(result.next_calls ?? []),
140
+ ...(result.continuation?.next_calls ?? []), ...(report?.next_calls ?? []),
141
+ ...(result.navigation?.next_calls ?? []), ...(result.family_result?.next_calls ?? []),
142
+ ...(result.approval_call ? [result.approval_call] : []), ...(report?.prepared_call ? [report.prepared_call] : []),
143
+ ...(report?.material_call ? [report.material_call] : [])];
144
+ if (competing.some(value => !value))
145
+ return base('requires_source', 'The correction action list is malformed. Preserve the source validation and obtain the canonical correction source.', source + '.material_call');
146
+ return selectForms([result.material_call, ...competing], source + '.material_call');
147
+ }
148
+ if (result.approval_call && result.presentation_delivery && !result.historical_effect && !result.presentation_delivery.historical_delivery
149
+ && ['accepted', 'already_applied'].includes(result.outcome)) return selectForms([result.approval_call], source + '.approval_call', { forceReply: true });
150
+ if (Array.isArray(result.recording_calls) && result.recording_calls.length)
151
+ return selectForms(result.recording_calls, source + '.recording_calls');
152
+ if (result.operation === 'operation-contract' && report?.prepared_call && report.available === false)
153
+ return base('requires_source', 'The operation-contract report is unavailable. Preserve its original binding and recovery instructions; no write form is selected.', source + '.report');
154
+ if (result.operation === 'operation-contract' && report?.prepared_call)
155
+ return selectForms([report.prepared_call], source + '.report.prepared_call');
156
+ if (result.operation === 'authoring-inputs' && report) {
157
+ if (report.available === false)
158
+ return base('requires_source', 'The authoring source is unavailable. Preserve its original binding and recovery instructions; no staging form is selected.', source + '.report');
159
+ const key = authoringKey(result, report);
160
+ if (report.material_call && (report.page_index === 0 || report.page_index === undefined)) remember(key, report.material_call);
161
+ if (key && superseded.has(authoringRevision(key)))
162
+ return base('requires_source', 'A newly supplied first-page form superseded this authoring revision. Preserve the selected source and obtain its canonical current form; no older binding or cached form is revived.', source + '.report');
163
+ if (report.complete !== true) {
164
+ if (report.next_calls?.length) {
165
+ const next = selectForms(report.next_calls, source + '.report.next_calls', { readOnly: true });
166
+ return next.state === 'ready' ? { ...next, state: 'read_required',
167
+ instruction: 'Read this exact next page before authoring. Retain earlier bytes and respect fragment identities; page transport does not prove review. ' + next.instruction } : next;
168
+ }
169
+ return base('requires_source', 'The authoring source is incomplete and no exact next-page call was supplied. Do not stage or edit incomplete content.', source + '.report');
170
+ }
171
+ if (report.authoring_scope === 'delivery-closeout')
172
+ return base('idle', 'The bound closeout evidence is complete. Use the current control and evidence for the requested handoff.', source + '.report');
173
+ let material = report.material_call ?? (key && forms.get(key));
174
+ if (material && !available(material)) {
175
+ if (key) forms.delete(key);
176
+ material = null;
177
+ }
178
+ if (material) return selectForms([material], source + (report.material_call ? '.report.material_call' : '.cached_material_call'));
179
+ if (report.first_page_call) {
180
+ const next = selectForms([report.first_page_call], source + '.report.first_page_call', { readOnly: true });
181
+ return next.state === 'ready' ? { ...next, state: 'read_required',
182
+ instruction: 'No first-page form is retained for this exact manifest. Read the supplied first page; never derive a cursor, reference or new binding. ' + next.instruction } : next;
183
+ }
184
+ return base('requires_source', 'No authoring form is available for this exact manifest. Obtain its canonical first page; do not reuse another target, revision or manifest.', source + '.report');
185
+ }
186
+ const supplied = [...(result.next_calls ?? []), ...(result.continuation?.next_calls ?? []),
187
+ ...(report?.next_calls ?? []), ...(result.navigation?.next_calls ?? []), ...(result.family_result?.next_calls ?? [])];
188
+ if (supplied.length) return selectForms(supplied, source + '.next_calls');
189
+ const resume = [...(result.resume_call ? [result.resume_call] : []),
190
+ ...(result.continuation?.resume_call ? [result.continuation.resume_call] : [])];
191
+ if (resume.length) return selectForms(resume, source + '.resume_call');
192
+ if ([result, result.continuation, report].filter(object).some(owner => owner.recovery_only?.unavailable_calls?.length))
193
+ return base('requires_source', 'No normal call could be registered. The exact original requests are retained only in recovery_only; follow original-operation recovery without creating new identities.', source);
194
+ return base('idle', 'No unique next action was supplied. Follow the canonical current-state instruction; no tool call is inferred.', source);
195
+ }
196
+ return Object.freeze({
197
+ project(domain) {
198
+ const result = clone(domain);
199
+ // An adapter may already have loaded one safe page after this result.
200
+ // Retain the exact outer first-page form before selecting that nested
201
+ // context; incomplete nested pages still select only their supplied read.
202
+ rememberAuthoring(result);
203
+ if (result.terminal === true) result.next_action = terminal(result, 'outer');
204
+ else if (result.next_read) {
205
+ const read = result.next_read, nested = read.result;
206
+ // An explicit null means the exact read could not be retained. Its Raw
207
+ // execution record remains evidence/recovery, never a normal fallback.
208
+ const retry = Object.hasOwn(read, 'call') ? read.call : read;
209
+ if (read.failure?.phase === 'validation') result.next_action = base('requires_source',
210
+ 'The supplied read could not be validated. Preserve the original outcome and receipt; obtain the canonical read source without repeating the write.', 'next_read');
211
+ else if (nested?.terminal === true) result.next_action = terminal(nested, 'next_read.result');
212
+ else if (!read.error && read.failed !== true && nested?.outcome === 'inspect_result' && nested.report?.available !== false)
213
+ result.next_action = fromContext(nested, 'next_read.result');
214
+ else if (callValue(retry)?.tool === 'agdf_inspect') {
215
+ const next = selectForms([retry], 'next_read', { readOnly: true });
216
+ result.next_action = next.state === 'ready' ? { ...next, state: 'read_required',
217
+ instruction: 'The follow-up read did not produce an available nonterminal result. Retry only this exact read when appropriate; never repeat the outer write. ' + next.instruction } : next;
218
+ } else result.next_action = base('requires_source', 'The follow-up read failed without an exact supplied read call. Preserve the outer outcome/receipt; do not retry the outer write.', 'next_read');
219
+ } else result.next_action = fromContext(result, 'outer');
220
+ result.next_action.context_path = result.next_read?.result ? 'next_read.result' : 'outer';
221
+ if (result.next_read?.result?.report) result.next_action.instruction +=
222
+ ' The already loaded source report is response.structuredContent.next_read.result.report. Consume that report without another inspect call.';
223
+ return result;
224
+ },
225
+ close() { forms.clear(); superseded.clear(); },
226
+ });
227
+ }
@@ -0,0 +1,306 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+
3
+ const writeTools = new Set(['agdf_project', 'agdf_run', 'agdf_prepare', 'agdf_record', 'agdf_approve', 'agdf_revise', 'agdf_closeout']);
4
+ const tools = new Set([...writeTools, 'agdf_inspect']);
5
+ const referencePattern = /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/u;
6
+ const WHOLE_PAYLOAD = '/command/payload';
7
+ const referenceSchema = { type: 'object', additionalProperties: false, required: ['prepared_call_id', 'inputs'], properties: {
8
+ prepared_call_id: { type: 'string', pattern: '^[0-9a-f-]{36}$' },
9
+ inputs: { type: 'object', maxProperties: 16 },
10
+ } };
11
+ const inputNames = pointers => {
12
+ const parts = pointers.map(pointer => pointer.split('/').slice(3));
13
+ const leaves = parts.map(path => path.at(-1) || 'payload');
14
+ const names = parts.map((path, index) => {
15
+ const base = /^[a-z_]/u.test(leaves[index]) && leaves.filter(leaf => leaf === leaves[index]).length === 1
16
+ ? leaves[index] : path.join('_') || 'payload';
17
+ return /^[a-z_]/u.test(base) ? base : `field_${base}`;
18
+ });
19
+ // Flattened paths may collide with literal underscore field names. The
20
+ // deterministic suffix belongs to this form only, never to a binding or UUID.
21
+ const reserved = new Set(names), used = new Set();
22
+ return names.map(base => {
23
+ let name = base, index = 1;
24
+ if (names.filter(candidate => candidate === base).length > 1 || used.has(name)) {
25
+ do { name = `${base}_${index++}`; } while (reserved.has(name) || used.has(name));
26
+ }
27
+ used.add(name); return name;
28
+ });
29
+ };
30
+
31
+ // Argument storage, never permission or policy. Owned plugin publishers may
32
+ // retain exact templates across connections; ad-hoc servers stay connection-local. The original
33
+ // group, immutable binding, UUID and every Core validator still execute unchanged.
34
+ export function preparedTransportSchema(name, schema) {
35
+ if (!tools.has(name)) return schema;
36
+ const { properties, $defs, type, additionalProperties, ...guards } = schema;
37
+ return { type, additionalProperties, required: [], ...($defs ? { $defs } : {}),
38
+ properties: { ...properties, ...referenceSchema.properties,
39
+ ...(name === 'agdf_inspect' ? { inputs: { type: 'object', maxProperties: 0 } }
40
+ : name === 'agdf_prepare' ? { inputs: { ...referenceSchema.properties.inputs, description: 'Named required fields; ready: {}.' } } : {}) },
41
+ anyOf: [{ ...guards, not: { anyOf: [...(guards.not ? [guards.not] : []),
42
+ { required: ['prepared_call_id'] }, { required: ['inputs'] }] } },
43
+ { required: referenceSchema.required, maxProperties: 2 }],
44
+ };
45
+ }
46
+ export function createPreparedCallTransport({ now = Date.now, maxEntries = 256, lifetimeMs = 30 * 60_000, validateRead = () => false, store } = {}) {
47
+ if (typeof validateRead !== 'function') throw Error('prepared_read_validator_invalid');
48
+ if (store && (typeof store.load !== 'function' || typeof store.register !== 'function')) throw Error('prepared_call_store_unavailable');
49
+ const rows = new Map(), signatures = new Map(), expired = new Map();
50
+ let unavailableReason = 'prepared_call_unavailable';
51
+ const storeError = error => ['runtime_provenance_invalid', 'dispatch_busy', 'prepared_call_store_unavailable'].includes(error?.message)
52
+ ? error.message : 'prepared_call_store_unavailable';
53
+ const fail = code => { throw Object.assign(Error(code), { facts: { code, dispatch: 'not_dispatched', field: 'arguments' } }); };
54
+ function expire() {
55
+ for (const [id, row] of rows) if (now() - row.created >= lifetimeMs) {
56
+ rows.delete(id); signatures.delete(row.signature); expired.set(id, now());
57
+ }
58
+ // Tombstones distinguish observed expiry from a typo without keeping an
59
+ // unbounded connection history or retaining the expired raw arguments.
60
+ while (expired.size > maxEntries) expired.delete(expired.keys().next().value);
61
+ }
62
+ function referenceState(id) {
63
+ if (typeof id !== 'string' || !id) return 'reference_empty';
64
+ if (!referencePattern.test(id)) return 'reference_invalid';
65
+ expire();
66
+ if (store) {
67
+ try {
68
+ const retained = store.load(id);
69
+ if (retained.state === 'available') {
70
+ const parsed = JSON.parse(retained.value), signature = createHash('sha256').update(retained.value).digest('hex');
71
+ if (retained.signature !== signature || !Number.isSafeInteger(retained.created) || retained.created < 0
72
+ || Buffer.byteLength(retained.value) > 65536 || !validTemplate(parsed.call, parsed.required)) throw Error('runtime_provenance_invalid');
73
+ if (now() - retained.created >= lifetimeMs) return 'reference_expired';
74
+ if (!rows.has(id) && rows.size >= maxEntries) { unavailableReason = 'prepared_call_unavailable'; return 'reference_unavailable'; }
75
+ rows.set(id, { call: parsed.call, required: parsed.required, names: inputNames(parsed.required), signature, created: retained.created });
76
+ signatures.set(signature, id); return 'available';
77
+ }
78
+ if (retained.state === 'reference_expired') return 'reference_expired';
79
+ if (retained.state !== 'reference_unknown') throw Error('runtime_provenance_invalid');
80
+ return 'reference_unknown';
81
+ } catch (error) { unavailableReason = storeError(error); return 'reference_unavailable'; }
82
+ }
83
+ return rows.has(id) ? 'available' : expired.has(id) ? 'reference_expired' : 'reference_unknown';
84
+ }
85
+ const operation = call => call.tool === 'agdf_inspect'
86
+ ? { kind: 'inspect.read', read_only: true, operation: call.arguments.operation,
87
+ ...Object.fromEntries(['target_id', 'run_id', 'expected_revision_id',
88
+ 'planning', 'gate', 'presentation_id', 'module', 'cursor']
89
+ .filter(key => call.arguments[key] !== undefined).map(key => [key, structuredClone(call.arguments[key])])) }
90
+ : ({ kind: call.arguments.command?.kind ?? null,
91
+ ...Object.fromEntries(['operation_id', 'target_id', 'run_id', 'expected_revision_id']
92
+ .filter(key => call.arguments[key] !== undefined).map(key => [key, call.arguments[key]])),
93
+ ...Object.fromEntries(['gate', 'presentation_id'].filter(key => call.arguments.command?.payload?.[key] !== undefined)
94
+ .map(key => [key, call.arguments.command.payload[key]])) });
95
+ function validTemplate(call, required = []) {
96
+ if (!tools.has(call?.tool) || !call.arguments || typeof call.arguments !== 'object' || Array.isArray(call.arguments)
97
+ || !Array.isArray(required)) return false;
98
+ if (call.tool === 'agdf_inspect') {
99
+ if (required.length || typeof call.arguments.operation !== 'string' || !call.arguments.operation
100
+ || ['prepared_call_id', 'inputs', 'command'].some(key => Object.hasOwn(call.arguments, key))) return false;
101
+ // Only the owning server can attest the original read schema and tool's
102
+ // read-only declaration. This callback never fills missing selectors.
103
+ try { return validateRead(structuredClone(call)) === true; } catch { return false; }
104
+ }
105
+ if (!referencePattern.test(call.arguments.operation_id ?? '')
106
+ || typeof call.arguments.command?.kind !== 'string' || !call.arguments.command.kind || !Array.isArray(required)
107
+ || required.length > 16 || new Set(required).size !== required.length
108
+ // Core asks for the whole payload only when no single variant applies;
109
+ // it is then the one input, never combined with nested field pointers.
110
+ || required.includes(WHOLE_PAYLOAD) && required.length !== 1
111
+ || required.some(p => !/^\/command\/payload(?:\/(?:[a-z_]+|[0-9]+))*$/u.test(p)
112
+ || p.split('/').some(k => ['__proto__', 'prototype', 'constructor'].includes(k)))) return false;
113
+ return true;
114
+ }
115
+ function originalProjection(raw, fields, names = inputNames(fields)) {
116
+ return { required_inputs: names, input_fields: names.map(name => ({ name, required: true })), operation: operation(raw), recovery_only: {
117
+ original_call: structuredClone(raw), required_inputs: [...fields], authorizes: false,
118
+ input_fields: names.map((name, index) => ({ name, pointer: fields[index] })),
119
+ instruction: raw.tool === 'agdf_inspect'
120
+ ? 'Recovery only, never the normal call path. Across reconnect, preserve this exact original read and its target, Run, revision, cursor and original operation-status selection. Never infer a target, refresh a selected revision or replace the original status UUID.'
121
+ : 'Recovery only, never the normal call path. Preserve this exact original raw call and UUID across reconnect. For an uncertain dispatch, first observe the original operation and retain exactly the inputs already submitted; never refresh the revision, invent a UUID or change the payload to escape uncertainty.' } };
122
+ }
123
+ const unregisteredRecovery = (call, required = []) => validTemplate(call, required) ? originalProjection(call, required) : null;
124
+ function submit(call, required = []) {
125
+ if (!validTemplate(call, required)) return undefined;
126
+ const value = JSON.stringify({ call, required });
127
+ if (Buffer.byteLength(value) > 65536) return undefined;
128
+ expire();
129
+ const signature = createHash('sha256').update(value).digest('hex');
130
+ let id = signatures.get(signature);
131
+ if (!id) {
132
+ if (rows.size >= maxEntries) return undefined;
133
+ let created = now();
134
+ if (store) {
135
+ try {
136
+ const retained = store.register({ value, signature, created });
137
+ if (!retained) return undefined;
138
+ if (!referencePattern.test(retained.id ?? '') || !Number.isSafeInteger(retained.created) || retained.created < 0) throw Error('runtime_provenance_invalid');
139
+ id = retained.id; created = retained.created;
140
+ } catch (error) { unavailableReason = storeError(error); return undefined; }
141
+ } else id = randomUUID();
142
+ signatures.set(signature, id);
143
+ rows.set(id, { call: JSON.parse(value).call, required: [...required], names: inputNames(required), signature, created });
144
+ } else if (store && referenceState(id) !== 'available') {
145
+ return undefined;
146
+ }
147
+ return { tool: call.tool, arguments: { prepared_call_id: id, inputs: {} } };
148
+ }
149
+ function projectCall(call, required = []) {
150
+ unavailableReason = 'prepared_call_unavailable';
151
+ if (!tools.has(call?.tool)) return call;
152
+ const alreadyPrepared = Object.hasOwn(call.arguments ?? {}, 'prepared_call_id');
153
+ const saved = alreadyPrepared && referenceState(call.arguments.prepared_call_id) === 'available'
154
+ ? rows.get(call.arguments.prepared_call_id) : null;
155
+ if (alreadyPrepared && (!saved || saved.call.tool !== call.tool
156
+ || Object.keys(call.arguments).some(key => !['prepared_call_id', 'inputs'].includes(key))
157
+ || !call.arguments.inputs || typeof call.arguments.inputs !== 'object' || Array.isArray(call.arguments.inputs)
158
+ || call.tool === 'agdf_inspect' && Object.keys(call.arguments.inputs).length)) return null;
159
+ const raw = saved?.call ?? call, fields = saved?.required ?? required;
160
+ const prepared = alreadyPrepared ? { tool: call.tool, arguments: structuredClone(call.arguments) } : submit(raw, fields);
161
+ if (!prepared) return null;
162
+ const names = [...(saved?.names ?? rows.get(prepared.arguments.prepared_call_id).names)];
163
+ return { ...prepared, ...originalProjection(raw, fields, names) };
164
+ }
165
+ return {
166
+ // Transport availability only: never a gate, review or permission decision.
167
+ // An offered input form legitimately has no authored values yet.
168
+ isAvailable(call) {
169
+ const args = call?.arguments;
170
+ if (!tools.has(call?.tool) || !args || typeof args !== 'object'
171
+ || !Object.hasOwn(args, 'prepared_call_id') || !Object.hasOwn(args, 'inputs')
172
+ || !args.inputs || typeof args.inputs !== 'object' || Array.isArray(args.inputs)
173
+ || Object.keys(args).some(key => !['prepared_call_id', 'inputs'].includes(key))
174
+ || referenceState(args.prepared_call_id) !== 'available') return false;
175
+ return rows.get(args.prepared_call_id).call.tool === call.tool
176
+ && (call.tool !== 'agdf_inspect' || Object.keys(args.inputs).length === 0);
177
+ },
178
+ decorate: function projectResult(result) {
179
+ const value = structuredClone(result);
180
+ // Explicit terminal/uncertain recovery can be resumed on a new connection.
181
+ // Keep its read requests independent of shared normal-form objects.
182
+ if (value.recovery && typeof value.recovery === 'object') value.recovery = structuredClone(value.recovery);
183
+ if (value.next_read?.result) value.next_read.result = projectResult(value.next_read.result);
184
+ if (value.next_read?.tool === 'agdf_inspect' && value.next_read.arguments) {
185
+ // tool/arguments are the honest record of the adapter's actual read.
186
+ // A separate normal retry retains that exact read without retyping it.
187
+ const raw = { tool: value.next_read.tool, arguments: value.next_read.arguments };
188
+ const retry = projectCall(raw);
189
+ value.next_read.call = retry ? { tool: retry.tool, arguments: retry.arguments } : null;
190
+ const projection = retry ?? unregisteredRecovery(raw);
191
+ if (projection) for (const key of ['required_inputs', 'input_fields', 'operation', 'recovery_only'])
192
+ value.next_read[key] = projection[key];
193
+ if (!retry) value.next_read.transport_reason = unavailableReason;
194
+ }
195
+ for (const owner of [value, value.report, value.continuation, value.recovery, value.navigation,
196
+ value.family_result, value.presentation_delivery, value.next_action].filter(Boolean)) {
197
+ const unavailable = [];
198
+ const projectReadyCall = call => {
199
+ if (owner === value.recovery && call?.tool === 'agdf_inspect') return call;
200
+ const projected = projectCall(call);
201
+ if (!projected) {
202
+ const recovery = unregisteredRecovery(call);
203
+ if (recovery) unavailable.push({ ...recovery.recovery_only, operation: recovery.operation, transport_reason: unavailableReason });
204
+ }
205
+ return projected;
206
+ };
207
+ const projectHelpers = container => {
208
+ for (const key of ['resume_call', 'operation_status_call', 'contract_call', 'first_page_call', 'larger_source_call'])
209
+ if (container?.[key]) container[key] = projectReadyCall(container[key]);
210
+ };
211
+ for (const form of [owner.prepared_call, owner.material_call, owner.approval_call, ...owner.recording_calls ?? []].filter(Boolean)) {
212
+ if (owner === value.recovery && form.call?.tool === 'agdf_inspect') continue;
213
+ const raw = form.call, projected = projectCall(raw, form.required_inputs);
214
+ delete form.submit;
215
+ if (!tools.has(raw?.tool)) continue;
216
+ form.call = projected ? { tool: projected.tool, arguments: projected.arguments } : null;
217
+ if (projected) {
218
+ form.required_inputs = projected.required_inputs; form.input_fields = projected.input_fields;
219
+ form.operation = projected.operation; form.recovery_only = projected.recovery_only;
220
+ form.instruction = (raw.tool === 'agdf_inspect'
221
+ ? 'Use call.tool with call.arguments unchanged, including inputs:{}. The adapter retains the exact read target and selectors. Do not rebuild an envelope or fill any inputs. recovery_only retains the original read for reconnect; it grants no authority. '
222
+ : 'Use call.tool with call.arguments. Fill only call.arguments.inputs using the named required_inputs fields; keep its reference unchanged. The adapter maps those names to the exact stored command fields and retains binding and UUID. Do not construct a raw envelope or copy technical JSON paths. Keep authored text as string data using host-supported serialization. Check failure before reading returned fields. recovery_only is separate original-request recovery, never the normal write path. ') + (form.instruction ?? '');
223
+ } else {
224
+ const recovery = unregisteredRecovery(raw, form.required_inputs);
225
+ if (recovery) Object.assign(form, recovery);
226
+ form.state = 'transport_unavailable'; form.transport_reason = unavailableReason;
227
+ form.authorizes = false;
228
+ }
229
+ projectHelpers(form);
230
+ projectHelpers(form.content_contract);
231
+ }
232
+ if (owner.next_calls) owner.next_calls = owner.next_calls.map(projectReadyCall).filter(Boolean);
233
+ projectHelpers(owner);
234
+ projectHelpers(owner.content_contract);
235
+ if (unavailable.length) owner.recovery_only = { ...owner.recovery_only, authorizes: false,
236
+ unavailable_calls: [...(owner.recovery_only?.unavailable_calls ?? []), ...unavailable] };
237
+ for (const call of owner.next_calls ?? []) if (call?.arguments?.prepared_call_id) {
238
+ call.required_inputs = [];
239
+ call.submission_instruction = 'This call is complete. Forward arguments unchanged, including inputs:{}. No cloning helper, new reference, UUID or binding is needed. Core still checks current eligibility.';
240
+ }
241
+ }
242
+ // The normal action has exactly the same call shape as named forms and
243
+ // ready calls; its original raw request stays in the explicit recovery branch.
244
+ if (value.next_action?.call) {
245
+ const projected = projectCall(value.next_action.call, value.next_action.required_inputs);
246
+ if (projected) value.next_action = { ...value.next_action,
247
+ call: { tool: projected.tool, arguments: projected.arguments }, required_inputs: projected.required_inputs,
248
+ input_fields: projected.input_fields, operation: projected.operation, recovery_only: projected.recovery_only };
249
+ else if (tools.has(value.next_action.call?.tool))
250
+ value.next_action = { ...value.next_action, ...(unregisteredRecovery(value.next_action.call, value.next_action.required_inputs) ?? {}),
251
+ state: 'transport_unavailable', authorizes: false, transport_reason: unavailableReason, call: null };
252
+ }
253
+ return value;
254
+ },
255
+ validationHint(name, input) {
256
+ if (!tools.has(name) || !input || typeof input !== 'object') return '';
257
+ const id = input.prepared_call_id ?? input.submit_id;
258
+ const prefix = 'Normal call arguments contain only prepared_call_id and inputs. Copy the supplied call.arguments; never submit_id, a new ID or duplicated raw fields. ';
259
+ if (typeof id !== 'string') {
260
+ if (!Object.hasOwn(input, 'inputs')) return '';
261
+ const raw = Object.keys(input).some(key => !['inputs', 'prepared_call_id', 'submit_id'].includes(key));
262
+ return prefix + (raw ? 'A full raw call cannot contain inputs. ' : 'The prepared reference is missing. ')
263
+ + 'Fill only its named required_inputs fields. Raw requests belong only to the explicit recovery path. No operation was dispatched.';
264
+ }
265
+ const state = referenceState(id);
266
+ if (state === 'reference_unavailable') return 'The owned reference store is unavailable or could not establish its integrity. Preserve the original receipt and saved request; no operation was dispatched by this attempt.';
267
+ if (state !== 'available') return state === 'reference_expired'
268
+ ? 'The supplied reference was issued previously and its original lifetime has expired. Use saved original-request/UUID observation and recovery; never generate another binding or UUID. No operation was dispatched.'
269
+ : state === 'reference_empty' ? 'The prepared reference is empty. Copy the existing reference in the supplied call.arguments; never use an empty placeholder. No operation was dispatched.'
270
+ : state === 'reference_invalid' ? 'The prepared reference is malformed. Copy the supplied call.arguments unchanged; never retype or autocorrect a reference. No operation was dispatched.'
271
+ : 'The reference is unknown on this connection; this is not proof of expiry. Copy the exact supplied call.arguments or use saved original-request/UUID recovery. Never guess or autocorrect. No operation was dispatched.';
272
+ const row = rows.get(id);
273
+ if (row.call.tool !== name) return 'A prepared reference cannot cross permission groups. No operation was dispatched.';
274
+ const conflict = Object.entries(input).some(([key, value]) => !['prepared_call_id', 'submit_id', 'inputs'].includes(key)
275
+ && JSON.stringify(row.call.arguments[key]) !== JSON.stringify(value));
276
+ if (conflict) return 'Do not merge raw and prepared calls: their fixed fields conflict. Review the intended binding; neither binding was executed.';
277
+ return (prefix + (row.required.length
278
+ ? `Fill exactly these named inputs from actual author/review/reply data: ${JSON.stringify(row.names)}. Do not invent values or mix named and legacy pointer inputs.`
279
+ : `Exact ready call: ${JSON.stringify({ tool: name, arguments: { prepared_call_id: id, inputs: {} } })}`)).slice(0, 768);
280
+ },
281
+ resolve(name, input) {
282
+ if (!Object.hasOwn(input, 'prepared_call_id')) return input;
283
+ const state = referenceState(input.prepared_call_id);
284
+ if (state !== 'available') return fail(state === 'reference_expired' ? 'session_expired'
285
+ : state === 'reference_unknown' ? 'prepared_call_unknown'
286
+ : state === 'reference_unavailable' ? unavailableReason === 'prepared_call_unavailable' ? 'resource_limit' : unavailableReason
287
+ : 'command_schema_invalid');
288
+ const row = rows.get(input.prepared_call_id);
289
+ if (row.call.tool !== name || Object.keys(input).some(k => !['prepared_call_id', 'inputs'].includes(k))
290
+ || !input.inputs || typeof input.inputs !== 'object' || Array.isArray(input.inputs)
291
+ || Buffer.byteLength(JSON.stringify(input)) > 65536) return fail('command_schema_invalid');
292
+ const keys = Object.keys(input.inputs);
293
+ const named = keys.length === row.names.length && row.names.every(key => Object.hasOwn(input.inputs, key));
294
+ const legacy = keys.length === row.required.length && row.required.every(key => Object.hasOwn(input.inputs, key));
295
+ if (!named && !legacy) return fail('command_schema_invalid');
296
+ const args = structuredClone(row.call.arguments);
297
+ for (const [index, pointer] of row.required.entries()) {
298
+ const parts = pointer.slice(1).split('/'); let destination = args;
299
+ for (const part of parts.slice(0, -1)) destination = destination[part];
300
+ destination[parts.at(-1)] = structuredClone(input.inputs[named ? row.names[index] : pointer]);
301
+ }
302
+ return args;
303
+ },
304
+ close() { rows.clear(); signatures.clear(); expired.clear(); },
305
+ };
306
+ }
@@ -0,0 +1,62 @@
1
+ // Only a single, exact Core-supplied inspect call may be folded into a response.
2
+ // Dispatch can repair sealed relationships; no dispatch or command is auto-run.
3
+ const operations = new Set(['authoring-inputs', 'gate-check', 'operation-contract']);
4
+ // Only read results fold a follow-up read. A write result returns at once so a
5
+ // slow or large follow-up can never delay or enlarge the receipt of a committed
6
+ // write; its next read stays a normal supplied call.
7
+ const readableOutcome = new Set(['inspect_result', 'skill_continuation', 'intake_continuation', 'control_result']);
8
+
9
+ export function suppliedReadContinuation(result) {
10
+ if (!result || result.terminal === true || !readableOutcome.has(result.outcome)) return null;
11
+ if (result.outcome === 'inspect_result' && result.report?.available === false) return null;
12
+ // Source pages are consumed explicitly, in order. Folding page N+1 into page N
13
+ // would create two competing source locations and could lose the first form.
14
+ if (result.operation === 'authoring-inputs') return null;
15
+ // Bootstrap state and initialization have compact response contracts. Their
16
+ // supplied setup/Run operation-contract remains an explicit next action
17
+ // instead of duplicating the full command schema inside the bootstrap result.
18
+ if (result.operation === 'project-state' || result.binding?.kind === 'project.initialize') return null;
19
+ // These are authoritative normal next steps, not recovery or optional preview.
20
+ const lists = [result.next_calls, result.continuation?.next_calls,
21
+ result.report?.next_calls, result.family_result?.next_calls].filter(Array.isArray);
22
+ const candidates = new Map(lists.flat().filter(Boolean).map(call => [JSON.stringify([call.tool, call.arguments]), call]));
23
+ if (candidates.size !== 1) return null;
24
+ const call = [...candidates.values()][0];
25
+ if (call.tool !== 'agdf_inspect' || !operations.has(call.arguments?.operation)
26
+ || call.arguments?.planning && call.arguments?.run_id) return null;
27
+ return { tool: call.tool, arguments: structuredClone(call.arguments) };
28
+ }
29
+
30
+ export async function appendSafeReadContinuation(result, { execute, validate, allowed = true } = {}) {
31
+ let call, phase = 'selection';
32
+ // execute owns normal parsing, policy and result validation. A follow-up failure
33
+ // is separate from the original read result and never replaces it.
34
+ try {
35
+ call = allowed && suppliedReadContinuation(result);
36
+ if (!call) return result;
37
+ phase = 'validation';
38
+ if (!validate?.(call)) return result;
39
+ phase = 'execute';
40
+ const observed = await execute(call);
41
+ return { ...result, next_read: { ...call, result: observed, authorizes: false } };
42
+ } catch {
43
+ if (!call) return result;
44
+ return { ...result, next_read: { ...call, result: null, authorizes: false,
45
+ failure: { code: 'read_followup_unavailable', phase, original_effect_unchanged: true,
46
+ instruction: 'The original operation result and receipt remain authoritative. No write was repeated. Inspect the supplied read separately; never replay a successful write to obtain its next step.' } } };
47
+ }
48
+ }
49
+
50
+ // Core validates the original domain before this explicit MCP wire projection.
51
+ // Open result schemas already permit the additive fields; dispatch is closed.
52
+ export function nextActionOutputSchema(name, schema) {
53
+ if (name !== 'agdf_dispatch' || !schema) return schema;
54
+ return { ...schema, properties: { ...schema.properties,
55
+ next_action: { type: 'object', required: ['state', 'authorizes'],
56
+ properties: { state: { type: 'string' }, authorizes: { const: false } } },
57
+ next_read: { type: 'object', required: ['tool', 'arguments', 'result', 'authorizes'],
58
+ properties: { tool: { const: 'agdf_inspect' }, arguments: { type: 'object' },
59
+ result: { type: ['object', 'null'] }, authorizes: { const: false } } },
60
+ recovery_only: { type: 'object' },
61
+ } };
62
+ }