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
@@ -1,5 +1,6 @@
1
1
  import { baseResult, bindHostAction } from "./result.js";
2
2
  import { inspectArtefactRecordingMode } from '../control-state/run-artefact-recording.js';
3
+ import { preparedCommandCall } from '../control-state/prepared-control-calls.js';
3
4
  import { inspectProjectState } from './project-state.js';
4
5
  import process from "node:process";
5
6
  import { DISPATCH_RECOVERY } from "../interaction-catalog.js";
@@ -10,8 +11,9 @@ import { readRuntimeContract, runtimeContractModules } from "../resources/contra
10
11
  import { renderSkillDispatchInputRecovery, renderSkillDispatchRecovery, renderTaskTargetOrientation, renderActiveRunInventory, renderRunInventory } from "../interaction-presentation.js";
11
12
  import { resolveTaskTarget, TaskTargetInputError } from "../task-target-resolution.js";
12
13
  import { SKILL_DISPATCH_PRESENTATION_LANGUAGE_RECOVERY, SkillDispatchInputError, emptySkillDispatchTiming } from "../skill-dispatch/contract.js";
13
- import { CONTROL_INSPECT_CONTRACT_VERSION, CONTROL_INSPECT_SCHEMA_VERSION, ReadSelectionError, normalizeControlInspectInput, inspectContractHelp, OPERATION_CONTRACT_MODULES, PRESENTATION_CATALOG_MODULE } from "./contract.js";
14
+ import { CONTROL_INSPECT_CONTRACT_VERSION, CONTROL_INSPECT_SCHEMA_VERSION, ReadSelectionError, normalizeControlInspectInput, inspectContractHelp, inspectModuleRecoveryCall, OPERATION_CONTRACT_MODULES, PRESENTATION_CATALOG_MODULE } from "./contract.js";
14
15
  import { RUN_COMMAND_DESCRIPTORS, operationContract } from '../control-state/run-command-contract.js';
16
+ import { PROPOSAL_COMMAND_KINDS, PROPOSAL_MATERIAL_SLOT } from '../control-state/run-command-schema.js';
15
17
  import { inspectRunOperation } from '../control-state/run-operation-status.js';
16
18
  import { resolveControlCommandTarget } from '../control-state/approval-command-contract.js';
17
19
  import { readRunState } from '../control-evaluation/run-state.js';
@@ -132,6 +134,19 @@ export function createControlInspectService(dependencies = {}) {
132
134
  result.diagnostics = [{ code: "inspect_input_invalid", field,
133
135
  ...(inputError?.allowedValues?.length ? { allowed_values: [...inputError.allowedValues] } : {}),
134
136
  }];
137
+ if (field === 'module') {
138
+ const supplied = { operation: rawInput.operation,
139
+ ...Object.fromEntries([['module', 'contractModule'], ['working_directory', 'workingDirectory'],
140
+ ['primary_target', 'primaryTarget'], ['target_source', 'targetSource'], ['presentation_language', 'presentationLanguage'],
141
+ ['run_id', 'runId'], ['expected_revision_id', 'expectedRevisionId'], ['gate', 'gate'], ['target_id', 'targetId']]
142
+ .filter(([, key]) => rawInput[key] !== undefined).map(([field, key]) => [field, rawInput[key]])) };
143
+ // Preserve unsupported selectors too, so they prevent a misleading
144
+ // executable suggestion rather than disappearing from the new lookup.
145
+ for (const [field, key] of [['presentation_id', 'presentationId'], ['cursor', 'cursor'], ['planning', 'planning'], ['all_active', 'allActive']])
146
+ if (rawInput[key] !== undefined) supplied[field] = rawInput[key];
147
+ const next = inspectModuleRecoveryCall(supplied);
148
+ if (next) result.recovery.next_calls = [next];
149
+ }
135
150
  return bindHostAction(result);
136
151
  }
137
152
  timing.input_ms = round(milliseconds(started, now()));
@@ -208,7 +223,7 @@ export function createControlInspectService(dependencies = {}) {
208
223
  if (!valid) return { report: { available: false, reason: 'operation_binding_stale_or_invalid', authorizes: false }, presentation: null };
209
224
  if (input.operation === 'runtime-generations') return { report: dependencies.runtimeControl?.status()
210
225
  ?? { available: false, reason: 'connection_control_unavailable', authorizes: false }, presentation: null };
211
- const decision = gateCheck(target.governance_target, { runId: input.run_id, presentationLanguage: input.presentationLanguage });
226
+ const decision = gateCheck(target.governance_target, { runId: input.run_id, presentationLanguage: input.presentation_language });
212
227
  return { report: { available: true, run_id: input.run_id, revision_id: state.meta.revision_id,
213
228
  ui_rendering_support: 'unknown', action_qualification: { qualified: false, reason: 'host_context_unavailable', authorizes: false },
214
229
  business_readiness: { current_gate: decision.current_gate, status: decision.status,
@@ -221,15 +236,27 @@ export function createControlInspectService(dependencies = {}) {
221
236
  next_calls: [{ tool: input.group, kind: input.kind, instruction: contract.planning_capture?.instructions
222
237
  ?? 'Use the confirmed planning scope and original UUID; no Run/revision. Planning never approves a gate. Start a Run only from a deliberately selected complete source.' }] }, presentation: null };
223
238
  }
224
- if (['agdf_run', 'agdf_project'].includes(input.group) && !input.run_id) return { report: { ...operationContract(input.group, input.kind),
239
+ if (['agdf_run', 'agdf_project'].includes(input.group) && !input.run_id) {
240
+ const prepared = preparedCommandCall(input.group, input.kind, { ...input, presentation_language: input.presentation_language,
241
+ target_id: resolveControlCommandTarget(target.governance_target).target_id });
242
+ return { report: { ...operationContract(input.group, input.kind),
225
243
  binding: { target_id: resolveControlCommandTarget(target.governance_target).target_id },
226
- next_calls: [{ tool: input.group, kind: input.kind, instruction: input.group === 'agdf_project' ? 'Explicit fixed setup only. Use the confirmed existing Git root and one original UUID. No Run/revision, force, repair, install or approval.' : 'Use a new original operation UUID and confirmed title; there is no prior Run/revision.' }] }, presentation: null };
244
+ prepared_call: prepared, next_calls: prepared?.state === 'ready' ? [prepared.call] : [],
245
+ next_action: input.group === 'agdf_project' ? 'Explicit fixed setup only. No Run, repair, installation or approval.'
246
+ : 'Fill the prepared title from the authorized original request, preserving its UUID and target. No prior Run/revision.' }, presentation: null };
247
+ }
227
248
  const state = readRunState(target.governance_target, { runId: input.run_id });
228
249
  const targetId = resolveControlCommandTarget(target.governance_target).target_id;
229
250
  const valid = parseRunState(state.content, input.run_id).valid && state.meta?.revision_id === input.expected_revision_id
230
251
  && runSealState(target.governance_target, state.content).status === 'valid';
231
252
  return { report: valid ? { ...operationContract(input.group, input.kind, { gate: input.gate ?? state.current_gate }),
253
+ prepared_call: preparedCommandCall(input.group, input.kind, { ...input, presentation_language: input.presentation_language, target_id: targetId },
254
+ { gate: input.gate ?? state.current_gate, recording: inspectArtefactRecordingMode(state, input.gate ?? state.current_gate) }),
232
255
  ...(input.kind === 'artefact.record' ? { recording: inspectArtefactRecordingMode(state, input.gate ?? state.current_gate) } : {}),
256
+ // Revision proposals are staged in their own slot. Offer that staging form with the
257
+ // revision commands and beside a material.stage form, whose prepared_call uses the gate's slot.
258
+ ...(PROPOSAL_COMMAND_KINDS.includes(input.kind) || input.kind === 'material.stage' ? { material_call: preparedCommandCall('agdf_record', 'material.stage',
259
+ { ...input, presentation_language: input.presentation_language, target_id: targetId }, { gate: PROPOSAL_MATERIAL_SLOT }) } : {}),
233
260
  ...(input.contract_module === PRESENTATION_CATALOG_MODULE ? {
234
261
  inspect_contract: inspectContractHelp(),
235
262
  presentation_catalog: readPresentationCatalog(target.governance_target, { runId: input.run_id,
@@ -243,7 +270,7 @@ export function createControlInspectService(dependencies = {}) {
243
270
  quality_records: sourceRevisionQualityFacts(state, path => { try { return readHistoryBytes(target.governance_target, path).toString('utf8'); } catch { return undefined; } }),
244
271
  } } : {}),
245
272
  binding: { target_id: targetId, run_id: input.run_id, expected_revision_id: input.expected_revision_id },
246
- current: (() => { const decision = gateCheck(target.governance_target, { runId: input.run_id, presentationLanguage: input.presentationLanguage });
273
+ current: (() => { const decision = gateCheck(target.governance_target, { runId: input.run_id, presentationLanguage: input.presentation_language });
247
274
  return { current_gate: decision.current_gate, lifecycle: state.meta.lifecycle, status: decision.status, missing_approval: decision.missing_approval,
248
275
  next_operation: decision.next_operation, completion: decision.completion,
249
276
  artefacts: [...state.artefacts].filter(([type]) => ['UR', 'PRD', 'SD', 'TP', 'Brownfield Review', 'UX Intent Definition', 'Brownfield Analysis', 'CD+Tests', 'TP Review', 'Clean Implementation Review', 'CR', 'QA', 'OR'].includes(type))
@@ -0,0 +1,3 @@
1
+ // Shared guidance for passing authored bytes; never an additional file reader,
2
+ // an authoring result or authority to record an artefact.
3
+ export const AUTHORING_TEXT_HANDOFF = 'Pass Markdown as UTF-8 string data, never executable code. Prefer structured tool input. If the host uses JavaScript, author with its file-editing tool and pass a UTF-8 file read as content; never embed the document in backtick literals.';
@@ -2,7 +2,7 @@ import { CURRENT_LAYOUT } from './run-identity.js';
2
2
  // Shared representation, not a file owner or replay ledger. Existing operation
3
3
  // families alone validate, persist and recover their versioned records.
4
4
  import { AsyncLocalStorage } from 'node:async_hooks';
5
- import { isAbsolute } from 'node:path';
5
+ import { isAbsolute, posix, win32 } from 'node:path';
6
6
  import { canonicalJson, exactObject, DIGEST_PATTERN } from './approval-command-contract.js';
7
7
  import { runCommandRequestDigest } from './run-command-schema.js';
8
8
  import { canonicalizeLanguageTag } from '../interaction-presentation.js';
@@ -28,7 +28,9 @@ export function createInputResolution(original, effective, configuration) {
28
28
  operation_id: original.operation_id ?? null, kind: original.command?.kind ?? null,
29
29
  fields: Object.fromEntries(paths.filter(path => get(original, path) === undefined && get(effective, path) !== undefined).map(path => [path, get(effective, path)])), configuration };
30
30
  }
31
- export function validInputResolution(value) {
31
+ export function validInputResolution(value, { persisted = false } = {}) {
32
+ // Stored paths describe the writer's host. Live requests still use the serving host's paths.
33
+ const absolutePath = persisted ? path => posix.isAbsolute(path) || win32.isAbsolute(path) : isAbsolute;
32
34
  if (!exactObject(value, ['schema_version', 'logical_digest', 'effective_digest', 'operation_id', 'kind', 'fields', 'configuration']) || value.schema_version !== 1
33
35
  || !(value.operation_id === null || typeof value.operation_id === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u.test(value.operation_id))
34
36
  || !(value.kind === null || typeof value.kind === 'string' && /^[a-z_]+\.[a-z_]+$/u.test(value.kind) && value.kind.length <= 64)
@@ -36,14 +38,14 @@ export function validInputResolution(value) {
36
38
  || Buffer.byteLength(canonicalJson(value)) > 8192 || Object.keys(value.fields).some(key => !paths.includes(key))) return false;
37
39
  const f = value.fields, c = value.configuration;
38
40
  if (Object.hasOwn(f, 'presentation_language') && !tag(f.presentation_language)
39
- || Object.hasOwn(f, 'working_directory') && (typeof f.working_directory !== 'string' || !isAbsolute(f.working_directory) || f.working_directory.length > 4096)
41
+ || Object.hasOwn(f, 'working_directory') && (typeof f.working_directory !== 'string' || !absolutePath(f.working_directory) || f.working_directory.length > 4096)
40
42
  || Object.hasOwn(f, 'schema_version') && f.schema_version !== '1'
41
43
  || Object.hasOwn(f, 'assurance') && f.assurance !== 'cooperative_local'
42
44
  || Object.hasOwn(f, 'variant') && !['status-card', 'approval-envelope'].includes(f.variant)
43
45
  || Object.hasOwn(f, 'command.payload.route') && !['markdown', 'automatic', 'fallback'].includes(f['command.payload.route'])) return false;
44
46
  if (!exactObject(c, ['root', 'control', 'config_digest', 'values', 'sources', 'defaults_digest', 'control_layout'])
45
47
  || (c.control === 'active' ? c.control_layout !== CURRENT_LAYOUT : c.control_layout !== null)
46
- || !(c.root === null || typeof c.root === 'string' && isAbsolute(c.root) && c.root.length <= 4096) || !['inactive', 'active'].includes(c.control)
48
+ || !(c.root === null || typeof c.root === 'string' && absolutePath(c.root) && c.root.length <= 4096) || !['inactive', 'active'].includes(c.control)
47
49
  || !(c.config_digest === null || hash(c.config_digest)) || !hash(c.defaults_digest)
48
50
  || !exactObject(c.values, preferenceKeys) || !exactObject(c.sources, preferenceKeys)
49
51
  || !tag(c.values.chat_language) || !tag(c.values.artifact_language)
@@ -82,7 +84,7 @@ export function resolutionRecord(record) {
82
84
  const { input_resolution: extension, ...body } = record;
83
85
  if (!plain(extension)) return null;
84
86
  const { record_version, ...resolution } = extension;
85
- if (!['string', 'number'].includes(typeof record_version) || !validInputResolution(resolution)) return null;
87
+ if (!['string', 'number'].includes(typeof record_version) || !validInputResolution(resolution, { persisted: true })) return null;
86
88
  // Pending journals retain the owning family's digest (approval/revision have
87
89
  // their own domain digest). The committed receipt binds the full command and
88
90
  // journal recovery cross-checks both retained resolutions below that owner.
@@ -0,0 +1,4 @@
1
+ // Private transfer limits; direct text is bounded independently from a multipart piece.
2
+ // The existing 64 KiB canonical command budget additionally bounds every JSON request.
3
+ export const MATERIAL_LIMITS = Object.freeze({ inline: 49152, part: 16384, file: 131072, set: 524288, sets: 4, total: 2097152,
4
+ lifetime: 600000, idle: 120000 });
@@ -0,0 +1,137 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { canonicalJson, digest } from './approval-command-contract.js';
3
+ import { RUN_COMMAND_DESCRIPTORS, validateRunCommand } from './run-command-schema.js';
4
+ import { closeoutConfirmation } from '../control-evaluation/closeout-readiness.js';
5
+ import { REPORT_DECISION_FORMAT } from '../control-evaluation/report-decision.js';
6
+ import { MATERIAL_LIMITS } from './material-limits.js';
7
+
8
+ // Call construction only. The existing command/dispatch owners still validate
9
+ // intent, current bindings, review, presentation and every actual mutation.
10
+ export function continueDeliveryCall(input, runId = input.run_id) {
11
+ return { tool: 'agdf_dispatch', arguments: { presentation_language: input.presentation_language,
12
+ working_directory: input.working_directory, primary_target: input.primary_target, target_source: input.target_source,
13
+ skill_id: 'gate-check', run_id: runId, continue_delivery: true } };
14
+ }
15
+
16
+ // Observation of the original UUID, never a new write or refreshed revision.
17
+ export function originalOperationCall(input) {
18
+ const kind = input.command?.kind;
19
+ if (!input.run_id && !input.planning && !['project.initialize', 'run.create'].includes(kind)) return undefined;
20
+ if (['material.stage', 'planned_material.stage', 'presentation.deliver'].includes(kind)) return undefined;
21
+ return { tool: 'agdf_inspect', arguments: {
22
+ presentation_language: input.presentation_language, working_directory: input.working_directory,
23
+ primary_target: input.primary_target, target_source: input.target_source,
24
+ operation: 'operation-status', module: input.planning || kind === 'project.initialize' ? `${kind}/${input.operation_id}` : input.operation_id,
25
+ ...(input.planning ? { planning: input.planning } : input.run_id ? { run_id: input.run_id, expected_revision_id: input.expected_revision_id } : {}),
26
+ } };
27
+ }
28
+
29
+ function compatible(schema, value) {
30
+ if (schema.oneOf || schema.anyOf) return (schema.oneOf ?? schema.anyOf).some(row => compatible(row, value));
31
+ if (schema.allOf) return schema.allOf.every(row => compatible(row, value));
32
+ if (schema.additionalProperties === false && value && typeof value === 'object'
33
+ && Object.keys(value).some(key => !Object.hasOwn(schema.properties ?? {}, key))) return false;
34
+ return Object.entries(schema.properties ?? {}).every(([key, rule]) => value?.[key] === undefined
35
+ || (!Object.hasOwn(rule, 'const') || value[key] === rule.const) && (!rule.enum || rule.enum.includes(value[key])));
36
+ }
37
+
38
+ function missing(schema, value, path) {
39
+ if (schema.oneOf || schema.anyOf) {
40
+ const variants = (schema.oneOf ?? schema.anyOf).filter(row => compatible(row, value));
41
+ return variants.length === 1 ? missing(variants[0], value, path) : [path];
42
+ }
43
+ if (schema.allOf) return [...new Set(schema.allOf.flatMap(row => missing(row, value, path)))];
44
+ if (schema.type === 'array' && Array.isArray(value)) return value.flatMap((row, i) => missing(schema.items, row, `${path}/${i}`));
45
+ if (schema.type !== 'object') return [];
46
+ return Object.entries(schema.properties ?? {}).flatMap(([key, rule]) => value?.[key] === undefined
47
+ ? (schema.required ?? []).includes(key) ? [`${path}/${key}`] : [] : missing(rule, value[key], `${path}/${key}`));
48
+ }
49
+
50
+ // Authoring gates whose staged source uses another material slot. A Quick Task
51
+ // closes with its mandatory Code Review, so that report is the material it stages.
52
+ const MATERIAL_SLOT_BY_GATE = Object.freeze({ 'Mode/Slice Decision': 'Brownfield Review',
53
+ 'Verified Change Execution': 'Verified Change', 'Quick Task Execution': 'CR' });
54
+ const INTERNAL_STEPS = Object.freeze(['UX Intent Definition', 'Brownfield Analysis', 'CD+Tests', 'TP Review', 'Clean Implementation Review', 'CR']);
55
+ // Reports whose recorded result Core reads with readReportDecision.
56
+ const DECISION_REPORT_SLOTS = new Set(['Brownfield Analysis', 'CD+Tests', 'TP Review', 'Clean Implementation Review', 'CR']);
57
+
58
+ // Selects the one step.record variant an authoring gate records, so the form's
59
+ // required inputs name concrete fields instead of the ambiguous whole payload.
60
+ function recordingStep(gate) {
61
+ if (gate === 'UR') return { step: 'ur' };
62
+ if (['Brownfield Review', 'Mode/Slice Decision'].includes(gate)) return { step: 'route' };
63
+ if (gate === 'Quick Task Execution') return { step: 'review' };
64
+ if (INTERNAL_STEPS.includes(gate)) return { step: 'internal', internal_step: gate };
65
+ return {};
66
+ }
67
+
68
+ // A restaged OR may have a different material handle but the same command identity.
69
+ function stagedCloseoutOperationId(binding, reportDigest) {
70
+ const hash = digest(`agdf-staged-closeout/1\0${canonicalJson([binding, reportDigest])}`).slice(7, 39);
71
+ const variant = (8 | (Number.parseInt(hash[16], 16) & 3)).toString(16);
72
+ return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-8${hash.slice(13, 16)}-${variant}${hash.slice(17, 20)}-${hash.slice(20)}`;
73
+ }
74
+
75
+ // `revision` continues an accepted source revision preview: apply keeps the
76
+ // preview's operation UUID, which the proposal binds, and its preview digest.
77
+ export function preparedCommandCall(group, kind, input, { gate, material, recording, presentationId, revision } = {}) {
78
+ if (!RUN_COMMAND_DESCRIPTORS[kind] || RUN_COMMAND_DESCRIPTORS[kind].group !== group) return undefined;
79
+ let payload = {}, slot;
80
+ if (kind === 'material.stage') {
81
+ slot = MATERIAL_SLOT_BY_GATE[gate] ?? gate ?? 'EVIDENCE';
82
+ const roles = RUN_COMMAND_DESCRIPTORS[kind].payload_schema.oneOf.find(row => row.properties.action.const === 'put').properties.files.items.properties.slot.enum;
83
+ if (!roles.includes(slot)) return undefined;
84
+ payload = { action: 'put', files: [{ slot }] };
85
+ }
86
+ if (kind === 'artefact.record') payload = { ...(gate ? { gate } : {}), ...(material ? { material } : {}),
87
+ ...(recording?.available ? { update_draft: recording.update_draft } : {}) };
88
+ if (['presentation.prepare', 'presentation.deliver', 'approval.record'].includes(kind)) payload = {
89
+ ...(gate ? { gate } : {}), ...(presentationId ? { presentation_id: presentationId } : {}),
90
+ ...(kind === 'presentation.deliver' ? { route: 'automatic' } : {}) };
91
+ if (kind === 'ur_draft.replace' && material) payload = { source: material };
92
+ if (kind === 'step.record') payload = { ...(material ? { source: material } : {}), ...recordingStep(gate) };
93
+ // The proposal reference stays an input: staged material rarely outlives the
94
+ // person's confirmation, and restaging identical bytes keeps the same digest.
95
+ if (kind === 'source_revision.apply' && revision) payload = { source_gate: revision.source_gate, preview_digest: revision.preview_digest };
96
+ const unbound = ['run.create', 'project.initialize'].includes(kind);
97
+ const binding = { schema_version: '1', presentation_language: input.presentation_language,
98
+ working_directory: input.working_directory, primary_target: input.primary_target, target_source: input.target_source,
99
+ target_id: input.target_id, ...(!unbound ? { run_id: input.run_id, expected_revision_id: input.expected_revision_id } : {}),
100
+ assurance: 'cooperative_local' };
101
+ const stagedCloseout = kind === 'closeout.record' && material;
102
+ const operation_id = stagedCloseout ? stagedCloseoutOperationId(binding, material.digest) : revision?.operation_id ?? randomUUID();
103
+ if (stagedCloseout) payload = { or: material,
104
+ confirmation: closeoutConfirmation(binding.run_id, binding.expected_revision_id, operation_id, material.digest) };
105
+ const argumentsValue = { ...binding, operation_id, command: { kind, payload } };
106
+ const required = missing(RUN_COMMAND_DESCRIPTORS[kind].payload_schema, payload, '/command/payload');
107
+ const valid = validateRunCommand(group, argumentsValue).length === 0;
108
+ return { state: valid ? 'ready' : 'requires_author_input', call: { tool: group, arguments: argumentsValue },
109
+ required_inputs: valid ? [] : required.length ? required : ['/command/payload'], authorizes: false,
110
+ ...(kind === 'material.stage' ? { content_contract: {
111
+ encoding: 'UTF-8', max_utf8_bytes_per_file: RUN_COMMAND_DESCRIPTORS[kind].payload_schema.oneOf[0].properties.files.items.properties.content.maxLength,
112
+ instruction: 'put accepts text up to this UTF-8 limit within the 64 KiB whole JSON request bound; no client hashes or byte counts are needed. If either bound would be exceeded, retain the complete text and use the supplied larger_source_call for multipart; never truncate or shorten approved source to fit.',
113
+ larger_source_call: { tool: 'agdf_inspect', arguments: { operation: 'operation-contract', module: `${group}/${kind}`,
114
+ presentation_language: input.presentation_language, working_directory: input.working_directory,
115
+ primary_target: input.primary_target, target_source: input.target_source,
116
+ run_id: input.run_id, expected_revision_id: input.expected_revision_id } },
117
+ // Staged material is private to the serving MCP process and short-lived,
118
+ // so a recording that waits for a person must not stage first.
119
+ retention: { idle_ms: MATERIAL_LIMITS.idle, lifetime_ms: MATERIAL_LIMITS.lifetime, scope: 'serving MCP server process',
120
+ instruction: 'Stage only when every input of the following recording (for example reviewer and review confirmation) is already available. Staged material does not survive a reconnect or a pause beyond idle_ms. After expiry stage the identical bytes again: a form that takes the material reference as an input (closeout, source revision apply) is reused with the new reference, which keeps its UUID and any confirmation valid; otherwise use the recording form returned by the new staging.' },
121
+ ...(DECISION_REPORT_SLOTS.has(slot) ? { report_decision: REPORT_DECISION_FORMAT } : {}),
122
+ } } : {}),
123
+ ...(kind === 'approval.record' && gate ? { contract_call: { tool: 'agdf_inspect', arguments: {
124
+ operation: 'operation-contract', module: 'agdf_approve/approval.record',
125
+ presentation_language: input.presentation_language, working_directory: input.working_directory,
126
+ primary_target: input.primary_target, target_source: input.target_source,
127
+ run_id: input.run_id, expected_revision_id: input.expected_revision_id, gate,
128
+ } }, response_contract: {
129
+ approval_value: `Approval: ${gate}`, exact: true,
130
+ instruction: 'Only a NEW deliberate reply for this presentation. Put the exact reply alone in response; simulation/reviewer explanation belongs outside response. Never prefix or suffix the approval formula. This value is a format, not a decision or permission. The complete approval form already binds the revision and presentation; fill response without another contract read. If explanatory schema help is needed, copy contract_call exactly; never omit or guess expected_revision_id.' } } : {}),
131
+ ...(kind === 'source_revision.apply' && revision ? { confirmation_contract: { confirmation_value: revision.confirmation_selector, exact: true,
132
+ instruction: 'confirmation is only the person\'s NEW deliberate reply with exactly this text. proposal is the reference of the previewed proposal; if its staged material expired, stage the identical bytes again and use the new reference. This form keeps the previewed UUID and digest.' } } : {}),
133
+ ...(stagedCloseout && valid ? { operation_status_call: originalOperationCall(argumentsValue) } : {}),
134
+ instruction: stagedCloseout
135
+ ? 'Invoke the supplied closeout separately. If its effect is uncertain, inspect the original operation first. If material expired and restaging is appropriate, stage the identical OR with the original binding and use the returned form for the same operation and digest.'
136
+ : 'Fill required_inputs from actual authored content, review or a NEW deliberate reply. Preserve the supplied binding and UUID. Retry an uncertain dispatch with the identical call; each new logical command already has its own supplied UUID; do not regenerate it or put IDs in inputs. This form is not permission or an approval.' };
137
+ }
@@ -4,6 +4,7 @@ import { readRun } from './run-state-edits.js';
4
4
  import { runSealState } from './run-seal.js';
5
5
  import { currentInputResolution } from './input-resolution.js';
6
6
  import { assertInputConfigurationCurrent } from '../resources/configuration.js';
7
+ import { preparedCommandCall } from './prepared-control-calls.js';
7
8
 
8
9
  export const presentationDeliveryKey = input => [input.target_id, input.run_id, input.expected_revision_id,
9
10
  input.command?.payload?.presentation_id ?? input.presentation_id ?? input.operation_id].join(':');
@@ -45,7 +46,9 @@ export function createPresentationDelivery({ now = Date.now } = {}) {
45
46
  if (row.pending || pendingRuns.has(runKey)) return { ...base, ...failure('busy') };
46
47
  const selected = row.selected;
47
48
  if (selected?.operation_id === input.operation_id && selected.digest !== base.request_digest) return { ...base, ...failure('operation_payload_conflict') };
48
- const emit = (mode, text, historical = false) => ({ ...base, historical_effect: historical, presentation_delivery: {
49
+ const emit = (mode, text, historical = false) => ({ ...base, historical_effect: historical, next_calls: [],
50
+ ...(!historical ? { approval_call: preparedCommandCall('agdf_approve', 'approval.record', input,
51
+ { gate: payload.gate, presentationId: payload.presentation_id }) } : {}), presentation_delivery: {
49
52
  delivery_id: selected?.operation_id ?? input.operation_id, mode, text, historical_delivery: historical,
50
53
  presentation_id: payload.presentation_id, revision_id: input.expected_revision_id, document_digest: row.result.family_result.document_digest,
51
54
  cleanup_state: row.cleanup ?? 'not_required',
@@ -1,3 +1,5 @@
1
+ import { MATERIAL_LIMITS } from './material-limits.js';
2
+ import { AUTHORING_TEXT_HANDOFF } from './authoring-text-handoff.js';
1
3
  import { projectMcpInputSchema } from '../mcp-input-schema.js';
2
4
  // Compatibility facade: existing exports retain the same schema/validator objects.
3
5
  export { RUN_COMMAND_VERSION, RUN_COMMAND_LIMITS, TARGET_SCOPED_COMMAND_KINDS, PLANNING_COMMAND_KINDS, PLANNING_SCOPE_SCHEMA, strictObject, MATERIAL_REFERENCE_SCHEMA, RUN_COMMAND_DESCRIPTORS, RUN_COMMAND_GROUPS, commandGroupSchema, compactCommandSchema, RUN_COMMAND_RESULT_SCHEMA, commandResultSchema, validateRunCommandResult, commandGroupDefinition, schemaDiagnostics, validateRunCommand, runCommandRequestDigest } from './run-command-schema.js';
@@ -7,6 +9,7 @@ import { PRD_DECISION_FORMAT } from '../control-evaluation/prd-readiness.js';
7
9
  import { SD_DECISION_FORMAT } from '../control-evaluation/sd-readiness.js';
8
10
  import { ACCEPTANCE_CRITERIA_FORMAT, TP_AUTHORING_FORMAT } from '../control-evaluation/traceability-readiness.js';
9
11
  import { UX_DECISION_FORMAT } from '../control-evaluation/definition-sources.js';
12
+ import { REPORT_DECISION_FORMAT } from '../control-evaluation/report-decision.js';
10
13
  import { REVIEWED_BINDING_FORMAT, REVISION_PROPOSAL_FORMAT } from './recording-formats.js';
11
14
  import { relationshipForGate } from '../control-evaluation/delivery-relationships.js';
12
15
  import { PREVIEW_REVIEW_FORMAT } from './preview-review.js';
@@ -23,17 +26,20 @@ export function operationContract(group, kind, { gate } = {}) {
23
26
  plan_id: 'plan-<planned_ur.create operation_id>', expected_digest: null,
24
27
  instructions: 'For a new planned UR, reserve the future planned_ur.create UUID first. Use plan- followed by that exact UUID as planning.plan_id. Begin, append and seal planned_material.stage with the same plan_id and null expected_digest; each material call has its own operation_id. Create with the reserved UUID. Creation source material is the plain canonical UR: omit Planning schema, Planning id and Planning priority lines; the writer adds them from the request. Replacement instead stages the full selected UR with its existing planning metadata. Never use a title/slug as the creation plan_id.',
25
28
  } } : {}),
26
- ...(['material.stage', 'planned_material.stage'].includes(kind) ? { material_transport: { part_bytes: 16384, file_bytes: 131072, set_bytes: 524288, max_sets: 4,
29
+ ...(['material.stage', 'planned_material.stage'].includes(kind) ? { material_transport: { inline_file_bytes: MATERIAL_LIMITS.inline, part_bytes: MATERIAL_LIMITS.part, file_bytes: MATERIAL_LIMITS.file, set_bytes: MATERIAL_LIMITS.set, max_sets: MATERIAL_LIMITS.sets,
30
+ preferred: 'action put with files [{slot,content}] seals exact plain UTF-8 text in one bounded private call; at most 49152 UTF-8 bytes per file within the existing 65536-byte JSON request bound. No byte counts, base64 or transfer choreography are needed. Use recording_calls after sealing. ' + AUTHORING_TEXT_HANDOFF,
27
31
  total_bytes: 2097152, lifetime_ms: 600000, idle_ms: 120000, effect: 'private transfer only; no canonical files or gate decision',
28
32
  encoding: 'append data is canonical standard base64 (no whitespace) of raw UTF-8 bytes; bytes and offsets count decoded bytes, not characters',
29
- replay: 'begin preserves its original UUID; append uses exact offsets/base64 bytes. Seal returns Core identity/digest. Read transfer status after uncertainty; generation loss requires restaging semantic bytes. Preserve the future canonical write UUID.',
33
+ replay: 'Every logical put/begin/append/seal/status call has its own operation UUID; reuse one UUID only for the identical request after uncertainty. transfer_id, not operation_id, links multipart actions. Seal/put return Core identity/digest. Generation loss requires restaging semantic bytes; preserve the future canonical write UUID.',
30
34
  lifecycle: 'A receipt-confirmed canonical commit retires its consumed set; otherwise discard it explicitly or let it expire.' } } : {}),
31
35
  internal_result_formats: kind === 'step.record' ? { 'UX Intent Definition': UX_DECISION_FORMAT,
32
- reviews: { declaration: '- decision: pass | revise | block | not_applicable', result_scope: 'actual current owner report; no generated judgement or approval' } } : undefined,
36
+ reviews: { section: REPORT_DECISION_FORMAT.section, declaration: '- decision: pass | revise | block | not_applicable',
37
+ instruction: REPORT_DECISION_FORMAT.instruction, result_scope: 'actual current owner report; no generated judgement or approval' } } : undefined,
33
38
  reviewed_binding_format: kind === 'artefact.record' ? { ...REVIEWED_BINDING_FORMAT, current_relationship: relationshipForGate(gate) ?? null,
34
39
  destination_status: gate === 'QA' ? 'pass | revise | block matching the actual QA report' : 'draft' } : undefined,
35
40
  proposal_format: kind.startsWith('source_revision.') ? REVISION_PROPOSAL_FORMAT : undefined,
36
41
  ...(kind === 'closeout.record' ? { confirmation_format: closeoutConfirmation('{run_id}', '{expected_revision_id}', '{operation_id}', '{or.digest}'),
42
+ confirmation_binding: 'The confirmation names the operation UUID of the prepared closeout form. Keep using that same form: if the staged OR expired, stage the identical bytes and put the new reference into or; digest and confirmation stay valid. A newly read form has a new UUID and needs a new confirmation.',
37
43
  closeout_modes: { quick_task: 'OR-lite: Result, Evidence, Risk, Next Step', verified_change: 'Verified Change Mini-Closeout; retain the same canonical record',
38
44
  structured_slice: 'Existing OR-full closeout and its applicable obligations', structured_delivery: 'Existing OR-full closeout and its applicable obligations' } } : {}),
39
45
  ...(kind === 'verified_change.record' ? { canonical_receipt_kind: 'step.record', execution: 'Actual edits/tests/Git actions remain external; this writer records their bounded observed result.' } : {}),
@@ -42,7 +48,7 @@ export function operationContract(group, kind, { gate } = {}) {
42
48
  priority: ['high', 'normal', 'low'], default_priority: 'normal only on explicit create', source_identity: 'SHA-256 of the whole canonical UR text',
43
49
  fields: kind === 'planned_ur.create' ? 'Stage the canonical UR without any Planning schema/id/priority lines. The create writer inserts all three from the request.' : 'Use the selected canonical UR including exactly one initial scalar of each planning metadata field. Planning id remains unchanged on replacement.' },
44
50
  authoring_format: UR_AUTHORING_FORMAT } : {}),
45
- authorizes: false, ...(!kind.startsWith('planned_ur.') && kind !== 'run.create_from_planned' ? { authoring_format: kind === 'closeout.record' ? { quick_task: QUICK_CLOSEOUT_AUTHORING_FORMAT } : kind === 'artefact.record' || kind === 'presentation.prepare' || kind === 'step.record'
51
+ authorizes: false, ...(!kind.startsWith('planned_ur.') && kind !== 'run.create_from_planned' ? { authoring_format: kind === 'closeout.record' ? { quick_task: QUICK_CLOSEOUT_AUTHORING_FORMAT } : kind === 'artefact.record' || kind === 'presentation.prepare' || kind === 'step.record' || kind === 'ur_draft.replace'
46
52
  ? ({ UR: UR_AUTHORING_FORMAT, PRD: { decisions: PRD_DECISION_FORMAT, criteria: ACCEPTANCE_CRITERIA_FORMAT, preview_review: PREVIEW_REVIEW_FORMAT }, SD: SD_DECISION_FORMAT, TP: TP_AUTHORING_FORMAT }[gate] ?? null) : undefined,
47
53
  } : {}),
48
54
  presentation_format: kind === 'presentation.prepare' || kind === 'artefact.record' ? {
@@ -1,3 +1,4 @@
1
+ import { MATERIAL_LIMITS } from './material-limits.js';
1
2
  import { projectMcpInputSchema } from '../mcp-input-schema.js';
2
3
  import { DIGEST_PATTERN, COOPERATIVE_ASSURANCE, canonicalJson, digest } from './approval-command-contract.js';
3
4
  import { RUN_ID_PATTERN, REVISION_ID_PATTERN, APPROVAL_GATES } from './run-identity.js';
@@ -23,6 +24,8 @@ const materialSource = { oneOf: [source, MATERIAL_REFERENCE_SCHEMA] };
23
24
  const materialSlot = enumeration(['UR', 'PRD', 'SD', 'TP', 'QA', 'OR', 'Verified Change', 'Brownfield Review', 'UX Intent Definition', 'Brownfield Analysis', 'CD+Tests', 'TP Review', 'Clean Implementation Review', 'CR', 'EVIDENCE']);
24
25
  const integer = maximum => ({ type: 'integer', minimum: 0, maximum });
25
26
  const materialStage = { oneOf: [
27
+ strictObject({ action: { const: 'put' }, files: { type: 'array', minItems: 1, maxItems: 4,
28
+ items: strictObject({ slot: materialSlot, content: { type: 'string', maxLength: MATERIAL_LIMITS.inline, description: 'Plain UTF-8 text, at most 49152 encoded bytes per file; the whole JSON request stays <=65536 bytes. Core computes sizes and digests and seals all files in this one call.' } }) } }),
26
29
  strictObject({ action: { const: 'begin' }, files: { type: 'array', minItems: 1, maxItems: 4, items: strictObject({ slot: materialSlot, bytes: integer(131072) }) } }),
27
30
  strictObject({ action: { const: 'append' }, transfer_id: identity, file: integer(3), offset: integer(131072),
28
31
  data: { type: 'string', maxLength: 21848, contentEncoding: 'base64', description: 'Standard base64 of at most 16384 raw UTF-8 bytes; no line breaks.' } }),
@@ -59,6 +62,9 @@ const runId = { type: 'string', pattern: RUN_ID_PATTERN.source };
59
62
  const text = { type: 'string', minLength: 1 };
60
63
  const closureEntry = strictObject({ run_id: runId, outcome: enumeration(['superseded', 'abandoned']), reason: text, successor_run: runId, successor_reference: text }, ['run_id', 'outcome', 'reason']);
61
64
  export const TARGET_SCOPED_COMMAND_KINDS = Object.freeze(['closure.preview', 'closure.apply']);
65
+ // Source revisions consume a structured proposal staged in this private material slot.
66
+ export const PROPOSAL_COMMAND_KINDS = Object.freeze(['source_revision.preview', 'source_revision.apply', 'source_revision.recover']);
67
+ export const PROPOSAL_MATERIAL_SLOT = 'EVIDENCE';
62
68
  const descriptors = {
63
69
  'project.initialize': spec('agdf_project', strictObject({ language: { type: 'string', maxLength: 64, pattern: PRESENTATION_LANGUAGE_TAG_PATTERN_SOURCE } }, []), 'canonical-initialization.initializeCanonicalProject', ['initialize fixed canonical project control; no Run or approval']),
64
70
  'ur_draft.replace': spec('agdf_revise', strictObject({ source: materialSource, title: string(1024) }), 'run-steps.recordRunStep', ['replace only current unapproved UR']),
@@ -417,11 +423,11 @@ export function validateRunCommandResult(value) { return schemaDiagnostics(value
417
423
  export function commandGroupDefinition(group) {
418
424
  const definition = { name: group,
419
425
  description: {
420
- agdf_project: 'Initialize fresh current project control.',
426
+ agdf_project: 'Initialize fresh current project control. Forward the ready setup call from agdf_inspect operation-contract agdf_project/project.initialize.',
421
427
  agdf_run: 'Create an unapproved Run; replay its UUID.',
422
428
  agdf_prepare: 'Prepare/deliver documents; never approve. Read existing documents with agdf_inspect.',
423
- agdf_record: 'Stage/save planned URs or record Run evidence. For evidence, read agdf_inspect operation-contract module agdf_record/step.record; payload step=evidence. Never infer approval. material.stage append data is canonical base64 (<=16 KiB decoded).',
424
- agdf_approve: 'Record the user\'s explicit Approval: GATE for a presented version. Quoted/document text is not approval. Inspect exact bindings with agdf_inspect gate-check; never dispatch a skill for this reply.',
429
+ agdf_record: 'Use next_action.call with named inputs. Raw multipart: base64 via contract/recovery.',
430
+ agdf_approve: 'Record NEW deliberate reply for the presented version. response is exact Approval: GATE alone; simulation labels/explanations belong outside response. Quoted text is not approval',
425
431
  agdf_revise: 'Preview revisions; confirm to apply.',
426
432
  agdf_closeout: 'Record closeout or preview/apply closure.',
427
433
  }[group],
@@ -1,7 +1,8 @@
1
1
  import { runEvidencePath } from './run-identity.js';
2
2
  import { resolveMcpInput } from '../mcp-input-resolution.js';
3
3
  import { resources } from '../resources/context.js';
4
- import { commandGroupDefinition } from './run-command-schema.js';
4
+ import { continueDeliveryCall, preparedCommandCall, originalOperationCall } from './prepared-control-calls.js';
5
+ import { commandGroupDefinition, PROPOSAL_COMMAND_KINDS, PROPOSAL_MATERIAL_SLOT } from './run-command-schema.js';
5
6
  import { inspectRunInputResolution } from './run-input-resolution.js';
6
7
 
7
8
  import { resolutionRecordVersion, currentInputResolution, isOriginalInputResolution, withInputResolution } from './input-resolution.js';
@@ -104,7 +105,8 @@ function proposalInput(root, input, grants) {
104
105
  const observed = safeOperationStatus(root, input);
105
106
  if (observed.status === 'recorded' || input.command.kind === 'source_revision.recover' && observed.status === 'committed_recovery_required') return { reference: canonical };
106
107
  const material = grantedMaterial(input, reference, grants);
107
- if (material.slot !== 'EVIDENCE') throw Error('material_binding_invalid');
108
+ if (material.slot !== PROPOSAL_MATERIAL_SLOT) throw Object.assign(Error('material_binding_invalid'), {
109
+ recovery: `A source revision proposal must be staged in slot ${PROPOSAL_MATERIAL_SLOT}, not ${material.slot}. Stage it with the material_call of operation-contract agdf_revise/${input.command.kind}, then retry with the new reference. No command was dispatched.` });
108
110
  return { reference: canonical, material: { path: canonical.path, digest: canonical.digest, content: material.content } };
109
111
  }
110
112
  export function createRunCommandService({ packageVersion = '0.14.5', enabledGroups = Object.keys(RUN_COMMAND_GROUPS), checkpoint = () => {}, runtimeControl, materialGrants = [], gitObservation, initializationProducer, inputDefaults = resources.defaults } = {}) {
@@ -150,6 +152,7 @@ export function createRunCommandService({ packageVersion = '0.14.5', enabledGrou
150
152
  // The envelope already carries this exact receipt; the family copy only doubled the response.
151
153
  family_result: family.receipt && receipt && canonicalJson(family.receipt) === canonicalJson(receipt)
152
154
  ? (({ receipt: _receipt, ...rest }) => rest)(family) : family, ...extra };
155
+ response.operation_status_call = originalOperationCall(input);
153
156
  if (['accepted', 'already_applied'].includes(outcome)) {
154
157
  const common = { presentation_language: input.presentation_language, working_directory: input.working_directory,
155
158
  primary_target: input.primary_target, target_source: input.target_source, target_id: input.target_id };
@@ -164,8 +167,20 @@ export function createRunCommandService({ packageVersion = '0.14.5', enabledGrou
164
167
  module: 'agdf_prepare/presentation.prepare', run_id, expected_revision_id: response.current.revision_id, gate: 'UR' })];
165
168
  }
166
169
  if (input.command.kind === 'presentation.prepare' && family.presentation_id && family.revision_id)
167
- response.next_calls = [inspect({ operation: 'presentation-document', run_id: input.run_id,
168
- expected_revision_id: family.revision_id, gate: family.gate, presentation_id: family.presentation_id })];
170
+ response.next_calls = response.current.lifecycle === 'active' && response.current.revision_id === family.revision_id
171
+ ? [preparedCommandCall('agdf_prepare', 'presentation.deliver', { ...input, expected_revision_id: family.revision_id },
172
+ { gate: family.gate, presentationId: family.presentation_id }).call]
173
+ : [inspect({ operation: 'presentation-document', run_id: input.run_id,
174
+ expected_revision_id: family.revision_id, gate: family.gate, presentation_id: family.presentation_id })];
175
+ // An accepted preview continues with its apply form: same UUID and preview digest,
176
+ // with the proposal reference and the person's confirmation left as inputs.
177
+ if (input.command.kind === 'source_revision.preview' && family.preview_digest && family.confirmation_selector)
178
+ response.recording_calls = [preparedCommandCall('agdf_revise', 'source_revision.apply', input, { revision: {
179
+ operation_id: input.operation_id, source_gate: input.command.payload.source_gate,
180
+ preview_digest: family.preview_digest, confirmation_selector: family.confirmation_selector } })];
181
+ if (!response.historical_effect && response.current.available && response.current.lifecycle === 'active'
182
+ && ['run.create', 'run.create_from_planned', 'step.record', 'artefact.record', 'ur_draft.replace', 'approval.record'].includes(input.command.kind))
183
+ response.next_calls = [continueDeliveryCall({ ...input, primary_target: root }, response.current.run_id ?? family.run_id ?? selectedInput.run_id)];
169
184
  }
170
185
  if (Buffer.byteLength(JSON.stringify(response)) > (input.command.kind === 'project.initialize' ? 16384 : RUN_COMMAND_LIMITS.result_bytes)) return { schema_version: '1', outcome: dispatched ? 'effect_unknown' : 'rejected',
171
186
  reason: 'command_result_budget_exceeded', operation_id: input.operation_id, binding: response.binding, authorizes: false,
@@ -217,9 +232,13 @@ export function createRunCommandService({ packageVersion = '0.14.5', enabledGrou
217
232
  const state = inspectCanonicalProject(root, { operationId: input.operation_id });
218
233
  if (state.receipt?.operation.operation_id === input.operation_id && state.receipt.operation.request_digest !== requestDigest)
219
234
  return result('rejected', 'operation_payload_conflict', {}, { dispatch: 'not_dispatched' });
220
- if (state.operation_status === 'recorded' && state.status !== 'pending') return result('already_applied', null, {
221
- receipt: state.receipt, historical_effect: true, status: 'unchanged', created_run: false,
222
- created_gate_approval: false, next_calls: inspectProjectState(root, input, gitObservation).next_calls });
235
+ if (state.operation_status === 'recorded' && state.status !== 'pending') {
236
+ const continuation = inspectProjectState(root, input, gitObservation);
237
+ return result('already_applied', null, {
238
+ receipt: state.receipt, historical_effect: true, status: 'unchanged', created_run: false,
239
+ created_gate_approval: false, next_calls: continuation.next_calls,
240
+ ...(continuation.recovery_only ? { recovery_only: continuation.recovery_only } : {}) });
241
+ }
223
242
  if (state.status === 'blocked') return result('rejected', state.reason, {}, { dispatch: 'not_dispatched' });
224
243
  canonicalInitPlan(payload.language); // Resource/plan failures are known before dispatch.
225
244
  if (state.operation?.operation_id === input.operation_id && state.operation.request_digest !== requestDigest)
@@ -235,8 +254,10 @@ export function createRunCommandService({ packageVersion = '0.14.5', enabledGrou
235
254
  afterPublish: () => checkpoint('project_after_publish'), afterReceipt: () => checkpoint('project_after_receipt'),
236
255
  beforeMarkerCleanup: () => checkpoint('project_before_marker_cleanup') });
237
256
  checkpoint('before_result');
257
+ const continuation = inspectProjectState(root, input, gitObservation);
238
258
  return result(family.historical_effect ? 'already_applied' : 'accepted', null,
239
- { ...family, next_calls: inspectProjectState(root, input, gitObservation).next_calls });
259
+ { ...family, next_calls: continuation.next_calls,
260
+ ...(continuation.recovery_only ? { recovery_only: continuation.recovery_only } : {}) });
240
261
  }
241
262
  if (kind === 'run.create') {
242
263
  // Preflight only; the writer repeats validation before publication.
@@ -267,6 +288,9 @@ export function createRunCommandService({ packageVersion = '0.14.5', enabledGrou
267
288
  } })).then(family => result(family.outcome, family.reason, family, { runtime_control: true }),
268
289
  error => result('effect_unknown', error.message, {}, { runtime_control: true }));
269
290
  }
291
+ // Binding the staged proposal is input validation: a missing or misplaced
292
+ // proposal is rejected before dispatch, never reported as an unknown effect.
293
+ const proposal = PROPOSAL_COMMAND_KINDS.includes(kind) ? proposalInput(root, input, materialGrants) : null;
270
294
  checkpoint('before_dispatch'); dispatched = true;
271
295
  if (kind === 'presentation.prepare') {
272
296
  family = withOwnedFileLock(runPath(root, input.run_id), () => {
@@ -290,12 +314,10 @@ export function createRunCommandService({ packageVersion = '0.14.5', enabledGrou
290
314
  resolveMaterial: reference => grantedMaterial(input, reference, materialGrants), gitObservation });
291
315
  } else if (kind === 'operation.recover') family = boundedRecover(root, input);
292
316
  else if (kind === 'source_revision.preview' || kind === 'source_revision.apply') {
293
- const proposal = proposalInput(root, input, materialGrants);
294
317
  const revised = { ...bound, sourceGate: payload.source_gate, evidence: proposal.reference.path, previewDigest: payload.preview_digest,
295
318
  proposalBinding: proposal.reference, proposalMaterial: proposal.material, confirmation: payload.confirmation, commandContext: context, packageVersion };
296
319
  family = kind.endsWith('.apply') ? applySourceRevision(root, revised, { afterWrite: checkpoint }) : previewSourceRevision(root, revised);
297
320
  } else if (kind === 'source_revision.recover') {
298
- const proposal = proposalInput(root, input, materialGrants);
299
321
  family = recoverSourceRevision(root, { ...bound, proposalBinding: proposal.reference, proposalMaterial: proposal.material, evidence: proposal.reference.path, sourceGate: payload.source_gate,
300
322
  recoveryRevisionId: payload.recovery_revision_id, pendingDigest: payload.pending_digest });
301
323
  } else if (kind === 'prd_revision.reopen') {
@@ -331,7 +353,9 @@ export function createRunCommandService({ packageVersion = '0.14.5', enabledGrou
331
353
  operation: 'project-state', primary_target: root, target_source: input.target_source,
332
354
  working_directory: input.working_directory, presentation_language: input.presentation_language } }] });
333
355
  if (error.message === 'AGDF_OPERATION_PAYLOAD_CONFLICT') return result('rejected', 'operation_payload_conflict');
334
- return result(dispatched ? 'effect_unknown' : 'rejected', error.message, {}, { dispatch: dispatched ? 'unknown' : 'not_dispatched' });
356
+ // A pre-dispatch input error may name its own correction.
357
+ return result(dispatched ? 'effect_unknown' : 'rejected', error.message, {}, { dispatch: dispatched ? 'unknown' : 'not_dispatched',
358
+ ...(!dispatched && error.recovery ? { recovery: error.recovery } : {}) });
335
359
  }
336
360
  });
337
361
  };
@@ -17,6 +17,8 @@ export const creationRunId = operationId => `run-${operationId}`;
17
17
  export const CURRENT_LAYOUT = 'run-folders-v1';
18
18
  export const CURRENT_RUN_VERSION = 4;
19
19
  export const RUN_MODES = Object.freeze(['undecided', 'quick_task', 'verified_change', 'structured_slice', 'structured_delivery', 'block']);
20
+ // The artefact slot each recorded run step writes (internal steps name their own slot).
21
+ export const RUN_STEP_SLOTS = Object.freeze({ ur: 'UR', route: 'Brownfield Review', review: 'CR', evidence: 'EVIDENCE', closeout: 'OR' });
20
22
  export function runRelativePath(runId, area = '', name = '') {
21
23
  if (!RUN_ID_PATTERN.test(String(runId ?? ''))) throw Error('AGDF_RUN_ID_INVALID');
22
24
  if (!['', 'documents', 'evidence', 'control', 'history'].includes(area)) throw Error('AGDF_RUN_PATH_INVALID');
@@ -7,8 +7,10 @@ import { discoverRuns } from "./run-state-reader.js";
7
7
  import { buildRunInventory } from "./run-inventory.js";
8
8
 
9
9
  // Feeds the pure inventory from the run discovery of the current read view: each run's parsed text
10
- // and, when the full parser rejected it, its findings. No run state is read a second time.
11
- export function readRunInventory(root, { language = "en" } = {}) {
10
+ // and, when the full parser rejected it, its findings. No run state is read a second time. `observe: false`
11
+ // skips the per-run gate observation, which reads registered documents, for a caller that evaluates the
12
+ // runs itself (the companion run view, which reads each run in its own captured snapshot).
13
+ export function readRunInventory(root, { language = "en", observe = true } = {}) {
12
14
  if (!existsSync(join(root, '.agdf/control'))) return buildRunInventory(null, { language });
13
15
  readControlLayout(root);
14
16
  if (!existsSync(join(root, '.agdf/control/runs'))) return buildRunInventory([], { language,
@@ -18,7 +20,7 @@ export function readRunInventory(root, { language = "en" } = {}) {
18
20
  const store = discovered.filter((run) => run.run_id === "<repository>");
19
21
  const sources = discovered.filter(run => run.run_id !== '<repository>').map(run => {
20
22
  const source = { run_id: run.run_id, ...(typeof run.content === 'string' ? { text: run.content } : {}), findings: run.valid ? [] : run.findings };
21
- if (run.valid) {
23
+ if (run.valid && observe) {
22
24
  try {
23
25
  const state = prepareRunContentState(root, run.content, run.path), decision = transitionDecisionForRunState(state);
24
26
  source.observation = { current_gate: decision.current_gate, decision: decision.status, missing: decision.missing_approval,