@openwop/openwop-conformance 1.162.0 → 2.0.0-rc.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/README.md +11 -2
- package/dist/cli.js +54 -1
- package/dist/lib/paths.js +25 -3
- package/dist/lib/requirement-ids.js +34 -4
- package/dist/lib/scenario-disposition.js +1 -0
- package/dist/lib/spec-coherence.js +13 -32
- package/dist/spec-artifacts.lock.json +5 -0
- package/package.json +11 -33
- package/requirements.json +20303 -11809
- package/scenario-majors.json +1343 -0
- package/schemas/CORPUS-STAMP.json +138 -6
- package/src/cli.ts +47 -1
- package/src/global-setup.ts +3 -2
- package/src/lib/corpus-stamp.ts +29 -1
- package/src/lib/paths.ts +25 -3
- package/src/lib/requirement-ids.ts +33 -4
- package/src/lib/scenario-disposition.ts +1 -0
- package/src/lib/spec-coherence.ts +15 -32
- package/src/scenarios/a2a-1-0-agent-card.test.ts +17 -16
- package/src/scenarios/a2a-1-0-task-roundtrip.test.ts +11 -10
- package/src/scenarios/a2a-card-runtime-consistency.test.ts +18 -17
- package/src/scenarios/a2a-peer-authority.test.ts +7 -6
- package/src/scenarios/a2a-task-roundtrip.test.ts +30 -29
- package/src/scenarios/a2a-version-negotiation.test.ts +16 -14
- package/src/scenarios/a2ui-surface-degrades.test.ts +5 -3
- package/src/scenarios/a2ui-surface-delta-transport.test.ts +35 -33
- package/src/scenarios/a2ui-surface-replay.test.ts +6 -4
- package/src/scenarios/a2ui-surface-shape.test.ts +11 -10
- package/src/scenarios/a2ui-surface-version-refusal.test.ts +6 -4
- package/src/scenarios/a2ui-untrusted-blocks-approval.test.ts +5 -3
- package/src/scenarios/agent-capability-degraded-projection.test.ts +12 -11
- package/src/scenarios/agent-channel-dispatch.test.ts +18 -16
- package/src/scenarios/agent-deployment-lifecycle.test.ts +20 -19
- package/src/scenarios/agent-deployment-shape.test.ts +22 -24
- package/src/scenarios/agent-eval-run.test.ts +19 -18
- package/src/scenarios/agent-eval-suite-shape.test.ts +20 -22
- package/src/scenarios/agent-live-allowlist-enforced.test.ts +6 -5
- package/src/scenarios/agent-live-invocation-bracket.test.ts +13 -12
- package/src/scenarios/agent-live-runtime-shape.test.ts +10 -12
- package/src/scenarios/agent-live-structured-output.test.ts +7 -6
- package/src/scenarios/agent-loop-iteration-monotonic.test.ts +3 -3
- package/src/scenarios/agent-loop-stateful-resume.test.ts +2 -2
- package/src/scenarios/agent-loop-version5-shape.test.ts +4 -4
- package/src/scenarios/agent-loop-workspace-snapshot.test.ts +3 -3
- package/src/scenarios/agent-manifest-role-profile.test.ts +9 -9
- package/src/scenarios/agent-manifest-runtime.test.ts +13 -12
- package/src/scenarios/agent-org-chart-scoping.test.ts +14 -13
- package/src/scenarios/agent-org-chart-shape.test.ts +11 -13
- package/src/scenarios/agent-platform-aggregate-evidence.test.ts +5 -4
- package/src/scenarios/agent-platform-profile.test.ts +18 -19
- package/src/scenarios/agent-requires-capabilities-shape.test.ts +4 -4
- package/src/scenarios/agent-roster-attribution.test.ts +18 -17
- package/src/scenarios/agent-roster-shape.test.ts +17 -19
- package/src/scenarios/agent-verifier-shape.test.ts +11 -11
- package/src/scenarios/agentConfidenceEscalation.test.ts +2 -1
- package/src/scenarios/agentMemoryCrossTenantIsolation.test.ts +6 -5
- package/src/scenarios/agentMemoryRedactionContract.test.ts +2 -1
- package/src/scenarios/agentMemoryRoundTrip.test.ts +2 -1
- package/src/scenarios/agentMemoryTtlExpiry.test.ts +4 -3
- package/src/scenarios/agentMessageReducer.test.ts +2 -1
- package/src/scenarios/agentMetadata.test.ts +2 -1
- package/src/scenarios/agentPackCatalog.test.ts +23 -21
- package/src/scenarios/agentPackExport.test.ts +4 -2
- package/src/scenarios/agentPackHandoffSchemaValidation.test.ts +5 -4
- package/src/scenarios/agentPackInstall.test.ts +4 -2
- package/src/scenarios/agentPackProvenance.test.ts +2 -1
- package/src/scenarios/agentReasoningEvents.test.ts +3 -2
- package/src/scenarios/agentReasoningStreaming.test.ts +11 -10
- package/src/scenarios/agents-run-tool-allowlist.test.ts +14 -12
- package/src/scenarios/ai-envelope-shape.test.ts +31 -29
- package/src/scenarios/aiEnvelope.capBreached.test.ts +26 -24
- package/src/scenarios/aiEnvelope.contractRefusal.test.ts +36 -34
- package/src/scenarios/aiEnvelope.correlationReplay.test.ts +17 -15
- package/src/scenarios/aiEnvelope.redaction.test.ts +22 -20
- package/src/scenarios/aiEnvelope.schemaDrift.test.ts +18 -16
- package/src/scenarios/aiEnvelope.trustBoundaryPropagation.test.ts +38 -36
- package/src/scenarios/aiEnvelope.universalKinds.test.ts +31 -29
- package/src/scenarios/aiproviders-input-shape.test.ts +5 -5
- package/src/scenarios/aiproviders-realtimevoice-shape.test.ts +14 -16
- package/src/scenarios/aiproviders-selfhosted-honesty.test.ts +6 -4
- package/src/scenarios/aiproviders-selfhosted-shape.test.ts +15 -17
- package/src/scenarios/aiproviders-speechsynth-shape.test.ts +6 -8
- package/src/scenarios/aiproviders-subscription-scope.test.ts +7 -8
- package/src/scenarios/anonymous-actor-audit-opaque.test.ts +9 -8
- package/src/scenarios/anonymous-actor-default-deny.test.ts +10 -9
- package/src/scenarios/anonymous-actor-egress-guarded.test.ts +6 -5
- package/src/scenarios/anonymous-actor-no-secret-reach.test.ts +7 -6
- package/src/scenarios/anonymous-actor-shape.test.ts +17 -19
- package/src/scenarios/anonymous-actor-write-gated.test.ts +9 -8
- package/src/scenarios/append-ordering.test.ts +7 -5
- package/src/scenarios/approval-gate-events.test.ts +4 -3
- package/src/scenarios/approval-gate-flow.test.ts +4 -3
- package/src/scenarios/approval-payload.test.ts +5 -4
- package/src/scenarios/artifact-auth.test.ts +7 -6
- package/src/scenarios/artifact-type-pack-install.test.ts +6 -6
- package/src/scenarios/artifact-type-pack-manifest-validation.test.ts +9 -8
- package/src/scenarios/artifact-type-registration-source.test.ts +20 -20
- package/src/scenarios/artifact-type-store-emission.test.ts +15 -18
- package/src/scenarios/artifact-type-store-without-render.test.ts +4 -4
- package/src/scenarios/audit-log-integrity.test.ts +8 -6
- package/src/scenarios/auth-api-key-rotation.test.ts +11 -9
- package/src/scenarios/auth-mtls.test.ts +22 -20
- package/src/scenarios/auth-oauth2-client-credentials.test.ts +16 -14
- package/src/scenarios/auth-oidc-user-bearer.test.ts +26 -24
- package/src/scenarios/auth-saml-profile.test.ts +14 -12
- package/src/scenarios/auth-scim-profile.test.ts +3 -2
- package/src/scenarios/auth-subject-link-key-class.test.ts +8 -7
- package/src/scenarios/auth-subject-link.test.ts +11 -10
- package/src/scenarios/auth.test.ts +5 -4
- package/src/scenarios/authorization-fail-closed.test.ts +3 -2
- package/src/scenarios/authorization-roles-shape.test.ts +9 -7
- package/src/scenarios/blob-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/blob-presign-expiry.test.ts +12 -10
- package/src/scenarios/blob-roundtrip.test.ts +0 -0
- package/src/scenarios/budget-enforcement.test.ts +15 -14
- package/src/scenarios/budget-policy-shape.test.ts +18 -19
- package/src/scenarios/bulk-cancel.test.ts +9 -8
- package/src/scenarios/byok-auth-modes.test.ts +13 -14
- package/src/scenarios/byok-roundtrip.test.ts +12 -10
- package/src/scenarios/cache-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/cache-ttl-expiry.test.ts +7 -5
- package/src/scenarios/callai-multimodal.test.ts +5 -3
- package/src/scenarios/cancellation.test.ts +6 -5
- package/src/scenarios/cap-breach.test.ts +15 -14
- package/src/scenarios/capability-arm-witness.test.ts +5 -3
- package/src/scenarios/certification-bundle-non-vacuous.test.ts +20 -19
- package/src/scenarios/certification-bundle-redaction.test.ts +11 -10
- package/src/scenarios/certification-bundle-v2.test.ts +11 -10
- package/src/scenarios/chain-compensation-expansion.test.ts +14 -13
- package/src/scenarios/chain-produced-var-roundtrip.test.ts +13 -14
- package/src/scenarios/chain-subchain-cycle-rejected.test.ts +9 -10
- package/src/scenarios/chain-subchain-fanout.test.ts +8 -9
- package/src/scenarios/chain-subchain-sibling.test.ts +14 -16
- package/src/scenarios/channel-presence-behavioral.test.ts +9 -7
- package/src/scenarios/channel-presence-shape.test.ts +11 -12
- package/src/scenarios/channel-ttl.test.ts +6 -5
- package/src/scenarios/chat-card-pack-execution.test.ts +4 -4
- package/src/scenarios/chat-card-pack-manifest-validation.test.ts +9 -8
- package/src/scenarios/commitment-fired.test.ts +6 -5
- package/src/scenarios/compensation-behavior.test.ts +24 -23
- package/src/scenarios/compensation-recovery.test.ts +28 -27
- package/src/scenarios/configurable-schema.test.ts +8 -6
- package/src/scenarios/conformance-advertised-seam-required.test.ts +6 -5
- package/src/scenarios/conformance-execution-witness.test.ts +9 -8
- package/src/scenarios/connection-pack-apihosts.test.ts +19 -17
- package/src/scenarios/connection-pack-manifest-valid.test.ts +12 -11
- package/src/scenarios/connection-pack-no-credential-material.test.ts +8 -6
- package/src/scenarios/connection-pack-reach-exclusive.test.ts +5 -4
- package/src/scenarios/connection-pack-write-reconsent.test.ts +6 -4
- package/src/scenarios/connection-provider-resolution.test.ts +18 -16
- package/src/scenarios/connector-manifest-validity.test.ts +8 -7
- package/src/scenarios/context-budget-transcript-bound.test.ts +17 -15
- package/src/scenarios/context-summarization-replay.test.ts +14 -12
- package/src/scenarios/contract-provenance.test.ts +18 -18
- package/src/scenarios/conversation-turn-model-provenance-shape.test.ts +14 -15
- package/src/scenarios/conversationCapabilityNegotiation.test.ts +2 -1
- package/src/scenarios/conversationLifecycle.test.ts +2 -1
- package/src/scenarios/conversationReplayDeterminism.test.ts +4 -2
- package/src/scenarios/conversationVsLegacySuspend.test.ts +2 -1
- package/src/scenarios/core-standard-profile.test.ts +8 -9
- package/src/scenarios/cost-attribution.test.ts +23 -21
- package/src/scenarios/credential-payload-redaction.test.ts +4 -3
- package/src/scenarios/credentials-capability-shape.test.ts +5 -4
- package/src/scenarios/cross-engine-append-behavior.test.ts +11 -10
- package/src/scenarios/cross-engine-append-ordering.test.ts +4 -3
- package/src/scenarios/cross-host-ancestry-endpoint.test.ts +11 -10
- package/src/scenarios/cross-host-causation-shape.test.ts +7 -6
- package/src/scenarios/cross-workspace-isolation.test.ts +4 -3
- package/src/scenarios/data-residency-admission.test.ts +15 -14
- package/src/scenarios/deadletter-capability-shape.test.ts +6 -4
- package/src/scenarios/deadletter-retry-exhaustion.test.ts +4 -3
- package/src/scenarios/debug-bundle-truncation.test.ts +9 -7
- package/src/scenarios/debugBundle.test.ts +25 -23
- package/src/scenarios/discovery-families-view.test.ts +5 -4
- package/src/scenarios/discovery.test.ts +30 -29
- package/src/scenarios/dispatch-cross-worker-handoff.test.ts +10 -8
- package/src/scenarios/dispatch-fanout-parallel.test.ts +24 -22
- package/src/scenarios/dispatch-input-mapping.test.ts +12 -10
- package/src/scenarios/dispatch-output-mapping.test.ts +9 -7
- package/src/scenarios/dispatch-per-item-input.test.ts +22 -20
- package/src/scenarios/dispatchLoop.test.ts +3 -2
- package/src/scenarios/distillation-index-roundtrip.test.ts +3 -3
- package/src/scenarios/distillation-secret-carryforward.test.ts +2 -2
- package/src/scenarios/distillation-shape.test.ts +4 -4
- package/src/scenarios/distillation-stable-archive.test.ts +6 -6
- package/src/scenarios/distillation-token-budget.test.ts +5 -5
- package/src/scenarios/durability-poison-exhaustion.test.ts +7 -6
- package/src/scenarios/egress-audience-binding.test.ts +11 -10
- package/src/scenarios/egress-decision-content-free.test.ts +6 -5
- package/src/scenarios/egress-provenance-shape.test.ts +17 -18
- package/src/scenarios/envelope-completion-distinguishes-truncation.test.ts +27 -25
- package/src/scenarios/envelope-nl-to-format-engaged.test.ts +19 -17
- package/src/scenarios/envelope-reasoning-secret-redaction.test.ts +28 -26
- package/src/scenarios/envelope-reasoning-shape.test.ts +19 -17
- package/src/scenarios/envelope-recovery-applied.test.ts +24 -22
- package/src/scenarios/envelope-refusal-shape.test.ts +31 -29
- package/src/scenarios/envelope-rendering-hint.test.ts +5 -4
- package/src/scenarios/envelope-retry-attempted.test.ts +33 -31
- package/src/scenarios/envelope-retry-exhausted.test.ts +22 -20
- package/src/scenarios/envelope-tier-one-subset-static.test.ts +9 -7
- package/src/scenarios/envelope-truncated.test.ts +19 -17
- package/src/scenarios/envelope-truncation-cap-exhaustion.test.ts +19 -17
- package/src/scenarios/envelope-variant-discriminator-static.test.ts +4 -3
- package/src/scenarios/errors.test.ts +20 -19
- package/src/scenarios/eventOrdering.test.ts +16 -14
- package/src/scenarios/exec-not-protocol-tier.test.ts +5 -7
- package/src/scenarios/experimental-tier-shape.test.ts +17 -15
- package/src/scenarios/export-bundle-portability.test.ts +17 -17
- package/src/scenarios/failure-path.test.ts +7 -6
- package/src/scenarios/feedback-capability-shape.test.ts +4 -3
- package/src/scenarios/feedback-correction-redaction.test.ts +2 -1
- package/src/scenarios/feedback-cross-tenant-isolation.test.ts +2 -1
- package/src/scenarios/feedback-fork-not-copied.test.ts +3 -2
- package/src/scenarios/feedback-on-terminal-run.test.ts +3 -2
- package/src/scenarios/feedback-record-and-list.test.ts +2 -1
- package/src/scenarios/feedback-unsupported-501.test.ts +2 -1
- package/src/scenarios/fixtures-gating.test.ts +29 -28
- package/src/scenarios/fixtures-valid.test.ts +16 -15
- package/src/scenarios/form-content-instantiation.test.ts +15 -14
- package/src/scenarios/frontend-plugin-packs.test.ts +29 -27
- package/src/scenarios/fs-path-traversal.test.ts +14 -12
- package/src/scenarios/goal-standing-continuation.test.ts +21 -21
- package/src/scenarios/grpc-transport.test.ts +9 -7
- package/src/scenarios/heartbeat-capability-shape.test.ts +3 -3
- package/src/scenarios/heartbeat-fires-once-per-tick.test.ts +2 -2
- package/src/scenarios/heartbeat-idempotent-no-spam.test.ts +3 -3
- package/src/scenarios/heartbeat-runtime-bound.test.ts +2 -2
- package/src/scenarios/highConcurrency.test.ts +14 -13
- package/src/scenarios/host-callback-declaration.test.ts +8 -7
- package/src/scenarios/http-client-ssrf.test.ts +7 -5
- package/src/scenarios/i18n-negotiation.test.ts +14 -12
- package/src/scenarios/idempotency-concurrent-claim.test.ts +14 -13
- package/src/scenarios/idempotency-key-determinism.test.ts +20 -18
- package/src/scenarios/idempotency.test.ts +8 -7
- package/src/scenarios/idempotencyRetry.test.ts +13 -11
- package/src/scenarios/identity-owner-shape.test.ts +6 -5
- package/src/scenarios/identity-passthrough.test.ts +4 -3
- package/src/scenarios/interrupt-approval.test.ts +6 -5
- package/src/scenarios/interrupt-approver-routing.test.ts +15 -15
- package/src/scenarios/interrupt-auth-required-resume.test.ts +5 -3
- package/src/scenarios/interrupt-clarification.test.ts +4 -3
- package/src/scenarios/interrupt-external-event-correlation.test.ts +6 -5
- package/src/scenarios/interrupt-parent-child-cascade.test.ts +4 -3
- package/src/scenarios/interrupt-quorum-resolution.test.ts +5 -4
- package/src/scenarios/interrupt-token-matrix.test.ts +8 -6
- package/src/scenarios/interruptRace.test.ts +12 -10
- package/src/scenarios/kv-atomic-increment.test.ts +11 -9
- package/src/scenarios/kv-cas.test.ts +14 -12
- package/src/scenarios/kv-cross-tenant-isolation.test.ts +12 -10
- package/src/scenarios/kv-ttl-expiry.test.ts +7 -5
- package/src/scenarios/localized-content-delivery.test.ts +24 -26
- package/src/scenarios/maliciousManifest.test.ts +10 -8
- package/src/scenarios/mcp-2026-07-28-discover.test.ts +15 -14
- package/src/scenarios/mcp-cache-tenant-scope.test.ts +6 -5
- package/src/scenarios/mcp-current-auth-boundary.test.ts +7 -6
- package/src/scenarios/mcp-discoverability.test.ts +9 -7
- package/src/scenarios/mcp-extension-opacity.test.ts +7 -6
- package/src/scenarios/mcp-mrtr-roundtrip.test.ts +18 -17
- package/src/scenarios/mcp-server-elicitation-bridge.test.ts +13 -12
- package/src/scenarios/mcp-server-prompt-roundtrip.test.ts +11 -10
- package/src/scenarios/mcp-server-resource-roundtrip.test.ts +11 -10
- package/src/scenarios/mcp-server-sampling-bridge.test.ts +12 -11
- package/src/scenarios/mcp-server-tool-roundtrip.test.ts +14 -13
- package/src/scenarios/mcp-server-untrusted-args.test.ts +14 -13
- package/src/scenarios/mcp-stateless-request.test.ts +11 -10
- package/src/scenarios/mcp-tool-roundtrip.test.ts +4 -3
- package/src/scenarios/mcp-toolcall-redaction.test.ts +4 -3
- package/src/scenarios/mcp-version-negotiation.test.ts +15 -14
- package/src/scenarios/media-url-inline-cap.test.ts +21 -19
- package/src/scenarios/memory-attribution-emits-on-write.test.ts +5 -5
- package/src/scenarios/memory-attribution-no-content.test.ts +4 -4
- package/src/scenarios/memory-attribution-replay-stable.test.ts +4 -3
- package/src/scenarios/memory-attribution-shape.test.ts +4 -3
- package/src/scenarios/memory-attribution-tenant-scoped.test.ts +3 -3
- package/src/scenarios/memory-capability-model-shape.test.ts +14 -15
- package/src/scenarios/memory-compaction-event-emitted.test.ts +7 -6
- package/src/scenarios/memory-compaction-provenance-tag.test.ts +3 -2
- package/src/scenarios/memory-compaction-sr1-carry-forward.test.ts +7 -6
- package/src/scenarios/memory-consolidation-idempotent.test.ts +5 -4
- package/src/scenarios/memory-consolidation-shape.test.ts +9 -11
- package/src/scenarios/memory-degraded-projection.test.ts +10 -9
- package/src/scenarios/memory-injection-budget.test.ts +15 -14
- package/src/scenarios/metric-emission.test.ts +4 -3
- package/src/scenarios/model-capability-insufficient.test.ts +19 -17
- package/src/scenarios/model-capability-substituted.test.ts +20 -18
- package/src/scenarios/multi-agent-confidence-escalation.test.ts +12 -11
- package/src/scenarios/multi-agent-handoff-state-machine.test.ts +10 -9
- package/src/scenarios/multi-agent-memory-lifecycle.test.ts +11 -10
- package/src/scenarios/multi-node-ordering.test.ts +4 -3
- package/src/scenarios/multi-party-conversation-behavioral.test.ts +6 -6
- package/src/scenarios/multi-party-conversation-shape.test.ts +21 -23
- package/src/scenarios/multi-region-idempotency-behavior.test.ts +16 -15
- package/src/scenarios/multi-region-idempotency.test.ts +6 -5
- package/src/scenarios/node-failed-payload-shape.test.ts +5 -4
- package/src/scenarios/node-module-required-capabilities-shape.test.ts +10 -8
- package/src/scenarios/oauth-authorization-code-roundtrip.test.ts +5 -4
- package/src/scenarios/oauth-capability-shape.test.ts +5 -4
- package/src/scenarios/oauth-connector-redaction.test.ts +4 -3
- package/src/scenarios/openapi-resolved-paths.test.ts +6 -5
- package/src/scenarios/orchestratorConservativePath.test.ts +2 -1
- package/src/scenarios/orchestratorDispatch.test.ts +2 -1
- package/src/scenarios/orchestratorTermination.test.ts +2 -1
- package/src/scenarios/org-position-no-authority-escalation.test.ts +2 -2
- package/src/scenarios/otel-collector-canary-inspection.test.ts +8 -7
- package/src/scenarios/otel-emission-grpc.test.ts +3 -2
- package/src/scenarios/otel-emission.test.ts +6 -5
- package/src/scenarios/otel-trace-propagation-subworkflow.test.ts +7 -6
- package/src/scenarios/otel-trace-propagation.test.ts +2 -1
- package/src/scenarios/owner-subject-echo.test.ts +13 -12
- package/src/scenarios/owner-subject-shape.test.ts +11 -10
- package/src/scenarios/pack-manifest-extension-opacity.test.ts +8 -8
- package/src/scenarios/pack-registry-isolation.test.ts +4 -3
- package/src/scenarios/pack-registry-publish.test.ts +65 -63
- package/src/scenarios/pack-registry.test.ts +38 -36
- package/src/scenarios/pause-resume.test.ts +18 -16
- package/src/scenarios/policies.test.ts +20 -18
- package/src/scenarios/production-backpressure.test.ts +18 -16
- package/src/scenarios/production-retention-expiry.test.ts +8 -6
- package/src/scenarios/profile-discovery-core-alias.test.ts +13 -11
- package/src/scenarios/profileDerivation.test.ts +34 -33
- package/src/scenarios/prompt-all-four-kinds-events.test.ts +11 -9
- package/src/scenarios/prompt-composed-secret-redaction.test.ts +11 -9
- package/src/scenarios/prompt-composed-trust-marker.test.ts +10 -8
- package/src/scenarios/prompt-end-to-end-events.test.ts +17 -15
- package/src/scenarios/prompt-list-and-fetch.test.ts +16 -14
- package/src/scenarios/prompt-mutable-lifecycle.test.ts +13 -11
- package/src/scenarios/prompt-mutation-workspace-membership-enforced.test.ts +6 -4
- package/src/scenarios/prompt-pack-install.test.ts +14 -12
- package/src/scenarios/prompt-prefix-cache.test.ts +19 -17
- package/src/scenarios/prompt-read-workspace-membership-enforced.test.ts +11 -9
- package/src/scenarios/prompt-render-deterministic.test.ts +19 -17
- package/src/scenarios/prompt-resolution-chain-agent-intrinsic.test.ts +7 -5
- package/src/scenarios/prompt-resolution-chain-event.test.ts +12 -10
- package/src/scenarios/prompt-resolution-chain-fallback-cascade.test.ts +10 -8
- package/src/scenarios/prompt-resolution-chain-node-wins.test.ts +8 -6
- package/src/scenarios/prompt-template-shape.test.ts +30 -28
- package/src/scenarios/proposal-reviewable-learning.test.ts +19 -19
- package/src/scenarios/protocol-versions-array.test.ts +10 -9
- package/src/scenarios/provider-usage.test.ts +17 -15
- package/src/scenarios/providerPolicyEnforcement.test.ts +16 -14
- package/src/scenarios/purpose-propagation.test.ts +23 -21
- package/src/scenarios/queue-ack-nack-dlq.test.ts +12 -10
- package/src/scenarios/queue-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/queue-publish-consume-roundtrip.test.ts +10 -8
- package/src/scenarios/rate-limit-envelope.test.ts +6 -5
- package/src/scenarios/redaction.test.ts +13 -11
- package/src/scenarios/redactionAdversarial.test.ts +11 -9
- package/src/scenarios/registry-public.test.ts +12 -11
- package/src/scenarios/replay-divergence-at-refusal.test.ts +16 -15
- package/src/scenarios/replay-fanout-suppression.test.ts +16 -15
- package/src/scenarios/replay-fork-arbitrary.test.ts +24 -23
- package/src/scenarios/replay-fork.test.ts +20 -19
- package/src/scenarios/replay-llm-cache-key-portable.test.ts +11 -9
- package/src/scenarios/replay-llm-cache-key.test.ts +22 -21
- package/src/scenarios/replay-observable-sequence-determinism.test.ts +4 -3
- package/src/scenarios/replay-retention-expiry.test.ts +11 -9
- package/src/scenarios/replay-side-effect-suppression.test.ts +21 -19
- package/src/scenarios/replayDeterminism.test.ts +13 -12
- package/src/scenarios/requirement-ledger.test.ts +15 -14
- package/src/scenarios/restart-during-run.test.ts +3 -2
- package/src/scenarios/route-coverage.test.ts +20 -19
- package/src/scenarios/run-diff.test.ts +22 -20
- package/src/scenarios/run-execution-bounds-shape.test.ts +14 -12
- package/src/scenarios/run-transport-economy.test.ts +13 -11
- package/src/scenarios/runner-ledger.test.ts +17 -16
- package/src/scenarios/runs-lifecycle.test.ts +7 -6
- package/src/scenarios/runtime-capabilities.test.ts +12 -10
- package/src/scenarios/runtime-requires-install-gate.test.ts +8 -8
- package/src/scenarios/runtime-requires-shape.test.ts +7 -6
- package/src/scenarios/safefetch-behavior.test.ts +22 -21
- package/src/scenarios/safefetch-live-audit.test.ts +14 -13
- package/src/scenarios/sandbox-memory-cap.test.ts +2 -1
- package/src/scenarios/sandbox-mvp-behavior.test.ts +24 -23
- package/src/scenarios/sandbox-no-host-fs-escape.test.ts +3 -2
- package/src/scenarios/sandbox-timeout-cap.test.ts +2 -1
- package/src/scenarios/sandbox-wasm-isolation.test.ts +14 -15
- package/src/scenarios/sandbox-wasm-timeout.test.ts +5 -6
- package/src/scenarios/scheduling-capability-shape.test.ts +8 -6
- package/src/scenarios/scheduling-cron-fires-once.test.ts +8 -6
- package/src/scenarios/search-bm25-roundtrip.test.ts +8 -6
- package/src/scenarios/secret-leakage-otel-attribute.test.ts +22 -20
- package/src/scenarios/self-hosted-runner.test.ts +26 -24
- package/src/scenarios/semantic-digest-vectors.test.ts +8 -7
- package/src/scenarios/speech-synthesis-roundtrip.test.ts +9 -7
- package/src/scenarios/speech-synthesis-unadvertised.test.ts +5 -3
- package/src/scenarios/sql-injection-rejection.test.ts +8 -6
- package/src/scenarios/sql-transaction-atomicity.test.ts +10 -8
- package/src/scenarios/staleClaim.test.ts +5 -4
- package/src/scenarios/stream-modes-buffer.test.ts +8 -7
- package/src/scenarios/stream-modes-mixed.test.ts +10 -9
- package/src/scenarios/stream-modes.test.ts +12 -11
- package/src/scenarios/stream-subscribe-from-beginning.test.ts +11 -9
- package/src/scenarios/stream-text-fixture.test.ts +14 -13
- package/src/scenarios/streamReconnect.test.ts +13 -11
- package/src/scenarios/strict-behavior-gate.test.ts +9 -8
- package/src/scenarios/subrun-approval-fail-closed.test.ts +2 -2
- package/src/scenarios/subrun-approval-gate.test.ts +3 -3
- package/src/scenarios/subrun-attestation-shape.test.ts +2 -2
- package/src/scenarios/subrun-checksum-stable.test.ts +4 -4
- package/src/scenarios/subworkflow-input-mapping.test.ts +16 -14
- package/src/scenarios/subworkflow.test.ts +10 -9
- package/src/scenarios/table-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/table-cursor-pagination.test.ts +8 -6
- package/src/scenarios/table-schema-enforcement.test.ts +7 -5
- package/src/scenarios/test-seam-unauthenticated.test.ts +2 -2
- package/src/scenarios/tool-catalog-compact-projection.test.ts +10 -8
- package/src/scenarios/tool-catalog-projection.test.ts +11 -9
- package/src/scenarios/tool-descriptor-shape.test.ts +14 -15
- package/src/scenarios/tool-hooks-authorization-fail-closed.test.ts +3 -3
- package/src/scenarios/tool-hooks-content-free.test.ts +4 -4
- package/src/scenarios/tool-hooks-failure-honesty.test.ts +4 -4
- package/src/scenarios/tool-hooks-rate-limit.test.ts +2 -2
- package/src/scenarios/tool-hooks-secret-redaction.test.ts +2 -2
- package/src/scenarios/tool-hooks-shape.test.ts +3 -3
- package/src/scenarios/tool-session-lifecycle.test.ts +14 -13
- package/src/scenarios/trigger-bridge-delivery.test.ts +14 -14
- package/src/scenarios/trigger-bridge-shape.test.ts +19 -20
- package/src/scenarios/trigger-ingestion.test.ts +19 -17
- package/src/scenarios/trigger-stream-cdc-sources.test.ts +16 -14
- package/src/scenarios/vector-knn-roundtrip.test.ts +9 -7
- package/src/scenarios/verifier-gating.test.ts +8 -6
- package/src/scenarios/version-fold.test.ts +9 -8
- package/src/scenarios/version-negotiation.test.ts +12 -11
- package/src/scenarios/voice-bargein-no-partial-leak.test.ts +8 -6
- package/src/scenarios/voice-event-payloads-shape.test.ts +10 -11
- package/src/scenarios/voice-interim-not-durable.test.ts +7 -5
- package/src/scenarios/voice-streamref-tenant-bound.test.ts +5 -3
- package/src/scenarios/voice-synthesis-streaming.test.ts +11 -9
- package/src/scenarios/voice-transcription-streaming.test.ts +8 -6
- package/src/scenarios/voice-transcription-unadvertised.test.ts +5 -3
- package/src/scenarios/wasm-pack-abi-version-rejection.test.ts +3 -2
- package/src/scenarios/wasm-pack-invoke-completed.test.ts +3 -2
- package/src/scenarios/wasm-pack-invoke-suspended.test.ts +3 -2
- package/src/scenarios/wasm-pack-load.test.ts +4 -3
- package/src/scenarios/wasm-pack-memory-cap.test.ts +5 -4
- package/src/scenarios/wasm-pack-replay-determinism.test.ts +2 -1
- package/src/scenarios/webhook-negative.test.ts +11 -9
- package/src/scenarios/webhook-receiver-adversarial.test.ts +8 -7
- package/src/scenarios/webhook-sig-algorithm.test.ts +5 -3
- package/src/scenarios/webhook-signed-delivery.test.ts +16 -15
- package/src/scenarios/webhook-tenant-isolation.test.ts +16 -14
- package/src/scenarios/workflow-chain-deferred-parameters.test.ts +28 -30
- package/src/scenarios/workflow-chain-expansion.test.ts +21 -20
- package/src/scenarios/workflow-chain-host-expansion.test.ts +21 -20
- package/src/scenarios/workflow-chain-pack-manifest-validation.test.ts +14 -12
- package/src/scenarios/workflow-chain-pack-signature-verification.test.ts +5 -4
- package/src/scenarios/workflow-chain-unresolvable-typeid.test.ts +9 -8
- package/src/scenarios/workflow-primary-output-annotation.test.ts +7 -6
- package/src/scenarios/workflow-variable-format.test.ts +24 -24
- package/src/scenarios/workload-identity-behavior.test.ts +15 -13
- package/src/scenarios/workload-identity-chain-bounds.test.ts +18 -17
- package/src/scenarios/workspace-behavior.test.ts +19 -18
- package/src/scenarios/workspace-capability-shape.test.ts +3 -2
- package/src/scenarios/workspace-cross-tenant-isolation-blackbox.test.ts +6 -5
- package/src/scenarios/workspace-cross-tenant-isolation.test.ts +7 -6
- package/src/scenarios/x-openwop-form-pack-manifest.test.ts +8 -7
- package/src/setup.ts +4 -2
- package/vitest.config.ts +5 -1
- package/api/.redocly.lint-ignore.yaml +0 -22
- package/api/asyncapi.yaml +0 -834
- package/api/grpc/openwop.proto +0 -251
- package/api/openapi.yaml +0 -2693
- package/api/redocly.yaml +0 -23
- package/schemas/README.md +0 -144
- package/schemas/a2a-task-state.schema.json +0 -78
- package/schemas/a2ui-surface-delta-frame.schema.json +0 -48
- package/schemas/agent-deployment-transition.schema.json +0 -49
- package/schemas/agent-deployment.schema.json +0 -54
- package/schemas/agent-eval-suite.schema.json +0 -140
- package/schemas/agent-inventory-response.schema.json +0 -115
- package/schemas/agent-manifest.schema.json +0 -156
- package/schemas/agent-org-chart.schema.json +0 -82
- package/schemas/agent-ref.schema.json +0 -63
- package/schemas/agent-roster-entry.schema.json +0 -81
- package/schemas/agent-roster-response.schema.json +0 -21
- package/schemas/ai-envelope.schema.json +0 -134
- package/schemas/annotation-create.schema.json +0 -37
- package/schemas/annotation.schema.json +0 -56
- package/schemas/artifact-type-pack-manifest.schema.json +0 -244
- package/schemas/audit-verify-result.schema.json +0 -90
- package/schemas/budget-policy.schema.json +0 -18
- package/schemas/capabilities.schema.json +0 -4124
- package/schemas/certification-bundle-v2.schema.json +0 -118
- package/schemas/channel-presence-payload.schema.json +0 -41
- package/schemas/channel-written-payload.schema.json +0 -55
- package/schemas/chat-card-pack-manifest.schema.json +0 -253
- package/schemas/compact-tool-descriptor.schema.json +0 -51
- package/schemas/compensation-policy.schema.json +0 -64
- package/schemas/conformance-certification-bundle.schema.json +0 -86
- package/schemas/connection-pack-manifest.schema.json +0 -353
- package/schemas/conversation-event.schema.json +0 -168
- package/schemas/conversation-turn.schema.json +0 -117
- package/schemas/core-conformance-mock-agent-config.schema.json +0 -152
- package/schemas/credential-provenance.schema.json +0 -18
- package/schemas/credential-reference.schema.json +0 -21
- package/schemas/debug-bundle.schema.json +0 -196
- package/schemas/dispatch-config.schema.json +0 -112
- package/schemas/envelopes/clarification.request.schema.json +0 -52
- package/schemas/envelopes/error.schema.json +0 -30
- package/schemas/envelopes/media.audio.schema.json +0 -38
- package/schemas/envelopes/media.file.schema.json +0 -37
- package/schemas/envelopes/media.image.schema.json +0 -33
- package/schemas/envelopes/schema.request.schema.json +0 -26
- package/schemas/envelopes/schema.response.schema.json +0 -22
- package/schemas/envelopes/ui.a2ui-surface.schema.json +0 -154
- package/schemas/error-envelope.schema.json +0 -25
- package/schemas/eval-summary.schema.json +0 -92
- package/schemas/export-bundle.schema.json +0 -66
- package/schemas/form-content-pack-manifest.schema.json +0 -243
- package/schemas/frontend-plugin-manifest.schema.json +0 -109
- package/schemas/goal.schema.json +0 -104
- package/schemas/heartbeat-evaluated.schema.json +0 -14
- package/schemas/heartbeat-state-changed.schema.json +0 -14
- package/schemas/localized-content-language-settings.schema.json +0 -26
- package/schemas/localized-content-page-response.schema.json +0 -60
- package/schemas/localized-content-page.schema.json +0 -62
- package/schemas/localized-content-section.schema.json +0 -51
- package/schemas/memory-entry.schema.json +0 -36
- package/schemas/memory-list-options.schema.json +0 -37
- package/schemas/node-pack-manifest.schema.json +0 -654
- package/schemas/orchestrator-decision.schema.json +0 -90
- package/schemas/org-chart-responsibility-view.schema.json +0 -26
- package/schemas/pack-lockfile.schema.json +0 -108
- package/schemas/prompt-kind.schema.json +0 -8
- package/schemas/prompt-pack-manifest.schema.json +0 -117
- package/schemas/prompt-ref.schema.json +0 -40
- package/schemas/prompt-template.schema.json +0 -149
- package/schemas/proposal.schema.json +0 -84
- package/schemas/registry-version-manifest.schema.json +0 -208
- package/schemas/residency.schema.json +0 -16
- package/schemas/run-ancestry-response.schema.json +0 -54
- package/schemas/run-diff-response.schema.json +0 -64
- package/schemas/run-event-payloads.schema.json +0 -4452
- package/schemas/run-event.schema.json +0 -211
- package/schemas/run-options.schema.json +0 -80
- package/schemas/run-orchestrator-decided-event.schema.json +0 -20
- package/schemas/run-snapshot.schema.json +0 -148
- package/schemas/security-advisory.schema.json +0 -109
- package/schemas/self-hosted-runner-dispatch-frame.schema.json +0 -79
- package/schemas/self-hosted-runner-registration.schema.json +0 -53
- package/schemas/self-hosted-runner-result-frame.schema.json +0 -38
- package/schemas/subject.schema.json +0 -56
- package/schemas/suspend-request.schema.json +0 -207
- package/schemas/tool-descriptor.schema.json +0 -63
- package/schemas/trigger-event.schema.json +0 -222
- package/schemas/trigger-subscription-registration.schema.json +0 -67
- package/schemas/trigger-subscription.schema.json +0 -26
- package/schemas/ui-plugin-message.schema.json +0 -90
- package/schemas/workflow-chain-pack-manifest.schema.json +0 -615
- package/schemas/workflow-definition.schema.json +0 -850
- package/schemas/workload-identity.schema.json +0 -79
- package/schemas/workspace-file-create.schema.json +0 -20
- package/schemas/workspace-file.schema.json +0 -39
|
@@ -64,10 +64,10 @@ async function emit(input: Record<string, unknown>): Promise<{ status: number; b
|
|
|
64
64
|
describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: seam emission (RFC 0032 §B.3 MUST)', () => {
|
|
65
65
|
it('accepts a well-formed `envelope.refusal` payload + writes it to the test event log', async () => {
|
|
66
66
|
const d = await readDiscovery();
|
|
67
|
-
if (d === null) return;
|
|
67
|
+
if (d === null) return softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
|
|
68
68
|
const reliability = capabilityFamily<{ reasoning?: Record<string, unknown>; tierOneSubsetCompliance?: unknown; reliability?: { completion?: Record<string, unknown> } & Record<string, unknown> }>(d, 'envelopes')?.reliability;
|
|
69
|
-
if (!reliability || reliability.supported !== true) return;
|
|
70
|
-
if (!Array.isArray(reliability.events) || !(reliability.events as unknown[]).includes('envelope.refusal')) return;
|
|
69
|
+
if (!reliability || reliability.supported !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!reliability || reliability.supported !== true` returned early');
|
|
70
|
+
if (!Array.isArray(reliability.events) || !(reliability.events as unknown[]).includes('envelope.refusal')) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!Array.isArray(reliability.events) || !(reliability.events as unknown[]).includes(\'envelope.refusal\')` returned early');
|
|
71
71
|
|
|
72
72
|
const r = await emit({
|
|
73
73
|
runId: 'conformance-refusal-1',
|
|
@@ -81,10 +81,10 @@ describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: seam emission (RFC 0032 §B.
|
|
|
81
81
|
},
|
|
82
82
|
nodeId: 'writer',
|
|
83
83
|
});
|
|
84
|
-
if (r.status === 404) return;
|
|
84
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
85
85
|
expect(
|
|
86
86
|
r.status,
|
|
87
|
-
|
|
87
|
+
req('openwop.it.envelope-refusal-shape.accepts-a-well-formed-envelope-refusal-payload-writes-it-to-the-test-event-log',
|
|
88
88
|
'schemas/run-event-payloads.schema.json §envelopeRefusal',
|
|
89
89
|
'a payload with the required {nodeId, provider, model} fields MUST be accepted by the seam',
|
|
90
90
|
),
|
|
@@ -108,10 +108,10 @@ describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: seam emission (RFC 0032 §B.
|
|
|
108
108
|
safetyCategory: 'harmful-content',
|
|
109
109
|
},
|
|
110
110
|
});
|
|
111
|
-
if (r.status === 404) return;
|
|
111
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
112
112
|
expect(
|
|
113
113
|
r.status,
|
|
114
|
-
|
|
114
|
+
req('openwop.it.envelope-refusal-shape.rejects-payloads-with-refusaltext-containing-a-secret-canary-substring-byok-leak',
|
|
115
115
|
'SECURITY/invariants.yaml §envelope-refusal-no-prompt-leak',
|
|
116
116
|
'envelope.refusal.refusalText MUST be passed through the host BYOK redaction harness; seam refuses payloads carrying secret-canary-* substrings (defense-in-depth CI gate per RFC 0032 §B.3 + §G)',
|
|
117
117
|
),
|
|
@@ -130,8 +130,8 @@ describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: seam emission (RFC 0032 §B.
|
|
|
130
130
|
credentialRef: 'secret-byok-abc123', // forbidden
|
|
131
131
|
},
|
|
132
132
|
});
|
|
133
|
-
if (r.status === 404) return;
|
|
134
|
-
expect(r.status).toBe(400);
|
|
133
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
134
|
+
expect(r.status, req('openwop.it.envelope-refusal-shape.rejects-payloads-with-a-top-level-credentialref-field', 'RFC 0032 §B.3', 'rejects payloads with a top-level `credentialRef` field')).toBe(400);
|
|
135
135
|
expect(readErrorCode(r.body)).toBe('envelope_reliability_credential_leak');
|
|
136
136
|
});
|
|
137
137
|
|
|
@@ -145,8 +145,8 @@ describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: seam emission (RFC 0032 §B.
|
|
|
145
145
|
model: 'claude-3-5-sonnet',
|
|
146
146
|
},
|
|
147
147
|
});
|
|
148
|
-
if (r.status === 404) return;
|
|
149
|
-
expect(r.status).toBe(400);
|
|
148
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
149
|
+
expect(r.status, req('openwop.it.envelope-refusal-shape.rejects-payloads-missing-required-provider-field', 'RFC 0032 §B.3', 'rejects payloads missing required `provider` field')).toBe(400);
|
|
150
150
|
expect(readErrorCode(r.body)).toBe('invalid_argument');
|
|
151
151
|
});
|
|
152
152
|
});
|
|
@@ -154,25 +154,25 @@ describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: seam emission (RFC 0032 §B.
|
|
|
154
154
|
describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: advertisement contract (RFC 0032 §C)', () => {
|
|
155
155
|
it('capabilities.envelopes.reliability (when supported: true with non-empty events[]) MUST list both MUST-tier events', async () => {
|
|
156
156
|
const d = await readDiscovery();
|
|
157
|
-
if (d === null) return;
|
|
157
|
+
if (d === null) return softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
|
|
158
158
|
const reliability = capabilityFamily<{ reasoning?: Record<string, unknown>; tierOneSubsetCompliance?: unknown; reliability?: { completion?: Record<string, unknown> } & Record<string, unknown> }>(d, 'envelopes')?.reliability;
|
|
159
|
-
if (!reliability || reliability.supported !== true) return;
|
|
159
|
+
if (!reliability || reliability.supported !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!reliability || reliability.supported !== true` returned early');
|
|
160
160
|
// Hosts running the legacy undifferentiated retry loop advertise
|
|
161
161
|
// `events: []` (per the OPENWOP_ENVELOPE_RELIABILITY_END_TO_END=false
|
|
162
162
|
// operator override). The two MUST-tier events still surface through
|
|
163
163
|
// the test seam in that case; the advertisement-shape MUST applies
|
|
164
164
|
// only when events[] is non-empty.
|
|
165
|
-
if (!Array.isArray(reliability.events) || (reliability.events as unknown[]).length === 0) return;
|
|
165
|
+
if (!Array.isArray(reliability.events) || (reliability.events as unknown[]).length === 0) return softSkip('blocked', 'precondition not met — `!Array.isArray(reliability.events) || (reliability.events as unknown[]).length === 0` returned early (Hosts running the legacy undifferentiated retry loop advertise `events: []` (per the OPENWO…');
|
|
166
166
|
expect(
|
|
167
167
|
(reliability.events as unknown[]).includes('envelope.refusal'),
|
|
168
|
-
|
|
168
|
+
req('openwop.it.envelope-refusal-shape.capabilities-envelopes-reliability-when-supported-true-with-non-empty-events-mus',
|
|
169
169
|
'RFCS/0032-envelope-reliability-events.md §C',
|
|
170
170
|
'hosts that advertise reliability.supported: true with non-empty events[] MUST include envelope.refusal (one of the two MUST-tier events per RFC 0032 §C normative text)',
|
|
171
171
|
),
|
|
172
172
|
).toBe(true);
|
|
173
173
|
expect(
|
|
174
174
|
(reliability.events as unknown[]).includes('envelope.retry.exhausted'),
|
|
175
|
-
|
|
175
|
+
req('openwop.it.envelope-refusal-shape.capabilities-envelopes-reliability-when-supported-true-with-non-empty-events-mus',
|
|
176
176
|
'RFCS/0032-envelope-reliability-events.md §C',
|
|
177
177
|
'hosts that advertise reliability.supported: true with non-empty events[] MUST also include envelope.retry.exhausted (the other MUST-tier event; both MUSTs land together)',
|
|
178
178
|
),
|
|
@@ -192,6 +192,8 @@ describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: advertisement contract (RFC
|
|
|
192
192
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
193
193
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
194
194
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
195
|
+
import { req } from '../lib/requirement-ids.js';
|
|
196
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
195
197
|
|
|
196
198
|
const E2E_FIXTURE = 'conformance-envelope-refusal';
|
|
197
199
|
const E2E_NODE_ID = 'structured-call';
|
|
@@ -224,17 +226,17 @@ async function runE2eAndRead(): Promise<{ events: E2eEvent[]; terminal: unknown
|
|
|
224
226
|
|
|
225
227
|
describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: end-to-end refusal through dispatchStructured', () => {
|
|
226
228
|
it('when mock provider returns stopReason: "safety" with refusalText, host emits exactly one envelope.refusal event AND does NOT retry', async () => {
|
|
227
|
-
if (!isFixtureAdvertised(E2E_FIXTURE)) return;
|
|
229
|
+
if (!isFixtureAdvertised(E2E_FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(E2E_FIXTURE)` returned early');
|
|
228
230
|
const seed = await programMockRefusal('I cannot help with that — safety filter triggered.');
|
|
229
|
-
if (seed.status === 404) return;
|
|
231
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
230
232
|
expect(seed.status).toBe(200);
|
|
231
233
|
|
|
232
234
|
const result = await runE2eAndRead();
|
|
233
|
-
if (result === null) return;
|
|
235
|
+
if (result === null) return softSkip('blocked', 'precondition not met — `result === null` returned early (seam, prior step, or fixture unavailable)');
|
|
234
236
|
const refusals = result.events.filter((e) => e.type === 'envelope.refusal');
|
|
235
237
|
expect(
|
|
236
238
|
refusals.length,
|
|
237
|
-
|
|
239
|
+
req('openwop.it.envelope-refusal-shape.when-mock-provider-returns-stopreason-safety-with-refusaltext-host-emits-exactly',
|
|
238
240
|
'RFCS/0032-envelope-reliability-events.md §B.3',
|
|
239
241
|
'exactly one envelope.refusal event MUST fire on provider safety-stop',
|
|
240
242
|
),
|
|
@@ -243,7 +245,7 @@ describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: end-to-end refusal through d
|
|
|
243
245
|
const retries = result.events.filter((e) => e.type === 'envelope.retry.attempted');
|
|
244
246
|
expect(
|
|
245
247
|
retries.length,
|
|
246
|
-
|
|
248
|
+
req('openwop.it.envelope-refusal-shape.when-mock-provider-returns-stopreason-safety-with-refusaltext-host-emits-exactly',
|
|
247
249
|
'RFCS/0033-envelope-completion-contract.md §D',
|
|
248
250
|
'host MUST NOT retry after envelope.refusal (refusal is terminal — retrying with prompt mutation creates a circumvention concern)',
|
|
249
251
|
),
|
|
@@ -251,16 +253,16 @@ describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: end-to-end refusal through d
|
|
|
251
253
|
});
|
|
252
254
|
|
|
253
255
|
it('node fails with RunSnapshot.error.code = "envelope_refusal" per RFC 0033 §F', async () => {
|
|
254
|
-
if (!isFixtureAdvertised(E2E_FIXTURE)) return;
|
|
256
|
+
if (!isFixtureAdvertised(E2E_FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(E2E_FIXTURE)` returned early');
|
|
255
257
|
const seed = await programMockRefusal('Refusal text for terminal-error-code assertion.');
|
|
256
|
-
if (seed.status === 404) return;
|
|
258
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
257
259
|
|
|
258
260
|
const result = await runE2eAndRead();
|
|
259
|
-
if (result === null) return;
|
|
261
|
+
if (result === null) return softSkip('blocked', 'precondition not met — `result === null` returned early (seam, prior step, or fixture unavailable)');
|
|
260
262
|
const code = (result.terminal as { error?: { code?: string } }).error?.code;
|
|
261
263
|
expect(
|
|
262
264
|
code,
|
|
263
|
-
|
|
265
|
+
req('openwop.it.envelope-refusal-shape.node-fails-with-runsnapshot-error-code-envelope-refusal-per-rfc-0033-f',
|
|
264
266
|
'RFCS/0033-envelope-completion-contract.md §F',
|
|
265
267
|
'refusal-driven failure MUST surface as RunSnapshot.error.code = envelope_refusal (renamed 2026-05-21 from envelope_refused_by_provider per the MyndHyve adoption-feedback amendment)',
|
|
266
268
|
),
|
|
@@ -268,21 +270,21 @@ describe.skipIf(HTTP_SKIP)('envelope-refusal-shape: end-to-end refusal through d
|
|
|
268
270
|
});
|
|
269
271
|
|
|
270
272
|
it('RunSnapshot.error.message MUST NOT echo the providers refusal text (SECURITY invariant envelope-refusal-no-prompt-leak)', async () => {
|
|
271
|
-
if (!isFixtureAdvertised(E2E_FIXTURE)) return;
|
|
273
|
+
if (!isFixtureAdvertised(E2E_FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(E2E_FIXTURE)` returned early');
|
|
272
274
|
// A distinctive refusal text so the message-no-echo assertion has
|
|
273
275
|
// a unique substring to scan for. Production refusal texts may
|
|
274
276
|
// contain prompt content; the host MUST keep it off the error
|
|
275
277
|
// message surface (event log only, scrubbed via SR-1).
|
|
276
278
|
const REFUSAL_TEXT = 'REFUSAL-CANARY-A8F3-do-not-echo-this-substring-into-RunSnapshot.error.message';
|
|
277
279
|
const seed = await programMockRefusal(REFUSAL_TEXT);
|
|
278
|
-
if (seed.status === 404) return;
|
|
280
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
279
281
|
|
|
280
282
|
const result = await runE2eAndRead();
|
|
281
|
-
if (result === null) return;
|
|
283
|
+
if (result === null) return softSkip('blocked', 'precondition not met — `result === null` returned early (seam, prior step, or fixture unavailable)');
|
|
282
284
|
const message = (result.terminal as { error?: { message?: string } }).error?.message ?? '';
|
|
283
285
|
expect(
|
|
284
286
|
message.includes(REFUSAL_TEXT),
|
|
285
|
-
|
|
287
|
+
req('openwop.it.envelope-refusal-shape.runsnapshot-error-message-must-not-echo-the-providers-refusal-text-security-inva',
|
|
286
288
|
'SECURITY/invariants.yaml §envelope-refusal-no-prompt-leak',
|
|
287
289
|
'RunSnapshot.error.message MUST NOT echo refusalText — the safety-filter text may contain prompt content; spec-compliant emission carries it only on the envelope.refusal event payload (subject to SR-1 redaction at the eventLog.append boundary)',
|
|
288
290
|
),
|
|
@@ -24,6 +24,7 @@ import addFormats from 'ajv-formats';
|
|
|
24
24
|
import { readFileSync } from 'node:fs';
|
|
25
25
|
import { join } from 'node:path';
|
|
26
26
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
27
|
+
import { req } from '../lib/requirement-ids.js';
|
|
27
28
|
|
|
28
29
|
function compileEnvelope(): ReturnType<Ajv2020['compile']> {
|
|
29
30
|
const ajv = new Ajv2020({ strict: false, allErrors: true });
|
|
@@ -57,7 +58,7 @@ describe('envelope-rendering-hint: meta.rendering shape (RFC 0055 §B)', () => {
|
|
|
57
58
|
const ok = validate(env);
|
|
58
59
|
expect(
|
|
59
60
|
ok,
|
|
60
|
-
'ai-envelope.md §"Rendering hints": ' + `meta.rendering MUST validate; errors: ${JSON.stringify(validate.errors)}
|
|
61
|
+
req('openwop.it.envelope-rendering-hint.accepts-an-envelope-carrying-a-well-formed-meta-rendering-hint', 'RFC 0055 §B', 'ai-envelope.md §"Rendering hints": ' + `meta.rendering MUST validate; errors: ${JSON.stringify(validate.errors)}`),
|
|
61
62
|
).toBe(true);
|
|
62
63
|
});
|
|
63
64
|
|
|
@@ -65,7 +66,7 @@ describe('envelope-rendering-hint: meta.rendering shape (RFC 0055 §B)', () => {
|
|
|
65
66
|
const ok = validate(baseEnvelope);
|
|
66
67
|
expect(
|
|
67
68
|
ok,
|
|
68
|
-
'ai-envelope.md §"Rendering hints": ' + 'meta.rendering MUST be optional — envelopes omitting it still validate',
|
|
69
|
+
req('openwop.it.envelope-rendering-hint.accepts-an-envelope-with-no-meta-rendering-proves-the-property-is-optional', 'RFC 0055 §B', 'ai-envelope.md §"Rendering hints": ' + 'meta.rendering MUST be optional — envelopes omitting it still validate'),
|
|
69
70
|
).toBe(true);
|
|
70
71
|
});
|
|
71
72
|
|
|
@@ -77,7 +78,7 @@ describe('envelope-rendering-hint: meta.rendering shape (RFC 0055 §B)', () => {
|
|
|
77
78
|
const ok = validate(env);
|
|
78
79
|
expect(
|
|
79
80
|
ok,
|
|
80
|
-
'ai-envelope.md §"Rendering hints": ' + 'display is a closed enum — unknown families MUST be rejected',
|
|
81
|
+
req('openwop.it.envelope-rendering-hint.rejects-an-unknown-display-value-closed-enum', 'RFC 0055 §B', 'ai-envelope.md §"Rendering hints": ' + 'display is a closed enum — unknown families MUST be rejected'),
|
|
81
82
|
).toBe(false);
|
|
82
83
|
});
|
|
83
84
|
|
|
@@ -89,7 +90,7 @@ describe('envelope-rendering-hint: meta.rendering shape (RFC 0055 §B)', () => {
|
|
|
89
90
|
const ok = validate(env);
|
|
90
91
|
expect(
|
|
91
92
|
ok,
|
|
92
|
-
'ai-envelope.md §"Rendering hints": ' + 'rendering is additionalProperties:false',
|
|
93
|
+
req('openwop.it.envelope-rendering-hint.rejects-an-unknown-property-under-rendering-additionalproperties-false', 'RFC 0055 §B', 'ai-envelope.md §"Rendering hints": ' + 'rendering is additionalProperties:false'),
|
|
93
94
|
).toBe(false);
|
|
94
95
|
});
|
|
95
96
|
});
|
|
@@ -58,12 +58,12 @@ async function readDiscovery(): Promise<DiscoveryDoc | null> {
|
|
|
58
58
|
describe.skipIf(HTTP_SKIP)('envelope-retry-attempted: advertisement shape (RFC 0032 §C)', () => {
|
|
59
59
|
it('capabilities.envelopes.reliability (when present) conforms to RFC 0032 §C', async () => {
|
|
60
60
|
const d = await readDiscovery();
|
|
61
|
-
if (d === null) return;
|
|
61
|
+
if (d === null) return softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
|
|
62
62
|
const reliability = capabilityFamily<{ reasoning?: Record<string, unknown>; tierOneSubsetCompliance?: unknown; reliability?: { completion?: Record<string, unknown> } & Record<string, unknown> }>(d, 'envelopes')?.reliability;
|
|
63
|
-
if (reliability === undefined) return;
|
|
64
|
-
expect(typeof reliability.supported, 'reliability.supported MUST be boolean').toBe('boolean');
|
|
63
|
+
if (reliability === undefined) return softSkip('blocked', 'precondition not met — `reliability === undefined` returned early (seam, prior step, or fixture unavailable)');
|
|
64
|
+
expect(typeof reliability.supported, req('openwop.it.envelope-retry-attempted.capabilities-envelopes-reliability-when-present-conforms-to-rfc-0032-c', 'RFC 0032 §C', 'reliability.supported MUST be boolean')).toBe('boolean');
|
|
65
65
|
if (reliability.events !== undefined) {
|
|
66
|
-
expect(Array.isArray(reliability.events), 'reliability.events MUST be an array').toBe(true);
|
|
66
|
+
expect(Array.isArray(reliability.events), req('openwop.it.envelope-retry-attempted.capabilities-envelopes-reliability-when-present-conforms-to-rfc-0032-c', 'RFC 0032 §C', 'reliability.events MUST be an array')).toBe(true);
|
|
67
67
|
const RFC_0032_EVENTS = [
|
|
68
68
|
'envelope.retry.attempted',
|
|
69
69
|
'envelope.retry.exhausted',
|
|
@@ -73,7 +73,7 @@ describe.skipIf(HTTP_SKIP)('envelope-retry-attempted: advertisement shape (RFC 0
|
|
|
73
73
|
'envelope.recovery.applied',
|
|
74
74
|
];
|
|
75
75
|
for (const e of reliability.events as unknown[]) {
|
|
76
|
-
expect(RFC_0032_EVENTS, `event "${String(e)}" MUST be one of the six RFC 0032 names`).toContain(String(e));
|
|
76
|
+
expect(RFC_0032_EVENTS, req('openwop.it.envelope-retry-attempted.capabilities-envelopes-reliability-when-present-conforms-to-rfc-0032-c', 'RFC 0032 §C', `event "${String(e)}" MUST be one of the six RFC 0032 names`)).toContain(String(e));
|
|
77
77
|
}
|
|
78
78
|
// When supported: true, MUST include the two MUST-tier events (per
|
|
79
79
|
// RFC 0032 §C). Hosts that have wired end-to-end emission from
|
|
@@ -87,17 +87,17 @@ describe.skipIf(HTTP_SKIP)('envelope-retry-attempted: advertisement shape (RFC 0
|
|
|
87
87
|
const evts = reliability.events as string[];
|
|
88
88
|
expect(
|
|
89
89
|
evts.includes('envelope.retry.exhausted'),
|
|
90
|
-
'RFC 0032 §C: hosts that advertise `supported: true` with non-empty `events[]` MUST include `envelope.retry.exhausted`',
|
|
90
|
+
req('openwop.it.envelope-retry-attempted.capabilities-envelopes-reliability-when-present-conforms-to-rfc-0032-c', 'RFC 0032 §C', 'RFC 0032 §C: hosts that advertise `supported: true` with non-empty `events[]` MUST include `envelope.retry.exhausted`'),
|
|
91
91
|
).toBe(true);
|
|
92
92
|
expect(
|
|
93
93
|
evts.includes('envelope.refusal'),
|
|
94
|
-
'RFC 0032 §C: hosts that advertise `supported: true` with non-empty `events[]` MUST include `envelope.refusal`',
|
|
94
|
+
req('openwop.it.envelope-retry-attempted.capabilities-envelopes-reliability-when-present-conforms-to-rfc-0032-c', 'RFC 0032 §C', 'RFC 0032 §C: hosts that advertise `supported: true` with non-empty `events[]` MUST include `envelope.refusal`'),
|
|
95
95
|
).toBe(true);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
if (reliability.maxRetryAttempts !== undefined) {
|
|
99
99
|
const n = reliability.maxRetryAttempts as number;
|
|
100
|
-
expect(typeof n === 'number' && n >= 1 && n <= 16, 'maxRetryAttempts MUST be integer in [1, 16]').toBe(true);
|
|
100
|
+
expect(typeof n === 'number' && n >= 1 && n <= 16, req('openwop.it.envelope-retry-attempted.capabilities-envelopes-reliability-when-present-conforms-to-rfc-0032-c', 'RFC 0032 §C', 'maxRetryAttempts MUST be integer in [1, 16]')).toBe(true);
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
103
|
});
|
|
@@ -115,6 +115,8 @@ describe.skipIf(HTTP_SKIP)('envelope-retry-attempted: advertisement shape (RFC 0
|
|
|
115
115
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
116
116
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
117
117
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
118
|
+
import { req } from '../lib/requirement-ids.js';
|
|
119
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
118
120
|
|
|
119
121
|
const FIXTURE = 'conformance-envelope-retry-attempted';
|
|
120
122
|
const NODE_ID = 'structured-call';
|
|
@@ -154,20 +156,20 @@ async function startRunAndRead(): Promise<RunEvent[] | null> {
|
|
|
154
156
|
|
|
155
157
|
describe.skipIf(HTTP_SKIP)('envelope-retry-attempted: runtime behavior (RFC 0032 §B.1)', () => {
|
|
156
158
|
it('when mock LLM emits invalid envelope on attempt 1 then valid on attempt 2, exactly one `envelope.retry.attempted` event fires before the second attempt', async () => {
|
|
157
|
-
if (!isFixtureAdvertised(FIXTURE)) return;
|
|
159
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
|
|
158
160
|
const seed = await programMock([
|
|
159
161
|
{ content: 'not valid json — provoke parse-error retry' },
|
|
160
162
|
{ content: '{"valid":true}' },
|
|
161
163
|
]);
|
|
162
|
-
if (seed.status === 404) return; // host doesn't expose the seam
|
|
164
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (host doesn\'t expose the seam) (seam, prior step, or fixture unavailable)'); // host doesn't expose the seam
|
|
163
165
|
expect(seed.status).toBe(200);
|
|
164
166
|
|
|
165
167
|
const events = await startRunAndRead();
|
|
166
|
-
if (events === null) return;
|
|
168
|
+
if (events === null) return softSkip('blocked', 'precondition not met — `events === null` returned early (seam, prior step, or fixture unavailable)');
|
|
167
169
|
const retries = events.filter((e) => e.type === 'envelope.retry.attempted');
|
|
168
170
|
expect(
|
|
169
171
|
retries.length,
|
|
170
|
-
|
|
172
|
+
req('openwop.it.envelope-retry-attempted.when-mock-llm-emits-invalid-envelope-on-attempt-1-then-valid-on-attempt-2-exactl',
|
|
171
173
|
'RFCS/0032-envelope-reliability-events.md §B.1',
|
|
172
174
|
'exactly one envelope.retry.attempted event MUST fire between attempts 1 and 2',
|
|
173
175
|
),
|
|
@@ -175,17 +177,17 @@ describe.skipIf(HTTP_SKIP)('envelope-retry-attempted: runtime behavior (RFC 0032
|
|
|
175
177
|
});
|
|
176
178
|
|
|
177
179
|
it('event payload carries `attempt: 2` (1-indexed; first attempt does not emit)', async () => {
|
|
178
|
-
if (!isFixtureAdvertised(FIXTURE)) return;
|
|
180
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
|
|
179
181
|
const seed = await programMock([{ content: 'invalid' }, { content: '{"valid":true}' }]);
|
|
180
|
-
if (seed.status === 404) return;
|
|
182
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
181
183
|
|
|
182
184
|
const events = await startRunAndRead();
|
|
183
|
-
if (events === null) return;
|
|
185
|
+
if (events === null) return softSkip('blocked', 'precondition not met — `events === null` returned early (seam, prior step, or fixture unavailable)');
|
|
184
186
|
const retry = events.find((e) => e.type === 'envelope.retry.attempted');
|
|
185
|
-
expect(retry, 'envelope.retry.attempted MUST appear in the event log').toBeDefined();
|
|
187
|
+
expect(retry, req('openwop.it.envelope-retry-attempted.event-payload-carries-attempt-2-1-indexed-first-attempt-does-not-emit', 'RFCS/0032-envelope-reliability-events.md §B.1', 'envelope.retry.attempted MUST appear in the event log')).toBeDefined();
|
|
186
188
|
expect(
|
|
187
189
|
retry!.payload?.attempt,
|
|
188
|
-
|
|
190
|
+
req('openwop.it.envelope-retry-attempted.event-payload-carries-attempt-2-1-indexed-first-attempt-does-not-emit',
|
|
189
191
|
'RFCS/0032-envelope-reliability-events.md §B.1',
|
|
190
192
|
'attempt field MUST be 2 (1-indexed; first attempt does not emit)',
|
|
191
193
|
),
|
|
@@ -193,19 +195,19 @@ describe.skipIf(HTTP_SKIP)('envelope-retry-attempted: runtime behavior (RFC 0032
|
|
|
193
195
|
});
|
|
194
196
|
|
|
195
197
|
it('`reason` is one of the spec-reserved closed-enum values OR matches the `x-host-<host>-<key>` extension pattern', async () => {
|
|
196
|
-
if (!isFixtureAdvertised(FIXTURE)) return;
|
|
198
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
|
|
197
199
|
const seed = await programMock([{ content: 'invalid' }, { content: '{"valid":true}' }]);
|
|
198
|
-
if (seed.status === 404) return;
|
|
200
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
199
201
|
|
|
200
202
|
const events = await startRunAndRead();
|
|
201
|
-
if (events === null) return;
|
|
203
|
+
if (events === null) return softSkip('blocked', 'precondition not met — `events === null` returned early (seam, prior step, or fixture unavailable)');
|
|
202
204
|
const retry = events.find((e) => e.type === 'envelope.retry.attempted');
|
|
203
205
|
expect(retry).toBeDefined();
|
|
204
206
|
const reason = retry!.payload?.reason;
|
|
205
207
|
expect(typeof reason).toBe('string');
|
|
206
208
|
expect(
|
|
207
209
|
RFC_0032_REASONS.has(reason as string) || HOST_REASON_EXT_RE.test(reason as string),
|
|
208
|
-
|
|
210
|
+
req('openwop.it.envelope-retry-attempted.reason-is-one-of-the-spec-reserved-closed-enum-values-or-matches-the-x-host-host',
|
|
209
211
|
'RFCS/0032-envelope-reliability-events.md §B.1',
|
|
210
212
|
'reason MUST be in the spec-reserved set OR match x-host-<host>-<key>',
|
|
211
213
|
),
|
|
@@ -213,17 +215,17 @@ describe.skipIf(HTTP_SKIP)('envelope-retry-attempted: runtime behavior (RFC 0032
|
|
|
213
215
|
});
|
|
214
216
|
|
|
215
217
|
it('eventual success records normally via envelope acceptance + downstream RunEventDoc', async () => {
|
|
216
|
-
if (!isFixtureAdvertised(FIXTURE)) return;
|
|
218
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
|
|
217
219
|
const seed = await programMock([{ content: 'invalid' }, { content: '{"valid":true}' }]);
|
|
218
|
-
if (seed.status === 404) return;
|
|
220
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
219
221
|
|
|
220
222
|
const events = await startRunAndRead();
|
|
221
|
-
if (events === null) return;
|
|
223
|
+
if (events === null) return softSkip('blocked', 'precondition not met — `events === null` returned early (seam, prior step, or fixture unavailable)');
|
|
222
224
|
const nodeCompleted = events.find((e) => e.type === 'node.completed' && e.nodeId === NODE_ID);
|
|
223
225
|
const runCompleted = events.find((e) => e.type === 'run.completed');
|
|
224
226
|
expect(
|
|
225
227
|
nodeCompleted,
|
|
226
|
-
|
|
228
|
+
req('openwop.it.envelope-retry-attempted.eventual-success-records-normally-via-envelope-acceptance-downstream-runeventdoc',
|
|
227
229
|
'RFCS/0032-envelope-reliability-events.md §B.1',
|
|
228
230
|
'eventual success MUST produce a node.completed for the dispatching node',
|
|
229
231
|
),
|
|
@@ -232,25 +234,25 @@ describe.skipIf(HTTP_SKIP)('envelope-retry-attempted: runtime behavior (RFC 0032
|
|
|
232
234
|
});
|
|
233
235
|
|
|
234
236
|
it('`previousError` (when populated) MUST NOT contain prompt or response substring excerpts — limit to validator output', async () => {
|
|
235
|
-
if (!isFixtureAdvertised(FIXTURE)) return;
|
|
237
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
|
|
236
238
|
const PROMPT_CANARY = 'PROMPT-CANARY-RETRY-ATTEMPTED-DO-NOT-LEAK-' + Math.random().toString(36).slice(2, 10);
|
|
237
239
|
const RESPONSE_CANARY = 'RESPONSE-CANARY-' + PROMPT_CANARY;
|
|
238
240
|
const seed = await programMock([
|
|
239
241
|
{ content: `not valid json mentioning ${RESPONSE_CANARY}` },
|
|
240
242
|
{ content: '{"valid":true}' },
|
|
241
243
|
]);
|
|
242
|
-
if (seed.status === 404) return;
|
|
244
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
243
245
|
|
|
244
246
|
const events = await startRunAndRead();
|
|
245
|
-
if (events === null) return;
|
|
247
|
+
if (events === null) return softSkip('blocked', 'precondition not met — `events === null` returned early (seam, prior step, or fixture unavailable)');
|
|
246
248
|
const retry = events.find((e) => e.type === 'envelope.retry.attempted');
|
|
247
|
-
if (!retry) return;
|
|
249
|
+
if (!retry) return softSkip('blocked', 'precondition not met — `!retry` returned early (seam, prior step, or fixture unavailable)');
|
|
248
250
|
const previousError = retry.payload?.previousError;
|
|
249
|
-
if (previousError === undefined || previousError === null) return; // field is optional
|
|
251
|
+
if (previousError === undefined || previousError === null) return softSkip('blocked', 'precondition not met — `previousError === undefined || previousError === null` returned early (field is optional) (seam, prior step, or fixture unavailable)'); // field is optional
|
|
250
252
|
const serialized = typeof previousError === 'string' ? previousError : JSON.stringify(previousError);
|
|
251
253
|
expect(
|
|
252
254
|
serialized.includes(RESPONSE_CANARY),
|
|
253
|
-
|
|
255
|
+
req('openwop.it.envelope-retry-attempted.previouserror-when-populated-must-not-contain-prompt-or-response-substring-excer',
|
|
254
256
|
'RFCS/0032-envelope-reliability-events.md §G',
|
|
255
257
|
'previousError MUST NOT echo provider response substrings — validator output only',
|
|
256
258
|
),
|
|
@@ -28,6 +28,8 @@ import { describe, it, expect } from 'vitest';
|
|
|
28
28
|
import { driver } from '../lib/driver.js';
|
|
29
29
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
30
30
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
31
|
+
import { req } from '../lib/requirement-ids.js';
|
|
32
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
31
33
|
|
|
32
34
|
const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
|
|
33
35
|
const FIXTURE = 'conformance-envelope-retry-exhausted';
|
|
@@ -69,7 +71,7 @@ async function startRunAndRead(): Promise<{ events: RunEvent[]; terminal: unknow
|
|
|
69
71
|
|
|
70
72
|
describe.skipIf(HTTP_SKIP)('envelope-retry-exhausted: runtime behavior (RFC 0032 §B.2 MUST)', () => {
|
|
71
73
|
it('host exhausts retries with all-invalid program → exactly one envelope.retry.exhausted event', async () => {
|
|
72
|
-
if (!isFixtureAdvertised(FIXTURE)) return;
|
|
74
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
|
|
73
75
|
// Seed maxRetryAttempts entries of invalid JSON so dispatchStructured
|
|
74
76
|
// hits every retry and then exhausts. The mock returns empty-stop
|
|
75
77
|
// after program exhaustion, but dispatchStructured short-circuits
|
|
@@ -80,16 +82,16 @@ describe.skipIf(HTTP_SKIP)('envelope-retry-exhausted: runtime behavior (RFC 0032
|
|
|
80
82
|
{ content: 'not json c' },
|
|
81
83
|
{ content: 'not json d' },
|
|
82
84
|
]);
|
|
83
|
-
if (seed.status === 404) return;
|
|
85
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
84
86
|
expect(seed.status).toBe(200);
|
|
85
87
|
|
|
86
88
|
const result = await startRunAndRead();
|
|
87
|
-
if (result === null) return;
|
|
89
|
+
if (result === null) return softSkip('blocked', 'precondition not met — `result === null` returned early (seam, prior step, or fixture unavailable)');
|
|
88
90
|
const { events } = result;
|
|
89
91
|
const exhausted = events.filter((e) => e.type === 'envelope.retry.exhausted');
|
|
90
92
|
expect(
|
|
91
93
|
exhausted.length,
|
|
92
|
-
|
|
94
|
+
req('openwop.it.envelope-retry-exhausted.host-exhausts-retries-with-all-invalid-program-exactly-one-envelope-retry-exhaus',
|
|
93
95
|
'RFCS/0032-envelope-reliability-events.md §B.2',
|
|
94
96
|
'exactly one envelope.retry.exhausted event MUST fire on retry-budget exhaustion',
|
|
95
97
|
),
|
|
@@ -97,32 +99,32 @@ describe.skipIf(HTTP_SKIP)('envelope-retry-exhausted: runtime behavior (RFC 0032
|
|
|
97
99
|
});
|
|
98
100
|
|
|
99
101
|
it('totalAttempts in payload matches the host advertised maxRetryAttempts', async () => {
|
|
100
|
-
if (!isFixtureAdvertised(FIXTURE)) return;
|
|
102
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
|
|
101
103
|
const seed = await programMock([{ content: 'x' }, { content: 'y' }, { content: 'z' }, { content: 'w' }]);
|
|
102
|
-
if (seed.status === 404) return;
|
|
104
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
103
105
|
|
|
104
106
|
const result = await startRunAndRead();
|
|
105
|
-
if (result === null) return;
|
|
107
|
+
if (result === null) return softSkip('blocked', 'precondition not met — `result === null` returned early (seam, prior step, or fixture unavailable)');
|
|
106
108
|
const exhausted = result.events.find((e) => e.type === 'envelope.retry.exhausted');
|
|
107
|
-
expect(exhausted).toBeDefined();
|
|
109
|
+
expect(exhausted, req('openwop.it.envelope-retry-exhausted.totalattempts-in-payload-matches-the-host-advertised-maxretryattempts', 'RFC 0032 §B.2', 'totalAttempts in payload matches the host advertised maxRetryAttempts')).toBeDefined();
|
|
108
110
|
const total = exhausted!.payload?.totalAttempts;
|
|
109
111
|
expect(typeof total === 'number' && (total as number) >= 1).toBe(true);
|
|
110
112
|
});
|
|
111
113
|
|
|
112
114
|
it('finalReason is in the spec-reserved enum OR matches x-host-<host>-<key>', async () => {
|
|
113
|
-
if (!isFixtureAdvertised(FIXTURE)) return;
|
|
115
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
|
|
114
116
|
const seed = await programMock([{ content: 'x' }, { content: 'y' }, { content: 'z' }, { content: 'w' }]);
|
|
115
|
-
if (seed.status === 404) return;
|
|
117
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
116
118
|
|
|
117
119
|
const result = await startRunAndRead();
|
|
118
|
-
if (result === null) return;
|
|
120
|
+
if (result === null) return softSkip('blocked', 'precondition not met — `result === null` returned early (seam, prior step, or fixture unavailable)');
|
|
119
121
|
const exhausted = result.events.find((e) => e.type === 'envelope.retry.exhausted');
|
|
120
122
|
expect(exhausted).toBeDefined();
|
|
121
123
|
const reason = exhausted!.payload?.finalReason;
|
|
122
124
|
expect(typeof reason).toBe('string');
|
|
123
125
|
expect(
|
|
124
126
|
RFC_0032_REASONS.has(reason as string) || HOST_REASON_EXT_RE.test(reason as string),
|
|
125
|
-
|
|
127
|
+
req('openwop.it.envelope-retry-exhausted.finalreason-is-in-the-spec-reserved-enum-or-matches-x-host-host-key',
|
|
126
128
|
'RFCS/0032-envelope-reliability-events.md §B.2',
|
|
127
129
|
'finalReason MUST be in the spec-reserved set OR match x-host-<host>-<key>',
|
|
128
130
|
),
|
|
@@ -130,16 +132,16 @@ describe.skipIf(HTTP_SKIP)('envelope-retry-exhausted: runtime behavior (RFC 0032
|
|
|
130
132
|
});
|
|
131
133
|
|
|
132
134
|
it('RunSnapshot.error.code is envelope_invalid for schema-violation exhaustion (RFC 0033 §C)', async () => {
|
|
133
|
-
if (!isFixtureAdvertised(FIXTURE)) return;
|
|
135
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
|
|
134
136
|
const seed = await programMock([{ content: 'x' }, { content: 'y' }, { content: 'z' }, { content: 'w' }]);
|
|
135
|
-
if (seed.status === 404) return;
|
|
137
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
136
138
|
|
|
137
139
|
const result = await startRunAndRead();
|
|
138
|
-
if (result === null) return;
|
|
140
|
+
if (result === null) return softSkip('blocked', 'precondition not met — `result === null` returned early (seam, prior step, or fixture unavailable)');
|
|
139
141
|
const code = (result.terminal as { error?: { code?: string } }).error?.code;
|
|
140
142
|
expect(
|
|
141
143
|
code,
|
|
142
|
-
|
|
144
|
+
req('openwop.it.envelope-retry-exhausted.runsnapshot-error-code-is-envelope-invalid-for-schema-violation-exhaustion-rfc-0',
|
|
143
145
|
'RFCS/0033-envelope-completion-contract.md §C',
|
|
144
146
|
'schema-violation-exhaustion MUST surface as RunSnapshot.error.code = envelope_invalid',
|
|
145
147
|
),
|
|
@@ -147,19 +149,19 @@ describe.skipIf(HTTP_SKIP)('envelope-retry-exhausted: runtime behavior (RFC 0032
|
|
|
147
149
|
});
|
|
148
150
|
|
|
149
151
|
it('envelope.retry.exhausted is emitted BEFORE node.failed (cause precedes effect)', async () => {
|
|
150
|
-
if (!isFixtureAdvertised(FIXTURE)) return;
|
|
152
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
|
|
151
153
|
const seed = await programMock([{ content: 'x' }, { content: 'y' }, { content: 'z' }, { content: 'w' }]);
|
|
152
|
-
if (seed.status === 404) return;
|
|
154
|
+
if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
153
155
|
|
|
154
156
|
const result = await startRunAndRead();
|
|
155
|
-
if (result === null) return;
|
|
157
|
+
if (result === null) return softSkip('blocked', 'precondition not met — `result === null` returned early (seam, prior step, or fixture unavailable)');
|
|
156
158
|
const exhaustedIdx = result.events.findIndex((e) => e.type === 'envelope.retry.exhausted');
|
|
157
159
|
const failedIdx = result.events.findIndex((e) => e.type === 'node.failed');
|
|
158
160
|
expect(exhaustedIdx).toBeGreaterThanOrEqual(0);
|
|
159
161
|
expect(failedIdx).toBeGreaterThanOrEqual(0);
|
|
160
162
|
expect(
|
|
161
163
|
exhaustedIdx < failedIdx,
|
|
162
|
-
|
|
164
|
+
req('openwop.it.envelope-retry-exhausted.envelope-retry-exhausted-is-emitted-before-node-failed-cause-precedes-effect',
|
|
163
165
|
'RFCS/0032-envelope-reliability-events.md §B.2',
|
|
164
166
|
'envelope.retry.exhausted MUST be emitted BEFORE node.failed (the event signals the host is about to surface the terminal failure)',
|
|
165
167
|
),
|
|
@@ -35,6 +35,8 @@ import { join } from 'node:path';
|
|
|
35
35
|
import { driver } from '../lib/driver.js';
|
|
36
36
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
37
37
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
38
|
+
import { req } from '../lib/requirement-ids.js';
|
|
39
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
38
40
|
|
|
39
41
|
const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
|
|
40
42
|
|
|
@@ -179,11 +181,11 @@ function walkSchema(
|
|
|
179
181
|
describe.skipIf(HTTP_SKIP)('envelope-tier-one-subset-static (RFC 0030 §B)', () => {
|
|
180
182
|
it('hosts advertising tierOneSubsetCompliance: "strict" have payload schemas that satisfy the Tier-1 intersection', async () => {
|
|
181
183
|
const d = await readDiscovery();
|
|
182
|
-
if (d === null) return; // host unreachable; soft-skip
|
|
184
|
+
if (d === null) return softSkip('blocked', 'precondition not met — `d === null` returned early (host unreachable; soft-skip) (seam, prior step, or fixture unavailable)'); // host unreachable; soft-skip
|
|
183
185
|
const compliance = capabilityFamily(d, 'envelopes')?.tierOneSubsetCompliance;
|
|
184
|
-
if (compliance !== 'strict') return; // gated on "strict" only
|
|
186
|
+
if (compliance !== 'strict') return softSkip('blocked', 'precondition not met — `compliance !== \'strict\'` returned early (gated on "strict" only) (seam, prior step, or fixture unavailable)'); // gated on "strict" only
|
|
185
187
|
const advertised = (capabilityFamily(d, 'supportedEnvelopes') ?? []) as string[];
|
|
186
|
-
if (advertised.length === 0) return;
|
|
188
|
+
if (advertised.length === 0) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `advertised.length === 0` returned early');
|
|
187
189
|
|
|
188
190
|
const violationsByKind: Record<string, Violation[]> = {};
|
|
189
191
|
for (const kind of advertised) {
|
|
@@ -202,7 +204,7 @@ describe.skipIf(HTTP_SKIP)('envelope-tier-one-subset-static (RFC 0030 §B)', ()
|
|
|
202
204
|
|
|
203
205
|
expect(
|
|
204
206
|
violationsByKind,
|
|
205
|
-
`RFC 0030 §B: schemas violating the Tier-1 subset under strict-mode advertisement: ${JSON.stringify(violationsByKind, null, 2)}
|
|
207
|
+
req('openwop.it.envelope-tier-one-subset-static.hosts-advertising-tieronesubsetcompliance-strict-have-payload-schemas-that-satis', 'RFC 0030 §B', `RFC 0030 §B: schemas violating the Tier-1 subset under strict-mode advertisement: ${JSON.stringify(violationsByKind, null, 2)}`),
|
|
206
208
|
).toEqual({});
|
|
207
209
|
});
|
|
208
210
|
});
|
|
@@ -216,14 +218,14 @@ describe('envelope-tier-one-subset-static: universal-kind schemas satisfy load-b
|
|
|
216
218
|
for (const kind of UNIVERSAL_KINDS) {
|
|
217
219
|
it(`${kind}.schema.json satisfies load-bearing Tier-1 rules (no oneOf/allOf/not/prefixItems/propertyNames anywhere)`, () => {
|
|
218
220
|
const schema = loadLocalSchema(kind);
|
|
219
|
-
expect(schema, `schemas/envelopes/${kind}.schema.json MUST exist`).not.toBeNull();
|
|
220
|
-
if (schema === null) return;
|
|
221
|
+
expect(schema, req('openwop.it.envelope-tier-one-subset-static.schema-json-satisfies-load-bearing-tier-1-rules-no-oneof-allof-not-prefixitems-p', 'RFC 0030 §B', `schemas/envelopes/${kind}.schema.json MUST exist`)).not.toBeNull();
|
|
222
|
+
if (schema === null) return softSkip('blocked', 'precondition not met — `schema === null` returned early (seam, prior step, or fixture unavailable)');
|
|
221
223
|
const violations: Violation[] = [];
|
|
222
224
|
const propCount = { n: 0 };
|
|
223
225
|
walkSchema(schema, `#`, 0, propCount, violations, 'load-bearing');
|
|
224
226
|
expect(
|
|
225
227
|
violations,
|
|
226
|
-
`${kind}.schema.json load-bearing Tier-1 violations (these fail across multiple vendors): ${JSON.stringify(violations, null, 2)}
|
|
228
|
+
req('openwop.it.envelope-tier-one-subset-static.schema-json-satisfies-load-bearing-tier-1-rules-no-oneof-allof-not-prefixitems-p', 'RFC 0030 §B', `${kind}.schema.json load-bearing Tier-1 violations (these fail across multiple vendors): ${JSON.stringify(violations, null, 2)}`),
|
|
227
229
|
).toEqual([]);
|
|
228
230
|
});
|
|
229
231
|
}
|