create-agdf 0.30.0 → 0.32.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 (366) 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 +436 -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 +119 -0
  20. package/generated/plugins/agdf/companion/figure.mjs +242 -111
  21. package/generated/plugins/agdf/companion/gate-bar.mjs +10 -28
  22. package/generated/plugins/agdf/companion/localization.mjs +15 -32
  23. package/generated/plugins/agdf/companion/notice.mjs +20 -10
  24. package/generated/plugins/agdf/companion/register.mjs +310 -66
  25. package/generated/plugins/agdf/companion/run-state.mjs +89 -90
  26. package/generated/plugins/agdf/companion/state.mjs +6 -32
  27. package/generated/plugins/agdf/companion/view.mjs +199 -24
  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 +14 -3
  36. package/generated/plugins/agdf/mcp/server/src/generation.js +8 -2
  37. package/generated/plugins/agdf/mcp/server/src/main.js +5 -1
  38. package/generated/plugins/agdf/mcp/server/src/next-action.js +227 -0
  39. package/generated/plugins/agdf/mcp/server/src/prepared-call-transport.js +306 -0
  40. package/generated/plugins/agdf/mcp/server/src/safe-read-continuation.js +62 -0
  41. package/generated/plugins/agdf/mcp/server/src/server.js +155 -37
  42. package/generated/plugins/agdf/mcp/server/ui/cockpit.html +130 -33
  43. package/generated/plugins/agdf/mcp/server/ui/decision-manifest.json +3 -3
  44. package/generated/plugins/agdf/mcp/server/ui/decision.html +3 -3
  45. package/generated/plugins/agdf/mcp/server/ui/manifest.json +3 -3
  46. package/generated/plugins/agdf/meta/agdf-interaction-locales.json +436 -2
  47. package/generated/plugins/agdf/meta/agdf-mcp-capability.json +1 -1
  48. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  49. package/generated/plugins/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
  50. package/generated/plugins/agdf/meta/contracts/interaction.md +10 -4
  51. package/generated/plugins/agdf/meta/contracts/modes.md +5 -0
  52. package/generated/plugins/agdf/meta/contracts/prd-definition.md +40 -1
  53. package/generated/plugins/agdf/meta/contracts/quality.md +35 -0
  54. package/generated/plugins/agdf/meta/contracts/request-activation.md +6 -3
  55. package/generated/plugins/agdf/meta/contracts/sd-definition.md +46 -0
  56. package/generated/plugins/agdf/meta/contracts/tp-definition.md +8 -0
  57. package/generated/plugins/agdf/meta/contracts/ur-definition.md +9 -5
  58. package/generated/plugins/agdf/meta/copilot-payload-baseline.json +3 -3
  59. package/generated/plugins/agdf/meta/distribution-profile-history.json +14 -0
  60. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +436 -2
  61. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  62. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
  63. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/interaction.md +10 -4
  64. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/modes.md +5 -0
  65. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/prd-definition.md +40 -1
  66. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/quality.md +35 -0
  67. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/request-activation.md +6 -3
  68. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/sd-definition.md +46 -0
  69. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/tp-definition.md +8 -0
  70. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/ur-definition.md +9 -5
  71. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +2 -1
  72. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/parse-args.js +7 -4
  73. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/project-read-command.js +29 -0
  74. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +2 -1
  75. package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-dispatch-runtime.js +36 -7
  76. package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-lifecycle/package.js +7 -0
  77. package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-lifecycle/plugin-runtime.js +34 -6
  78. package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-lifecycle/prepared-call-journal.js +269 -0
  79. package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-worker-runtime.js +86 -83
  80. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/validator-application.js +2 -2
  81. package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
  82. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/events.js +157 -0
  83. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/figure-state.js +38 -0
  84. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/journal.js +186 -0
  85. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/run-view.js +227 -0
  86. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/acceptance-criteria.js +2 -0
  87. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/closeout-readiness.js +24 -6
  88. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/decision-content-placeholder.js +4 -1
  89. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-check.js +49 -7
  90. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-inputs.js +2 -0
  91. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-pure.js +7 -3
  92. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/prd-readiness.js +7 -2
  93. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/report-decision.js +9 -0
  94. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/traceability-readiness.js +57 -8
  95. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/ur-readiness.js +15 -2
  96. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/artifact-readiness.js +5 -3
  97. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/authoring-inputs.js +107 -22
  98. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/cockpit-list.js +10 -8
  99. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/cockpit-session.js +11 -3
  100. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/cockpit-work.js +4 -2
  101. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/cockpit.js +47 -33
  102. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/contract.js +64 -24
  103. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/material-recording-calls.js +54 -0
  104. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/project-state.js +2 -1
  105. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/run-classification.js +31 -0
  106. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/selection.js +6 -0
  107. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/service.js +32 -5
  108. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/work-situation.js +25 -0
  109. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-read/cockpit-worker.js +1 -0
  110. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/authoring-text-handoff.js +3 -0
  111. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/input-resolution.js +7 -5
  112. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/material-limits.js +4 -0
  113. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/prepared-control-calls.js +137 -0
  114. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/presentation-delivery.js +4 -1
  115. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-contract.js +10 -4
  116. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-schema.js +9 -3
  117. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-service.js +35 -11
  118. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-create-command.js +6 -1
  119. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-identity.js +2 -0
  120. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-inventory-reader.js +54 -5
  121. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-inventory.js +12 -27
  122. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-material.js +25 -7
  123. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-presentation-render.js +113 -28
  124. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-revision.js +38 -20
  125. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-source-revisions.js +37 -17
  126. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-state-reader.js +10 -3
  127. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-steps.js +8 -5
  128. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-title.js +43 -0
  129. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/index.js +3 -1
  130. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog-validation.js +7 -1
  131. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog.js +8 -0
  132. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/interaction-presentation.js +31 -10
  133. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/mcp-input-hints.js +30 -1
  134. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/mcp-tool-errors.js +5 -3
  135. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/resources/canonical-init-plan.js +1 -1
  136. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/runtime/plugin-provenance.js +9 -2
  137. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/contract.js +6 -4
  138. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/delivery-intake.js +3 -1
  139. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/mcp-continuation.js +25 -2
  140. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/prd-definition.js +3 -2
  141. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/readiness-findings.js +7 -0
  142. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/sd-definition.js +4 -2
  143. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/service.js +17 -4
  144. package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/tp-definition.js +4 -2
  145. package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
  146. package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +4 -3
  147. package/generated/plugins/agdf/skills/ux-intent-definition/SKILL.md +31 -2
  148. package/generated/plugins/agdf/skills/ux-intent-definition/help.md +8 -1
  149. package/generated/plugins/agdf/submission/openai/availability.md +1 -1
  150. package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
  151. package/generated/plugins/agdf/submission/openai/release-notes.md +5 -8
  152. package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
  153. package/generated/plugins/agdf-planning/.codex-plugin/plugin.json +1 -1
  154. package/generated/plugins/agdf-planning/plugin.json +1 -1
  155. package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +358 -203
  156. package/generated/plugins/copilot/agdf/control/README.md +5 -0
  157. package/generated/plugins/copilot/agdf/control/templates/BRAND.md +28 -0
  158. package/generated/plugins/copilot/agdf/control/templates/artefacts/PRD.md +11 -0
  159. package/generated/plugins/copilot/agdf/control/templates/artefacts/SD.md +4 -0
  160. package/generated/plugins/copilot/agdf/control/templates/artefacts/UX_INTENT_DEFINITION.md +1 -1
  161. package/generated/plugins/copilot/agdf/mcp/server/README.md +26 -2
  162. package/generated/plugins/copilot/agdf/mcp/server/package.json +3 -3
  163. package/generated/plugins/copilot/agdf/mcp/server/src/generation-runtime.js +14 -3
  164. package/generated/plugins/copilot/agdf/mcp/server/src/generation.js +8 -2
  165. package/generated/plugins/copilot/agdf/mcp/server/src/main.js +5 -1
  166. package/generated/plugins/copilot/agdf/mcp/server/src/next-action.js +227 -0
  167. package/generated/plugins/copilot/agdf/mcp/server/src/prepared-call-transport.js +306 -0
  168. package/generated/plugins/copilot/agdf/mcp/server/src/safe-read-continuation.js +62 -0
  169. package/generated/plugins/copilot/agdf/mcp/server/src/server.js +155 -37
  170. package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +1 -1
  171. package/generated/plugins/copilot/agdf/meta/distribution-profile-history.json +14 -0
  172. package/generated/plugins/copilot/agdf/plugin.json +1 -1
  173. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +436 -2
  174. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  175. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
  176. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/interaction.md +10 -4
  177. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/modes.md +5 -0
  178. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/prd-definition.md +40 -1
  179. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/quality.md +35 -0
  180. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/request-activation.md +6 -3
  181. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/sd-definition.md +46 -0
  182. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/tp-definition.md +8 -0
  183. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/ur-definition.md +9 -5
  184. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +2 -1
  185. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +7 -4
  186. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/project-read-command.js +29 -0
  187. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +2 -1
  188. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-dispatch-runtime.js +36 -7
  189. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-lifecycle/package.js +7 -0
  190. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-lifecycle/plugin-runtime.js +34 -6
  191. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-lifecycle/prepared-call-journal.js +269 -0
  192. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-worker-runtime.js +81 -78
  193. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/validator-application.js +2 -2
  194. package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +1 -1
  195. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/events.js +157 -0
  196. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/figure-state.js +38 -0
  197. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/journal.js +186 -0
  198. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/run-view.js +227 -0
  199. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/acceptance-criteria.js +2 -0
  200. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/closeout-readiness.js +24 -6
  201. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/decision-content-placeholder.js +4 -1
  202. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-check.js +49 -7
  203. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-inputs.js +2 -0
  204. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-pure.js +7 -3
  205. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/prd-readiness.js +7 -2
  206. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/report-decision.js +9 -0
  207. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/traceability-readiness.js +57 -8
  208. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/ur-readiness.js +15 -2
  209. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/artifact-readiness.js +5 -3
  210. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/authoring-inputs.js +107 -22
  211. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/contract.js +64 -24
  212. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/material-recording-calls.js +54 -0
  213. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/project-state.js +2 -1
  214. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/run-classification.js +31 -0
  215. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/selection.js +6 -0
  216. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/service.js +32 -5
  217. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/work-situation.js +25 -0
  218. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/authoring-text-handoff.js +3 -0
  219. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/input-resolution.js +7 -5
  220. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/material-limits.js +4 -0
  221. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/prepared-control-calls.js +137 -0
  222. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/presentation-delivery.js +4 -1
  223. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-contract.js +10 -4
  224. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-schema.js +9 -3
  225. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-service.js +35 -11
  226. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-create-command.js +6 -1
  227. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-identity.js +2 -0
  228. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-inventory-reader.js +54 -5
  229. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-inventory.js +12 -27
  230. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-material.js +25 -7
  231. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-presentation-render.js +113 -28
  232. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-revision.js +38 -20
  233. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-source-revisions.js +37 -17
  234. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-state-reader.js +10 -3
  235. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-steps.js +8 -5
  236. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-title.js +43 -0
  237. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/index.js +3 -1
  238. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog-validation.js +7 -1
  239. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog.js +8 -0
  240. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/interaction-presentation.js +31 -10
  241. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/mcp-input-hints.js +30 -1
  242. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/mcp-tool-errors.js +5 -3
  243. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/resources/canonical-init-plan.js +1 -1
  244. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/runtime/plugin-provenance.js +9 -2
  245. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/contract.js +6 -4
  246. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/delivery-intake.js +3 -1
  247. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/mcp-continuation.js +25 -2
  248. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/prd-definition.js +3 -2
  249. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/readiness-findings.js +7 -0
  250. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/sd-definition.js +4 -2
  251. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/service.js +17 -4
  252. package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/tp-definition.js +4 -2
  253. package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +2 -2
  254. package/generated/plugins/copilot/agdf/skills/agdf-interaction-locales.json +1 -1
  255. package/generated/plugins/copilot/agdf/skills/agdf-ux-intent-definition/SKILL.md +31 -2
  256. package/generated/plugins/copilot/agdf/skills/contracts/gate-artifact-preparation.md +9 -3
  257. package/generated/plugins/copilot/agdf/skills/contracts/interaction.md +10 -4
  258. package/generated/plugins/copilot/agdf/skills/contracts/modes.md +5 -0
  259. package/generated/plugins/copilot/agdf/skills/contracts/prd-definition.md +40 -1
  260. package/generated/plugins/copilot/agdf/skills/contracts/quality.md +35 -0
  261. package/generated/plugins/copilot/agdf/skills/contracts/request-activation.md +6 -3
  262. package/generated/plugins/copilot/agdf/skills/contracts/sd-definition.md +46 -0
  263. package/generated/plugins/copilot/agdf/skills/contracts/tp-definition.md +8 -0
  264. package/generated/plugins/copilot/agdf/skills/contracts/ur-definition.md +9 -5
  265. package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
  266. package/generated/submissions/openai/agdf/meta/agdf-interaction-locales.json +436 -2
  267. package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +1 -1
  268. package/generated/submissions/openai/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
  269. package/generated/submissions/openai/agdf/meta/contracts/interaction.md +10 -4
  270. package/generated/submissions/openai/agdf/meta/contracts/modes.md +5 -0
  271. package/generated/submissions/openai/agdf/meta/contracts/prd-definition.md +40 -1
  272. package/generated/submissions/openai/agdf/meta/contracts/quality.md +35 -0
  273. package/generated/submissions/openai/agdf/meta/contracts/request-activation.md +6 -3
  274. package/generated/submissions/openai/agdf/meta/contracts/sd-definition.md +46 -0
  275. package/generated/submissions/openai/agdf/meta/contracts/tp-definition.md +8 -0
  276. package/generated/submissions/openai/agdf/meta/contracts/ur-definition.md +9 -5
  277. package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +3 -3
  278. package/generated/submissions/openai/agdf/meta/distribution-profile-history.json +14 -0
  279. package/generated/submissions/openai/agdf/plugin.json +1 -1
  280. package/generated/submissions/openai/agdf/skills/ux-intent-definition/SKILL.md +31 -2
  281. package/generated/submissions/openai/agdf/skills/ux-intent-definition/help.md +8 -1
  282. package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
  283. package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
  284. package/generated/submissions/openai/agdf/submission/openai/inventory.json +24 -24
  285. package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
  286. package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
  287. package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
  288. package/generated/submissions/openai/agdf/submission/openai/release-notes.md +5 -8
  289. package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
  290. package/lib/cli/command-registry.js +2 -1
  291. package/lib/cli/parse-args.js +7 -4
  292. package/lib/cli/project-read-command.js +29 -0
  293. package/lib/cli/validation-handlers.js +2 -1
  294. package/lib/mcp-dispatch-runtime.js +36 -7
  295. package/lib/mcp-lifecycle/package.js +7 -0
  296. package/lib/mcp-lifecycle/plugin-runtime.js +34 -6
  297. package/lib/mcp-lifecycle/prepared-call-journal.js +269 -0
  298. package/lib/mcp-worker-runtime.js +86 -83
  299. package/lib/runtime/validator-application.js +2 -2
  300. package/lib/scaffold/plan.js +2 -0
  301. package/package.json +1 -1
  302. package/runtime/core/lib/companion/events.js +157 -0
  303. package/runtime/core/lib/companion/figure-state.js +38 -0
  304. package/runtime/core/lib/companion/journal.js +186 -0
  305. package/runtime/core/lib/companion/run-view.js +227 -0
  306. package/runtime/core/lib/control-evaluation/acceptance-criteria.js +2 -0
  307. package/runtime/core/lib/control-evaluation/closeout-readiness.js +24 -6
  308. package/runtime/core/lib/control-evaluation/decision-content-placeholder.js +4 -1
  309. package/runtime/core/lib/control-evaluation/gate-check.js +49 -7
  310. package/runtime/core/lib/control-evaluation/gate-policy-inputs.js +2 -0
  311. package/runtime/core/lib/control-evaluation/gate-policy-pure.js +7 -3
  312. package/runtime/core/lib/control-evaluation/prd-readiness.js +7 -2
  313. package/runtime/core/lib/control-evaluation/report-decision.js +9 -0
  314. package/runtime/core/lib/control-evaluation/traceability-readiness.js +57 -8
  315. package/runtime/core/lib/control-evaluation/ur-readiness.js +15 -2
  316. package/runtime/core/lib/control-inspect/artifact-readiness.js +5 -3
  317. package/runtime/core/lib/control-inspect/authoring-inputs.js +107 -22
  318. package/runtime/core/lib/control-inspect/cockpit-list.js +10 -8
  319. package/runtime/core/lib/control-inspect/cockpit-session.js +11 -3
  320. package/runtime/core/lib/control-inspect/cockpit-work.js +4 -2
  321. package/runtime/core/lib/control-inspect/cockpit.js +47 -33
  322. package/runtime/core/lib/control-inspect/contract.js +64 -24
  323. package/runtime/core/lib/control-inspect/material-recording-calls.js +54 -0
  324. package/runtime/core/lib/control-inspect/project-state.js +2 -1
  325. package/runtime/core/lib/control-inspect/run-classification.js +31 -0
  326. package/runtime/core/lib/control-inspect/selection.js +6 -0
  327. package/runtime/core/lib/control-inspect/service.js +32 -5
  328. package/runtime/core/lib/control-inspect/work-situation.js +25 -0
  329. package/runtime/core/lib/control-read/cockpit-worker.js +1 -0
  330. package/runtime/core/lib/control-state/authoring-text-handoff.js +3 -0
  331. package/runtime/core/lib/control-state/input-resolution.js +7 -5
  332. package/runtime/core/lib/control-state/material-limits.js +4 -0
  333. package/runtime/core/lib/control-state/prepared-control-calls.js +137 -0
  334. package/runtime/core/lib/control-state/presentation-delivery.js +4 -1
  335. package/runtime/core/lib/control-state/run-command-contract.js +10 -4
  336. package/runtime/core/lib/control-state/run-command-schema.js +9 -3
  337. package/runtime/core/lib/control-state/run-command-service.js +35 -11
  338. package/runtime/core/lib/control-state/run-create-command.js +6 -1
  339. package/runtime/core/lib/control-state/run-identity.js +2 -0
  340. package/runtime/core/lib/control-state/run-inventory-reader.js +54 -5
  341. package/runtime/core/lib/control-state/run-inventory.js +12 -27
  342. package/runtime/core/lib/control-state/run-material.js +25 -7
  343. package/runtime/core/lib/control-state/run-presentation-render.js +113 -28
  344. package/runtime/core/lib/control-state/run-revision.js +38 -20
  345. package/runtime/core/lib/control-state/run-source-revisions.js +37 -17
  346. package/runtime/core/lib/control-state/run-state-reader.js +10 -3
  347. package/runtime/core/lib/control-state/run-steps.js +8 -5
  348. package/runtime/core/lib/control-state/run-title.js +43 -0
  349. package/runtime/core/lib/index.js +3 -1
  350. package/runtime/core/lib/interaction-catalog-validation.js +7 -1
  351. package/runtime/core/lib/interaction-catalog.js +8 -0
  352. package/runtime/core/lib/interaction-presentation.js +31 -10
  353. package/runtime/core/lib/mcp-input-hints.js +30 -1
  354. package/runtime/core/lib/mcp-tool-errors.js +5 -3
  355. package/runtime/core/lib/resources/canonical-init-plan.js +1 -1
  356. package/runtime/core/lib/runtime/plugin-provenance.js +9 -2
  357. package/runtime/core/lib/skill-dispatch/contract.js +6 -4
  358. package/runtime/core/lib/skill-dispatch/delivery-intake.js +3 -1
  359. package/runtime/core/lib/skill-dispatch/mcp-continuation.js +25 -2
  360. package/runtime/core/lib/skill-dispatch/prd-definition.js +3 -2
  361. package/runtime/core/lib/skill-dispatch/readiness-findings.js +7 -0
  362. package/runtime/core/lib/skill-dispatch/sd-definition.js +4 -2
  363. package/runtime/core/lib/skill-dispatch/service.js +17 -4
  364. package/runtime/core/lib/skill-dispatch/tp-definition.js +4 -2
  365. package/generated/plugins/agdf/companion/core.mjs +0 -16
  366. package/generated/plugins/agdf/companion/locales.json +0 -200
@@ -1,129 +1,258 @@
1
- // The companion figure (SDD-09, AC-010): an SVG document per mood. Accessories are drawn only inside
2
- // ACCESSORY_REGION, which lies outside FIGURE_BOX (the figure's extent including its motion), so no
3
- // accessory can cover the figure. The still pose emits no animation element at all.
4
-
1
+ // Shared, self-contained artwork for the Companion and Cockpit. Core supplies the Run state.
5
2
  export const VIEW = Object.freeze({ width: 200, height: 140 });
6
- // Body, ears, feet and shadow span x 34..126, y 26..134; motion adds up to 7 px sideways and 10 px upwards.
7
- export const FIGURE_BOX = Object.freeze({ x: 20, y: 8, width: 120, height: 132 });
8
- export const ACCESSORY_REGION = Object.freeze({ x: 148, y: 8, width: 48, height: 48 });
9
- // Each accessory's extent in region coordinates, including its strokes and motion.
10
- export const ACCESSORY_BOUNDS = Object.freeze({
11
- laeuft: { x: 8, y: 20, width: 32, height: 8 },
12
- baut: { x: 1, y: 16, width: 45, height: 31 },
13
- wartet: { x: 8, y: 8, width: 32, height: 32 },
14
- blockiert: { x: 6, y: 6, width: 36, height: 36 },
15
- fertig: { x: 1, y: 1, width: 46, height: 46 },
16
- neutral: null,
17
- });
18
- // The build accessory in region coordinates: a hammer swinging around the end of its handle between
19
- // the two angles (degrees, clockwise positive), and three bricks; strokes are at most 1.5 px wide.
20
- export const HAMMER = Object.freeze({ pivot: Object.freeze({ x: 36, y: 44 }), swing: Object.freeze([-55, 5]),
21
- head: Object.freeze({ x: -6, y: -26, width: 12, height: 6 }), handle: Object.freeze({ x: -1.5, y: -20, width: 3, height: 20 }) });
22
- export const BRICKS = Object.freeze([{ x: 2, y: 38 }, { x: 17, y: 38 }, { x: 9.5, y: 30 }].map(Object.freeze));
23
- export const BRICK_SIZE = Object.freeze({ width: 14, height: 7 });
24
3
 
25
- const BODY = Object.freeze({
26
- laeuft: { fill: '#4F7FD9', stroke: '#2D4E8F' },
27
- baut: { fill: '#3E8FB0', stroke: '#235A70' },
28
- wartet: { fill: '#E0A030', stroke: '#9A6A12' },
29
- blockiert: { fill: '#D9534F', stroke: '#8F2D2A' },
30
- fertig: { fill: '#3FA66A', stroke: '#23663F' },
31
- neutral: { fill: '#9AA3B2', stroke: '#5C6575' },
4
+ const SIGNAL = Object.freeze({
5
+ laeuft: '#a8d9ff',
6
+ baut: '#88f3ee',
7
+ wartet: '#ffd080',
8
+ blockiert: '#ff9b8c',
9
+ fertig: '#b8f5ad',
10
+ bereit: '#d0e4eb',
11
+ });
12
+ // Static shapes remain legible when reduced motion is requested; colors remain supplemental.
13
+ const FACES = Object.freeze({
14
+ bereit: { x: [62, 101], y: [52, 52], ry: [3.5, 3.5], mouth: 'M74 65h14', brow: '' },
15
+ laeuft: { x: [64, 103], y: [52, 52], ry: [4, 4], mouth: 'M75 64q6 3 12 0', brow: '' },
16
+ baut: { x: [66, 105], y: [52, 52], ry: [3.5, 3.5], mouth: 'M74 64q7 3 14 0', brow: 'M54 47q7-1 14 0 M94 47q7-1 14 0' },
17
+ wartet: { x: [62, 101], y: [52, 52], ry: [4, 4], mouth: 'M75 64q6 2 12 0', brow: 'M55 45q5-3 12 0' },
18
+ blockiert: { x: [66, 105], y: [52, 52], ry: [4.5, 4.5], mouth: 'M75 66q6-3 12 0', brow: 'M54 46q6-2 13 0 M94 46q6-2 13 0' },
19
+ fertig: { x: [62, 101], y: [52, 52], ry: [2.5, 2.5], mouth: 'M73 62q8 9 16 0', brow: '' },
32
20
  });
33
- const INK = '#1F2430';
21
+ // A friendly, closed smile for the ready figure; softer than the open smile of `fertig`.
22
+ const IDLE_SMILE = 'M74 63q7 6 14 0';
23
+ const GESTURES = new Set(['baut', 'wartet', 'blockiert', 'fertig']);
24
+ const GATES = new Set(['UR', 'PRD', 'SD', 'TP', 'QA', 'UAT', 'OR']);
25
+
26
+ export function observeFigure(previous, { scope, figure, current }) {
27
+ if (!scope || !figure || !Object.hasOwn(SIGNAL, figure.mood)) return null;
28
+ const { mood, reason } = figure;
29
+ const state = JSON.stringify([scope, mood, reason?.key, reason?.gate, reason?.decision, current]);
30
+ if (previous?.state === state) return previous;
31
+ const gate = reason?.key === 'waitingApproval' && GATES.has(reason.gate) ? reason.gate : undefined;
32
+ const changed = previous?.mood !== mood || (mood === 'wartet' && previous?.gate !== gate);
33
+ const sameScope = previous?.scope === scope;
34
+ const firstGesture = GESTURES.has(mood) && (!sameScope || !previous.seenCurrent);
35
+ const transition = previous?.current && previous.scope === scope && changed && GESTURES.has(mood);
36
+ const gesture = Boolean(current && (firstGesture || transition));
37
+ const seenCurrent = Boolean(current || (sameScope && previous.seenCurrent));
38
+ return { scope, state, current, mood, gate, gesture, seenCurrent, sequence: (previous?.sequence ?? 0) + 1 };
39
+ }
34
40
 
35
41
  const escape = text => String(text).replace(/[&<>"]/gu, char => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[char]);
36
- const loop = (isMoving, animation) => (isMoving ? animation : '');
42
+ const motion = (type, values, duration, keyTimes = '0;0.5;1') =>
43
+ `<animateTransform attributeName="transform" type="${type}" values="${values}" keyTimes="${keyTimes}" dur="${duration}s" repeatCount="1"/>`;
37
44
 
38
- function eyes(mood, isMoving) {
39
- if (mood === 'blockiert') {
40
- const cross = x => `<path d="M${x - 6} 66 l12 12 M${x + 6} 66 l-12 12" stroke="${INK}" stroke-width="3.5" stroke-linecap="round"/>`;
41
- return cross(64) + cross(96);
42
- }
43
- if (mood === 'fertig') {
44
- const arc = x => `<path d="M${x - 7} 74 q7 -9 14 0" fill="none" stroke="${INK}" stroke-width="3.5" stroke-linecap="round"/>`;
45
- return arc(64) + arc(96);
46
- }
47
- const blink = loop(isMoving, '<animate attributeName="ry" values="9;9;1;9" keyTimes="0;0.9;0.95;1" dur="3.6s" repeatCount="indefinite"/>');
48
- const look = mood === 'laeuft'
49
- ? loop(isMoving, '<animateTransform attributeName="transform" type="translate" values="-3 0;3 0;-3 0" dur="1.6s" repeatCount="indefinite"/>')
50
- : '';
51
- // A figure that builds looks down at its work on the right.
52
- const [dx, dy] = mood === 'baut' ? [3, 2] : [0, 0];
53
- const eye = x => `<ellipse cx="${x}" cy="72" rx="9" ry="9" fill="#FFFFFF">${blink}</ellipse><g>${look}<circle cx="${x + dx}" cy="${73 + dy}" r="4" fill="${INK}"/></g>`;
54
- return eye(64) + eye(96);
45
+ // The pit crew's round release sign (owner request of 2026-11-12): a project without AGDF is invited to
46
+ // start. The raised arm holds it; the counter-rotation keeps the sign nearly upright in the hand, and
47
+ // the slow sway is idle motion, so a still pose leaves it out. The word is part of the artwork.
48
+ function startSign(still) {
49
+ const sway = still ? '' : '<animateTransform attributeName="transform" type="rotate" values="-30 112 95;-36 112 95;-30 112 95;-25 112 95;-30 112 95" dur="5s" repeatCount="indefinite"/>';
50
+ return { angle: -30, sway, sign: `<g data-accessory="start-sign" transform="rotate(45 150 95)">
51
+ <path d="M150 95V62" stroke="#546d7a" stroke-width="4" stroke-linecap="round"/>
52
+ <circle cx="150" cy="48" r="17" fill="#17544e" stroke="#c9ebd9" stroke-width="2.5"/>
53
+ <text x="150" y="51.5" text-anchor="middle" fill="#f8fcff" font-size="9" font-weight="700" font-family="sans-serif">START</text>
54
+ </g>` };
55
55
  }
56
56
 
57
- const MOUTH = Object.freeze({
58
- laeuft: `<ellipse cx="80" cy="96" rx="4" ry="5" fill="${INK}"/>`,
59
- baut: `<path d="M74 97 q6 4 12 0" fill="none" stroke="${INK}" stroke-width="3" stroke-linecap="round"/>`,
60
- wartet: `<path d="M72 97 h16" stroke="${INK}" stroke-width="3" stroke-linecap="round"/>`,
61
- blockiert: `<path d="M70 101 q10 -9 20 0" fill="none" stroke="${INK}" stroke-width="3" stroke-linecap="round"/>`,
62
- fertig: `<path d="M68 93 q12 12 24 0" fill="none" stroke="${INK}" stroke-width="3" stroke-linecap="round"/>`,
63
- neutral: `<path d="M73 97 h14" stroke="${INK}" stroke-width="3" stroke-linecap="round"/>`,
64
- });
65
-
66
- const MOTION = Object.freeze({
67
- laeuft: '<animateTransform attributeName="transform" type="translate" values="0 0;0 -7;0 0" dur="0.7s" repeatCount="indefinite"/>',
68
- // A slow bob in time with the hammer.
69
- baut: '<animateTransform attributeName="transform" type="translate" values="0 0;0 -3;0 0" keyTimes="0;0.35;1" dur="0.9s" repeatCount="indefinite"/>',
70
- wartet: '<animateTransform attributeName="transform" type="rotate" values="-4 80 124;4 80 124;-4 80 124" dur="2.6s" repeatCount="indefinite"/>',
71
- blockiert: '<animateTransform attributeName="transform" type="translate" values="0 0;-4 0;4 0;-4 0;4 0;0 0;0 0" keyTimes="0;0.04;0.08;0.12;0.16;0.2;1" dur="2.2s" repeatCount="indefinite"/>',
72
- fertig: '<animateTransform attributeName="transform" type="translate" values="0 0;0 0;0 -10;0 0" keyTimes="0;0.6;0.8;1" dur="2s" repeatCount="indefinite"/>',
73
- neutral: '',
74
- });
57
+ function arm(mood, gesture, showpiece, invite = null) {
58
+ const pivot = '112 95';
59
+ const angles = invite ? [invite.angle]
60
+ : { baut: [-10, -52, 12, -52, -10], wartet: [-10, -34, -20, -34, -10], blockiert: [-10, -50, -28, -50, -10], fertig: [-10, 15, -2, 15, -10] }[mood] ?? [-10];
61
+ const movement = invite ? invite.sway : gesture && angles.length > 1
62
+ ? motion('rotate', angles.map(angle => `${angle} ${pivot}`).join(';'), 2.4, '0;0.2;0.5;0.75;1')
63
+ : '';
64
+ const torqueWrench = mood === 'baut' && !showpiece
65
+ ? `<g data-tool="torque-wrench">
66
+ <rect x="149" y="53" width="6" height="43" rx="3" fill="url(#metal)" stroke="#546d7a"/>
67
+ <rect x="148" y="78" width="8" height="15" rx="3" fill="#29434b"/>
68
+ <path d="M149 82h6m-6 4h6" stroke="#89c9c6" stroke-width="1"/>
69
+ <circle cx="152" cy="52" r="7" fill="url(#metal)" stroke="#546d7a" stroke-width="1.3"/>
70
+ <path d="M150 48h4l2 4-2 4h-4l-2-4z" fill="#334852" stroke="#d5e5e9" stroke-width=".7"/>
71
+ </g>`
72
+ : '';
73
+ const flagMotion = gesture && mood === 'fertig' ? motion('rotate', '0 151 95;-9 151 95;9 151 95;-9 151 95;0 151 95', 2.4, '0;0.2;0.5;0.75;1') : '';
74
+ const finishFlag = mood === 'fertig' ? `<g data-accessory="finish-flag">${flagMotion}
75
+ <path d="M151 95V42" fill="none" stroke="#546d7a" stroke-width="3" stroke-linecap="round"/>
76
+ <rect x="152" y="42" width="26" height="18" rx="1.5" fill="#f8fcff" stroke="#546d7a" stroke-width="1"/>
77
+ <path d="M152 42h6.5v6H152z M165 42h6.5v6H165z M158.5 48h6.5v6h-6.5z M171.5 48h6.5v6h-6.5z M152 54h6.5v6H152z M165 54h6.5v6H165z" fill="#25343d"/>
78
+ </g>` : '';
79
+ return `<g transform="rotate(${angles[0]} ${pivot})">${movement}${torqueWrench}${finishFlag}${invite?.sign ?? ''}
80
+ <rect x="106" y="88" width="45" height="14" rx="7" fill="url(#metal)" stroke="#546d7a"/>
81
+ <circle cx="115" cy="95" r="4" fill="#243644" stroke="#adc3cb"/>
82
+ <rect x="143" y="86" width="15" height="18" rx="5" fill="url(#metal)" stroke="#546d7a"/>
83
+ </g>`;
84
+ }
75
85
 
76
- // Drawn in region coordinates (0..48); ACCESSORY_BOUNDS states each extent.
77
- function accessory(mood, isMoving) {
78
- if (mood === 'laeuft') {
79
- const dot = (x, begin) => `<circle cx="${x}" cy="24" r="4" fill="#4F7FD9">${loop(isMoving, `<animate attributeName="opacity" values="0.2;1;0.2" dur="1.2s" begin="${begin}" repeatCount="indefinite"/>`)}</circle>`;
80
- return dot(12, '0s') + dot(24, '0.2s') + dot(36, '0.4s');
81
- }
82
- if (mood === 'baut') {
83
- // One brick appears per hammer stroke; the still pose shows all three and the raised hammer.
84
- const brick = ({ x, y }, begin) => `<rect x="${x}" y="${y}" width="${BRICK_SIZE.width}" height="${BRICK_SIZE.height}" rx="1" fill="#C8643C" stroke="#7A3A1E" stroke-width="1.5" opacity="${isMoving ? 0 : 1}">`
85
- + `${loop(isMoving, `<animate attributeName="opacity" values="0;1;1;0" keyTimes="0;0.1;0.9;1" dur="2.7s" begin="${begin}" repeatCount="indefinite"/>`)}</rect>`;
86
- const { pivot: { x: px, y: py }, swing: [strike, raised], head, handle } = HAMMER;
87
- const swing = loop(isMoving, `<animateTransform attributeName="transform" type="rotate" values="${raised} ${px} ${py};${strike} ${px} ${py};${raised} ${px} ${py}" keyTimes="0;0.35;1" dur="0.9s" repeatCount="indefinite"/>`);
88
- return BRICKS.map((position, index) => brick(position, `${index * 0.9}s`)).join('')
89
- + `<g transform="rotate(${raised} ${px} ${py})">${swing}`
90
- + `<rect x="${px + handle.x}" y="${py + handle.y}" width="${handle.width}" height="${handle.height}" rx="1" fill="#A0703C" stroke="#5C3A1A" stroke-width="1"/>`
91
- + `<rect x="${px + head.x}" y="${py + head.y}" width="${head.width}" height="${head.height}" rx="1" fill="#8A93A3" stroke="#374151" stroke-width="1.5"/></g>`;
92
- }
93
- if (mood === 'wartet') {
94
- const turn = loop(isMoving, '<animateTransform attributeName="transform" type="rotate" values="0 24 24;0 24 24;180 24 24" keyTimes="0;0.7;1" dur="2.4s" repeatCount="indefinite"/>');
95
- return `<g>${turn}<path d="M16 12 h16 l-8 12 l8 12 h-16 l8 -12 z" fill="#FFF3D6" stroke="#9A6A12" stroke-width="2.5" stroke-linejoin="round"/></g>`;
86
+ function accessory(mood, gate, gesture) {
87
+ if (mood === 'wartet' && gate) {
88
+ const raise = gesture ? motion('translate', '-2 5;0 -2;0 0', 2.4) : '';
89
+ const sway = gesture ? motion('rotate', '0 160 86;-8 160 86;8 160 86;-8 160 86;0 160 86', 2.4, '0;0.2;0.5;0.75;1') : '';
90
+ return `<g>${raise}<g>${sway}<g transform="rotate(-7 160 86)">
91
+ <rect x="131" y="74" width="60" height="24" rx="6" fill="#fff6e4" stroke="#995a25" stroke-width="1.2"/>
92
+ <text x="161" y="90" text-anchor="middle" fill="#774100" font-size="13" font-weight="700" font-family="sans-serif">${gate}</text>
93
+ </g></g></g>`;
96
94
  }
97
95
  if (mood === 'blockiert') {
98
- return '<g transform="translate(24 24)"><polygon points="-7,-17 7,-17 17,-7 17,7 7,17 -7,17 -17,7 -17,-7" fill="#D9534F" stroke="#8F2D2A" stroke-width="2"/>'
99
- + '<rect x="-2" y="-10" width="4" height="12" rx="1.5" fill="#FFFFFF"/><circle cx="0" cy="7" r="2.4" fill="#FFFFFF"/></g>';
96
+ const alert = gesture ? '<animateTransform attributeName="transform" type="rotate" values="0 0 0;360 0 0" keyTimes="0;1" calcMode="spline" keySplines=".42 0 .58 1" dur="1s" repeatCount="1"/>' : '';
97
+ return `<g transform="translate(162 49)"><g>${alert}
98
+ <path d="M-3 -13 Q0 -17 3 -13 L16 9 Q18 13 13 13 H-13 Q-18 13 -16 9Z" fill="#3b2830" stroke="#ff9b8c" stroke-width="2"/>
99
+ <path d="M0 -6 V3" stroke="#ff9b8c" stroke-width="3" stroke-linecap="round"/><circle cy="8" r="1.6" fill="#ff9b8c"/>
100
+ </g></g>`;
100
101
  }
101
- if (mood === 'fertig') {
102
- const sparkle = (x, y, begin) => `<path d="M${x} ${y - 7} L${x + 2} ${y - 2} L${x + 7} ${y} L${x + 2} ${y + 2} L${x} ${y + 7} L${x - 2} ${y + 2} L${x - 7} ${y} L${x - 2} ${y - 2} Z" fill="#F2C94C">`
103
- + `${loop(isMoving, `<animate attributeName="opacity" values="0;1;0" dur="1.8s" begin="${begin}" repeatCount="indefinite"/>`)}</path>`;
104
- return sparkle(8, 8, '0s') + sparkle(40, 8, '0.6s') + sparkle(40, 40, '1.2s')
105
- + '<g transform="translate(22 28)"><circle r="12" fill="#FFFFFF" stroke="#23663F" stroke-width="2.5"/>'
106
- + '<path d="M-6 0 l4 5 l8 -10" fill="none" stroke="#23663F" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></g>';
102
+ if (mood === 'baut' && gesture) {
103
+ return '<path d="M165 102v-9m-5 5h10m4-8 4-4" fill="none" stroke="#88f3ee" stroke-width="2" stroke-linecap="round" opacity="0"><animate attributeName="opacity" values="0;1;0;1;0" dur="2.4s" repeatCount="1"/></path>';
107
104
  }
108
105
  return '';
109
106
  }
110
107
 
111
- // mood: one of the five moods or 'neutral' (no run assigned, status unreadable).
112
- export function figureSvg(mood, { still = false, title = '' } = {}) {
113
- const isMoving = !still;
114
- const { fill, stroke } = BODY[mood];
115
- const { x, y } = ACCESSORY_REGION;
116
- return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${VIEW.width} ${VIEW.height}" width="${VIEW.width}" height="${VIEW.height}">`
117
- + `<title>${escape(title)}</title>`
118
- + '<ellipse cx="80" cy="128" rx="40" ry="6" fill="#000000" opacity="0.12"/>'
119
- + `<g>${loop(isMoving, MOTION[mood])}`
120
- + `<ellipse cx="62" cy="122" rx="11" ry="6" fill="${stroke}"/><ellipse cx="98" cy="122" rx="11" ry="6" fill="${stroke}"/>`
121
- + `<path d="M34 84 q0 -46 46 -46 q46 0 46 46 q0 36 -46 36 q-46 0 -46 -36 z" fill="${fill}" stroke="${stroke}" stroke-width="3"/>`
122
- + `<path d="M52 40 l-8 -14 l18 8 z M108 40 l8 -14 l-18 8 z" fill="${fill}" stroke="${stroke}" stroke-width="3" stroke-linejoin="round"/>`
123
- + '<ellipse cx="80" cy="100" rx="26" ry="17" fill="#FFFFFF" opacity="0.28"/>'
124
- + eyes(mood, isMoving) + MOUTH[mood] + '</g>'
125
- + `<g transform="translate(${x} ${y})">${accessory(mood, isMoving)}</g>`
126
- + '</svg>';
108
+ // A plan is a contextual prop, not a claim that a task or review has passed.
109
+ // The overview tablet: a crew member looking at the board, no run state. Three independent cycles with
110
+ // pairwise coprime lengths (17 s tap, 23 s scroll, 29 s lift) overlap with the blink (12 s) and the head
111
+ // (31 s), so the motion stays irregular without randomness: an unchanged read keeps the same SVG bytes.
112
+ function tabletAccessory(still) {
113
+ const lift = still ? '' : '<animateTransform attributeName="transform" type="rotate" values="-8 151 82;-8 151 82;-11 151 82;-10 151 82;-8 151 82;-8 151 82" keyTimes="0;0.41;0.44;0.5;0.54;1" dur="29s" repeatCount="indefinite"/>';
114
+ // A double tap early in the cycle, a single tap late, uneven pauses in between.
115
+ const tap = still ? '' : '<animateTransform attributeName="transform" type="translate" values="0 0;0 0;-3 -3;0 0;-3 -3;0 0;0 0;-3 -3;0 0;0 0" keyTimes="0;0.3;0.315;0.33;0.345;0.36;0.78;0.795;0.81;1" dur="17s" repeatCount="indefinite"/>';
116
+ // The screen scrolls one line, then the page quietly refreshes.
117
+ const scroll = still ? '' : '<animateTransform attributeName="transform" type="translate" values="0 0;0 0;0 -5;0 -5;0 0" keyTimes="0;0.62;0.66;0.97;1" dur="23s" repeatCount="indefinite"/>'
118
+ + '<animate attributeName="opacity" values="1;1;0;1" keyTimes="0;0.96;0.98;1" dur="23s" repeatCount="indefinite"/>';
119
+ return `<g data-accessory="overview-tablet" transform="rotate(-8 151 82)">${lift}
120
+ <clipPath id="tablet-screen"><rect x="136" y="65" width="35" height="27" rx="2"/></clipPath>
121
+ <rect x="132" y="61" width="43" height="36" rx="5" fill="#213a43" stroke="#a9c3ca" stroke-width="2"/>
122
+ <rect x="136" y="65" width="35" height="27" rx="2" fill="#416a6c"/>
123
+ <g clip-path="url(#tablet-screen)"><g>${scroll}<path d="M141 72h20M141 77h15M141 82h18M141 87h12M141 92h17" stroke="#9edbd1" stroke-width="1.5" stroke-linecap="round"/></g></g>
124
+ <g>${tap}<rect x="135" y="86" width="13" height="9" rx="4" fill="url(#metal)" stroke="#41616a" stroke-width="1.5"/></g>
125
+ </g>`;
126
+ }
127
+
128
+ // The TP plan as a showpiece (the cockpit's About page): a full sheet that the figure waves about.
129
+ // A run's own TP work is drawn by the writing clipboard below, like every other document gate.
130
+ function showpiecePlan(still) {
131
+ const movement = still ? '' : '<animateTransform attributeName="transform" type="rotate" values="0 155 80;-7 155 80;7 155 80;-4 155 80;0 155 80;0 155 80" keyTimes="0;0.12;0.26;0.38;0.5;1" dur="4s" repeatCount="indefinite"/>';
132
+ const pen = still ? '' : '<animateTransform attributeName="transform" type="translate" values="0 0;3 -3;0 0;0 0" keyTimes="0;0.18;0.36;1" dur="4s" repeatCount="indefinite"/>';
133
+ return `<g data-accessory="tp-plan" transform="rotate(-6 157 81)">${movement}
134
+ <rect x="127" y="54" width="62" height="49" rx="6" fill="#25454b" stroke="#a9c3cb" stroke-width="2"/>
135
+ <rect x="132" y="59" width="52" height="39" rx="3" fill="#e8f4ed"/>
136
+ <rect x="136" y="63" width="20" height="11" rx="3" fill="#c9e8dc"/>
137
+ <text x="146" y="71" text-anchor="middle" fill="#17544e" font-size="8" font-weight="700" font-family="sans-serif">TP</text>
138
+ <path d="M139 79h3m4 0h26m-33 6h3m4 0h23m-30 6h3m4 0h20" fill="none" stroke="#4d867b" stroke-width="1.5" stroke-linecap="round"/>
139
+ <g data-tool="planning-pen">${pen}<path d="M170 93l10-14" stroke="#243e48" stroke-width="3" stroke-linecap="round"/><path d="M170 93l-2 3" stroke="#d59751" stroke-width="2" stroke-linecap="round"/><rect x="174" y="87" width="11" height="8" rx="4" fill="url(#metal)" stroke="#546d7a" stroke-width="1"/></g>
140
+ </g>`;
141
+ }
142
+
143
+ // The document gates Claude drafts. A working figure writes on that gate's clipboard, so it is never
144
+ // empty-handed (owner request of 2026-11-12). The same rule holds at all four: the clipboard while Claude
145
+ // works, the gate sign while an approval is pending, the warning while the run is blocked.
146
+ const DRAFT_GATES = new Set(['UR', 'PRD', 'SD', 'TP']);
147
+ // One sheet takes WRITING.cycle seconds: the pen writes the three lines one after another, rests beside
148
+ // the full sheet, the lines fade and the sheet starts anew. Each line is { y, length, from, to } in
149
+ // seconds; the nib's tip rests at (168, 96), so a pen at (x, y) is moved by (x - 168, y - 96).
150
+ const WRITING = Object.freeze({ cycle: 9, rest: 6.8, fade: 8, reset: 8.6,
151
+ lines: Object.freeze([{ y: 79, length: 26, from: 0, to: 2 }, { y: 85, length: 23, from: 2.4, to: 4.2 }, { y: 91, length: 20, from: 4.6, to: 6.2 }]) });
152
+
153
+ // The clipboard of a document gate. In motion the lines appear behind the writing pen; the still pose
154
+ // shows the full sheet with the pen at rest. At TP it is the TP plan and keeps that name.
155
+ function draftBoard(label, still) {
156
+ const { cycle, rest, fade, reset, lines } = WRITING;
157
+ const at = seconds => +(seconds / cycle).toFixed(3);
158
+ const times = list => list.map(at).join(';');
159
+ const animated = (attribute, values, keyTimes) => `<animate attributeName="${attribute}" values="${values.join(';')}" keyTimes="${times(keyTimes)}" dur="${cycle}s" repeatCount="indefinite"/>`;
160
+ const tip = (x, y) => `${x - 168} ${y - 96}`;
161
+ const written = lines.map(({ y, length, from, to }) => {
162
+ if (still) return `<path d="M146 ${y}h${length}"/>`;
163
+ // Hidden until its turn, drawn while the pen passes, kept until the sheet resets.
164
+ const [values, keyTimes] = from ? [[length, length, 0, 0, length, length], [0, from, to, reset - 0.01, reset, cycle]]
165
+ : [[length, 0, 0, length, length], [0, to, reset - 0.01, reset, cycle]];
166
+ return `<path d="M146 ${y}h${length}" stroke-dasharray="${length} ${length}" stroke-dashoffset="${length}">${animated('stroke-dashoffset', values, keyTimes)}</path>`;
167
+ }).join('');
168
+ const penPath = lines.flatMap(({ y, length }) => [tip(146, y), tip(146 + length, y)]);
169
+ const pen = still ? '' : `<animateTransform attributeName="transform" type="translate" values="${[...penPath, '0 0', '0 0', penPath[0]].join(';')}" keyTimes="${times([...lines.flatMap(({ from, to }) => [from, to]), rest, reset, cycle])}" dur="${cycle}s" repeatCount="indefinite"/>`;
170
+ const wide = label.length > 2;
171
+ return `<g data-accessory="${label === 'TP' ? 'tp-plan' : 'gate-board'}" transform="rotate(-6 157 81)">
172
+ <rect x="127" y="54" width="62" height="49" rx="6" fill="#25454b" stroke="#a9c3cb" stroke-width="2"/>
173
+ <rect x="132" y="59" width="52" height="39" rx="3" fill="#e8f4ed"/>
174
+ <rect x="136" y="63" width="${wide ? 26 : 20}" height="11" rx="3" fill="#c9e8dc"/>
175
+ <text x="${wide ? 149 : 146}" y="71" text-anchor="middle" fill="#17544e" font-size="8" font-weight="700" font-family="sans-serif">${label}</text>
176
+ <path d="M139 79h3m-3 6h3m-3 6h3" fill="none" stroke="#4d867b" stroke-width="1.5" stroke-linecap="round"/>
177
+ <g data-sheet="lines" fill="none" stroke="#4d867b" stroke-width="1.5" stroke-linecap="round">${still ? '' : animated('opacity', [1, 1, 0, 1, 1], [0, fade, reset - 0.01, reset, cycle])}${written}</g>
178
+ <g data-tool="planning-pen">${pen}<path d="M170 93l10-14" stroke="#243e48" stroke-width="3" stroke-linecap="round"/><path d="M170 93l-2 3" stroke="#d59751" stroke-width="2" stroke-linecap="round"/><rect x="174" y="87" width="11" height="8" rx="4" fill="url(#metal)" stroke="#546d7a" stroke-width="1"/></g>
179
+ </g>`;
180
+ }
181
+
182
+ export function figureSvg(mood, { still = false, title = '', gate, workGate, gesture = false, sequence = 0, showcase = false, smile = false, tablet = false, invite = false, resting = false } = {}) {
183
+ // The About page shows the TP plan as a showpiece, whatever the mood.
184
+ const showpiece = showcase && workGate === 'TP';
185
+ // Only a working figure drafts: a waiting one keeps its gate sign and a blocked one its warning.
186
+ // While the run rests (`resting`: nobody works on the step right now) the pen lies on the full sheet.
187
+ const board = !showpiece && mood === 'laeuft' && DRAFT_GATES.has(workGate) ? workGate : null;
188
+ // The start sign belongs to a ready figure that shows no run; it is an invitation, never a run state.
189
+ const inviting = invite && mood === 'bereit' && !showpiece ? startSign(still) : null;
190
+ const signal = SIGNAL[mood] ?? SIGNAL.bereit;
191
+ // A ready figure without a run to show may smile; it is a face only, never a run state.
192
+ const face = smile && mood === 'bereit' ? { ...FACES.bereit, mouth: IDLE_SMILE } : FACES[mood] ?? FACES.bereit;
193
+ const act = gesture && !still;
194
+ const eye = index => {
195
+ const ry = face.ry[index];
196
+ const blink = still ? '' : showcase ? `<animate attributeName="ry" values="${ry};${ry};0.55;${ry};${ry}" keyTimes="0;0.2;0.23;0.27;1" dur="4s" repeatCount="indefinite"/>` : `<animate attributeName="ry" values="${ry};${ry};0.55;${ry};${ry}" keyTimes="0;0.965;0.973;0.983;1" dur="12s" repeatCount="indefinite"/>`;
197
+ return `<ellipse cx="${face.x[index]}" cy="${face.y[index]}" rx="8" ry="${ry}">${blink}</ellipse>`;
198
+ };
199
+ // Two small head movements are separated by unequal, long pauses; no motion in a still pose.
200
+ const idleHead = still ? '' : '<animateTransform attributeName="transform" type="rotate" values="0 82 82;0 82 82;3 82 82;0 82 82;0 82 82;-2 82 82;0 82 82;0 82 82" keyTimes="0;0.22;0.235;0.25;0.71;0.725;0.74;1" dur="31s" repeatCount="indefinite"/>';
201
+ const headBase = mood === 'wartet' ? 'rotate(3 82 82)' : 'rotate(0 82 82)';
202
+ const headTilt = act && mood === 'wartet' ? motion('rotate', '3 82 82;6 82 82;3 82 82', 2.4)
203
+ : act && mood === 'fertig' ? motion('rotate', '0 82 82;7 82 82;0 82 82', 2.4) : '';
204
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${VIEW.width} ${VIEW.height}" width="${VIEW.width}" height="${VIEW.height}"${act && Number.isSafeInteger(sequence) ? ` data-gesture="${sequence}"` : ''}>
205
+ <title>${escape(title)}</title>
206
+ <defs>
207
+ <linearGradient id="metal" x2="88%" y2="100%">
208
+ <stop stop-color="#f8fcff"/><stop offset=".55" stop-color="#adc3cb"/><stop offset="1" stop-color="#546d7a"/>
209
+ </linearGradient>
210
+ <linearGradient id="visor" x2="66%" y2="100%"><stop stop-color="#425763"/><stop offset=".64" stop-color="#1c2d3b"/><stop offset="1" stop-color="#0f1a25"/></linearGradient>
211
+ <linearGradient id="glint"><stop stop-color="#f8fcff" stop-opacity="0"/><stop offset=".5" stop-color="#f8fcff" stop-opacity=".53"/><stop offset="1" stop-color="#f8fcff" stop-opacity="0"/></linearGradient>
212
+ <radialGradient id="shadow"><stop stop-color="#111f31" stop-opacity=".38"/><stop offset="1" stop-color="#111f31" stop-opacity="0"/></radialGradient>
213
+ </defs>
214
+ <ellipse cx="88" cy="126" rx="64" ry="11" fill="url(#shadow)"/>
215
+ ${arm(mood, act, showpiece, inviting)}
216
+ <g fill="url(#metal)" stroke="#546d7a" stroke-width="1.4">
217
+ <rect x="53" y="113" width="24" height="11" rx="4"/>
218
+ <rect x="91" y="113" width="24" height="11" rx="4"/>
219
+ <rect x="50" y="76" width="67" height="42" rx="16"/>
220
+ </g>
221
+ <g data-crew="vest">
222
+ <path d="M54 85 65 81 82 91 100 81 113 85 113 108 Q112 115 105 116 H61 Q54 115 54 108Z" fill="#284d53" stroke="#173942" stroke-width="1"/>
223
+ <path d="M60 85 68 83 77 91 71 95 60 91Z M104 85 97 83 88 91 94 95 104 91Z" fill="#77c8bd"/>
224
+ <path d="M57 105h11 M100 105h10" stroke="#c9ebd9" stroke-width="2.8" stroke-linecap="round"/>
225
+ <path d="M57 111h53" stroke="#65b3aa" stroke-width="1.2" opacity=".85"/>
226
+ </g>
227
+ <rect x="71" y="91" width="26" height="13" rx="4" fill="#1c2d3b" stroke="#546d7a"/>
228
+ <path d="M77 97h3m3 0h3m3 0h3" stroke="${signal}" stroke-width="3" stroke-linecap="round"/>
229
+ <g>${idleHead}<g transform="${headBase}">${headTilt}
230
+ <path d="M57 23 51 9" stroke="#546d7a" stroke-width="3.5" stroke-linecap="round"/>
231
+ <circle cx="51" cy="9" r="4.5" fill="${signal}" stroke="#546d7a"/>
232
+ <rect x="123" y="43" width="17" height="24" rx="7" fill="url(#metal)" stroke="#546d7a" stroke-width="1.4"/>
233
+ <rect x="32" y="22" width="99" height="63" rx="22" fill="url(#metal)" stroke="#546d7a" stroke-width="1.4"/>
234
+ <g data-crew="headset">
235
+ <path d="M30 47 Q24 17 53 17 H109 Q136 17 135 47" fill="none" stroke="#234d54" stroke-width="5" stroke-linecap="round"/>
236
+ <path d="M35 30 Q40 20 53 20 H109 Q124 20 130 30" fill="none" stroke="#83c7bd" stroke-width="1.8" stroke-linecap="round"/>
237
+ <rect x="24" y="40" width="12" height="25" rx="6" fill="#26535a" stroke="#163940" stroke-width="1.2"/>
238
+ <rect x="128" y="40" width="12" height="25" rx="6" fill="#26535a" stroke="#163940" stroke-width="1.2"/>
239
+ <path d="M29 61 Q29 76 50 76" fill="none" stroke="#234d54" stroke-width="3" stroke-linecap="round"/>
240
+ <rect x="47" y="73" width="10" height="6" rx="3" fill="#24464d" stroke="#83c7bd" stroke-width=".8"/>
241
+ </g>
242
+ <path d="M48 28q6-3 14-3h38" stroke="#f8fcff" stroke-width="1.5" fill="none" opacity=".8"/>
243
+ <rect x="41" y="33" width="81" height="41" rx="13" fill="url(#visor)" stroke="#546d7a" stroke-width="1.3"/>
244
+ <path d="M49 39h65" stroke="url(#glint)" stroke-width="1.4"/>
245
+ <g fill="${signal}" stroke="${signal}" stroke-opacity=".25" stroke-width="2.5">
246
+ ${eye(0)}
247
+ ${eye(1)}
248
+ </g>
249
+ <path d="${face.mouth}" fill="none" stroke="${signal}" stroke-width="1.8" stroke-linecap="round"/>
250
+ ${face.brow ? `<path d="${face.brow}" fill="none" stroke="${signal}" stroke-width="1.4" stroke-linecap="round"/>` : ''}
251
+ </g></g>
252
+ ${accessory(mood, !showpiece && GATES.has(gate) ? gate : undefined, act)}
253
+ ${showpiece ? showpiecePlan(still) : board ? draftBoard(board, still || resting) : ''}
254
+ ${tablet && !showpiece && !inviting ? tabletAccessory(still) : ''}
255
+ </svg>`;
127
256
  }
128
257
 
129
258
  // The terminal has no Svg: a short face stands for the figure there.
@@ -133,5 +262,7 @@ export const FIGURE_TEXT = Object.freeze({
133
262
  wartet: '(-_-) ⧗',
134
263
  blockiert: '(x_x) !',
135
264
  fertig: '(^_^) ✓',
136
- neutral: '(·_·)',
265
+ bereit: '(·_·)',
137
266
  });
267
+ // The inviting figure of a project without AGDF: a friendly face with a raised hand.
268
+ export const INVITE_TEXT = '(^_^)/';
@@ -1,41 +1,23 @@
1
1
  // Single-line gate bar (SDD-02, AC-001, AC-003): ✓ done, ● current, ○ open, without separators. It
2
- // follows the status card's path for the run's route and adds the build phase as `CD+Tests` between
3
- // TP and QA on structured paths. Below the width the full bar needs, a condensed form keeps every
4
- // mark and still names the current gate.
2
+ // draws the status card's own path from the run view (SD SDD-001) and adds the build phase as
3
+ // `CD+Tests` between TP and QA on structured paths. Below the width the full bar needs, a condensed
4
+ // form keeps every mark and still names the current gate.
5
5
 
6
6
  import { BUILD_GATES, isStructured } from './run-state.mjs';
7
7
 
8
8
  const GLYPH = Object.freeze({ done: '✓', current: '●', open: '○' });
9
- const STRUCTURED = Object.freeze(['UR', 'PRD', 'SD', 'TP', 'QA', 'UAT', 'OR']);
10
- // The status card's paths (`BREADCRUMB_PATH_TEMPLATES`, gate-check.js); parity-tested.
11
- export const PATHS = Object.freeze({
12
- structured_delivery: STRUCTURED,
13
- structured_slice: STRUCTURED,
14
- verified_change: Object.freeze(['UR', 'Verified Change', 'OR']),
15
- quick_task: Object.freeze(['UR', 'Compact Delivery']),
16
- block: Object.freeze(['UR', 'Block']),
17
- undecided: Object.freeze(['UR']),
18
- });
19
9
  export const BUILD_MARK = 'CD+Tests';
20
- const USER_GATES = new Set(['UR', 'PRD', 'SD', 'TP', 'QA', 'UAT']);
10
+ // The status card's breadcrumb states; a blocked gate is the current one.
11
+ const MARK = Object.freeze({ fulfilled: 'done', current: 'current', blocked: 'current', open: 'open' });
21
12
  const AFTER_BUILD = new Set(['QA', 'UAT', 'OR']);
22
- const COMPACT = Object.freeze({ 'Verified Change': 'verified_change', 'Compact Delivery': 'quick_task', Block: 'block' });
23
-
24
- // One path entry's mark as `buildBreadcrumbPath` derives it; a completed run at OR has its closeout.
25
- function cardMark(gate, run) {
26
- if (USER_GATES.has(gate)) return run.approved.includes(gate) ? 'done' : gate === run.gate ? 'current' : 'open';
27
- if (gate === 'OR' && run.gate === 'OR' && run.lifecycle === 'completed') return 'done';
28
- if (gate === run.gate) return 'current';
29
- if ((gate === 'Verified Change' || gate === 'Compact Delivery') && run.gate === 'OR') return 'done';
30
- return Object.hasOwn(COMPACT, gate) && COMPACT[gate] === run.route ? 'current' : 'open';
31
- }
32
13
 
33
14
  export function gateMarks(run) {
34
- const path = Object.hasOwn(PATHS, run.route) ? PATHS[run.route] : PATHS.undecided;
35
- const marks = path.map(gate => ({ gate, mark: cardMark(gate, run) }));
36
- if (!isStructured(run.route)) return marks;
15
+ const path = run.path ?? [];
16
+ const marks = path.map(({ gate, status }) => ({ gate, mark: MARK[status] ?? 'open' }));
17
+ const qa = marks.findIndex(({ gate }) => gate === 'QA');
18
+ if (!isStructured(run.route) || qa < 0) return marks;
37
19
  const build = BUILD_GATES.includes(run.gate) ? 'current' : AFTER_BUILD.has(run.gate) || run.lifecycle === 'completed' ? 'done' : 'open';
38
- marks.splice(path.indexOf('QA'), 0, { gate: BUILD_MARK, mark: build });
20
+ marks.splice(qa, 0, { gate: BUILD_MARK, mark: build });
39
21
  return marks;
40
22
  }
41
23
 
@@ -1,8 +1,7 @@
1
- // Localization (SDD-05, AC-005) with the existing AGDF data: the chat language from config.json,
2
- // gate titles and next-step values from meta/agdf-interaction-locales.json (the registry), and the
3
- // companion's own labels from companion/locales.json. Mirrors resolveConfiguredChatLanguage
4
- // (packages/core/lib/resources/context.js) and localizedOperationalValue
5
- // (packages/core/lib/interaction-presentation.js); parity tests keep them equal.
1
+ // Localization (SDD-05, AC-005; SD SDD-004) with the existing AGDF data: the chat language from
2
+ // config.json and every text from meta/agdf-interaction-locales.json (the registry): gate titles and
3
+ // the companion section. Next steps and blocking texts arrive localized in the run view. Mirrors
4
+ // resolveConfiguredChatLanguage (packages/core/lib/resources/context.js); parity tests keep it equal.
6
5
 
7
6
  const TAG = /^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{1,8})*$/u;
8
7
 
@@ -25,7 +24,7 @@ export function resolveLocale(registry, requested) {
25
24
  }
26
25
 
27
26
  // Claude's own `language` setting is free text: a supported language tag (exact or base language)
28
- // or one of a locale's `languageNames` in the companion's locales.json, compared without case;
27
+ // or one of a locale's `languageNames` in the catalog's companion section, compared without case;
29
28
  // anything else names no locale (null).
30
29
  export function settingLocale(registry, labels, value) {
31
30
  const text = typeof value === 'string' ? value.trim() : '';
@@ -34,7 +33,7 @@ export function settingLocale(registry, labels, value) {
34
33
  if (tag && (registry.locales[tag] || registry.locales[tag.split('-')[0]])) return resolveLocale(registry, tag);
35
34
  const name = text.toLowerCase();
36
35
  const match = Object.entries(labels?.locales ?? {})
37
- .find(([locale, pack]) => registry.locales[locale] && (pack.languageNames ?? []).some(entry => entry.toLowerCase() === name));
36
+ .find(([locale, pack]) => registry.locales[locale] && Object.values(pack.languageNames ?? {}).some(entry => String(entry).toLowerCase() === name));
38
37
  return match?.[0] ?? null;
39
38
  }
40
39
 
@@ -53,31 +52,15 @@ export function gateTitle(registry, locale, gate) {
53
52
  return registry.locales[locale]?.gateTitles?.[gate] ?? registry.locales[registry.fallbackLocale]?.gateTitles?.[gate] ?? gate;
54
53
  }
55
54
 
56
- // The localized status-card value for a next-step source text, or the source text itself
57
- // ({ text, isLocalized }); an empty or "none" value becomes the pack's "none".
58
- export function localizeNextStep(registry, locale, value) {
59
- const source = String(value ?? '').trim();
60
- const pack = registry.locales[locale];
61
- const fallback = registry.locales[registry.fallbackLocale];
62
- if (!source || source === 'none') return { text: pack.primary.none, isLocalized: true };
63
- if (locale === registry.fallbackLocale) return { text: source, isLocalized: true };
64
- const groups = [
65
- [fallback.operationalValues, pack.operationalValues],
66
- [fallback.primary.actions, pack.primary.actions],
67
- [fallback.primary.afterApproval, pack.primary.afterApproval],
68
- ];
69
- for (const [sources, targets] of groups) {
70
- for (const [key, text] of Object.entries(sources ?? {})) {
71
- if (text === source) {
72
- const localized = String(targets?.[key] ?? '').trim();
73
- return localized ? { text: localized, isLocalized: true } : { text: source, isLocalized: false };
74
- }
75
- }
76
- }
77
- if (fallback.primary.quality === source && String(pack.primary.quality ?? '').trim()) {
78
- return { text: pack.primary.quality.trim(), isLocalized: true };
79
- }
80
- return { text: source, isLocalized: false };
55
+ // What a gate decides, in one sentence from the catalog; null for a step without one.
56
+ export function gateRationale(registry, locale, gate) {
57
+ return registry.locales[locale]?.gateRationale?.[gate] ?? registry.locales[registry.fallbackLocale]?.gateRationale?.[gate] ?? null;
58
+ }
59
+
60
+ // The companion's labels: the catalog's companion section per locale, in the shape label() reads.
61
+ export function companionLabels(registry) {
62
+ return { fallbackLocale: registry.fallbackLocale,
63
+ locales: Object.fromEntries(Object.entries(registry.locales).map(([locale, pack]) => [locale, pack.companion ?? {}])) };
81
64
  }
82
65
 
83
66
  // A companion label by dotted path with {name} parameters; missing keys fall back to the
@@ -8,18 +8,24 @@ import { gateTitle, label } from './localization.mjs';
8
8
  import { runState } from './state.mjs';
9
9
 
10
10
  const NOTICE_MOODS = new Set(['wartet', 'blockiert']);
11
+ // The reasons a toast announces: exactly those with a text under `notices` in the catalog. A run that
12
+ // cannot be read is blocked in the pane and the status line, but raises no toast.
13
+ const NOTICE_REASONS = new Set(['waitingApproval', 'waitingDecision', 'blocked']);
11
14
 
12
15
  // What the status line and the detector observe: { kind: 'run', runId, state } with the run-derived
13
- // state, { kind: 'unreadable' } or { kind: 'idle' } (nothing read yet, no control, no shown run).
16
+ // state, { kind: 'unreadable' }, { kind: 'notSetUp' } (a project without AGDF control) or
17
+ // { kind: 'idle' } (nothing read yet, no shown run).
14
18
  // mention: the chat's named run (chat-run navigation SDD-06); browsing never changes what is observed.
15
19
  export function observedRun({ snapshot, sessionStartedAt, selection = null, mention = null }) {
16
20
  if (!snapshot) return { kind: 'idle' };
17
- if (snapshot.status === 'failed') return { kind: 'unreadable' };
21
+ if (snapshot.status === 'failed' || snapshot.status === 'unavailable') return { kind: 'unreadable' };
22
+ if (snapshot.status === 'no_control') return { kind: 'notSetUp' };
18
23
  if (snapshot.status !== 'ok') return { kind: 'idle' };
19
24
  const { run } = assignRun({ runs: snapshot.runs, sessionStartedAt, selection, mention });
20
25
  if (!run) return selection && snapshot.unreadable.some(item => item.id === selection) ? { kind: 'unreadable' } : { kind: 'idle' };
21
- const state = runState(run);
22
- return state.mood === null ? { kind: 'unreadable' } : { kind: 'run', runId: run.id, state };
26
+ const figure = runState(run);
27
+ // The blocking text arrives localized in the run view; the signature keeps the code.
28
+ return { kind: 'run', runId: run.id, state: { ...figure, reason: { ...figure.reason, decisionText: run.blockingText || undefined } } };
23
29
  }
24
30
 
25
31
  const signature = ({ mood, reason }) => [mood, reason.key, reason.gate ?? '', reason.decision ?? ''].join('|');
@@ -32,14 +38,16 @@ export function observeNotice(previous, observed) {
32
38
  if (observed.kind !== 'run') return { observation: null, notice: null };
33
39
  const observation = { runId: observed.runId, signature: signature(observed.state) };
34
40
  const changed = previous?.runId === observed.runId && previous.signature !== observation.signature;
35
- return { observation, notice: changed && NOTICE_MOODS.has(observed.state.mood) ? observed.state : null };
41
+ const announced = NOTICE_MOODS.has(observed.state.mood) && NOTICE_REASONS.has(observed.state.reason.key);
42
+ return { observation, notice: changed && announced ? observed.state : null };
36
43
  }
37
44
 
38
- // The toast for a notice, e.g. "<run> wartet auf Freigabe: Qualitätssicherung".
39
- export function noticeText(runId, state, { registry, labels, locale }) {
45
+ // The toast for a notice, e.g. "Wartet auf Freigabe: Qualitätssicherung". A notice always concerns
46
+ // the run the status line follows, so it names no run (owner request of 2026-11-06, T-013).
47
+ export function noticeText(state, { registry, labels, locale }) {
40
48
  const t = (path, params) => label(labels, locale, path, params);
41
- const params = { run: runId, gate: gateTitle(registry, locale, state.reason.gate) };
42
- if (state.reason.decision) params.decision = t(`decisions.${state.reason.decision}`);
49
+ const params = { gate: gateTitle(registry, locale, state.reason.gate) };
50
+ if (state.reason.decision) params.decision = state.reason.decisionText ?? state.reason.decision;
43
51
  return t(`notices.${state.reason.key}`, params);
44
52
  }
45
53
 
@@ -47,7 +55,9 @@ export function noticeText(runId, state, { registry, labels, locale }) {
47
55
  export function statusText(observed, { labels, locale }) {
48
56
  const t = path => label(labels, locale, path);
49
57
  if (observed.kind === 'unreadable') return `AGDF · ${t('statusStates.unreadable')}`;
50
- if (observed.kind !== 'run') return `AGDF · ${t('statusStates.neutral')}`;
58
+ // A project without AGDF is told apart from a set-up project that has nothing to do.
59
+ if (observed.kind === 'notSetUp') return `AGDF · ${t('statusStates.notSetUp')}`;
60
+ if (observed.kind !== 'run') return `AGDF · ${t('statusStates.bereit')}`;
51
61
  const { mood, reason } = observed.state;
52
62
  return mood === 'fertig' || !reason.gate ? `AGDF · ${t(`statusStates.${mood}`)}` : `AGDF · ${reason.gate} · ${t(`statusStates.${mood}`)}`;
53
63
  }