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
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// Companion run view (SD SDD-001, SDD-002): a read-only projection of the unchanged gate-check
|
|
2
|
+
// report of each run, beside the run inventory of one project root. It never re-derives a gate
|
|
3
|
+
// rule: status fields are copied from the status card verbatim, so every consumer of the run
|
|
4
|
+
// view sees exactly what the status card shows. Nothing here writes or authorizes.
|
|
5
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { readFileSync, statSync } from '../control-read/fs.js';
|
|
8
|
+
import { captureControlScope } from '../control-read/snapshot.js';
|
|
9
|
+
import { containedRegularFile, hasSymlinkComponent, isSafeControlRelativePath } from '../control-state/contained-file.js';
|
|
10
|
+
import { parseControlState } from '../control-state/run-state-parser.js';
|
|
11
|
+
import { runIdentity } from '../control-state/run-title.js';
|
|
12
|
+
import { localizedDecisionFields } from '../control-evaluation/decision-content-readiness.js';
|
|
13
|
+
import { evaluateGateCheck } from '../control-evaluation/gate-check.js';
|
|
14
|
+
import { readRunInventory } from '../control-state/run-inventory-reader.js';
|
|
15
|
+
import { runFolderEntries } from '../control-state/run-state-reader.js';
|
|
16
|
+
import { readArtefactBindings } from '../control-state/artefact-bindings.js';
|
|
17
|
+
import { readEvidenceBindings } from '../control-state/evidence-bindings.js';
|
|
18
|
+
import { runRelativePath } from '../control-state/run-identity.js';
|
|
19
|
+
import { artefactFileDigest } from '../control-state/run-seal-compute.js';
|
|
20
|
+
import { boundedCode } from '../control-inspect/run-classification.js';
|
|
21
|
+
import { localizeBlockingCondition, localizeOperationalValue } from '../interaction-presentation.js';
|
|
22
|
+
import { interactionLocales, resolveArtifactPresentationLanguages } from '../resources/context.js';
|
|
23
|
+
import { deriveFigureState } from './figure-state.js';
|
|
24
|
+
|
|
25
|
+
export const RUN_VIEW_SCHEMA = 'run-view/1';
|
|
26
|
+
export const DIAGNOSIS_REASONS = Object.freeze(['run_version_unsupported', 'run_state_invalid', 'too_large', 'missing']);
|
|
27
|
+
// The reader's findings for a run folder without a readable run state: the path finding of
|
|
28
|
+
// run-state-reader.js (invalidRun) and the inventory's finding for a run without text (run-inventory.js).
|
|
29
|
+
const MISSING_CODES = new Set(['AGDF_RUN_PATH_INVALID', 'AGDF_RUN_STATE_UNAVAILABLE']);
|
|
30
|
+
// The classifications run-state-resolver.js treats as unsupported (AGDF_RUN_VERSION_UNSUPPORTED).
|
|
31
|
+
const UNSUPPORTED_CLASSIFICATIONS = new Set(['unsupported_version', 'unsupported_layout']);
|
|
32
|
+
|
|
33
|
+
// Per-run reason of an unreadable run (SD SDD-003) from the reader findings: unsupported by their
|
|
34
|
+
// classification, as run-state-resolver.js and the cockpit decide it (CR finding CIR-03), missing
|
|
35
|
+
// when only the missing-state findings are present, otherwise invalid. Core reports no size bound
|
|
36
|
+
// of its own, so an oversized run state is reported with the reason Core gives it; too_large stays
|
|
37
|
+
// reserved for such a bound (contradiction C1).
|
|
38
|
+
export function diagnosisReason(findings) {
|
|
39
|
+
if (findings.some(finding => UNSUPPORTED_CLASSIFICATIONS.has(finding.classification))) return 'run_version_unsupported';
|
|
40
|
+
if (findings.length && findings.every(finding => MISSING_CODES.has(finding.code))) return 'missing';
|
|
41
|
+
return 'run_state_invalid';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function projectDiagnosis(entries) {
|
|
45
|
+
const unreadable = entries.filter(entry => !entry.valid).map(entry => ({ run_id: entry.run_id, reason: entry.unreadable_reason ?? 'run_state_invalid', codes: entry.findings }));
|
|
46
|
+
const by_reason = Object.fromEntries(DIAGNOSIS_REASONS.map(reason => [reason, unreadable.filter(row => row.reason === reason).length]));
|
|
47
|
+
return { unreadable, counts: { unreadable: unreadable.length, readable: entries.length - unreadable.length, by_reason } };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const NAMING_TEXT_LIMIT = 500;
|
|
51
|
+
const UR_READ_LIMIT = 131072;
|
|
52
|
+
const bounded = value => (typeof value === 'string' && value.length > NAMING_TEXT_LIMIT ? `${value.slice(0, NAMING_TEXT_LIMIT - 1)}…` : value);
|
|
53
|
+
|
|
54
|
+
// How a run names itself to a person, read inside the run's own snapshot: the stable title of the
|
|
55
|
+
// shared Run title rule (registered UR heading, then the authored Objective; a bare Run ID is no
|
|
56
|
+
// title) and the goal in the display language. Where display and artefact language differ, the goal
|
|
57
|
+
// is the one the UR's localized approval summary states. An unreadable UR leaves both to the Run document.
|
|
58
|
+
export function readRunNaming(root, runId, language = 'en') {
|
|
59
|
+
let content;
|
|
60
|
+
try { content = readFileSync(join(root, runRelativePath(runId, '', 'RUN_STATE.md')), 'utf8'); } catch { return null; }
|
|
61
|
+
let urHeading = '', localizedGoal = null;
|
|
62
|
+
try {
|
|
63
|
+
const path = String(parseControlState(content).artefacts.get('UR')?.path ?? '').replace(/^`|`$/gu, '').trim();
|
|
64
|
+
if (isSafeControlRelativePath(path) && path.startsWith('.agdf/control/') && !hasSymlinkComponent(root, path)) {
|
|
65
|
+
const file = containedRegularFile(root, path);
|
|
66
|
+
if (file.status === 'valid' && statSync(file.path).size <= UR_READ_LIMIT) {
|
|
67
|
+
const text = readFileSync(file.path, 'utf8');
|
|
68
|
+
urHeading = (text.match(/^#\s+(.+)$/mu)?.[1] ?? '').replace(/^UR:\s*/iu, '').trim();
|
|
69
|
+
const sourceLanguage = resolveArtifactPresentationLanguages(root, language).artifact_language;
|
|
70
|
+
localizedGoal = localizedDecisionFields('UR', text, { locale: String(language).split('-')[0], sourceLanguage, path }).fields.goal ?? null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch (error) { if (error?.code === 'source_changed') throw error; }
|
|
74
|
+
const identity = runIdentity({ runId, runContent: content, urHeading });
|
|
75
|
+
return { run_title: identity.title_source === 'run_id' ? null : bounded(identity.title),
|
|
76
|
+
run_title_source: identity.title_source, goal: bounded(localizedGoal ?? identity.objective) };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// One run entry: inventory facts plus, when evaluated, the status card fields of its report.
|
|
80
|
+
// `naming` is readRunNaming's result for an evaluated run; without it the inventory names the run.
|
|
81
|
+
export function projectRunEntry(inventoryEntry, report, { registry = interactionLocales, language = 'en', naming = null } = {}) {
|
|
82
|
+
const authored = inventoryEntry.title_source === 'objective' ? inventoryEntry.title ?? null : null;
|
|
83
|
+
const base = {
|
|
84
|
+
run_id: inventoryEntry.run_id,
|
|
85
|
+
title: inventoryEntry.title ?? null,
|
|
86
|
+
// The stable human title, the same at every gate; null while only the Run ID could name the run.
|
|
87
|
+
run_title: naming ? naming.run_title : authored,
|
|
88
|
+
run_title_source: naming?.run_title_source ?? (authored ? 'objective' : 'run_id'),
|
|
89
|
+
// The goal in the display language where the UR states one, otherwise the authored objective.
|
|
90
|
+
goal: naming ? naming.goal : inventoryEntry.objective ?? null,
|
|
91
|
+
// The authored objective only, from the shared Run title rule; a template objective or a
|
|
92
|
+
// bare Run ID is no goal (CR finding C2).
|
|
93
|
+
objective: inventoryEntry.objective ?? null,
|
|
94
|
+
lifecycle: inventoryEntry.lifecycle ?? null,
|
|
95
|
+
valid: inventoryEntry.valid !== false,
|
|
96
|
+
revision: inventoryEntry.revision ?? null,
|
|
97
|
+
revision_id: inventoryEntry.revision_id ?? null,
|
|
98
|
+
last_activity: inventoryEntry.last_activity?.at ?? null,
|
|
99
|
+
findings: (inventoryEntry.findings ?? []).map(finding => finding.code),
|
|
100
|
+
};
|
|
101
|
+
if (!base.valid) base.unreadable_reason = diagnosisReason(inventoryEntry.findings ?? []);
|
|
102
|
+
// A run whose evaluation threw is reported with the bounded reason, never as an idle run (CR A7).
|
|
103
|
+
if (report?.evaluation_error) return withFigure({ ...base, evaluated: false, evaluation_error: report.evaluation_error });
|
|
104
|
+
if (!report?.status_card) return withFigure({ ...base, evaluated: false });
|
|
105
|
+
const card = report.status_card;
|
|
106
|
+
return withFigure({
|
|
107
|
+
...base,
|
|
108
|
+
title: card.humanPresentation?.runTitle ?? base.title,
|
|
109
|
+
evaluated: true,
|
|
110
|
+
completion_confirmed: base.lifecycle === 'completed' && report.completion?.fulfilled === true,
|
|
111
|
+
status: card.status,
|
|
112
|
+
current_gate: card.current_gate,
|
|
113
|
+
path: card.breadcrumb.map(({ gate, status }) => ({ gate, status })),
|
|
114
|
+
missing_approval: card.missing_approval,
|
|
115
|
+
blocking_reason: card.blocking_condition,
|
|
116
|
+
blocking_text: localizeBlockingCondition(card.blocking_condition, { registry, requestedLocale: language }) ?? card.blocking_condition,
|
|
117
|
+
next_step: card.next_step,
|
|
118
|
+
next_step_text: localizeOperationalValue(card.next_step, { registry, requestedLocale: language }) ?? card.next_step,
|
|
119
|
+
user_action_required: card.user_action_required,
|
|
120
|
+
doctor_status: report.doctor_status,
|
|
121
|
+
mode: card.mode_slice_decision ?? card.mode ?? null,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
const withFigure = entry => ({ ...entry, figure: deriveFigureState(entry) });
|
|
125
|
+
|
|
126
|
+
// Pure assembly of the versioned view from already evaluated parts.
|
|
127
|
+
export function projectRunView({ root, language, store, entries }) {
|
|
128
|
+
return {
|
|
129
|
+
schema_version: RUN_VIEW_SCHEMA,
|
|
130
|
+
root,
|
|
131
|
+
language,
|
|
132
|
+
store,
|
|
133
|
+
diagnosis: projectDiagnosis(entries.filter(entry => entry.listed !== false)),
|
|
134
|
+
runs: entries,
|
|
135
|
+
authorizes: false,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Drift warnings (SD SDD-008, PRD AC-008): documents the run state binds with a recorded digest
|
|
140
|
+
// (effective artefact binding destination, latest evidence report per path) whose file now has another
|
|
141
|
+
// canonical digest from the node digest owner. Declared input files of a recording are not kept in
|
|
142
|
+
// the run state, so only bound documents are compared (contradiction C5 of this run). An unreadable
|
|
143
|
+
// run state yields no warning; the status card reports it.
|
|
144
|
+
export function readRunDrift(root, runId) {
|
|
145
|
+
let content;
|
|
146
|
+
try { content = readFileSync(join(root, runRelativePath(runId, '', 'RUN_STATE.md')), 'utf8'); } catch { return []; }
|
|
147
|
+
const declared = new Map();
|
|
148
|
+
const artefacts = readArtefactBindings(content);
|
|
149
|
+
// A binding a recorded source revision invalidated is superseded for Core, so its document being
|
|
150
|
+
// re-drafted is no drift (CR finding A5).
|
|
151
|
+
for (const receipt of artefacts.valid ? artefacts.active ?? [] : []) {
|
|
152
|
+
declared.set(receipt.destination.path, { document: receipt.destination.type, digest: receipt.destination.digest });
|
|
153
|
+
}
|
|
154
|
+
const evidence = readEvidenceBindings(content);
|
|
155
|
+
for (const row of evidence.valid ? evidence.bindings : []) {
|
|
156
|
+
declared.set(row.report.path, { document: row.report.path.split('/').at(-1).replace(/\.md$/u, ''), digest: row.report.digest });
|
|
157
|
+
}
|
|
158
|
+
const drift = [];
|
|
159
|
+
for (const [path, { document, digest }] of declared) {
|
|
160
|
+
const current = artefactFileDigest(root, path);
|
|
161
|
+
if (current === digest) continue;
|
|
162
|
+
drift.push({ document, path, recorded_digest: digest, current_digest: /^sha256:/u.test(current) ? current : null });
|
|
163
|
+
}
|
|
164
|
+
return drift;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Active runs are evaluated; terminal and unreadable runs are summarized unless requested by id, so
|
|
168
|
+
// neither a large history nor many unreadable runs cost one evaluation per run. An unreadable run's
|
|
169
|
+
// reason and figure come from the inventory findings.
|
|
170
|
+
const needsEvaluation = (entry, requested) => requested.has(entry.run_id) || (entry.valid && entry.lifecycle === 'active');
|
|
171
|
+
|
|
172
|
+
// A write that lands during a capture invalidates it (source_changed); the read is repeated a bounded
|
|
173
|
+
// number of times before the change is reported (CR delta review RV-1).
|
|
174
|
+
export const CAPTURE_ATTEMPTS = 3;
|
|
175
|
+
export function captured(readRoot, project, capture = captureControlScope) {
|
|
176
|
+
for (let attempt = 1; ; attempt += 1) {
|
|
177
|
+
try { return capture(readRoot, view => project(view.root)).data; }
|
|
178
|
+
catch (error) { if (error?.code !== 'source_changed' || attempt >= CAPTURE_ATTEMPTS) throw error; }
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Reads inside bounded, revalidated control snapshots (TP T-002, SD section 4: captureControlScope,
|
|
183
|
+
// CR finding CIR-01): the inventory in one snapshot and each evaluated run with its drift in its own,
|
|
184
|
+
// so a read-boundary failure of one run (a linked file, a document outside the control folder, a read
|
|
185
|
+
// limit) marks only that run and the readable runs stay listed (SDD-003, RV-2). The root is resolved
|
|
186
|
+
// first, as MCP canonicalizes its target, so a junction or symlinked project root reads like its
|
|
187
|
+
// target; the view keeps the caller's spelling (RV-3). A missing root has no control folder (RV-5).
|
|
188
|
+
export function readRunView(root, { language = 'en', runIds = [] } = {}) {
|
|
189
|
+
const empty = store => projectRunView({ root, language, store, entries: [] });
|
|
190
|
+
if (!existsSync(root)) return empty({ status: 'no_control', reason: null });
|
|
191
|
+
let readRoot;
|
|
192
|
+
try { readRoot = realpathSync(root); } catch (error) { return empty({ status: 'unavailable', reason: boundedCode(error) }); }
|
|
193
|
+
const requested = new Set(runIds);
|
|
194
|
+
const evaluate = runId => {
|
|
195
|
+
try {
|
|
196
|
+
return captured(readRoot, base => {
|
|
197
|
+
const report = evaluateGateCheck(base, { runId, ignoreRunIdEnv: true, presentationLanguage: language });
|
|
198
|
+
return { report, drift: report?.status_card ? readRunDrift(base, runId) : null, naming: readRunNaming(base, runId, language) };
|
|
199
|
+
});
|
|
200
|
+
} catch (error) { return { report: { evaluation_error: boundedCode(error) }, drift: null, naming: null }; }
|
|
201
|
+
};
|
|
202
|
+
const entryOf = (inventoryEntry, evaluated) => {
|
|
203
|
+
const entry = projectRunEntry(inventoryEntry, evaluated?.report ?? null, { language, naming: evaluated?.naming ?? null });
|
|
204
|
+
return entry.evaluated && entry.valid !== false && evaluated.drift ? { ...entry, drift: evaluated.drift } : entry;
|
|
205
|
+
};
|
|
206
|
+
let inventory = null, store;
|
|
207
|
+
try {
|
|
208
|
+
inventory = captured(readRoot, base => readRunInventory(base, { language, observe: false }));
|
|
209
|
+
store = { status: inventory.state === 'absent' ? 'no_control' : 'ok', reason: null };
|
|
210
|
+
} catch (error) {
|
|
211
|
+
store = { status: 'unavailable', reason: boundedCode(error) };
|
|
212
|
+
// An unsupported layout lists no run, but its run folders can be counted, so a consumer names count
|
|
213
|
+
// and reason instead of "no open runs" (PRD AC-002, TP T-004). A failing count leaves the field out.
|
|
214
|
+
if (store.reason === 'control_layout_unsupported') {
|
|
215
|
+
try { store.run_folders = captured(readRoot, base => runFolderEntries(base).length); } catch { /* count unknown */ }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const listed = inventory?.runs ?? [];
|
|
219
|
+
const entries = listed.map(entry => entryOf(entry, needsEvaluation(entry, requested) ? evaluate(entry.run_id) : null));
|
|
220
|
+
for (const runId of requested) {
|
|
221
|
+
if (listed.some(entry => entry.run_id === runId)) continue;
|
|
222
|
+
// Requested but not listed by the inventory (for example behind an unsupported layout):
|
|
223
|
+
// evaluated for its card, never counted in the diagnosis of listed runs.
|
|
224
|
+
entries.push({ ...entryOf({ run_id: runId, findings: [] }, evaluate(runId)), valid: null, listed: false });
|
|
225
|
+
}
|
|
226
|
+
return projectRunView({ root, language, store, entries });
|
|
227
|
+
}
|
|
@@ -4,6 +4,8 @@ const CRITERION_ID = /^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*$/u;
|
|
|
4
4
|
export const ACCEPTANCE_CRITERIA_FORMAT = Object.freeze({
|
|
5
5
|
section: "Acceptance Criteria", declaration: "criterion_id: <stable id>",
|
|
6
6
|
fields: "semicolon-separated inline fields or following bullet key: value lines",
|
|
7
|
+
description_fields: Object.freeze(["observable_success", "visible_feedback", "expected_effective_state"]),
|
|
8
|
+
description_rule: "For same-language approval rendering, provide at least one nonempty description field separately. Never concatenate field names or infer their meaning from combined keys.",
|
|
7
9
|
id_pattern: CRITERION_ID.source,
|
|
8
10
|
examples: Object.freeze([
|
|
9
11
|
"## Acceptance Criteria\n- criterion_id: AC-001; observable_success: Saved choice remains selected",
|
|
@@ -24,6 +24,24 @@ export function closeoutContext(text) {
|
|
|
24
24
|
}
|
|
25
25
|
export const closeoutContextDigest = text => digest(`agdf-closeout-context/1\0${canonicalJson(closeoutContext(text))}`);
|
|
26
26
|
|
|
27
|
+
// Bindings a structured OR states; the same tables drive the check and the
|
|
28
|
+
// expectations returned with a refusal.
|
|
29
|
+
const OR_SOURCE_FIELDS = Object.freeze({ related_ur: 'UR', related_prd: 'PRD', related_sd: 'SD', related_tp: 'TP', related_qa_report: 'QA' });
|
|
30
|
+
const OR_GATE_ROWS = Object.freeze(['UR', 'PRD', 'SD', 'TP', 'Brownfield Review', 'Brownfield Analysis', 'CD+Tests', 'CR', 'QA', 'UAT']);
|
|
31
|
+
const OR_MEMORY_TARGETS = Object.freeze(['context_graph', 'sot_registry', 'scope_artifact', 'open_questions', 'none']);
|
|
32
|
+
const gateRowExpectation = (state, type) => ({
|
|
33
|
+
status: state.approvals.has(type) ? state.approvals.get(type).status : state.artefacts.get(type)?.status,
|
|
34
|
+
reference: state.artefacts.get(type)?.path || state.approvals.get(type)?.evidence,
|
|
35
|
+
});
|
|
36
|
+
function structuredOrExpectations(state, route) {
|
|
37
|
+
return {
|
|
38
|
+
fields: { ...Object.fromEntries(Object.entries(OR_SOURCE_FIELDS).map(([field, type]) => [field, state.artefacts.get(type)?.path ?? null])),
|
|
39
|
+
mode_slice_decision: route, current_gate: 'OR', decision: 'pass', required_approval: 'none' },
|
|
40
|
+
gate_state_rows: Object.fromEntries(OR_GATE_ROWS.map(type => [type, gateRowExpectation(state, type)])),
|
|
41
|
+
memory_target: OR_MEMORY_TARGETS, memory_fields: 'memory_reason and memory_refs need concrete text',
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
27
45
|
// Shared observation of registered OR and prepared OR candidates. Legacy reports retain
|
|
28
46
|
// their documented formats; the new writer additionally requires the complete template.
|
|
29
47
|
export function evaluateCloseoutReadiness(state, report, readArtefact, { prepared = false } = {}) {
|
|
@@ -85,14 +103,13 @@ export function evaluateCloseoutReadiness(state, report, readArtefact, { prepare
|
|
|
85
103
|
...Object.keys(context), 'next_allowed_action', 'required_approval', 'forbidden_until_then']) {
|
|
86
104
|
if ([...report.matchAll(new RegExp(`^- ${field}:[ \\t]*(.*)$`, 'gmu'))].length !== 1) fail('or_field_ambiguous:' + field);
|
|
87
105
|
}
|
|
88
|
-
for (const [field, type] of Object.entries(
|
|
106
|
+
for (const [field, type] of Object.entries(OR_SOURCE_FIELDS)) {
|
|
89
107
|
if (value(report, field) !== state.artefacts.get(type)?.path) fail('or_source_reference_invalid:' + field);
|
|
90
108
|
}
|
|
91
109
|
if (value(report, 'mode_slice_decision') !== route || value(report, 'current_gate') !== 'OR' || value(report, 'decision') !== 'pass') fail('or_control_binding_invalid');
|
|
92
110
|
const gateRows = tableRows(markdownSection(report, 'Gate State')).filter(row => row[0] !== 'Gate or step');
|
|
93
|
-
for (const type of
|
|
94
|
-
const rows = gateRows.filter(row => row[0] === type), expected =
|
|
95
|
-
const reference = state.artefacts.get(type)?.path || state.approvals.get(type)?.evidence;
|
|
111
|
+
for (const type of OR_GATE_ROWS) {
|
|
112
|
+
const rows = gateRows.filter(row => row[0] === type), { status: expected, reference } = gateRowExpectation(state, type);
|
|
96
113
|
if (rows.length !== 1 || rows[0][1] !== expected || !concrete(rows[0][2])
|
|
97
114
|
|| cleanStatusCell(rows[0][2]) !== cleanStatusCell(reference)) fail('or_gate_state_unconfirmed:' + type);
|
|
98
115
|
}
|
|
@@ -101,11 +118,12 @@ export function evaluateCloseoutReadiness(state, report, readArtefact, { prepare
|
|
|
101
118
|
if (!concrete(text) || /<[^>]+>|\|[ \t]*\|/u.test(text)) fail('or_section_incomplete:' + section);
|
|
102
119
|
}
|
|
103
120
|
for (const section of ['Missing Evidence', 'Risks And Open Items']) if (/\|\s*(?:revise|block)\s*\|/u.test(markdownSection(report, section))) fail('or_required_obligation_open:' + section);
|
|
104
|
-
if (!
|
|
121
|
+
if (!OR_MEMORY_TARGETS.includes(context.memory_target)
|
|
105
122
|
|| !concrete(context.memory_reason) || !concrete(context.memory_refs)) fail('or_knowledge_decision_incomplete');
|
|
106
123
|
if (value(report, 'required_approval') !== 'none') fail('or_required_approval_open');
|
|
107
124
|
}
|
|
108
125
|
}
|
|
109
126
|
return { ready: findings.length === 0, findings, route, context_digest: closeoutContextDigest(report),
|
|
110
|
-
parent_reconciliation: parent ?? null, programme_aggregation: programme ?? null
|
|
127
|
+
parent_reconciliation: parent ?? null, programme_aggregation: programme ?? null,
|
|
128
|
+
...(prepared && structured && findings.length ? { expected: structuredOrExpectations(state, route) } : {}) };
|
|
111
129
|
}
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
// run inventory and other `node:`-free readers share the same rule.
|
|
3
3
|
const prompts = new Set(['describe the trustworthy outcome.', 'what outcome should become possible?',
|
|
4
4
|
'which tp tasks are fully done, partially done or not done?', 'what remains unverified?', 'which risks remain and what is their impact?']);
|
|
5
|
+
// A bare generated Run ID (`run-<operation uuid>`) names the Run but states no outcome.
|
|
6
|
+
const generatedRunId = /^run-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u;
|
|
5
7
|
export function isDecisionContentPlaceholder(value) {
|
|
6
8
|
if (typeof value !== 'string') return true;
|
|
7
9
|
const text = value.trim().replace(/^`([^`]+)`$/u, '$1').replace(/\s+/gu, ' ').toLowerCase();
|
|
8
|
-
return !text || prompts.has(text) ||
|
|
10
|
+
return !text || prompts.has(text) || generatedRunId.test(text)
|
|
11
|
+
|| /^(?:todo|tbd|<[^>]+>|(?:draft|done|ready|blocked|pass|revise|block)(?:\s*\|\s*(?:draft|done|ready|blocked|pass|revise|block))+)$/.test(text);
|
|
9
12
|
}
|
|
@@ -9,7 +9,8 @@ import { isGateSatisfied, transitionDecisionForRunState } from "./gate-policy.js
|
|
|
9
9
|
import { effectiveNextAllowedAction } from "./next-action.js";
|
|
10
10
|
import { evaluateVerifiedChange, extractField, verifiedChangeEscalationTargets } from "./verified-change.js";
|
|
11
11
|
import { gateApprovalStatus, isInternalStepSatisfied, modeSliceDecision, readArtefactHeading, readRunState, resolvedArtefactFile } from "./run-state.js";
|
|
12
|
-
import { renderReviewableApproval } from "../control-state/run-presentation-render.js";
|
|
12
|
+
import { evaluateApprovalSummaryReadiness, renderApprovalSummaryIssue, renderReviewableApproval } from "../control-state/run-presentation-render.js";
|
|
13
|
+
import { readFileSync } from "../control-read/fs.js";
|
|
13
14
|
import { evaluateUrReadiness } from "./ur-readiness.js";
|
|
14
15
|
import { inspectDefinitionSources } from "./definition-sources.js";
|
|
15
16
|
import { evaluatePrdReadiness } from "./prd-readiness.js";
|
|
@@ -158,7 +159,7 @@ export function isReadyUserGateApproval({ status, currentGate, missingApproval }
|
|
|
158
159
|
|
|
159
160
|
function buildBreadcrumbPath(modeSliceDecision, currentGate, runState) {
|
|
160
161
|
const gates = BREADCRUMB_PATH_TEMPLATES[modeSliceDecision] ?? ["UR"];
|
|
161
|
-
return gates.map((gate) => {
|
|
162
|
+
return gates.map((gate, index) => {
|
|
162
163
|
if (BREADCRUMB_STANDARD_GATES.includes(gate)) {
|
|
163
164
|
if (gateApprovalStatus(runState, gate) === "approved") return { gate, status: "fulfilled" };
|
|
164
165
|
if (gate === currentGate) return { gate, status: "current" };
|
|
@@ -169,6 +170,10 @@ function buildBreadcrumbPath(modeSliceDecision, currentGate, runState) {
|
|
|
169
170
|
if (gate === currentGate) return { gate, status: "current" };
|
|
170
171
|
if ((gate === "Verified Change" || gate === "Compact Delivery") && currentGate === "OR")
|
|
171
172
|
return { gate, status: "fulfilled" };
|
|
173
|
+
// A path has one current entry: while an earlier gate is still the current one (a stored route
|
|
174
|
+
// with an unapproved UR), the route entry after it is open, not current by its route.
|
|
175
|
+
if (gates.slice(0, index).some((earlier) => earlier === currentGate && gateApprovalStatus(runState, earlier) !== "approved"))
|
|
176
|
+
return { gate, status: "open" };
|
|
172
177
|
if (gate === "Verified Change" && modeSliceDecision === "verified_change")
|
|
173
178
|
return { gate, status: "current" };
|
|
174
179
|
if (gate === "Compact Delivery" && modeSliceDecision === "quick_task")
|
|
@@ -427,31 +432,58 @@ export function evaluateGateCheck(targetDir, selection = {}, dependencies = {})
|
|
|
427
432
|
if (status === "open" && prdReadiness && transitionDecision.next_operation?.type !== "reassess_source_analysis" && isGateSatisfied(runState, "UR") && isInternalStepSatisfied(runState, "Brownfield Review")
|
|
428
433
|
&& ["structured_delivery", "structured_slice"].includes(modeSliceDecision(runState))) {
|
|
429
434
|
const inputFacts = inspectDefinitionSources(targetDir, runState, extractField(runState.content, "run_id"), "PRD", ["UR", "Brownfield Review"]);
|
|
430
|
-
if (inputFacts.issue) prdReadiness = { ready: false, open_decisions: [...prdReadiness.open_decisions,
|
|
435
|
+
if (inputFacts.issue) prdReadiness = { ...prdReadiness, ready: false, source_issue: inputFacts.issue, open_decisions: [...prdReadiness.open_decisions,
|
|
431
436
|
renderDefinitionSourceRecovery(inputFacts.issue, { registry: interactionLocales, requestedLocale: presentationLocale })] };
|
|
432
437
|
}
|
|
433
438
|
if (status === "open" && currentGate === "PRD" && prdReadiness && !prdReadiness.ready) {
|
|
434
439
|
status = "blocked";
|
|
440
|
+
const checks = prdReadiness.readiness_checks;
|
|
435
441
|
blockingReason = "AGDF_PRD_DECISIONS_OPEN";
|
|
442
|
+
if (checks?.decisions_ready) {
|
|
443
|
+
const sourceCriteriaIncomplete = !checks.approval_summary.ready && [
|
|
444
|
+
"approval_summary_criterion_content_missing", "approval_summary_source_criteria_invalid",
|
|
445
|
+
"approval_summary_source_criteria_duplicate", "approval_summary_criteria_missing",
|
|
446
|
+
].includes(checks.approval_summary.reason);
|
|
447
|
+
blockingReason = prdReadiness.source_issue || !checks.preview_ready || !checks.criteria_ready || sourceCriteriaIncomplete
|
|
448
|
+
? "AGDF_PRD_READINESS_INCOMPLETE" : "AGDF_APPROVAL_SUMMARY_INCOMPLETE";
|
|
449
|
+
}
|
|
436
450
|
allowed = ["complete the listed PRD readiness items together and record a new run revision"];
|
|
437
451
|
forbidden = [...forbidden, "present or approve PRD before required decisions and acceptance criteria are ready"];
|
|
438
452
|
// Fixed text keeps the card localizable; detailed gaps travel separately in prd_readiness.open_decisions.
|
|
439
453
|
nextAllowedAction = "complete the open PRD readiness items together, then record the revision through the inspected current recording operation";
|
|
440
454
|
}
|
|
441
|
-
|
|
442
|
-
|
|
455
|
+
let sdReadiness = currentGate === "SD" && approvalArtefactReady ? evaluateSdReadiness(targetDir, runState) : null;
|
|
456
|
+
let traceabilityReadiness = status === "open" && approvalArtefactReady && currentGate === "SD"
|
|
443
457
|
? evaluateSdTraceability(targetDir, runState)
|
|
444
458
|
: status === "open" && approvalArtefactReady && currentGate === "TP"
|
|
445
459
|
? evaluateTpTraceability(targetDir, runState)
|
|
446
460
|
: null;
|
|
447
|
-
|
|
461
|
+
// Presentation readiness belongs to the existing authoring gate, not to the
|
|
462
|
+
// traceability grammar. Use the same summary owner as preflight and rendering
|
|
463
|
+
// before a registered SD/TP draft can bypass its author and request approval.
|
|
464
|
+
let approvalSummaryReadiness = null;
|
|
465
|
+
if (status === "open" && approvalArtefactReady && ["SD", "TP"].includes(currentGate)) {
|
|
466
|
+
const path = runState.artefacts.get(currentGate).path;
|
|
467
|
+
const file = resolvedArtefactFile(targetDir, path);
|
|
468
|
+
const languages = resolveArtifactPresentationLanguages(targetDir, presentationLocale);
|
|
469
|
+
const summary = evaluateApprovalSummaryReadiness(currentGate, readFileSync(file, "utf8"), languages, { path });
|
|
470
|
+
if (!summary.ready) {
|
|
471
|
+
approvalSummaryReadiness = summary;
|
|
472
|
+
const issue = renderApprovalSummaryIssue(summary, { path, presentationLanguage: presentationLocale });
|
|
473
|
+
if (currentGate === "SD") sdReadiness = { ...sdReadiness, ready: false, decisions_ready: sdReadiness.ready,
|
|
474
|
+
open_decisions: [...sdReadiness.open_decisions, issue] };
|
|
475
|
+
else traceabilityReadiness = { ...traceabilityReadiness, ready: false, traceability_ready: traceabilityReadiness.ready,
|
|
476
|
+
open_items: [...traceabilityReadiness.open_items, issue] };
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
if (status === "open" && sdReadiness && !sdReadiness.ready && sdReadiness.decisions_ready !== true) {
|
|
448
480
|
status = "blocked";
|
|
449
481
|
blockingReason = "AGDF_SD_DECISIONS_OPEN";
|
|
450
482
|
allowed = ["complete the listed SD readiness items together and record a new run revision"];
|
|
451
483
|
forbidden = [...forbidden, "present or approve SD before required design decisions are ready"];
|
|
452
484
|
nextAllowedAction = "complete the open SD readiness items together, then record the revision with the shared artefact writer";
|
|
453
485
|
}
|
|
454
|
-
if (status === "open" && traceabilityReadiness && !traceabilityReadiness.ready) {
|
|
486
|
+
if (status === "open" && traceabilityReadiness && !traceabilityReadiness.ready && traceabilityReadiness.traceability_ready !== true) {
|
|
455
487
|
status = "blocked";
|
|
456
488
|
blockingReason = currentGate === "SD" ? "AGDF_SD_TRACEABILITY_INCOMPLETE" : "AGDF_TP_TRACEABILITY_INCOMPLETE";
|
|
457
489
|
allowed = [currentGate === "SD"
|
|
@@ -462,6 +494,15 @@ export function evaluateGateCheck(targetDir, selection = {}, dependencies = {})
|
|
|
462
494
|
? "complete the listed SD traceability rows, then record the revision through the inspected current recording operation"
|
|
463
495
|
: "complete the listed TP traceability rows, then record the revision through the inspected current recording operation";
|
|
464
496
|
}
|
|
497
|
+
if (status === "open" && approvalSummaryReadiness) {
|
|
498
|
+
status = "blocked";
|
|
499
|
+
blockingReason = "AGDF_APPROVAL_SUMMARY_INCOMPLETE";
|
|
500
|
+
}
|
|
501
|
+
if (blockingReason === "AGDF_APPROVAL_SUMMARY_INCOMPLETE") {
|
|
502
|
+
allowed = ["complete the current artefact approval summary and record a new run revision"];
|
|
503
|
+
forbidden = [...forbidden, "present or approve the current artefact before its required approval summary is ready"];
|
|
504
|
+
nextAllowedAction = "complete the current artefact approval summary, then record the revision through the inspected current recording operation";
|
|
505
|
+
}
|
|
465
506
|
if (status === "open" && /^Approval: /u.test(missingApproval) && !approvalArtefactReady) {
|
|
466
507
|
allowed = allowed.filter((action) => !/^request exact .* approval$/iu.test(action));
|
|
467
508
|
if (/request exact approval: Approval: /iu.test(nextAllowedAction)) {
|
|
@@ -662,6 +703,7 @@ export function evaluateGateCheck(targetDir, selection = {}, dependencies = {})
|
|
|
662
703
|
...(prdReadiness ? { prd_readiness: prdReadiness } : {}),
|
|
663
704
|
...(sdReadiness ? { sd_readiness: sdReadiness } : {}),
|
|
664
705
|
...(traceabilityReadiness ? { traceability_readiness: traceabilityReadiness } : {}),
|
|
706
|
+
...(approvalSummaryReadiness ? { approval_summary_readiness: approvalSummaryReadiness } : {}),
|
|
665
707
|
next_gate_after_approval: postApproval.next_gate_after_approval,
|
|
666
708
|
allowed_after_approval: postApproval.allowed_after_approval,
|
|
667
709
|
allowed,
|
|
@@ -6,6 +6,8 @@ export function extractField(content, field) {
|
|
|
6
6
|
|
|
7
7
|
export const verifiedChangeEscalationTargets = new Set(["structured_slice", "structured_delivery"]);
|
|
8
8
|
export const STRUCTURED_REQUIRED_REVIEWS = Object.freeze(['TP Review', 'Clean Implementation Review']);
|
|
9
|
+
// The skill that owns each required review report.
|
|
10
|
+
export const REVIEW_SKILLS = Object.freeze({ 'TP Review': 'task-plan-review', 'Clean Implementation Review': 'clean-implementation-review' });
|
|
9
11
|
// `Clean Review` is the supported legacy name of the Clean Implementation Review row.
|
|
10
12
|
export const reviewArtefactType = (state, step) => step === 'Clean Implementation Review' && !state.artefacts.get(step)?.path
|
|
11
13
|
&& state.artefacts.get('Clean Review')?.path ? 'Clean Review' : step;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { extractField, verifiedChangeEscalationTargets } from "./gate-policy-inputs.js";
|
|
2
2
|
import { gateApprovalStatus, gateArtefactStatus, isDurableGateArtefactSatisfied, isInternalStepSatisfied, modeSliceDecision } from "./run-state-policy.js";
|
|
3
|
-
import { STRUCTURED_REQUIRED_REVIEWS, reviewArtefactType } from "./gate-policy-inputs.js";
|
|
3
|
+
import { REVIEW_SKILLS, STRUCTURED_REQUIRED_REVIEWS, reviewArtefactType } from "./gate-policy-inputs.js";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
// Shared policy over prepared facts. The Core supplies its validated receipt reader;
|
|
@@ -310,8 +310,9 @@ function gateDecisionForRunState(runState, verifiedChange = null) {
|
|
|
310
310
|
const acceptedPlanDeviation = runState.qa_acceptance?.eligible || runState.qa_acceptance?.accepted;
|
|
311
311
|
const structuredBeforeQaApproval = ["structured_slice", "structured_delivery"].includes(modeSliceDecision(runState))
|
|
312
312
|
&& gateApprovalStatus(runState, "QA") !== "approved";
|
|
313
|
-
|
|
314
|
-
|
|
313
|
+
const pendingReview = structuredBeforeQaApproval && STRUCTURED_REQUIRED_REVIEWS.find(step => !isInternalStepSatisfied(runState, reviewArtefactType(runState, step))
|
|
314
|
+
&& !(step === "TP Review" && acceptedPlanDeviation && runState.artefacts.get(step)?.status === "revise"));
|
|
315
|
+
if (pendingReview) {
|
|
315
316
|
return {
|
|
316
317
|
status: "open",
|
|
317
318
|
current_gate: "QA",
|
|
@@ -320,6 +321,9 @@ function gateDecisionForRunState(runState, verifiedChange = null) {
|
|
|
320
321
|
allowed: ["record TP Review and Clean Implementation Review", "run QA gate"],
|
|
321
322
|
forbidden: ["request QA approval", "request UAT approval", "release", "claim delivery readiness"],
|
|
322
323
|
next_allowed_action: "Record TP Review and Clean Implementation Review before requesting Approval: QA.",
|
|
324
|
+
// Names the review owed next so authoring offers that report's forms, not the QA report's.
|
|
325
|
+
next_operation: { type: "record_required_review", skill_id: REVIEW_SKILLS[pendingReview], operation_key: "review.record",
|
|
326
|
+
actor: "agent", effect: "preparation", gate: "QA", internal_step: pendingReview },
|
|
323
327
|
};
|
|
324
328
|
}
|
|
325
329
|
// A QA report recorded before current evidence (for example reviews recorded after it)
|
|
@@ -22,7 +22,8 @@ export function evaluatePrdReadiness(targetDir, runState, { presentationLanguage
|
|
|
22
22
|
return { ready: false, open_decisions: ["Approval Decisions table is empty or malformed"] };
|
|
23
23
|
}
|
|
24
24
|
const open = [];
|
|
25
|
-
|
|
25
|
+
let previewReady = true, previewIssue;
|
|
26
|
+
try { previewForState(targetDir, runState); } catch (error) { previewReady = false; previewIssue = error.message; }
|
|
26
27
|
const seen = new Set();
|
|
27
28
|
const incomplete = (value) => !value || /^(?:<|tbd\b|to confirm\b)/iu.test(value);
|
|
28
29
|
for (const [decision, timing, status, resolution, owner, ...extra] of rows.slice(2)) {
|
|
@@ -38,6 +39,8 @@ export function evaluatePrdReadiness(targetDir, runState, { presentationLanguage
|
|
|
38
39
|
// [ \t] rather than \s: an empty Owner line must not capture the following line.
|
|
39
40
|
const owner = content.match(/^Owner:[ \t]*(.*)$/mu)?.[1]?.trim();
|
|
40
41
|
if (incomplete(owner) || /\bto confirm\b|named individual/iu.test(owner)) open.unshift("Named PRD owner");
|
|
42
|
+
const decisionsReady = open.length === 0;
|
|
43
|
+
if (!previewReady) open.unshift(previewIssue);
|
|
41
44
|
const criteria = evaluatePrdCriteriaReadiness(content);
|
|
42
45
|
open.push(...criteria.open_items);
|
|
43
46
|
// Use the presentation owner's validator before a registered draft can take the ready route.
|
|
@@ -47,5 +50,7 @@ export function evaluatePrdReadiness(targetDir, runState, { presentationLanguage
|
|
|
47
50
|
if (!summary.ready) open.push(renderApprovalSummaryIssue(summary, {
|
|
48
51
|
path, presentationLanguage: languages.presentation_language,
|
|
49
52
|
}));
|
|
50
|
-
return { ready: open.length === 0, open_decisions: open
|
|
53
|
+
return { ready: open.length === 0, open_decisions: open,
|
|
54
|
+
readiness_checks: { decisions_ready: decisionsReady, preview_ready: previewReady, criteria_ready: criteria.ready,
|
|
55
|
+
approval_summary: summary } };
|
|
51
56
|
}
|
|
@@ -222,6 +222,15 @@ export function readAuthoredContent(text, profile, { locale, sourceLanguage } =
|
|
|
222
222
|
return sections === 1 && (spec.paragraph ? lines.length : Object.keys(fields).length) ? spec.paragraph ? lines.join(' ') : fields : null;
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
+
// Authoring guidance owned next to the parser that enforces it. Only a level-1
|
|
226
|
+
// title's metadata or a level-2 "Decision" section carries the result; a
|
|
227
|
+
// "## Code Review" style heading closes the readable metadata block.
|
|
228
|
+
export const REPORT_DECISION_FORMAT = Object.freeze({
|
|
229
|
+
section: '## Decision',
|
|
230
|
+
field: '- decision: <pass|revise|block>',
|
|
231
|
+
instruction: 'State the result in a level-2 "## Decision" section whose first line is "- decision: <value>". The value must equal the decision supplied when recording. A result under any other heading is not read.',
|
|
232
|
+
});
|
|
233
|
+
|
|
225
234
|
// Observe an authored technical result, never decide or approve QA. The closed
|
|
226
235
|
// internal opt-in preserves analysis not_applicable; QA's domain stays unchanged.
|
|
227
236
|
export function readReportDecision(text, { allowNotApplicable = false } = {}) {
|
|
@@ -45,6 +45,49 @@ function designDecisionIds(value) {
|
|
|
45
45
|
return text.split(",").map((item) => item.trim().toUpperCase());
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
const JSON_TYPE_METAVARIABLE = /^<(?:uuid|string|non-empty string|number|integer|(?:positive|non-negative) (?:integer|number)|boolean|null|object|array)>$/iu;
|
|
49
|
+
|
|
50
|
+
// Only typed JSON string values in an explicitly labelled schema/example are
|
|
51
|
+
// metavariables. Literal JSON keys may name words such as "todo"; angle-bracket
|
|
52
|
+
// key prompts, unknown values, arbitrary code and author fields stay checked.
|
|
53
|
+
function schemaExampleText(code) {
|
|
54
|
+
let parsed;
|
|
55
|
+
try { parsed = JSON.parse(code); } catch { return code; }
|
|
56
|
+
if (parsed === null || typeof parsed !== 'object') return code;
|
|
57
|
+
return code.replace(/"(?:\\.|[^"\\])*"/gu, (quoted, offset) => {
|
|
58
|
+
const key = /^[ \t]*:/u.test(code.slice(offset + quoted.length));
|
|
59
|
+
const value = JSON.parse(quoted);
|
|
60
|
+
if (key && !/<[^>]+>/u.test(value)) return '"literal-key"';
|
|
61
|
+
return JSON.stringify(!key && JSON_TYPE_METAVARIABLE.test(value) ? value.slice(1, -1) : value);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// A quoted command such as `done <id>` is concrete CLI syntax. Schema examples
|
|
66
|
+
// are permitted only in the decision clause, never instead of its rationale or
|
|
67
|
+
// consequence. The source text itself is never changed.
|
|
68
|
+
function unfinishedDecisionPrompts(value, { schemaExamples = false } = {}) {
|
|
69
|
+
const text = value.replace(/`([^`\n]+)`/gu, (span, code, offset) => {
|
|
70
|
+
if (/^[a-z][a-z0-9._/-]*(?:[ \t]+(?:--?[a-z0-9][a-z0-9_-]*|[a-z0-9._/-]+|<[a-z][a-z0-9_-]*>))+$/iu.test(code))
|
|
71
|
+
return code.replace(/<([a-z][a-z0-9_-]*)>/giu, '$1');
|
|
72
|
+
if (schemaExamples && /\b(?:(?:json[ \t]+)?schema(?:[ \t]+example)?|json[ \t]+example)[ \t]*[:=]?[ \t]*$/iu.test(value.slice(0, offset)))
|
|
73
|
+
return schemaExampleText(code);
|
|
74
|
+
return span;
|
|
75
|
+
});
|
|
76
|
+
// Preserve the original unfinished-field prefix guard even when an author
|
|
77
|
+
// has not closed its opening angle bracket yet.
|
|
78
|
+
return [...new Set(text.match(/<[^>]+>|^<[^>\s;]*|\b(?:tbd|to confirm|todo)\b/giu) ?? [])];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function decisionClauses(detail) {
|
|
82
|
+
// Semicolons or field-looking strings inside literal examples cannot declare
|
|
83
|
+
// the required author fields. Keep character offsets into the original text.
|
|
84
|
+
const labels = [...detail.replace(/`[^`\n]+`/gu, span => '_'.repeat(span.length))
|
|
85
|
+
.matchAll(/(?:^|;[ \t]*)(rationale|consequence|trade-off):[ \t]*/giu)];
|
|
86
|
+
return [{ field: 'decision', text: detail.slice(0, labels[0]?.index ?? detail.length).trim() },
|
|
87
|
+
...labels.map((label, index) => ({ field: label[1].toLowerCase() === 'rationale' ? 'rationale' : 'consequence',
|
|
88
|
+
text: detail.slice(label.index + label[0].length, labels[index + 1]?.index ?? detail.length).trim() }))];
|
|
89
|
+
}
|
|
90
|
+
|
|
48
91
|
function architectureDecisionIds(markdown) {
|
|
49
92
|
const body = section(markdown, "Architecture Decisions");
|
|
50
93
|
const openItems = [];
|
|
@@ -54,7 +97,7 @@ function architectureDecisionIds(markdown) {
|
|
|
54
97
|
for (const line of body.split("\n").map((item) => item.trim()).filter((item) => /^[-*]\s+/u.test(item))) {
|
|
55
98
|
const decision = line.replace(/^[-*]\s+/u, "").trim();
|
|
56
99
|
if (/^none\b/iu.test(decision)) {
|
|
57
|
-
if (!reasonedNone(decision) ||
|
|
100
|
+
if (!reasonedNone(decision) || unfinishedDecisionPrompts(decision).length) {
|
|
58
101
|
openItems.push("State why no binding SD decision is needed after 'none'");
|
|
59
102
|
}
|
|
60
103
|
if (none || ids.length) openItems.push("SD cannot combine 'none' with binding design decisions");
|
|
@@ -70,12 +113,18 @@ function architectureDecisionIds(markdown) {
|
|
|
70
113
|
if (none) openItems.push("SD cannot combine 'none' with binding design decisions");
|
|
71
114
|
if (ids.includes(id)) openItems.push(`Duplicate SD design decision ID: ${id}`);
|
|
72
115
|
ids.push(id);
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
116
|
+
const clauses = decisionClauses(match[2]);
|
|
117
|
+
for (const field of ['decision', 'rationale', 'consequence']) {
|
|
118
|
+
const declarations = clauses.filter(clause => clause.field === field);
|
|
119
|
+
if (declarations.length > 1)
|
|
120
|
+
openItems.push(`SD design decision ${id} needs exactly one nonempty ${field}: field; found ${declarations.length} declarations`);
|
|
121
|
+
else if (!declarations.length || !declarations[0].text)
|
|
122
|
+
openItems.push(field === 'decision' ? `SD design decision ${id} needs a concrete decision statement`
|
|
123
|
+
: `SD design decision ${id} is missing a nonempty ${field}: field`);
|
|
124
|
+
}
|
|
125
|
+
for (const clause of clauses) {
|
|
126
|
+
const prompts = unfinishedDecisionPrompts(clause.text, { schemaExamples: clause.field === 'decision' });
|
|
127
|
+
if (prompts.length) openItems.push(`SD design decision ${id} contains unresolved author prompts in ${clause.field}: ${prompts.slice(0, 8).map(token => JSON.stringify(token)).join(', ')}${prompts.length > 8 ? ` (${prompts.length - 8} more)` : ''}`);
|
|
79
128
|
}
|
|
80
129
|
}
|
|
81
130
|
if (!ids.length && !none) openItems.push("List binding SD decisions by SDD ID, or record a reasoned none");
|
|
@@ -192,7 +241,7 @@ export function evaluateTpTraceability(targetDir, runState) {
|
|
|
192
241
|
for (const column of ["expected_result", "evidence"]) if (unfinished(row[column])) openItems.push(`TP scenario ${scenario || "without id"} needs ${column}`);
|
|
193
242
|
const expectedDecisions = decisionsByCriterion.get(criterion) ?? [];
|
|
194
243
|
if (expectedDecisions.length) {
|
|
195
|
-
if (!expectedDecisions.includes(decision)) openItems.push(`TP scenario ${scenario || "without id"}
|
|
244
|
+
if (!expectedDecisions.includes(decision)) openItems.push(`TP scenario ${scenario || "without id"} for ${criterion} has design_decision_id ${decision || "empty"}; set that table column to one of the mapped SD IDs: ${expectedDecisions.join(", ")}. Scenario prose cannot replace this cell.`);
|
|
196
245
|
else {
|
|
197
246
|
if (!verifiedDecisions.has(criterion)) verifiedDecisions.set(criterion, new Set());
|
|
198
247
|
verifiedDecisions.get(criterion).add(decision);
|