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
|
@@ -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 });
|
|
@@ -50,7 +50,12 @@ export function sourceRevisionQualityFacts(state, readArtefact) {
|
|
|
50
50
|
return facts;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
export
|
|
53
|
+
export const validExpandedRevisionProof = (...args) => revisionProofProblems(...args).length === 0;
|
|
54
|
+
|
|
55
|
+
// The same rules as a list of named violations, so a rejected proposal can be
|
|
56
|
+
// corrected deliberately instead of by trial. Later checks rely on the structure
|
|
57
|
+
// confirmed by earlier ones, so each block stops at its own violations.
|
|
58
|
+
export function revisionProofProblems(proposal, state, readArtefact, phase) {
|
|
54
59
|
const changed = proposal.changed_statements, affected = SOURCE_GATES.slice(SOURCE_GATES.indexOf(proposal.source_gate));
|
|
55
60
|
const nonempty = value => typeof value === 'string' && value.trim() && value.length <= 4096;
|
|
56
61
|
const assessmentProof = proposal.impact_assessment, index = SOURCE_GATES.indexOf(proposal.source_gate);
|
|
@@ -64,25 +69,40 @@ export function validExpandedRevisionProof(proposal, state, readArtefact, phase)
|
|
|
64
69
|
|| !Array.isArray(assessmentProof.analyses) || assessmentProof.analyses.length !== analyticalTypes.length
|
|
65
70
|
|| !assessmentProof.analyses.every((row, i) => exactObject(row, REVISION_ANALYSIS_FIELDS) && row.type === analyticalTypes[i]
|
|
66
71
|
&& row.path === state.artefacts.get(row.type).path && hashes(row.digest) && nonempty(row.reason)
|
|
67
|
-
&& ['retain', 'reassess'].includes(row.disposition) && (proposal.source_gate !== 'UR' || row.disposition === 'reassess')))
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
&& ['retain', 'reassess'].includes(row.disposition) && (proposal.source_gate !== 'UR' || row.disposition === 'reassess')))
|
|
73
|
+
return ['impact_assessment is invalid'];
|
|
74
|
+
const statementProblem = (row, i) => {
|
|
75
|
+
if (!exactObject(row, REVISION_STATEMENT_FIELDS)) return `changed_statements[${i}] fields must be exactly ${REVISION_STATEMENT_FIELDS.join(', ')}`;
|
|
76
|
+
if (!affected.includes(row.type)) return `changed_statements[${i}].type must be one of ${affected.join(', ')}`;
|
|
77
|
+
if (!proposal.sources.some(source => source.type === row.type && source.path === row.path && source.digest === row.digest))
|
|
78
|
+
return `changed_statements[${i}] path and digest must equal its entry in sources`;
|
|
79
|
+
if (![row.statement, row.intended_change, row.reason].every(nonempty)) return `changed_statements[${i}] statement, intended_change and reason must be nonempty text`;
|
|
80
|
+
if (!String(readArtefact(row.path)).replace(/\r\n?/gu, '\n').includes(row.statement))
|
|
81
|
+
return `changed_statements[${i}].statement must be an exact excerpt of ${row.path}`;
|
|
82
|
+
return null;
|
|
83
|
+
};
|
|
84
|
+
const changeProblems = [
|
|
85
|
+
...(proposal.policy_version === 2 ? [] : ['policy_version must be 2']),
|
|
86
|
+
...(proposal.initiating_phase === phase ? [] : [`initiating_phase must be "${phase}"`]),
|
|
87
|
+
...(Array.isArray(changed) && changed.length ? changed.map(statementProblem).filter(Boolean) : ['changed_statements must be a nonempty list']),
|
|
88
|
+
...(Array.isArray(changed) && changed.some(row => row?.type === proposal.source_gate) ? [] : [`changed_statements must include a ${proposal.source_gate} statement`]),
|
|
89
|
+
];
|
|
90
|
+
if (changeProblems.length) return changeProblems;
|
|
74
91
|
const facts = sourceRevisionQualityFacts(state, readArtefact), assessment = proposal.quality_assessment;
|
|
75
|
-
if (!Array.isArray(assessment) || !assessment.length || assessment.length !== facts.length)
|
|
76
|
-
|
|
77
|
-
|
|
92
|
+
if (!Array.isArray(assessment) || !assessment.length || assessment.length !== facts.length)
|
|
93
|
+
return [`quality_assessment must contain exactly ${facts.length} rows, one per quality record in order`];
|
|
94
|
+
return assessment.map((row, i) => {
|
|
95
|
+
if (!exactObject(row, REVISION_QUALITY_FIELDS) || !['retain', 'reassess'].includes(row.disposition) || !nonempty(row.reason))
|
|
96
|
+
return `quality_assessment[${i}] needs exactly ${REVISION_QUALITY_FIELDS.join(', ')} with disposition retain or reassess and a nonempty reason`;
|
|
78
97
|
const { disposition, reason, ...proof } = row;
|
|
79
|
-
if (canonicalJson(proof) !== canonicalJson(facts[i])) return
|
|
98
|
+
if (canonicalJson(proof) !== canonicalJson(facts[i])) return `quality_assessment[${i}] must copy quality record ${canonicalJson(facts[i])} unchanged`;
|
|
80
99
|
const analysis = proposal.impact_assessment.analyses.find(item => item.type === row.record.type);
|
|
81
|
-
if (analysis && (analysis.disposition !== disposition || analysis.path !== row.record.path || analysis.digest !== row.record.digest))
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
&& !(proposal.source_gate === 'UR' && analysis)
|
|
85
|
-
|
|
100
|
+
if (analysis && (analysis.disposition !== disposition || analysis.path !== row.record.path || analysis.digest !== row.record.digest))
|
|
101
|
+
return `quality_assessment[${i}].disposition must equal the ${row.record.type} analysis disposition`;
|
|
102
|
+
if (disposition === 'retain' && !(row.association === 'current' && !row.sources.some(source => affected.includes(source.type))
|
|
103
|
+
&& !(proposal.source_gate === 'UR' && analysis))) return `quality_assessment[${i}] must be reassess: its record is not current or depends on a changed source`;
|
|
104
|
+
return null;
|
|
105
|
+
}).filter(Boolean);
|
|
86
106
|
}
|
|
87
107
|
|
|
88
108
|
export function sourceRevisionImpact(proposal, activeBindings) {
|
|
@@ -41,6 +41,15 @@ export function readSelectedRun(root, id) {
|
|
|
41
41
|
last_updated_at: parsed.meta.updated_at || stateStats.mtime.toISOString() };
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
// The entry names discovery treats as runs: every non-dot entry of the runs folder, sorted. Empty when the
|
|
45
|
+
// folder is missing or no directory. It reads no layout, so the companion run view also counts the run
|
|
46
|
+
// folders of a store whose layout is not supported (PRD AC-002, TP T-004).
|
|
47
|
+
export function runFolderEntries(root) {
|
|
48
|
+
const dir = join(root, ".agdf", "control", "runs");
|
|
49
|
+
if (!existsSync(dir) || lstatKindSync(dir) !== 'directory') return [];
|
|
50
|
+
return readdirSync(dir).filter((entry) => !entry.startsWith(".")).sort();
|
|
51
|
+
}
|
|
52
|
+
|
|
44
53
|
function discoverCapturedRuns(root) {
|
|
45
54
|
const dir = join(root, ".agdf", "control", "runs");
|
|
46
55
|
if (!existsSync(dir)) return [];
|
|
@@ -48,9 +57,7 @@ function discoverCapturedRuns(root) {
|
|
|
48
57
|
if (lstatKindSync(dir) !== 'directory') {
|
|
49
58
|
return [invalidRun("<repository>", dir)];
|
|
50
59
|
}
|
|
51
|
-
return
|
|
52
|
-
.filter((entry) => !entry.startsWith("."))
|
|
53
|
-
.sort()
|
|
60
|
+
return runFolderEntries(root)
|
|
54
61
|
.map((id) => {
|
|
55
62
|
const directory = join(dir, id);
|
|
56
63
|
const path = join(directory, "RUN_STATE.md");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { extractField } from '../control-evaluation/verified-change.js';
|
|
2
2
|
import { transitionDecisionForRunState } from '../control-evaluation/gate-policy.js';
|
|
3
|
-
import { runDocumentPath, runEvidencePath, isRunDataPath } from './run-identity.js';
|
|
3
|
+
import { runDocumentPath, runEvidencePath, isRunDataPath, RUN_STEP_SLOTS } from './run-identity.js';
|
|
4
4
|
import { resolutionRecordVersion } from './input-resolution.js';
|
|
5
5
|
import { resolveControlCommandTarget } from './approval-command-contract.js';
|
|
6
6
|
|
|
@@ -48,7 +48,7 @@ import { withRunMutationLock, writeRunMutationLocked } from './run-mutation.js';
|
|
|
48
48
|
import { APPROVAL_GATES as DECISION_GATES, REVISION_ID_PATTERN } from './run-identity.js';
|
|
49
49
|
import { runSealState, artefactFileDigest } from './run-seal.js';
|
|
50
50
|
import { inspectUxIntentDecision } from '../control-evaluation/definition-sources.js';
|
|
51
|
-
import { readReportDecision } from '../control-evaluation/report-decision.js';
|
|
51
|
+
import { readReportDecision, REPORT_DECISION_FORMAT } from '../control-evaluation/report-decision.js';
|
|
52
52
|
import { prepareVerifiedChangeRecording } from './run-verified-change.js';
|
|
53
53
|
|
|
54
54
|
// Record one typed transition and its owned files in a single sealed revision.
|
|
@@ -77,6 +77,8 @@ function readRunArtefact(root, runId, rawPath, limit = 131072) {
|
|
|
77
77
|
// Review reports are read within the bound of the closeout quality inspection (inspectQaReports).
|
|
78
78
|
const REVIEW_REPORT_LIMIT = 262144;
|
|
79
79
|
// Every recording of a review or QA report applies the closeout quality rules; at most 64 diagnostics are returned.
|
|
80
|
+
// The staged report must state the result where the parser reads it.
|
|
81
|
+
const unconfirmedDecision = runId => rejected(runId, 'internal_result_unconfirmed', { recovery: REPORT_DECISION_FORMAT.instruction });
|
|
80
82
|
const findingsRefusal = (runId, diagnostics) => rejected(runId, 'review_findings_invalid',
|
|
81
83
|
{ diagnostics: diagnostics.slice(0, 64), ...(diagnostics.length > 64 ? { diagnostics_truncated: true } : {}) });
|
|
82
84
|
function qaReportDiagnostics(root, runId, qa, control, proposedContent) {
|
|
@@ -132,7 +134,7 @@ function recordRunStepLocked(root, input, { policy, date, afterWrite, operationC
|
|
|
132
134
|
stagedSource = resolveMaterial?.(input.sourceBinding);
|
|
133
135
|
const slot = input.step === 'internal' ? input.internalStep : input.step === 'verified_change' ? 'Verified Change'
|
|
134
136
|
: input.step === 'closeout' && stagedSource?.slot === 'Verified Change' ? 'Verified Change'
|
|
135
|
-
:
|
|
137
|
+
: RUN_STEP_SLOTS[input.step];
|
|
136
138
|
if (!stagedSource || stagedSource.slot !== slot) return rejected(runId, 'material_slot_mismatch');
|
|
137
139
|
const file = slot === 'EVIDENCE' ? `EVIDENCE-${stagedSource.digest.slice(7)}.md`
|
|
138
140
|
: ({ UR: 'UR.md', OR: 'OR.md', 'Verified Change': 'VERIFIED_CHANGE.md', ...INTERNAL_STEP_FILES })[slot];
|
|
@@ -178,7 +180,7 @@ function recordRunStepLocked(root, input, { policy, date, afterWrite, operationC
|
|
|
178
180
|
if (step === "review") {
|
|
179
181
|
if (!['CR', 'Quick Task Execution'].includes(before.current_gate)
|
|
180
182
|
|| !['pass', 'revise', 'block'].includes(input.decision)) return rejected(runId, "review_step_not_ready");
|
|
181
|
-
if (readReportDecision(operationSource.content) !== input.decision) return
|
|
183
|
+
if (readReportDecision(operationSource.content) !== input.decision) return unconfirmedDecision(runId);
|
|
182
184
|
const diagnostics = reviewFindingDiagnostics('CR', operationSource.content, { decision: input.decision });
|
|
183
185
|
if (diagnostics.length) return findingsRefusal(runId, diagnostics);
|
|
184
186
|
}
|
|
@@ -218,7 +220,7 @@ function recordRunStepLocked(root, input, { policy, date, afterWrite, operationC
|
|
|
218
220
|
if (!checked.well_formed || !checked.supported || checked.decision !== input.decision
|
|
219
221
|
|| input.decision === 'not_applicable' && (control.source_revision_ux_required || before.next_operation?.analysis === input.internalStep)) return rejected(runId, 'internal_result_unconfirmed');
|
|
220
222
|
} else {
|
|
221
|
-
if (readReportDecision(operationSource.content, { allowNotApplicable: true }) !== input.decision) return
|
|
223
|
+
if (readReportDecision(operationSource.content, { allowNotApplicable: true }) !== input.decision) return unconfirmedDecision(runId);
|
|
222
224
|
}
|
|
223
225
|
if (CORRECTABLE_REVIEWS.includes(input.internalStep)) {
|
|
224
226
|
const diagnostics = reviewFindingDiagnostics(input.internalStep, operationSource.content, { decision: input.decision });
|
|
@@ -306,6 +308,7 @@ function recordRunStepLocked(root, input, { policy, date, afterWrite, operationC
|
|
|
306
308
|
// The quality obligation still names the decisive finding and, where available, its correction path.
|
|
307
309
|
const qa = readiness.findings.includes('closeout_quality_unconfirmed') ? inspectQaReports(root, control, runId, 'pass', 64, true) : null;
|
|
308
310
|
return rejected(runId, 'closeout_obligations_unfulfilled', { findings: readiness.findings,
|
|
311
|
+
...(readiness.expected ? { expected: readiness.expected } : {}),
|
|
309
312
|
...(qa?.reason ? { reason_detail: closeoutQualityDetail(qa, control) } : {}) });
|
|
310
313
|
}
|
|
311
314
|
if (!exactApprovedArtefacts(root, control)) return rejected(runId, 'approved_source_proof_invalid');
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// One owner for a Run's human title and orienting Objective. Pure: no `node:` import, so the run
|
|
2
|
+
// inventory, the cockpit, the companion run view and the status card share exactly this rule.
|
|
3
|
+
// Precedence: registered UR heading, then the authored Objective, then the normalized Run ID.
|
|
4
|
+
import { isDecisionContentPlaceholder } from "../control-evaluation/decision-content-placeholder.js";
|
|
5
|
+
|
|
6
|
+
// The run-ID title every reader shows when no authored title exists.
|
|
7
|
+
export function normalizedRunTitle(runId) {
|
|
8
|
+
const words = String(runId ?? "").replace(/[._-]+/g, " ").replace(/\s+/g, " ").trim();
|
|
9
|
+
return words ? words.replace(/\b\p{L}/gu, (letter) => letter.toUpperCase()) : "AGDF run";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// A heading as display text: no leading hashes and no inline Markdown marks.
|
|
13
|
+
export function plainHeading(value) {
|
|
14
|
+
return String(value ?? "").replace(/^#+\s*/u, "").replace(/[`*_]/gu, "").replace(/\s+/gu, " ").trim();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Lines of one level-two section up to the next heading; an empty section stays empty.
|
|
18
|
+
function sectionLines(text, heading) {
|
|
19
|
+
const lines = text.split("\n"), start = lines.findIndex(line => line.trimEnd() === `## ${heading}`);
|
|
20
|
+
if (start < 0) return [];
|
|
21
|
+
const rest = lines.slice(start + 1), end = rest.findIndex(line => /^#{1,2} /u.test(line));
|
|
22
|
+
return end < 0 ? rest : rest.slice(0, end);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// The first paragraph of the Objective, so hard-wrapped objectives stay whole. A template prompt,
|
|
26
|
+
// a status word or a bare generated Run ID is no orientation and yields null.
|
|
27
|
+
export function authoredObjective(runContent) {
|
|
28
|
+
const text = String(runContent ?? "").replace(/^/u, "").replace(/\r\n?/gu, "\n");
|
|
29
|
+
const lines = sectionLines(text, "Objective").map(value => value.trim()), first = lines.findIndex(Boolean);
|
|
30
|
+
if (first < 0) return null;
|
|
31
|
+
const paragraph = lines.slice(first), end = paragraph.indexOf("");
|
|
32
|
+
const value = (end < 0 ? paragraph : paragraph.slice(0, end)).join(" ")
|
|
33
|
+
.replace(/^(?:[-*>]|#+|\d+\.)\s+/u, "").replace(/\*\*|__|`/gu, "").replace(/\s+/gu, " ").trim();
|
|
34
|
+
return isDecisionContentPlaceholder(value) ? null : value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// `urHeading` is the registered UR document heading without its "UR:" prefix, when the caller read it.
|
|
38
|
+
export function runIdentity({ runId, runContent, urHeading } = {}) {
|
|
39
|
+
const objective = authoredObjective(runContent), ur = plainHeading(urHeading);
|
|
40
|
+
if (ur) return { title: ur, title_source: "ur", objective };
|
|
41
|
+
if (objective) return { title: objective, title_source: "objective", objective };
|
|
42
|
+
return { title: normalizedRunTitle(runId), title_source: "run_id", objective: null };
|
|
43
|
+
}
|
|
@@ -4,12 +4,14 @@ import { createDeliveryContinuationService } from "./delivery-continuation/servi
|
|
|
4
4
|
import { createControlInspectService } from "./control-inspect/service.js";
|
|
5
5
|
import { createRunCommandService } from "./control-state/run-command-service.js";
|
|
6
6
|
import { createRunMaterialStore } from './control-state/run-material.js';
|
|
7
|
+
import { withMaterialRecordingCalls } from './control-inspect/material-recording-calls.js';
|
|
7
8
|
import { evaluateGateCheck } from './control-evaluation/gate-check.js';
|
|
8
9
|
import { evaluateDoctor } from './control-evaluation/doctor.js';
|
|
9
10
|
export { createResourceContext, resources } from "./resources/context.js";
|
|
10
11
|
export function createCoreServices({ resources: context = resources, observers = {}, runtimeBinding } = {}) {
|
|
11
12
|
const contracts = { runtimeContractModules: () => runtimeContractModules(context.pluginDefinition), readRuntimeContract: module => readRuntimeContract(module, { context }), readSkillRuntimeContracts: skill => readSkillRuntimeContracts(skill, { context }) };
|
|
12
|
-
const
|
|
13
|
+
const store = createRunMaterialStore();
|
|
14
|
+
const material = Object.freeze({ ...store, stage: input => withMaterialRecordingCalls(input, store.stage(input)) });
|
|
13
15
|
const reads = observers.gitObservation ? { ...observers,
|
|
14
16
|
evaluateGateCheck: observers.evaluateGateCheck ?? ((root, selection) => evaluateGateCheck(root, selection, observers.gitObservation)),
|
|
15
17
|
evaluateDoctor: observers.evaluateDoctor ?? ((root, selection) => evaluateDoctor(root, selection, observers.gitObservation)),
|