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.
- package/generated/.agdf/control/README.md +5 -0
- package/generated/.agdf/control/templates/BRAND.md +28 -0
- package/generated/.agdf/control/templates/artefacts/PRD.md +11 -0
- package/generated/.agdf/control/templates/artefacts/SD.md +4 -0
- package/generated/.agdf/control/templates/artefacts/UX_INTENT_DEFINITION.md +1 -1
- package/generated/.opencode/agdf-interaction-locales.json +436 -2
- package/generated/.opencode/contracts/gate-artifact-preparation.md +9 -3
- package/generated/.opencode/contracts/interaction.md +10 -4
- package/generated/.opencode/contracts/modes.md +5 -0
- package/generated/.opencode/contracts/prd-definition.md +40 -1
- package/generated/.opencode/contracts/quality.md +35 -0
- package/generated/.opencode/contracts/request-activation.md +6 -3
- package/generated/.opencode/contracts/sd-definition.md +46 -0
- package/generated/.opencode/contracts/tp-definition.md +8 -0
- package/generated/.opencode/contracts/ur-definition.md +9 -5
- package/generated/.opencode/skills/agdf-ux-intent-definition/SKILL.md +31 -2
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/companion/events.mjs +119 -0
- package/generated/plugins/agdf/companion/figure.mjs +242 -111
- package/generated/plugins/agdf/companion/gate-bar.mjs +10 -28
- package/generated/plugins/agdf/companion/localization.mjs +15 -32
- package/generated/plugins/agdf/companion/notice.mjs +20 -10
- package/generated/plugins/agdf/companion/register.mjs +310 -66
- package/generated/plugins/agdf/companion/run-state.mjs +89 -90
- package/generated/plugins/agdf/companion/state.mjs +6 -32
- package/generated/plugins/agdf/companion/view.mjs +199 -24
- package/generated/plugins/agdf/control/README.md +5 -0
- package/generated/plugins/agdf/control/templates/BRAND.md +28 -0
- package/generated/plugins/agdf/control/templates/artefacts/PRD.md +11 -0
- package/generated/plugins/agdf/control/templates/artefacts/SD.md +4 -0
- package/generated/plugins/agdf/control/templates/artefacts/UX_INTENT_DEFINITION.md +1 -1
- package/generated/plugins/agdf/mcp/server/README.md +26 -2
- package/generated/plugins/agdf/mcp/server/package.json +3 -3
- package/generated/plugins/agdf/mcp/server/src/generation-runtime.js +14 -3
- package/generated/plugins/agdf/mcp/server/src/generation.js +8 -2
- package/generated/plugins/agdf/mcp/server/src/main.js +5 -1
- package/generated/plugins/agdf/mcp/server/src/next-action.js +227 -0
- package/generated/plugins/agdf/mcp/server/src/prepared-call-transport.js +306 -0
- package/generated/plugins/agdf/mcp/server/src/safe-read-continuation.js +62 -0
- package/generated/plugins/agdf/mcp/server/src/server.js +155 -37
- package/generated/plugins/agdf/mcp/server/ui/cockpit.html +130 -33
- package/generated/plugins/agdf/mcp/server/ui/decision-manifest.json +3 -3
- package/generated/plugins/agdf/mcp/server/ui/decision.html +3 -3
- package/generated/plugins/agdf/mcp/server/ui/manifest.json +3 -3
- package/generated/plugins/agdf/meta/agdf-interaction-locales.json +436 -2
- package/generated/plugins/agdf/meta/agdf-mcp-capability.json +1 -1
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
- package/generated/plugins/agdf/meta/contracts/interaction.md +10 -4
- package/generated/plugins/agdf/meta/contracts/modes.md +5 -0
- package/generated/plugins/agdf/meta/contracts/prd-definition.md +40 -1
- package/generated/plugins/agdf/meta/contracts/quality.md +35 -0
- package/generated/plugins/agdf/meta/contracts/request-activation.md +6 -3
- package/generated/plugins/agdf/meta/contracts/sd-definition.md +46 -0
- package/generated/plugins/agdf/meta/contracts/tp-definition.md +8 -0
- package/generated/plugins/agdf/meta/contracts/ur-definition.md +9 -5
- package/generated/plugins/agdf/meta/copilot-payload-baseline.json +3 -3
- package/generated/plugins/agdf/meta/distribution-profile-history.json +14 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +436 -2
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/interaction.md +10 -4
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/modes.md +5 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/prd-definition.md +40 -1
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/quality.md +35 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/request-activation.md +6 -3
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/sd-definition.md +46 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/tp-definition.md +8 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/ur-definition.md +9 -5
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +2 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/parse-args.js +7 -4
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/project-read-command.js +29 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +2 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-dispatch-runtime.js +36 -7
- package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-lifecycle/package.js +7 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-lifecycle/plugin-runtime.js +34 -6
- package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-lifecycle/prepared-call-journal.js +269 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/mcp-worker-runtime.js +86 -83
- package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/validator-application.js +2 -2
- package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/events.js +157 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/figure-state.js +38 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/journal.js +186 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/companion/run-view.js +227 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/acceptance-criteria.js +2 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/closeout-readiness.js +24 -6
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/decision-content-placeholder.js +4 -1
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-check.js +49 -7
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-inputs.js +2 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-pure.js +7 -3
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/prd-readiness.js +7 -2
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/report-decision.js +9 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/traceability-readiness.js +57 -8
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/ur-readiness.js +15 -2
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/artifact-readiness.js +5 -3
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/authoring-inputs.js +107 -22
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/cockpit-list.js +10 -8
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/cockpit-session.js +11 -3
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/cockpit-work.js +4 -2
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/cockpit.js +47 -33
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/contract.js +64 -24
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/material-recording-calls.js +54 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/project-state.js +2 -1
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/run-classification.js +31 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/selection.js +6 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/service.js +32 -5
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/work-situation.js +25 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-read/cockpit-worker.js +1 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/authoring-text-handoff.js +3 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/input-resolution.js +7 -5
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/material-limits.js +4 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/prepared-control-calls.js +137 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/presentation-delivery.js +4 -1
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-contract.js +10 -4
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-schema.js +9 -3
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-service.js +35 -11
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-create-command.js +6 -1
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-identity.js +2 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-inventory-reader.js +54 -5
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-inventory.js +12 -27
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-material.js +25 -7
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-presentation-render.js +113 -28
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-revision.js +38 -20
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-source-revisions.js +37 -17
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-state-reader.js +10 -3
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-steps.js +8 -5
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-title.js +43 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/index.js +3 -1
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog-validation.js +7 -1
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog.js +8 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/interaction-presentation.js +31 -10
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/mcp-input-hints.js +30 -1
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/mcp-tool-errors.js +5 -3
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/resources/canonical-init-plan.js +1 -1
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/runtime/plugin-provenance.js +9 -2
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/contract.js +6 -4
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/delivery-intake.js +3 -1
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/mcp-continuation.js +25 -2
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/prd-definition.js +3 -2
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/readiness-findings.js +7 -0
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/sd-definition.js +4 -2
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/service.js +17 -4
- package/generated/plugins/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/tp-definition.js +4 -2
- package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +4 -3
- package/generated/plugins/agdf/skills/ux-intent-definition/SKILL.md +31 -2
- package/generated/plugins/agdf/skills/ux-intent-definition/help.md +8 -1
- package/generated/plugins/agdf/submission/openai/availability.md +1 -1
- package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/plugins/agdf/submission/openai/release-notes.md +5 -8
- package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
- package/generated/plugins/agdf-planning/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf-planning/plugin.json +1 -1
- package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +358 -203
- package/generated/plugins/copilot/agdf/control/README.md +5 -0
- package/generated/plugins/copilot/agdf/control/templates/BRAND.md +28 -0
- package/generated/plugins/copilot/agdf/control/templates/artefacts/PRD.md +11 -0
- package/generated/plugins/copilot/agdf/control/templates/artefacts/SD.md +4 -0
- package/generated/plugins/copilot/agdf/control/templates/artefacts/UX_INTENT_DEFINITION.md +1 -1
- package/generated/plugins/copilot/agdf/mcp/server/README.md +26 -2
- package/generated/plugins/copilot/agdf/mcp/server/package.json +3 -3
- package/generated/plugins/copilot/agdf/mcp/server/src/generation-runtime.js +14 -3
- package/generated/plugins/copilot/agdf/mcp/server/src/generation.js +8 -2
- package/generated/plugins/copilot/agdf/mcp/server/src/main.js +5 -1
- package/generated/plugins/copilot/agdf/mcp/server/src/next-action.js +227 -0
- package/generated/plugins/copilot/agdf/mcp/server/src/prepared-call-transport.js +306 -0
- package/generated/plugins/copilot/agdf/mcp/server/src/safe-read-continuation.js +62 -0
- package/generated/plugins/copilot/agdf/mcp/server/src/server.js +155 -37
- package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/copilot/agdf/meta/distribution-profile-history.json +14 -0
- package/generated/plugins/copilot/agdf/plugin.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +436 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/interaction.md +10 -4
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/modes.md +5 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/prd-definition.md +40 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/quality.md +35 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/request-activation.md +6 -3
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/sd-definition.md +46 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/tp-definition.md +8 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/contracts/ur-definition.md +9 -5
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +2 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +7 -4
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/project-read-command.js +29 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +2 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-dispatch-runtime.js +36 -7
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-lifecycle/package.js +7 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-lifecycle/plugin-runtime.js +34 -6
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-lifecycle/prepared-call-journal.js +269 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/mcp-worker-runtime.js +81 -78
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/validator-application.js +2 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/events.js +157 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/figure-state.js +38 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/journal.js +186 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/companion/run-view.js +227 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/acceptance-criteria.js +2 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/closeout-readiness.js +24 -6
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/decision-content-placeholder.js +4 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-check.js +49 -7
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-inputs.js +2 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/gate-policy-pure.js +7 -3
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/prd-readiness.js +7 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/report-decision.js +9 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/traceability-readiness.js +57 -8
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-evaluation/ur-readiness.js +15 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/artifact-readiness.js +5 -3
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/authoring-inputs.js +107 -22
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/contract.js +64 -24
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/material-recording-calls.js +54 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/project-state.js +2 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/run-classification.js +31 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/selection.js +6 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/service.js +32 -5
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-inspect/work-situation.js +25 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/authoring-text-handoff.js +3 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/input-resolution.js +7 -5
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/material-limits.js +4 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/prepared-control-calls.js +137 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/presentation-delivery.js +4 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-contract.js +10 -4
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-schema.js +9 -3
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-command-service.js +35 -11
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-create-command.js +6 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-identity.js +2 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-inventory-reader.js +54 -5
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-inventory.js +12 -27
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-material.js +25 -7
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-presentation-render.js +113 -28
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-revision.js +38 -20
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-source-revisions.js +37 -17
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-state-reader.js +10 -3
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-steps.js +8 -5
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/control-state/run-title.js +43 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/index.js +3 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog-validation.js +7 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/interaction-catalog.js +8 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/interaction-presentation.js +31 -10
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/mcp-input-hints.js +30 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/mcp-tool-errors.js +5 -3
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/resources/canonical-init-plan.js +1 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/runtime/plugin-provenance.js +9 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/contract.js +6 -4
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/delivery-intake.js +3 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/mcp-continuation.js +25 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/prd-definition.js +3 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/readiness-findings.js +7 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/sd-definition.js +4 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/service.js +17 -4
- package/generated/plugins/copilot/agdf/runtime/create-agdf/runtime/core/lib/skill-dispatch/tp-definition.js +4 -2
- package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/plugins/copilot/agdf/skills/agdf-interaction-locales.json +1 -1
- package/generated/plugins/copilot/agdf/skills/agdf-ux-intent-definition/SKILL.md +31 -2
- package/generated/plugins/copilot/agdf/skills/contracts/gate-artifact-preparation.md +9 -3
- package/generated/plugins/copilot/agdf/skills/contracts/interaction.md +10 -4
- package/generated/plugins/copilot/agdf/skills/contracts/modes.md +5 -0
- package/generated/plugins/copilot/agdf/skills/contracts/prd-definition.md +40 -1
- package/generated/plugins/copilot/agdf/skills/contracts/quality.md +35 -0
- package/generated/plugins/copilot/agdf/skills/contracts/request-activation.md +6 -3
- package/generated/plugins/copilot/agdf/skills/contracts/sd-definition.md +46 -0
- package/generated/plugins/copilot/agdf/skills/contracts/tp-definition.md +8 -0
- package/generated/plugins/copilot/agdf/skills/contracts/ur-definition.md +9 -5
- package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/submissions/openai/agdf/meta/agdf-interaction-locales.json +436 -2
- package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/submissions/openai/agdf/meta/contracts/gate-artifact-preparation.md +9 -3
- package/generated/submissions/openai/agdf/meta/contracts/interaction.md +10 -4
- package/generated/submissions/openai/agdf/meta/contracts/modes.md +5 -0
- package/generated/submissions/openai/agdf/meta/contracts/prd-definition.md +40 -1
- package/generated/submissions/openai/agdf/meta/contracts/quality.md +35 -0
- package/generated/submissions/openai/agdf/meta/contracts/request-activation.md +6 -3
- package/generated/submissions/openai/agdf/meta/contracts/sd-definition.md +46 -0
- package/generated/submissions/openai/agdf/meta/contracts/tp-definition.md +8 -0
- package/generated/submissions/openai/agdf/meta/contracts/ur-definition.md +9 -5
- package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +3 -3
- package/generated/submissions/openai/agdf/meta/distribution-profile-history.json +14 -0
- package/generated/submissions/openai/agdf/plugin.json +1 -1
- package/generated/submissions/openai/agdf/skills/ux-intent-definition/SKILL.md +31 -2
- package/generated/submissions/openai/agdf/skills/ux-intent-definition/help.md +8 -1
- package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
- package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/inventory.json +24 -24
- package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
- package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
- package/generated/submissions/openai/agdf/submission/openai/release-notes.md +5 -8
- package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
- package/lib/cli/command-registry.js +2 -1
- package/lib/cli/parse-args.js +7 -4
- package/lib/cli/project-read-command.js +29 -0
- package/lib/cli/validation-handlers.js +2 -1
- package/lib/mcp-dispatch-runtime.js +36 -7
- package/lib/mcp-lifecycle/package.js +7 -0
- package/lib/mcp-lifecycle/plugin-runtime.js +34 -6
- package/lib/mcp-lifecycle/prepared-call-journal.js +269 -0
- package/lib/mcp-worker-runtime.js +86 -83
- package/lib/runtime/validator-application.js +2 -2
- package/lib/scaffold/plan.js +2 -0
- package/package.json +1 -1
- package/runtime/core/lib/companion/events.js +157 -0
- package/runtime/core/lib/companion/figure-state.js +38 -0
- package/runtime/core/lib/companion/journal.js +186 -0
- package/runtime/core/lib/companion/run-view.js +227 -0
- package/runtime/core/lib/control-evaluation/acceptance-criteria.js +2 -0
- package/runtime/core/lib/control-evaluation/closeout-readiness.js +24 -6
- package/runtime/core/lib/control-evaluation/decision-content-placeholder.js +4 -1
- package/runtime/core/lib/control-evaluation/gate-check.js +49 -7
- package/runtime/core/lib/control-evaluation/gate-policy-inputs.js +2 -0
- package/runtime/core/lib/control-evaluation/gate-policy-pure.js +7 -3
- package/runtime/core/lib/control-evaluation/prd-readiness.js +7 -2
- package/runtime/core/lib/control-evaluation/report-decision.js +9 -0
- package/runtime/core/lib/control-evaluation/traceability-readiness.js +57 -8
- package/runtime/core/lib/control-evaluation/ur-readiness.js +15 -2
- package/runtime/core/lib/control-inspect/artifact-readiness.js +5 -3
- package/runtime/core/lib/control-inspect/authoring-inputs.js +107 -22
- package/runtime/core/lib/control-inspect/cockpit-list.js +10 -8
- package/runtime/core/lib/control-inspect/cockpit-session.js +11 -3
- package/runtime/core/lib/control-inspect/cockpit-work.js +4 -2
- package/runtime/core/lib/control-inspect/cockpit.js +47 -33
- package/runtime/core/lib/control-inspect/contract.js +64 -24
- package/runtime/core/lib/control-inspect/material-recording-calls.js +54 -0
- package/runtime/core/lib/control-inspect/project-state.js +2 -1
- package/runtime/core/lib/control-inspect/run-classification.js +31 -0
- package/runtime/core/lib/control-inspect/selection.js +6 -0
- package/runtime/core/lib/control-inspect/service.js +32 -5
- package/runtime/core/lib/control-inspect/work-situation.js +25 -0
- package/runtime/core/lib/control-read/cockpit-worker.js +1 -0
- package/runtime/core/lib/control-state/authoring-text-handoff.js +3 -0
- package/runtime/core/lib/control-state/input-resolution.js +7 -5
- package/runtime/core/lib/control-state/material-limits.js +4 -0
- package/runtime/core/lib/control-state/prepared-control-calls.js +137 -0
- package/runtime/core/lib/control-state/presentation-delivery.js +4 -1
- package/runtime/core/lib/control-state/run-command-contract.js +10 -4
- package/runtime/core/lib/control-state/run-command-schema.js +9 -3
- package/runtime/core/lib/control-state/run-command-service.js +35 -11
- package/runtime/core/lib/control-state/run-create-command.js +6 -1
- package/runtime/core/lib/control-state/run-identity.js +2 -0
- package/runtime/core/lib/control-state/run-inventory-reader.js +54 -5
- package/runtime/core/lib/control-state/run-inventory.js +12 -27
- package/runtime/core/lib/control-state/run-material.js +25 -7
- package/runtime/core/lib/control-state/run-presentation-render.js +113 -28
- package/runtime/core/lib/control-state/run-revision.js +38 -20
- package/runtime/core/lib/control-state/run-source-revisions.js +37 -17
- package/runtime/core/lib/control-state/run-state-reader.js +10 -3
- package/runtime/core/lib/control-state/run-steps.js +8 -5
- package/runtime/core/lib/control-state/run-title.js +43 -0
- package/runtime/core/lib/index.js +3 -1
- package/runtime/core/lib/interaction-catalog-validation.js +7 -1
- package/runtime/core/lib/interaction-catalog.js +8 -0
- package/runtime/core/lib/interaction-presentation.js +31 -10
- package/runtime/core/lib/mcp-input-hints.js +30 -1
- package/runtime/core/lib/mcp-tool-errors.js +5 -3
- package/runtime/core/lib/resources/canonical-init-plan.js +1 -1
- package/runtime/core/lib/runtime/plugin-provenance.js +9 -2
- package/runtime/core/lib/skill-dispatch/contract.js +6 -4
- package/runtime/core/lib/skill-dispatch/delivery-intake.js +3 -1
- package/runtime/core/lib/skill-dispatch/mcp-continuation.js +25 -2
- package/runtime/core/lib/skill-dispatch/prd-definition.js +3 -2
- package/runtime/core/lib/skill-dispatch/readiness-findings.js +7 -0
- package/runtime/core/lib/skill-dispatch/sd-definition.js +4 -2
- package/runtime/core/lib/skill-dispatch/service.js +17 -4
- package/runtime/core/lib/skill-dispatch/tp-definition.js +4 -2
- package/generated/plugins/agdf/companion/core.mjs +0 -16
- package/generated/plugins/agdf/companion/locales.json +0 -200
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
import { readControlLayout } from './control-layout.js';
|
|
2
|
-
import { prepareRunContentState } from '../control-evaluation/run-state.js';
|
|
2
|
+
import { prepareRunContentState, readArtefactHeading } from '../control-evaluation/run-state.js';
|
|
3
3
|
import { transitionDecisionForRunState } from '../control-evaluation/gate-policy.js';
|
|
4
|
+
import { evaluateGateCheck } from '../control-evaluation/gate-check.js';
|
|
5
|
+
import { projectCockpitAssessment } from '../control-inspect/run-classification.js';
|
|
6
|
+
import { projectWorkSituation } from '../control-inspect/work-situation.js';
|
|
7
|
+
import { runClosure } from './run-operations.js';
|
|
4
8
|
import { existsSync } from "../control-read/fs.js";
|
|
5
9
|
import { join } from "node:path";
|
|
6
10
|
import { discoverRuns } from "./run-state-reader.js";
|
|
7
11
|
import { buildRunInventory } from "./run-inventory.js";
|
|
12
|
+
import { parseControlState } from './run-state-parser.js';
|
|
13
|
+
import { runSealState, listedArtefactPaths } from './run-seal.js';
|
|
14
|
+
import { isSafeControlRelativePath } from './contained-file.js';
|
|
15
|
+
|
|
16
|
+
const READ_BOUNDARY_CODES = ['source_changed', 'resource_limit', 'resource_denied', 'timeout'];
|
|
17
|
+
const inControlScope = path => isSafeControlRelativePath(path) && path.startsWith('.agdf/control/');
|
|
18
|
+
// The detail reader's boundary: a run registering sources outside .agdf/control cannot be proven here.
|
|
19
|
+
const registersOnlyControlSources = content => listedArtefactPaths(content).every(inControlScope);
|
|
8
20
|
|
|
9
21
|
// 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
|
-
|
|
22
|
+
// and, when the full parser rejected it, its findings. No run state is read a second time. `observe: false`
|
|
23
|
+
// skips the per-run gate observation, which reads registered documents, for a caller that evaluates the
|
|
24
|
+
// runs itself (the companion run view, which reads each run in its own captured snapshot).
|
|
25
|
+
// `cockpitAssessment` evaluates active runs only, like the companion run view: terminal runs stay
|
|
26
|
+
// summarized history, so a long history costs no gate evaluation per run and per refresh.
|
|
27
|
+
export function readRunInventory(root, { language = "en", observe = true, includePresentation = false, cockpitAssessment = false } = {}) {
|
|
12
28
|
if (!existsSync(join(root, '.agdf/control'))) return buildRunInventory(null, { language });
|
|
13
29
|
readControlLayout(root);
|
|
14
30
|
if (!existsSync(join(root, '.agdf/control/runs'))) return buildRunInventory([], { language,
|
|
@@ -18,12 +34,45 @@ export function readRunInventory(root, { language = "en" } = {}) {
|
|
|
18
34
|
const store = discovered.filter((run) => run.run_id === "<repository>");
|
|
19
35
|
const sources = discovered.filter(run => run.run_id !== '<repository>').map(run => {
|
|
20
36
|
const source = { run_id: run.run_id, ...(typeof run.content === 'string' ? { text: run.content } : {}), findings: run.valid ? [] : run.findings };
|
|
21
|
-
if (run.
|
|
37
|
+
if (includePresentation && typeof run.content === 'string') {
|
|
38
|
+
let name = '', seal = 'unconfirmed';
|
|
39
|
+
try {
|
|
40
|
+
const ur = parseControlState(run.content).artefacts.get('UR');
|
|
41
|
+
const path = String(ur?.path ?? '').replace(/^`|`$/g, '').trim();
|
|
42
|
+
if (inControlScope(path)) name = readArtefactHeading(root, ur).replace(/^UR:\s*/i, '').trim();
|
|
43
|
+
} catch { /* An unreadable title must not hide the inventory. */ }
|
|
44
|
+
try {
|
|
45
|
+
if (registersOnlyControlSources(run.content)) {
|
|
46
|
+
const result = runSealState(root, run.content).status;
|
|
47
|
+
seal = result === 'valid' ? 'valid' : result === 'unsealed' ? 'unsealed'
|
|
48
|
+
: ['invalid', 'content_changed', 'approvals_changed'].includes(result) ? 'invalid' : 'unconfirmed';
|
|
49
|
+
}
|
|
50
|
+
} catch { /* Unavailable evidence cannot prove a seal state. */ }
|
|
51
|
+
source.presentation = { name: name || null, seal };
|
|
52
|
+
}
|
|
53
|
+
if (run.valid && observe) {
|
|
22
54
|
try {
|
|
23
55
|
const state = prepareRunContentState(root, run.content, run.path), decision = transitionDecisionForRunState(state);
|
|
24
56
|
source.observation = { current_gate: decision.current_gate, decision: decision.status, missing: decision.missing_approval,
|
|
25
57
|
next_action: decision.next_allowed_action, presentation_decision: Boolean(decision.presentation_decision?.decided) };
|
|
26
|
-
|
|
58
|
+
if (cockpitAssessment && run.meta?.lifecycle === 'active') {
|
|
59
|
+
let report = null;
|
|
60
|
+
if (registersOnlyControlSources(run.content)) { try { report = evaluateGateCheck(root, { runId: run.run_id, ignoreRunIdEnv: true }); } catch (error) {
|
|
61
|
+
if (READ_BOUNDARY_CODES.includes(error.code)) throw error;
|
|
62
|
+
// Preserve the Run but do not claim a verified assessment.
|
|
63
|
+
} }
|
|
64
|
+
const assessed = report ? projectCockpitAssessment(report, run.meta?.lifecycle) : { state: 'unconfirmed' };
|
|
65
|
+
source.observation.work_situation = projectWorkSituation({ assessment: assessed.state,
|
|
66
|
+
gate: report?.current_gate, blockingReason: report?.blocking_reason, missingApproval: report?.missing_approval,
|
|
67
|
+
persistedGate: report ? state.current_gate : undefined, persistedNext: state.next_allowed_action, nextAllowedAction: report?.next_allowed_action,
|
|
68
|
+
closureOutcome: runClosure(run.content)?.outcome });
|
|
69
|
+
if (report) Object.assign(source.observation, { current_gate: report.current_gate, decision: report.status,
|
|
70
|
+
missing: report.missing_approval, next_action: report.next_allowed_action });
|
|
71
|
+
}
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (cockpitAssessment && READ_BOUNDARY_CODES.includes(error.code)) throw error;
|
|
74
|
+
source.findings = [{ code: 'AGDF_RUN_OBSERVATION_UNAVAILABLE' }];
|
|
75
|
+
}
|
|
27
76
|
}
|
|
28
77
|
return source;
|
|
29
78
|
});
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
// Callers pass validity findings from the full parser; this module never validates receipts.
|
|
4
4
|
import { scalarFields, sectionTableRows, projectRunFacts } from "./run-state-document.js";
|
|
5
5
|
import { RUN_ID_PATTERN } from "./run-identity.js";
|
|
6
|
-
import {
|
|
6
|
+
import { normalizedRunTitle, runIdentity } from "./run-title.js";
|
|
7
|
+
|
|
8
|
+
export { normalizedRunTitle };
|
|
7
9
|
|
|
8
10
|
export const RUN_INVENTORY_SCHEMA_VERSION = "1";
|
|
9
11
|
export const RUN_INVENTORY_LIFECYCLES = Object.freeze(["active", "completed", "superseded", "abandoned"]);
|
|
@@ -42,29 +44,10 @@ const ISO_TIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$/u;
|
|
|
42
44
|
const plain = value => String(value ?? "").replace(/`/gu, "").trim();
|
|
43
45
|
const clip = text => (text.length > TITLE_LIMIT ? `${text.slice(0, TITLE_LIMIT - 1)}…` : text);
|
|
44
46
|
|
|
45
|
-
// The
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
return
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Lines of one level-two section up to the next heading; an empty section stays empty.
|
|
52
|
-
function sectionLines(text, heading) {
|
|
53
|
-
const lines = text.split("\n"), start = lines.findIndex(line => line.trimEnd() === `## ${heading}`);
|
|
54
|
-
if (start < 0) return [];
|
|
55
|
-
const rest = lines.slice(start + 1), end = rest.findIndex(line => /^#{1,2} /u.test(line));
|
|
56
|
-
return end < 0 ? rest : rest.slice(0, end);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function objectiveTitle(text, runId) {
|
|
60
|
-
// The first paragraph, so hard-wrapped objectives stay whole.
|
|
61
|
-
const lines = sectionLines(text, "Objective").map(value => value.trim()), first = lines.findIndex(Boolean);
|
|
62
|
-
const paragraph = first < 0 ? [] : lines.slice(first), end = paragraph.indexOf("");
|
|
63
|
-
const line = (end < 0 ? paragraph : paragraph.slice(0, end)).join(" ");
|
|
64
|
-
const stripped = line.replace(/^(?:[-*>]|#+|\d+\.)\s+/u, "").replace(/\*\*|__|`/gu, "").replace(/\s+/gu, " ").trim();
|
|
65
|
-
return isDecisionContentPlaceholder(stripped)
|
|
66
|
-
? { title: normalizedRunTitle(runId), title_source: "run_id" }
|
|
67
|
-
: { title: clip(stripped), title_source: "objective" };
|
|
47
|
+
// The inventory reads no UR document, so its title source is the Objective or the Run ID.
|
|
48
|
+
function titleFacts(text, runId) {
|
|
49
|
+
const { title, title_source, objective } = runIdentity({ runId, runContent: text });
|
|
50
|
+
return { title: clip(title), title_source, objective: objective === null ? null : clip(objective) };
|
|
68
51
|
}
|
|
69
52
|
|
|
70
53
|
// Base64url receipt cells decoded for display facts only; undecodable cells are skipped.
|
|
@@ -126,17 +109,19 @@ function entryOf(source, language) {
|
|
|
126
109
|
const gateResult = facts?.artefacts.get(gate === 'Quick Task Execution' ? 'CR' : gate)?.status ?? null;
|
|
127
110
|
const presentationDecision = source.observation?.presentation_decision === true;
|
|
128
111
|
const missing = source.observation?.missing === 'none' ? '' : source.observation?.missing ?? '';
|
|
129
|
-
const
|
|
112
|
+
const situation = source.observation?.work_situation;
|
|
113
|
+
const attention = situation?.code ?? runAttention({ lifecycle, valid, decision, gateResult, presentationDecision, missing });
|
|
130
114
|
const revision = /^[1-9]\d*$/u.test(meta.get("revision") ?? "") ? Number(meta.get("revision")) : null;
|
|
131
115
|
const index = languageIndex(language);
|
|
132
116
|
return {
|
|
133
117
|
run_id: runId,
|
|
134
|
-
...(text
|
|
118
|
+
...titleFacts(text, runId),
|
|
119
|
+
...(source.presentation ? { presentation: source.presentation } : {}),
|
|
135
120
|
valid,
|
|
136
121
|
lifecycle: valid ? lifecycle : null,
|
|
137
122
|
current_gate: gate,
|
|
138
123
|
decision,
|
|
139
|
-
attention: { code: attention, label: LABELS[attention][index] },
|
|
124
|
+
attention: { code: attention, label: situation ? (index === 1 ? situation.de : situation.en) : LABELS[attention][index] },
|
|
140
125
|
basis: revision === null ? TEXT.basisUnknown[index]() : TEXT.basis[index](revision),
|
|
141
126
|
last_activity: text ? lastActivity(decoded) : { at: null, source: "none", precision: null },
|
|
142
127
|
revision,
|
|
@@ -15,8 +15,8 @@ import { containedRegularFile, hasSymlinkComponent } from './contained-file.js';
|
|
|
15
15
|
import { readPendingSourceRevisionJournal } from './run-step-transaction.js';
|
|
16
16
|
import { inspectPlannedOperation, inspectPlannedSelection } from './planned-entry.js';
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
import { MATERIAL_LIMITS } from './material-limits.js';
|
|
19
|
+
export { MATERIAL_LIMITS } from './material-limits.js';
|
|
20
20
|
|
|
21
21
|
// A rejected transfer step names its concrete cause; the reason code stays stable for clients.
|
|
22
22
|
const MATERIAL_RECOVERY = Object.freeze({
|
|
@@ -108,23 +108,34 @@ export function createRunMaterialStore({ now = Date.now } = {}) {
|
|
|
108
108
|
const state = current(input), p = input.command.payload;
|
|
109
109
|
expire();
|
|
110
110
|
let row;
|
|
111
|
-
if (p.action === 'begin') {
|
|
111
|
+
if (p.action === 'begin' || p.action === 'put') {
|
|
112
|
+
// The small-text path bundles only private transfer work. Validate the
|
|
113
|
+
// whole set before allocating; canonical recording still uses its owner.
|
|
114
|
+
const files = p.action === 'put' ? p.files.map(({ slot, content }) => {
|
|
115
|
+
const bytes = Buffer.from(content, 'utf8');
|
|
116
|
+
if (bytes.length > MATERIAL_LIMITS.inline || new TextDecoder('utf-8', { fatal: true }).decode(bytes) !== content)
|
|
117
|
+
throw Error('material_text_invalid');
|
|
118
|
+
return { slot, bytes: bytes.length, content, data: bytes };
|
|
119
|
+
}) : p.files;
|
|
112
120
|
const request = digest(canonicalJson(input));
|
|
113
121
|
row = sets.get(input.operation_id);
|
|
114
122
|
if (row) {
|
|
115
123
|
if (row.request !== request || row.binding !== binding(input)) throw Error('operation_payload_conflict');
|
|
116
124
|
} else {
|
|
117
|
-
const size =
|
|
125
|
+
const size = files.reduce((n, f) => n + f.bytes, 0);
|
|
118
126
|
const resolutionBytes = currentInputResolution() ? Buffer.byteLength(canonicalJson(currentInputResolution())) : 0;
|
|
119
|
-
if (!
|
|
127
|
+
if (!files.length || files.length > 4 || files.some(f => !Number.isSafeInteger(f.bytes) || f.bytes < 0 || f.bytes > MATERIAL_LIMITS.file)
|
|
120
128
|
|| size + resolutionBytes > MATERIAL_LIMITS.set || sets.size >= MATERIAL_LIMITS.sets
|
|
121
129
|
|| [...sets.values()].reduce((n, r) => n + r.size + r.resolutionBytes, size + resolutionBytes) > MATERIAL_LIMITS.total) throw Error('material_resource_limit');
|
|
122
130
|
row = { request, binding: binding(input), size, created: now(), touched: now(), resolutions: new Map(), resolutionBytes: 0,
|
|
123
|
-
files:
|
|
131
|
+
files: files.map(f => ({ slot: f.slot, bytes: f.bytes, parts: f.data ? [f.data] : [],
|
|
132
|
+
received: f.data ? f.bytes : 0, material_id: randomUUID(), content: f.content ?? null,
|
|
133
|
+
digest: f.data ? digest(canonicalRunText(f.content)) : null })) };
|
|
124
134
|
sets.set(input.operation_id, row);
|
|
125
135
|
}
|
|
126
136
|
rememberResolution(row, input);
|
|
127
|
-
return envelope('accepted', null, { transfer_id: input.operation_id, files: row.files.map(({ slot, bytes, received }) => ({ slot, bytes, received
|
|
137
|
+
return envelope('accepted', null, { transfer_id: input.operation_id, files: row.files.map(({ slot, bytes, received, content, material_id, digest }) => ({ slot, bytes, received,
|
|
138
|
+
...(content !== null ? { sealed: true, reference: { material_id, digest } } : {}) })), limits: MATERIAL_LIMITS }, state);
|
|
128
139
|
}
|
|
129
140
|
row = rowFor(input, p.transfer_id);
|
|
130
141
|
rememberResolution(row, input);
|
|
@@ -195,6 +206,13 @@ export function createRunMaterialStore({ now = Date.now } = {}) {
|
|
|
195
206
|
// parts in that same set cannot be used for another current write.
|
|
196
207
|
for (const [id, row] of sets) if (row.files.some(file => ids.has(file.material_id))) sets.delete(id);
|
|
197
208
|
},
|
|
209
|
+
// Review facts (companion core SDD-008): the sealed text of one transfer for the runtime's bounded
|
|
210
|
+
// preview, or null when it is unknown or not sealed. It reads only; it is never a material grant.
|
|
211
|
+
sealedFiles(transferId) {
|
|
212
|
+
const row = sets.get(transferId);
|
|
213
|
+
if (closed || !row || row.files.some(file => file.content === null)) return null;
|
|
214
|
+
return row.files.map(({ slot, content, digest: hash }) => Object.freeze({ slot, content, digest: hash }));
|
|
215
|
+
},
|
|
198
216
|
close() { closed = true; sets.clear(); },
|
|
199
217
|
inspectOwnership() { expire(); return { sets: sets.size, bytes: [...sets.values()].reduce((n, r) => n + r.size, 0) }; },
|
|
200
218
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readAcceptanceCriteria } from "../control-evaluation/traceability-readiness.js";
|
|
1
|
+
import { readAcceptanceCriteria, ACCEPTANCE_CRITERIA_FORMAT, TRACEABILITY_CONTRACT } from "../control-evaluation/traceability-readiness.js";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { readFileSync } from "../control-read/fs.js";
|
|
4
4
|
import { basename } from "node:path";
|
|
@@ -43,6 +43,14 @@ export function presentationVersionComparison(root, state, gate, currentDigest)
|
|
|
43
43
|
const MAX_APPROVAL_ARTEFACT_BYTES = 131072;
|
|
44
44
|
const MAX_LOCALIZED_SUMMARY_ITEM_CHARS = 1200;
|
|
45
45
|
const MAX_LOCALIZED_SUMMARY_CHARS = 24000;
|
|
46
|
+
const PRD_LOCALIZED_SUMMARY_FIELDS = Object.freeze([
|
|
47
|
+
{ pattern: /^(?:[-*]\s*)?(?:Nutzerziel|User intent|Ziel|Goal)\s*:/iu,
|
|
48
|
+
de: '- Ziel:', en: '- Goal:', reason: 'approval_summary_user_goal_missing' },
|
|
49
|
+
{ pattern: /^(?:[-*]\s*)?(?:Umfang|Scope|Produktumfang|Product scope)\s*:/iu,
|
|
50
|
+
de: '- Umfang:', en: '- Scope:', reason: 'approval_summary_scope_missing' },
|
|
51
|
+
{ pattern: /^(?:[-*]\s*)?(?:Entscheidungen|Decisions|Geklärte Entscheidungen|Resolved decisions|Offene Entscheidungen|Open decisions)\s*:/iu,
|
|
52
|
+
de: '- Entscheidungen:', en: '- Decisions:', reason: 'approval_summary_decisions_missing', conditional: true },
|
|
53
|
+
]);
|
|
46
54
|
const SUMMARY_SECTIONS = Object.freeze({
|
|
47
55
|
UR: [
|
|
48
56
|
["Problem", /problem|need|anlass/iu], ["Ziel", /goal|objective|ziel/iu],
|
|
@@ -83,8 +91,13 @@ const SUMMARY_LABELS_EN = Object.freeze({
|
|
|
83
91
|
export const hash = (value) => `sha256:${createHash("sha256").update(value).digest("hex")}`;
|
|
84
92
|
|
|
85
93
|
function compactSummaryText(value) {
|
|
86
|
-
|
|
87
|
-
|
|
94
|
+
// Markup outside code spans is dropped. A code span naming syntax such as
|
|
95
|
+
// `node app.js <file>` keeps its backticks: unwrapped, Markdown would treat
|
|
96
|
+
// <file> as an HTML tag and the reader would lose it.
|
|
97
|
+
return value.replace(/\[([^\]]+)\]\([^)]*\)/gu, "$1")
|
|
98
|
+
.split(/(`[^`]+`)/u)
|
|
99
|
+
.map(part => /^`[^`]+`$/u.test(part) ? (part.includes("<") ? part : part.slice(1, -1)) : part.replace(/<[^>]+>/gu, ""))
|
|
100
|
+
.join("").replace(/\s+/gu, " ").trim();
|
|
88
101
|
}
|
|
89
102
|
|
|
90
103
|
function userFacingSummaryText(value) {
|
|
@@ -111,14 +124,14 @@ function substantiveMarkdown(markdown) {
|
|
|
111
124
|
return markdown.replace(/^## AGDF Approval Summary \([^\r\n]*\)\s*\r?\n[\s\S]*?(?=^#{1,2}\s|(?![\s\S]))/gmu, "");
|
|
112
125
|
}
|
|
113
126
|
|
|
114
|
-
function criterionEntries(markdown) {
|
|
115
|
-
const parsed = readAcceptanceCriteria(substantiveMarkdown(markdown));
|
|
127
|
+
function criterionEntries(markdown, source) {
|
|
128
|
+
const parsed = readAcceptanceCriteria(substantiveMarkdown(markdown), { source });
|
|
116
129
|
if (parsed.diagnostics.length) throw Object.assign(new Error("approval_summary_source_criteria_invalid"), { diagnostics: parsed.diagnostics });
|
|
117
130
|
return parsed.entries;
|
|
118
131
|
}
|
|
119
132
|
|
|
120
133
|
function criterionDescription(entry) {
|
|
121
|
-
for (const field of
|
|
134
|
+
for (const field of ACCEPTANCE_CRITERIA_FORMAT.description_fields) {
|
|
122
135
|
const value = String(entry.fields[field] ?? "").trim();
|
|
123
136
|
if (value) return capitalizeSummary(compactSummaryText(value));
|
|
124
137
|
}
|
|
@@ -158,16 +171,35 @@ function validateLocalizedSummaryBlock(gate, block, sourceMarkdown, sourceLangua
|
|
|
158
171
|
if (summaryIds.some((id) => !sourceSet.has(id))) throw new Error("approval_summary_criteria_unknown");
|
|
159
172
|
if (summaryIds.length !== sourceIds.length || sourceIds.some((id) => !summaryIds.includes(id)))
|
|
160
173
|
throw new Error("approval_summary_criteria_incomplete");
|
|
161
|
-
if (!lines.some((line) => /^(?:[-*]\s*)?(?:Nutzerziel|User intent|Ziel|Goal)\s*:/iu.test(line)))
|
|
162
|
-
throw new Error("approval_summary_user_goal_missing");
|
|
163
|
-
if (!lines.some((line) => /^(?:[-*]\s*)?(?:Umfang|Scope|Produktumfang|Product scope)\s*:/iu.test(line)))
|
|
164
|
-
throw new Error("approval_summary_scope_missing");
|
|
165
174
|
const decisions = approvalDecisionEntries(sourceMarkdown);
|
|
166
|
-
|
|
167
|
-
throw new Error(
|
|
175
|
+
for (const field of PRD_LOCALIZED_SUMMARY_FIELDS)
|
|
176
|
+
if ((!field.conditional || decisions.length) && !lines.some(line => field.pattern.test(line))) throw new Error(field.reason);
|
|
168
177
|
}
|
|
169
178
|
}
|
|
170
179
|
|
|
180
|
+
// Syntax guidance comes from the presentation owner, never inferred product
|
|
181
|
+
// content. An incomplete source remains readable through its authoring route.
|
|
182
|
+
export function approvalSummaryAuthoringFormat(gate, markdown, languages) {
|
|
183
|
+
if (!languages.approval_summary_required || !['UR', 'PRD', 'SD', 'TP', 'QA'].includes(gate)) return null;
|
|
184
|
+
const locale = languages.presentation_language.toLowerCase().startsWith('de') ? 'de' : 'en';
|
|
185
|
+
const format = { heading: languages.approval_summary_heading, body_required: true,
|
|
186
|
+
required_fields: localizedDecisionFields(gate, '', { locale, sourceLanguage: languages.artifact_language }).gaps.map(gap => gap.expected),
|
|
187
|
+
instruction: 'Use the exact heading and a nonempty authored summary in the presentation language. Required fields are separate list declarations with concrete content; a heading or generic criteria paragraph does not replace them. This is syntax guidance, never supplied product content, review or approval.' };
|
|
188
|
+
if (gate === 'PRD') {
|
|
189
|
+
const decisions = approvalDecisionEntries(markdown);
|
|
190
|
+
format.required_fields = PRD_LOCALIZED_SUMMARY_FIELDS.filter(field => !field.conditional || decisions.length).map(field => field[locale]);
|
|
191
|
+
format.conditional_fields = [{ field: PRD_LOCALIZED_SUMMARY_FIELDS.find(field => field.conditional)[locale],
|
|
192
|
+
when: 'Required when the source PRD contains Approval Decisions rows.' }];
|
|
193
|
+
try {
|
|
194
|
+
const entries = criterionEntries(markdown);
|
|
195
|
+
format.criterion_fields = entries.map(entry => `- ${entry.id}:`);
|
|
196
|
+
format.criteria_state = entries.length ? 'available' : 'not_declared';
|
|
197
|
+
} catch { format.criterion_fields = []; format.criteria_state = 'source_invalid'; }
|
|
198
|
+
format.criteria_instruction = 'For every exact criterion_id in the authored PRD, write one separate list item beginning with that ID followed by a colon, exactly once. Retain the source IDs; do not combine them in a generic criteria item. If IDs are not yet available, complete the source criteria first.';
|
|
199
|
+
}
|
|
200
|
+
return format;
|
|
201
|
+
}
|
|
202
|
+
|
|
171
203
|
function requiredLocalizedSummary(gate, markdown, languages, { path } = {}) {
|
|
172
204
|
if (!languages.approval_summary_required) return null;
|
|
173
205
|
const blocks = localizedSummaryBlocks(markdown).filter(block => block.locale === languages.presentation_language);
|
|
@@ -186,6 +218,11 @@ function requiredLocalizedSummary(gate, markdown, languages, { path } = {}) {
|
|
|
186
218
|
export function evaluateApprovalSummaryReadiness(gate, markdown, languages, { path } = {}) {
|
|
187
219
|
try {
|
|
188
220
|
requiredLocalizedSummary(gate, markdown, languages, { path });
|
|
221
|
+
if (gate === "PRD" && markdown.includes(TRACEABILITY_CONTRACT)
|
|
222
|
+
&& languages.artifact_language === languages.presentation_language.split("-")[0]) {
|
|
223
|
+
artifactSummary(gate, markdown, { language: languages.presentation_language,
|
|
224
|
+
sourceLanguage: languages.artifact_language, artefactPath: path });
|
|
225
|
+
}
|
|
189
226
|
return Object.freeze({ ready: true, required_heading: languages.approval_summary_heading, reason: null });
|
|
190
227
|
} catch (error) {
|
|
191
228
|
if (!String(error.message).startsWith("approval_summary_")) throw error;
|
|
@@ -197,12 +234,25 @@ export function evaluateApprovalSummaryReadiness(gate, markdown, languages, { pa
|
|
|
197
234
|
export function renderApprovalSummaryIssue(summary, { path, presentationLanguage }) {
|
|
198
235
|
const locale = resolvePresentationLocale(interactionLocales, presentationLanguage);
|
|
199
236
|
const pack = localePack(interactionLocales, locale), german = locale.split("-")[0] === "de";
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
237
|
+
if (summary.reason === "approval_summary_criterion_content_missing") {
|
|
238
|
+
const fields = ACCEPTANCE_CRITERIA_FORMAT.description_fields.map(field => `\`${field}\``).join(" / ");
|
|
239
|
+
const locations = (summary.diagnostics ?? []).map(row =>
|
|
240
|
+
`- ${row.criterion_id}${row.line ? ` (${german ? 'Zeile' : 'line'} ${row.line})` : ''}`).join("\n");
|
|
241
|
+
return [
|
|
242
|
+
`${german ? 'PRD-Quellkriterien korrigieren' : 'Correct PRD source criteria'}: \`${path}\``,
|
|
243
|
+
`${pack.statusCard.summaryReason}: \`${summary.reason}\``,
|
|
244
|
+
locations,
|
|
245
|
+
german
|
|
246
|
+
? `Je betroffenem Kriterium mindestens eines dieser Felder einzeln und mit Inhalt angeben: ${fields}. Zusammengesetzte Feldnamen werden nicht aufgeteilt.`
|
|
247
|
+
: `For each affected criterion, provide at least one separate nonempty field: ${fields}. Combined field names are not split.`,
|
|
248
|
+
german
|
|
249
|
+
? 'Eine zusätzliche AGDF Approval Summary ersetzt diese Quellfelder nicht. Die Kriterien-IDs und den fachlichen Inhalt erhalten; über den bestehenden Autorpfad korrigieren und erneut prüfen.'
|
|
250
|
+
: 'An additional AGDF Approval Summary does not replace these source fields. Preserve criterion IDs and product intent; correct through the existing authoring route and recheck.',
|
|
251
|
+
].filter(Boolean).join("\n");
|
|
252
|
+
}
|
|
253
|
+
const expected = PRD_LOCALIZED_SUMMARY_FIELDS.find(field => field.reason === summary.reason)?.[german ? 'de' : 'en']
|
|
254
|
+
?? (summary.reason === 'approval_summary_field_unreadable' ? summary.diagnostics?.map(row => row.expected).join("` · `") || undefined : undefined)
|
|
255
|
+
?? summary.required_heading;
|
|
206
256
|
return [
|
|
207
257
|
`${pack.statusCard.summaryRecovery}: \`${path}\``,
|
|
208
258
|
`${pack.statusCard.summaryReason}: \`${summary.reason}\``,
|
|
@@ -210,7 +260,8 @@ export function renderApprovalSummaryIssue(summary, { path, presentationLanguage
|
|
|
210
260
|
].join("\n");
|
|
211
261
|
}
|
|
212
262
|
|
|
213
|
-
|
|
263
|
+
// Pure summary extraction; exported so its text rules are tested directly.
|
|
264
|
+
export function sectionBody(markdown, pattern, contentPattern = null, maxItems = 3) {
|
|
214
265
|
const lines = markdown.replace(/\r\n?/gu, "\n").split("\n");
|
|
215
266
|
for (let index = 0; index < lines.length; index += 1) {
|
|
216
267
|
const heading = lines[index].match(/^(#{2,6})\s+(?:\d+\.\s*)?(.+?)\s*#*\s*$/u);
|
|
@@ -233,6 +284,9 @@ function sectionBody(markdown, pattern, contentPattern = null, maxItems = 3) {
|
|
|
233
284
|
}
|
|
234
285
|
if (contentPattern && !contentPattern.test(line)) continue;
|
|
235
286
|
const cleaned = userFacingSummaryText(line);
|
|
287
|
+
// A lead-in such as "covers exactly these points:" says nothing on its own;
|
|
288
|
+
// the items that follow it carry the content.
|
|
289
|
+
if (/:$/u.test(cleaned)) continue;
|
|
236
290
|
if (!cleaned || /^(?:what|which|how|who|every field|specify|decision:|status:|gate:|date:|owner:)/iu.test(cleaned)
|
|
237
291
|
|| /^(?:ui_ux_impact|ux_intent_definition|primary_user_intent|success_signal|primary_decision_or_action):/iu.test(cleaned)) continue;
|
|
238
292
|
body.push(cleaned);
|
|
@@ -275,14 +329,15 @@ function artifactSummary(gate, markdown, { runId, revisionId, language, sourceLa
|
|
|
275
329
|
if (decision) items.unshift(`- ${german ? 'Entscheidung' : 'Decision'}: ${decision}`);
|
|
276
330
|
}
|
|
277
331
|
if (gate === "PRD") {
|
|
278
|
-
const criteria = criterionEntries(source);
|
|
332
|
+
const criteria = criterionEntries(source, artefactPath);
|
|
279
333
|
if (!criteria.length) throw new Error("approval_summary_criteria_missing");
|
|
280
334
|
if (new Set(criteria.map((entry) => entry.id)).size !== criteria.length) throw new Error("approval_summary_source_criteria_duplicate");
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
335
|
+
const missing = criteria.filter(entry => !criterionDescription(entry));
|
|
336
|
+
if (missing.length) throw Object.assign(new Error("approval_summary_criterion_content_missing"), {
|
|
337
|
+
diagnostics: missing.map(entry => ({ code: 'criterion_description_missing', source: entry.source,
|
|
338
|
+
line: entry.line, criterion_id: entry.id, expected: ACCEPTANCE_CRITERIA_FORMAT.description_fields })),
|
|
285
339
|
});
|
|
340
|
+
const criterionRows = criteria.map(entry => ` - ${entry.id}: ${criterionDescription(entry)}`);
|
|
286
341
|
items.push(`- ${german ? "Abnahmekriterien" : "Acceptance criteria"}:\n${criterionRows.join("\n")}`);
|
|
287
342
|
const decisions = approvalDecisionEntries(source);
|
|
288
343
|
if (decisions.length) {
|
|
@@ -300,6 +355,35 @@ function artifactSummary(gate, markdown, { runId, revisionId, language, sourceLa
|
|
|
300
355
|
return { markdown: summary, digest: hash(summary) };
|
|
301
356
|
}
|
|
302
357
|
|
|
358
|
+
// Cockpit presentation reuses the same language and summary owner as authoring checks.
|
|
359
|
+
// The structured rows are derived from that summary; no second content authority is created.
|
|
360
|
+
export function projectCockpitSummary(gate, markdown, languages, context = {}) {
|
|
361
|
+
if (!['UR', 'PRD', 'SD', 'TP'].includes(gate)) return null;
|
|
362
|
+
try {
|
|
363
|
+
const readiness = evaluateApprovalSummaryReadiness(gate, markdown, languages, { path: context.artefactPath });
|
|
364
|
+
if (!readiness.ready) return null;
|
|
365
|
+
const summary = artifactSummary(gate, markdown, { ...context, language: languages.presentation_language, sourceLanguage: languages.artifact_language });
|
|
366
|
+
const priorities = {
|
|
367
|
+
UR: [/^(?:Ziel|Goal)$/iu, /^(?:Umfang|Scope)$/iu, /^(?:Abnahme|Abnahmesignal|Acceptance)$/iu],
|
|
368
|
+
PRD: [/^(?:Ziel|Nutzerziel|Goal|User intent)$/iu, /^(?:Umfang|Produktumfang|Scope|Product scope)$/iu, /^(?:AC-[A-Z0-9-]+)$/iu],
|
|
369
|
+
SD: [/^(?:Lösung|Solution)$/iu, /^(?:Verantwortung|Ownership)$/iu, /^(?:Entscheidungen|Design decisions)$/iu],
|
|
370
|
+
TP: [/^(?:Aufgaben|Tasks)$/iu, /^(?:Tests)$/iu, /^(?:Risiken|Risks)$/iu],
|
|
371
|
+
};
|
|
372
|
+
const rows = summary.markdown.split(/\r?\n/u).flatMap(line => {
|
|
373
|
+
const match = line.match(/^[-*]\s+([^:\n]{1,80}):\s*(\S.*)$/u);
|
|
374
|
+
return match && match[2].length <= 1200 ? [{ label: match[1].trim(), text: match[2].trim() }] : [];
|
|
375
|
+
});
|
|
376
|
+
const items = priorities[gate].flatMap(pattern => {
|
|
377
|
+
const matches = rows.filter(row => pattern.test(row.label));
|
|
378
|
+
return matches.length === 1 ? matches : [];
|
|
379
|
+
});
|
|
380
|
+
return { state: 'available', gate, items, markdown: summary.markdown, authorizes: false };
|
|
381
|
+
} catch (error) {
|
|
382
|
+
if (String(error.message).startsWith('approval_summary_')) return null;
|
|
383
|
+
throw error;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
303
387
|
// A compact decision brief is a projection of the already validated, source-
|
|
304
388
|
// authored summary. Missing authored fields stay absent; no agent/UI paraphrase.
|
|
305
389
|
export function decisionBriefFromSummary(summary, language) {
|
|
@@ -388,16 +472,17 @@ export function renderReviewableApproval(root, report, { runId, gate, revisionId
|
|
|
388
472
|
const languageName = pack.statusCard[locale.split("-")[0] === "de" ? "languageGerman" : "languageEnglish"];
|
|
389
473
|
const artifactLabel = german ? "Artefakt" : "Artefact";
|
|
390
474
|
const requiredHeading = languages.approval_summary_heading ?? `AGDF Approval Summary (${locale}; source=${sourceLanguage})`;
|
|
475
|
+
const sourceIssue = error.message === 'approval_summary_criterion_content_missing';
|
|
391
476
|
error.recovery = [
|
|
392
|
-
`## ${pack.statusCard.summaryRecovery}`,
|
|
477
|
+
`## ${sourceIssue ? (german ? 'PRD-Quellkriterien korrigieren' : 'Correct PRD source criteria') : pack.statusCard.summaryRecovery}`,
|
|
393
478
|
`Run: \`${runId}\` · Gate: \`${gate}\` · Revision: \`${revisionId}\``,
|
|
394
479
|
renderApprovalSummaryIssue({ reason: error.message, required_heading: requiredHeading, diagnostics: error.diagnostics }, {
|
|
395
480
|
path, presentationLanguage: p.presentation_language,
|
|
396
481
|
}),
|
|
397
|
-
pack.operationalValues.approvalSummaryRecovery.replace("{language}", languageName),
|
|
398
|
-
|
|
482
|
+
...(!sourceIssue ? [pack.operationalValues.approvalSummaryRecovery.replace("{language}", languageName),
|
|
483
|
+
`${german ? "Erforderlicher Abschnitt" : "Required section"}: \`${requiredHeading}\``] : []),
|
|
399
484
|
`${artifactLabel}: [${basename(path)}](<${path}>)`,
|
|
400
|
-
pack.operationalValues.completeMissingApprovalSummary,
|
|
485
|
+
...(!sourceIssue ? [pack.operationalValues.completeMissingApprovalSummary] : []),
|
|
401
486
|
].join("\n\n");
|
|
402
487
|
}
|
|
403
488
|
throw error;
|
|
@@ -22,7 +22,7 @@ import { join } from "node:path";
|
|
|
22
22
|
import { runPath } from "./run-state-reader.js";
|
|
23
23
|
import { readArtefactBindings } from "./artefact-bindings.js";
|
|
24
24
|
import { exactApprovedArtefacts, readContainedJson, validateBindingProof } from "./artefact-binding-proof.js";
|
|
25
|
-
import { SOURCE_GATES, appendSourceRevision, readSourceRevisions, revisionHistoryPrefix, sourceRevisionImpact, sourceRevisionConfirmation,
|
|
25
|
+
import { SOURCE_GATES, appendSourceRevision, readSourceRevisions, revisionHistoryPrefix, sourceRevisionImpact, sourceRevisionConfirmation, revisionProofProblems } from "./run-source-revisions.js";
|
|
26
26
|
import { collectRevisionHistory, byteDigest, inspectRevisionHistory, readHistoryBytes } from "./run-revision-history.js";
|
|
27
27
|
import { commitRunStepLocked, recoverPendingRunStepLocked, pendingRunStepConflictIds, readPendingRunStepJournal, readPendingSourceRevisionJournal } from "./run-step-transaction.js";
|
|
28
28
|
import { pendingRunStepPath } from "./run-step-pending.js";
|
|
@@ -139,27 +139,45 @@ function prepareSourceRevision(root, input) {
|
|
|
139
139
|
|| boundary.approved.includes(row.type) && state.approvals.get(row.type)?.status !== "approved")) throw revisionError("approved_source_invalid");
|
|
140
140
|
if (input.commandContext && input.proposalBinding?.path !== evidence) throw revisionError('revision_source_binding_invalid');
|
|
141
141
|
const boundProposal = input.proposalMaterial ? { validate: () => {} } : input.proposalBinding ? readOperationSource(root, runId, input.proposalBinding) : null;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
// Name each violated field with its expected binding: these are facts the caller
|
|
143
|
+
// may read anyway, and the proposal can only be corrected when they are known.
|
|
144
|
+
const expected = { target_id: resolveControlCommandTarget(root).target_id, run_id: runId, expected_revision_id: revisionId,
|
|
145
|
+
operation_id: operationId, source_gate: sourceGate, sources };
|
|
146
|
+
const problems = [
|
|
147
|
+
...(exactObject(proposal, REVISION_PROPOSAL_FIELDS) ? [] : [`fields must be exactly ${REVISION_PROPOSAL_FIELDS.join(", ")}`]),
|
|
148
|
+
...Object.entries(expected).filter(([key, value]) => canonicalJson(proposal[key] ?? null) !== canonicalJson(value))
|
|
149
|
+
.map(([key, value]) => `${key} must be ${canonicalJson(value)}`),
|
|
150
|
+
...["reason", "intended_change"].filter(key => !nonempty(proposal[key])).map(key => `${key} must be nonempty text`),
|
|
151
|
+
];
|
|
152
|
+
if (problems.length) throw revisionError("revision_proposal_invalid",
|
|
153
|
+
`Correct the staged proposal and stage it again; operation_id is the UUID of this source_revision command. ${problems.join("; ")}.`);
|
|
147
154
|
const assessment = proposal.impact_assessment, index = SOURCE_GATES.indexOf(sourceGate);
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
155
|
+
// Like the binding check above, each rejection names the expected entries.
|
|
156
|
+
const identity = row => canonicalJson({ type: row?.type, path: row?.path, digest: row?.digest });
|
|
157
|
+
const upstream = sources.slice(0, index);
|
|
158
|
+
const impactProblems = [
|
|
159
|
+
...(exactObject(assessment, REVISION_IMPACT_FIELDS) ? [] : [`impact_assessment fields must be exactly ${REVISION_IMPACT_FIELDS.join(", ")}`]),
|
|
160
|
+
...(nonempty(assessment?.reviewer) ? [] : ["impact_assessment.reviewer must be nonempty text"]),
|
|
161
|
+
...(assessment?.earliest_source === sourceGate ? [] : [`impact_assessment.earliest_source must be "${sourceGate}"`]),
|
|
162
|
+
...(nonempty(assessment?.implementation_evidence) ? [] : ["impact_assessment.implementation_evidence must be nonempty text"]),
|
|
163
|
+
...(Array.isArray(assessment?.unresolved) && !assessment.unresolved.length ? [] : ["impact_assessment.unresolved must be []"]),
|
|
164
|
+
...(Array.isArray(assessment?.upstream) && assessment.upstream.length === upstream.length
|
|
165
|
+
&& assessment.upstream.every((row, i) => exactObject(row, REVISION_UPSTREAM_FIELDS) && nonempty(row.rationale) && identity(row) === identity(upstream[i]))
|
|
166
|
+
? [] : [`impact_assessment.upstream must list exactly ${canonicalJson(upstream)} in order, each with a nonempty rationale`]),
|
|
167
|
+
];
|
|
168
|
+
if (impactProblems.length) throw revisionError("source_impact_unresolved",
|
|
169
|
+
`Resolve the earliest changed source and unchanged upstream rationale with its owner; then regenerate the proposal. ${impactProblems.join("; ")}.`);
|
|
170
|
+
const analyses = ["Brownfield Review", "UX Intent Definition"].filter(type => state.artefacts.get(type)?.path)
|
|
171
|
+
.map(type => ({ type, path: state.artefacts.get(type).path, digest: artefactFileDigest(root, state.artefacts.get(type).path) }));
|
|
172
|
+
const dispositions = sourceGate === "UR" ? ["reassess"] : ["retain", "reassess"];
|
|
173
|
+
if (!Array.isArray(assessment.analyses) || assessment.analyses.length !== analyses.length
|
|
174
|
+
|| !assessment.analyses.every((row, i) => exactObject(row, REVISION_ANALYSIS_FIELDS) && identity(row) === identity(analyses[i])
|
|
175
|
+
&& nonempty(row.reason) && dispositions.includes(row.disposition)))
|
|
176
|
+
throw revisionError("analysis_applicability_unresolved", `Set impact_assessment.analyses to exactly the registered analyses ${canonicalJson(analyses)} in order, each with a nonempty reason and disposition ${dispositions.join(" or ")}; unregistered analyses are not listed.`);
|
|
160
177
|
const readArtefact = path => { try { return readHistoryBytes(root, path).toString('utf8'); } catch { return undefined; } };
|
|
161
|
-
|
|
162
|
-
|
|
178
|
+
const proofProblems = revisionProofProblems(proposal, state, readArtefact, boundary.initiating_phase);
|
|
179
|
+
if (proofProblems.length) throw revisionError('revision_impact_proof_invalid',
|
|
180
|
+
`Bind concrete changed statements, earliest source, actual phase and every exact quality record; unknown or affected associations require reassessment. ${proofProblems.slice(0, 5).join('; ')}.`);
|
|
163
181
|
const affected = SOURCE_GATES.slice(index);
|
|
164
182
|
const qualityPaths = proposal.quality_assessment.map(row => row.record.path).filter(Boolean);
|
|
165
183
|
const history = collectRunRevisionClosure(root, run, state, operationId, boundary.approved, [evidence, ...qualityPaths], { proposalMaterial: input.proposalMaterial });
|