@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
|
@@ -30,8 +30,8 @@ import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
|
30
30
|
import { driver } from '../lib/driver.js';
|
|
31
31
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
32
32
|
import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
import { req } from '../lib/requirement-ids.js';
|
|
34
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
35
35
|
function loadSchema(name: string): Record<string, unknown> {
|
|
36
36
|
return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
|
|
37
37
|
}
|
|
@@ -43,12 +43,12 @@ describe('export-bundle-portability: capability advertisement (RFC 0098 §A, ser
|
|
|
43
43
|
const portability = (caps.properties as Record<string, { properties?: Record<string, unknown>; if?: unknown; then?: unknown }>).portability;
|
|
44
44
|
|
|
45
45
|
it('capabilities schema declares portability with its sub-flags + the import⇒dryRun if/then', () => {
|
|
46
|
-
expect(portability,
|
|
46
|
+
expect(portability, req('openwop.it.export-bundle-portability.capabilities-schema-declares-portability-with-its-sub-flags-the-import-dryrun-if', 'capabilities.md §portability', 'portability MUST be declared')).toBeDefined();
|
|
47
47
|
for (const flag of ['export', 'import', 'kinds', 'dryRun']) {
|
|
48
|
-
expect(portability?.properties?.[flag],
|
|
48
|
+
expect(portability?.properties?.[flag], req('openwop.it.export-bundle-portability.capabilities-schema-declares-portability-with-its-sub-flags-the-import-dryrun-if', 'RFC 0098 §A', `portability.${flag} MUST be declared`)).toBeDefined();
|
|
49
49
|
}
|
|
50
|
-
expect(portability?.if,
|
|
51
|
-
expect(portability?.then,
|
|
50
|
+
expect(portability?.if, req('openwop.it.export-bundle-portability.capabilities-schema-declares-portability-with-its-sub-flags-the-import-dryrun-if', 'RFC 0098 §A', 'a JSON-Schema if/then MUST enforce dryRun:true when import:true')).toBeDefined();
|
|
51
|
+
expect(portability?.then, req('openwop.it.export-bundle-portability.capabilities-schema-declares-portability-with-its-sub-flags-the-import-dryrun-if', 'RFC 0098 §A', 'the then-branch MUST require dryRun')).toBeDefined();
|
|
52
52
|
});
|
|
53
53
|
});
|
|
54
54
|
|
|
@@ -67,19 +67,19 @@ describe('export-bundle-portability: ExportBundle shape (RFC 0098 §B, server-fr
|
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
it('validates a conforming bundle with refs only', () => {
|
|
70
|
-
expect(validate(good),
|
|
70
|
+
expect(validate(good), req('openwop.it.export-bundle-portability.validates-a-conforming-bundle-with-refs-only', 'RFC 0098 §B', `a conforming bundle MUST validate. Errors: ${JSON.stringify(validate.errors)}`)).toBe(true);
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
it('rejects a wrong bundleVersion, an unknown kind, and a missing item ref', () => {
|
|
74
|
-
expect(validate({ ...good, bundleVersion: '2' }),
|
|
75
|
-
expect(validate({ ...good, items: [{ kind: 'mystery', ref: 'x', payload: {} }] }),
|
|
76
|
-
expect(validate({ ...good, items: [{ kind: 'agent', payload: {} }] }),
|
|
74
|
+
expect(validate({ ...good, bundleVersion: '2' }), req('openwop.it.export-bundle-portability.rejects-a-wrong-bundleversion-an-unknown-kind-and-a-missing-item-ref', 'RFC 0098 §B', 'an unsupported bundleVersion MUST be rejected')).toBe(false);
|
|
75
|
+
expect(validate({ ...good, items: [{ kind: 'mystery', ref: 'x', payload: {} }] }), req('openwop.it.export-bundle-portability.rejects-a-wrong-bundleversion-an-unknown-kind-and-a-missing-item-ref', 'RFC 0098 §B', 'an unknown item kind MUST be rejected')).toBe(false);
|
|
76
|
+
expect(validate({ ...good, items: [{ kind: 'agent', payload: {} }] }), req('openwop.it.export-bundle-portability.rejects-a-wrong-bundleversion-an-unknown-kind-and-a-missing-item-ref', 'RFC 0098 §B', 'an item without a ref MUST be rejected')).toBe(false);
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
it('the bundle envelope admits no credential-named field at the root or source level (additionalProperties:false)', () => {
|
|
80
80
|
for (const name of CRED_NAMES) {
|
|
81
|
-
expect(validate({ ...good, [name]: 'xxx' }),
|
|
82
|
-
expect(validate({ ...good, source: { ...good.source, [name]: 'xxx' } }),
|
|
81
|
+
expect(validate({ ...good, [name]: 'xxx' }), req('openwop.it.export-bundle-portability.the-bundle-envelope-admits-no-credential-named-field-at-the-root-or-source-level', 'SECURITY invariant export-bundle-no-credential-material', `a "${name}" field at the bundle root MUST NOT validate`)).toBe(false);
|
|
82
|
+
expect(validate({ ...good, source: { ...good.source, [name]: 'xxx' } }), req('openwop.it.export-bundle-portability.the-bundle-envelope-admits-no-credential-named-field-at-the-root-or-source-level', 'SECURITY invariant export-bundle-no-credential-material', `a "${name}" field under source MUST NOT validate`)).toBe(false);
|
|
83
83
|
}
|
|
84
84
|
});
|
|
85
85
|
});
|
|
@@ -93,10 +93,10 @@ describe('export-bundle-portability: content-free event (RFC 0098 §D, server-fr
|
|
|
93
93
|
|
|
94
94
|
it('import.applied is in the RunEventType enum and is content-free (counts + refs only)', () => {
|
|
95
95
|
const en = (runEvent.$defs as Record<string, { enum?: string[] }>).RunEventType?.enum ?? [];
|
|
96
|
-
expect(en).toContain('import.applied');
|
|
96
|
+
expect(en, req('openwop.it.export-bundle-portability.import-applied-is-in-the-runeventtype-enum-and-is-content-free-counts-refs-only', 'export-bundle-portability.test.ts (no spec citation in file)', 'import.applied is in the RunEventType enum and is content-free (counts + refs only)')).toContain('import.applied');
|
|
97
97
|
const applied = ajv.getSchema('payloads#/$defs/importApplied')!;
|
|
98
|
-
expect(applied({ bundleOrigin: 'https://host-a.example', counts: { created: 2, skipped: 1 }, secretsToRebind: ['anthropic'] }),
|
|
99
|
-
expect(applied({ bundleOrigin: 'h', counts: { created: 1 }, items: [{ payload: {} }] }),
|
|
98
|
+
expect(applied({ bundleOrigin: 'https://host-a.example', counts: { created: 2, skipped: 1 }, secretsToRebind: ['anthropic'] }), req('openwop.it.export-bundle-portability.import-applied-is-in-the-runeventtype-enum-and-is-content-free-counts-refs-only', 'RFC 0098 §D', 'a content-free import.applied MUST validate')).toBe(true);
|
|
99
|
+
expect(applied({ bundleOrigin: 'h', counts: { created: 1 }, items: [{ payload: {} }] }), req('openwop.it.export-bundle-portability.import-applied-is-in-the-runeventtype-enum-and-is-content-free-counts-refs-only', 'SECURITY invariant export-bundle-no-credential-material', 'import.applied MUST NOT carry item payloads')).toBe(false);
|
|
100
100
|
});
|
|
101
101
|
});
|
|
102
102
|
|
|
@@ -111,10 +111,10 @@ describe('export-bundle-portability: behavioral (RFC 0098 §E, capability-gated)
|
|
|
111
111
|
items: [{ kind: 'connection-ref', ref: 'c1', payload: { provider: 'anthropic', apiKey: 'sk-conformance-canary' } }],
|
|
112
112
|
};
|
|
113
113
|
const res = await driver.post('/v1/host/sample/import?dryRun=true', { bundle: leaky });
|
|
114
|
-
if (res.status === 404 || res.status === 403) return; // seam unwired — soft-skip
|
|
114
|
+
if (res.status === 404 || res.status === 403) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 403` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
|
|
115
115
|
expect(
|
|
116
116
|
res.status,
|
|
117
|
-
|
|
117
|
+
req('openwop.it.export-bundle-portability.importing-a-bundle-with-a-literal-credential-value-is-rejected-422', 'portability.md §Invariants clause 1', 'a bundle carrying a literal credential value MUST be rejected (422)'),
|
|
118
118
|
).toBe(422);
|
|
119
119
|
});
|
|
120
120
|
});
|
|
@@ -8,6 +8,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
8
8
|
import { driver } from '../lib/driver.js';
|
|
9
9
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
10
10
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
11
|
+
import { req } from '../lib/requirement-ids.js';
|
|
11
12
|
|
|
12
13
|
const WORKFLOW_ID = 'conformance-failure';
|
|
13
14
|
const SKIP_NO_FIXTURE = !isFixtureAdvertised(WORKFLOW_ID);
|
|
@@ -15,7 +16,7 @@ const SKIP_NO_FIXTURE = !isFixtureAdvertised(WORKFLOW_ID);
|
|
|
15
16
|
describe.skipIf(SKIP_NO_FIXTURE)('failure: conformance-failure fixture reaches terminal `failed`', () => {
|
|
16
17
|
it('POST /v1/runs accepts the run and run terminates as failed with structured error', async () => {
|
|
17
18
|
const create = await driver.post('/v1/runs', { workflowId: WORKFLOW_ID });
|
|
18
|
-
expect(create.status,
|
|
19
|
+
expect(create.status, req('openwop.it.failure-path.post-v1-runs-accepts-the-run-and-run-terminates-as-failed-with-structured-error',
|
|
19
20
|
'rest-endpoints.md',
|
|
20
21
|
'POST /v1/runs MUST return 201 even for fixtures that fail at runtime',
|
|
21
22
|
)).toBe(201);
|
|
@@ -23,22 +24,22 @@ describe.skipIf(SKIP_NO_FIXTURE)('failure: conformance-failure fixture reaches t
|
|
|
23
24
|
|
|
24
25
|
const terminal = await pollUntilTerminal(runId);
|
|
25
26
|
|
|
26
|
-
expect(terminal.status,
|
|
27
|
+
expect(terminal.status, req('openwop.it.failure-path.post-v1-runs-accepts-the-run-and-run-terminates-as-failed-with-structured-error',
|
|
27
28
|
'fixtures.md conformance-failure §Terminal status',
|
|
28
29
|
'fixture MUST reach terminal `failed`',
|
|
29
30
|
)).toBe('failed');
|
|
30
31
|
|
|
31
|
-
expect(typeof terminal.error,
|
|
32
|
+
expect(typeof terminal.error, req('openwop.it.failure-path.post-v1-runs-accepts-the-run-and-run-terminates-as-failed-with-structured-error',
|
|
32
33
|
'rest-endpoints.md RunSnapshot.error',
|
|
33
34
|
'RunSnapshot.error MUST be a structured object on terminal `failed`',
|
|
34
35
|
)).toBe('object');
|
|
35
|
-
expect(terminal.error, 'RunSnapshot.error MUST be non-null').not.toBeNull();
|
|
36
|
+
expect(terminal.error, req('openwop.it.failure-path.post-v1-runs-accepts-the-run-and-run-terminates-as-failed-with-structured-error', 'rest-endpoints.md RunSnapshot.error', 'RunSnapshot.error MUST be non-null')).not.toBeNull();
|
|
36
37
|
|
|
37
|
-
expect(typeof terminal.error?.code,
|
|
38
|
+
expect(typeof terminal.error?.code, req('openwop.it.failure-path.post-v1-runs-accepts-the-run-and-run-terminates-as-failed-with-structured-error',
|
|
38
39
|
'rest-endpoints.md RunSnapshot.error.code',
|
|
39
40
|
'RunSnapshot.error.code MUST be a string',
|
|
40
41
|
)).toBe('string');
|
|
41
|
-
expect(typeof terminal.error?.message,
|
|
42
|
+
expect(typeof terminal.error?.message, req('openwop.it.failure-path.post-v1-runs-accepts-the-run-and-run-terminates-as-failed-with-structured-error',
|
|
42
43
|
'rest-endpoints.md RunSnapshot.error.message',
|
|
43
44
|
'RunSnapshot.error.message MUST be a string',
|
|
44
45
|
)).toBe('string');
|
|
@@ -10,16 +10,17 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { describe, it, expect } from 'vitest';
|
|
13
|
-
import { driver } from '../lib/driver.js';
|
|
14
13
|
import { readFeedbackCap } from '../lib/feedback.js';
|
|
14
|
+
import { req } from '../lib/requirement-ids.js';
|
|
15
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
15
16
|
|
|
16
17
|
describe('feedback-capability-shape: advertisement (RFC 0056 §A)', () => {
|
|
17
18
|
it('capabilities.feedback is absent or a well-formed object', async () => {
|
|
18
19
|
const cap = await readFeedbackCap();
|
|
19
|
-
if (cap === null) return; // not advertised — valid
|
|
20
|
+
if (cap === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === null` returned early (not advertised — valid)'); // not advertised — valid
|
|
20
21
|
expect(
|
|
21
22
|
typeof cap.supported,
|
|
22
|
-
|
|
23
|
+
req('openwop.it.feedback-capability-shape.capabilities-feedback-is-absent-or-a-well-formed-object', 'capabilities.schema.json §feedback', 'capabilities.feedback.supported MUST be a boolean when present'),
|
|
23
24
|
).toBe('boolean');
|
|
24
25
|
if (Array.isArray(cap.targets)) {
|
|
25
26
|
for (const t of cap.targets) {
|
|
@@ -12,6 +12,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
12
12
|
import { softSkip } from '../lib/soft-skip.js';
|
|
13
13
|
import { driver } from '../lib/driver.js';
|
|
14
14
|
import { readFeedbackCap, seedRun } from '../lib/feedback.js';
|
|
15
|
+
import { req } from '../lib/requirement-ids.js';
|
|
15
16
|
|
|
16
17
|
const CANARY = 'sk-canary-rfc0056-do-not-leak-abc123';
|
|
17
18
|
|
|
@@ -30,7 +31,7 @@ describe('feedback-correction-redaction (RFC 0056 §E)', () => {
|
|
|
30
31
|
const list = await driver.get(`/v1/runs/${runId}/annotations`);
|
|
31
32
|
expect(
|
|
32
33
|
JSON.stringify(list.json ?? {}).includes(CANARY),
|
|
33
|
-
|
|
34
|
+
req('openwop.it.feedback-correction-redaction.secret-shaped-material-in-correction-note-is-redacted-in-the-annotation-list', 'RFC 0056 §E', 'secret-shaped material MUST be redacted before persistence/listing (SR-1)'),
|
|
34
35
|
).toBe(false);
|
|
35
36
|
});
|
|
36
37
|
});
|
|
@@ -16,6 +16,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
16
16
|
import { softSkip } from '../lib/soft-skip.js';
|
|
17
17
|
import { driver } from '../lib/driver.js';
|
|
18
18
|
import { readFeedbackCap, seedRun } from '../lib/feedback.js';
|
|
19
|
+
import { req } from '../lib/requirement-ids.js';
|
|
19
20
|
|
|
20
21
|
describe('feedback-cross-tenant-isolation (RFC 0056 §E)', () => {
|
|
21
22
|
it('a run\'s annotation list contains only that run\'s annotations', async () => {
|
|
@@ -31,7 +32,7 @@ describe('feedback-cross-tenant-isolation (RFC 0056 §E)', () => {
|
|
|
31
32
|
for (const a of ann) {
|
|
32
33
|
expect(
|
|
33
34
|
a.target?.runId,
|
|
34
|
-
|
|
35
|
+
req('openwop.it.feedback-cross-tenant-isolation.a-run-s-annotation-list-contains-only-that-run-s-annotations', 'RFC 0056 §E', 'an annotation list MUST contain only this run\'s annotations (CTI-1)'),
|
|
35
36
|
).toBe(runId);
|
|
36
37
|
}
|
|
37
38
|
});
|
|
@@ -12,6 +12,7 @@ import { softSkip } from '../lib/soft-skip.js';
|
|
|
12
12
|
import { driver } from '../lib/driver.js';
|
|
13
13
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
14
14
|
import { readFeedbackCap, seedRun } from '../lib/feedback.js';
|
|
15
|
+
import { req } from '../lib/requirement-ids.js';
|
|
15
16
|
|
|
16
17
|
describe('feedback-fork-not-copied (RFC 0056 §D)', () => {
|
|
17
18
|
it('a fork of an annotated run starts with zero annotations', async () => {
|
|
@@ -25,7 +26,7 @@ describe('feedback-fork-not-copied (RFC 0056 §D)', () => {
|
|
|
25
26
|
try {
|
|
26
27
|
await pollUntilTerminal(runId, { timeoutMs: 10_000 });
|
|
27
28
|
} catch {
|
|
28
|
-
return;
|
|
29
|
+
return softSkip('blocked', 'precondition not met — an earlier step threw (seam, prior step, or fixture unavailable)');
|
|
29
30
|
}
|
|
30
31
|
const fork = await driver.post(`/v1/runs/${runId}:fork`, { fromSeq: 0, mode: 'branch' });
|
|
31
32
|
if (fork.status !== 200 && fork.status !== 201) return softSkip('inapplicable', 'fork unsupported — soft-skip (fork.status !== 200 && fork.status !== 201)');
|
|
@@ -35,7 +36,7 @@ describe('feedback-fork-not-copied (RFC 0056 §D)', () => {
|
|
|
35
36
|
const ann = (list.json as { annotations?: unknown[] } | undefined)?.annotations ?? [];
|
|
36
37
|
expect(
|
|
37
38
|
ann.length,
|
|
38
|
-
|
|
39
|
+
req('openwop.it.feedback-fork-not-copied.a-fork-of-an-annotated-run-starts-with-zero-annotations', 'RFC 0056 §D', 'annotations are a side-store and MUST NOT be copied into a fork'),
|
|
39
40
|
).toBe(0);
|
|
40
41
|
});
|
|
41
42
|
});
|
|
@@ -11,6 +11,7 @@ import { softSkip } from '../lib/soft-skip.js';
|
|
|
11
11
|
import { driver } from '../lib/driver.js';
|
|
12
12
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
13
13
|
import { readFeedbackCap, seedRun } from '../lib/feedback.js';
|
|
14
|
+
import { req } from '../lib/requirement-ids.js';
|
|
14
15
|
|
|
15
16
|
describe('feedback-on-terminal-run (RFC 0056 §C)', () => {
|
|
16
17
|
it('annotating a terminal run is accepted', async () => {
|
|
@@ -21,13 +22,13 @@ describe('feedback-on-terminal-run (RFC 0056 §C)', () => {
|
|
|
21
22
|
try {
|
|
22
23
|
await pollUntilTerminal(runId, { timeoutMs: 10_000 });
|
|
23
24
|
} catch {
|
|
24
|
-
return; // run didn't reach terminal in time — soft-skip
|
|
25
|
+
return softSkip('blocked', 'precondition not met — an earlier step threw (run didn\'t reach terminal in time — soft-skip) (seam, prior step, or fixture unavailable)'); // run didn't reach terminal in time — soft-skip
|
|
25
26
|
}
|
|
26
27
|
const post = await driver.post(`/v1/runs/${runId}/annotations`, { signal: { kind: 'flag' }, note: 'post-hoc review' });
|
|
27
28
|
if (post.status === 501 || post.status === 404) return softSkip('blocked', 'precondition not met — `post.status === 501 || post.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
28
29
|
expect(
|
|
29
30
|
post.status,
|
|
30
|
-
|
|
31
|
+
req('openwop.it.feedback-on-terminal-run.annotating-a-terminal-run-is-accepted', 'RFC 0056 §C', 'a host MUST accept an annotation on a terminal run'),
|
|
31
32
|
).toBe(201);
|
|
32
33
|
});
|
|
33
34
|
});
|
|
@@ -10,6 +10,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
10
10
|
import { softSkip } from '../lib/soft-skip.js';
|
|
11
11
|
import { driver } from '../lib/driver.js';
|
|
12
12
|
import { readFeedbackCap, seedRun } from '../lib/feedback.js';
|
|
13
|
+
import { req } from '../lib/requirement-ids.js';
|
|
13
14
|
|
|
14
15
|
describe('feedback-record-and-list (RFC 0056 §C)', () => {
|
|
15
16
|
it('POST an annotation then GET returns it', async () => {
|
|
@@ -21,7 +22,7 @@ describe('feedback-record-and-list (RFC 0056 §C)', () => {
|
|
|
21
22
|
if (post.status === 501 || post.status === 404) return softSkip('blocked', 'precondition not met — `post.status === 501 || post.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
22
23
|
expect(
|
|
23
24
|
post.status,
|
|
24
|
-
|
|
25
|
+
req('openwop.it.feedback-record-and-list.post-an-annotation-then-get-returns-it', 'RFC 0056 §C', 'POST annotation returns 201 with the persisted annotation'),
|
|
25
26
|
).toBe(201);
|
|
26
27
|
const created = post.json as { annotationId?: string };
|
|
27
28
|
expect(typeof created.annotationId).toBe('string');
|
|
@@ -14,6 +14,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
14
14
|
import { softSkip } from '../lib/soft-skip.js';
|
|
15
15
|
import { driver } from '../lib/driver.js';
|
|
16
16
|
import { readFeedbackCap } from '../lib/feedback.js';
|
|
17
|
+
import { req } from '../lib/requirement-ids.js';
|
|
17
18
|
|
|
18
19
|
describe('feedback-unsupported-501 (RFC 0056 §C)', () => {
|
|
19
20
|
it('POST annotations returns 501 capability_not_provided when feedback is unadvertised', async () => {
|
|
@@ -25,7 +26,7 @@ describe('feedback-unsupported-501 (RFC 0056 §C)', () => {
|
|
|
25
26
|
if (res.status === 404 || res.status === 405) return softSkip('blocked', 'route absent — host predates RFC 0056');
|
|
26
27
|
expect(
|
|
27
28
|
res.status,
|
|
28
|
-
|
|
29
|
+
req('openwop.it.feedback-unsupported-501.post-annotations-returns-501-capability-not-provided-when-feedback-is-unadvertis', 'rest-endpoints.md / RFC 0056 §C', 'unadvertised feedback MUST return 501, not 404'),
|
|
29
30
|
).toBe(501);
|
|
30
31
|
const code = (res.json as { error?: string } | undefined)?.error;
|
|
31
32
|
expect(code).toBe('capability_not_provided');
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
__resetForTests,
|
|
28
28
|
} from '../lib/fixtures.js';
|
|
29
29
|
import { isScenarioOptedOut } from '../lib/env.js';
|
|
30
|
+
import { req } from '../lib/requirement-ids.js';
|
|
30
31
|
|
|
31
32
|
beforeEach(() => {
|
|
32
33
|
__resetForTests();
|
|
@@ -34,54 +35,54 @@ beforeEach(() => {
|
|
|
34
35
|
|
|
35
36
|
describe('fixtures: cache lifecycle', () => {
|
|
36
37
|
it('returns false from isFixtureAdvertised before cache is populated', () => {
|
|
37
|
-
expect(isFixtureCacheReady()).toBe(false);
|
|
38
|
+
expect(isFixtureCacheReady(), req('openwop.it.fixtures-gating.returns-false-from-isfixtureadvertised-before-cache-is-populated', 'RFC 0003', 'returns false from isFixtureAdvertised before cache is populated')).toBe(false);
|
|
38
39
|
expect(isFixtureAdvertised('conformance-noop')).toBe(false);
|
|
39
40
|
});
|
|
40
41
|
|
|
41
42
|
it('returns null from getAdvertisedFixtures before cache is populated', () => {
|
|
42
|
-
expect(getAdvertisedFixtures()).toBe(null);
|
|
43
|
+
expect(getAdvertisedFixtures(), req('openwop.it.fixtures-gating.returns-null-from-getadvertisedfixtures-before-cache-is-populated', 'RFC 0003', 'returns null from getAdvertisedFixtures before cache is populated')).toBe(null);
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
it('isFixtureCacheReady becomes true after setAdvertisedFixtures', () => {
|
|
46
47
|
setAdvertisedFixtures({ fixtures: [] });
|
|
47
|
-
expect(isFixtureCacheReady()).toBe(true);
|
|
48
|
+
expect(isFixtureCacheReady(), req('openwop.it.fixtures-gating.isfixturecacheready-becomes-true-after-setadvertisedfixtures', 'RFC 0003', 'isFixtureCacheReady becomes true after setAdvertisedFixtures')).toBe(true);
|
|
48
49
|
});
|
|
49
50
|
|
|
50
51
|
it('returns empty set when called with null', () => {
|
|
51
52
|
setAdvertisedFixtures(null);
|
|
52
|
-
expect(getAdvertisedFixtures()?.size).toBe(0);
|
|
53
|
+
expect(getAdvertisedFixtures()?.size, req('openwop.it.fixtures-gating.returns-empty-set-when-called-with-null', 'RFC 0003', 'returns empty set when called with null')).toBe(0);
|
|
53
54
|
expect(isFixtureAdvertised('conformance-noop')).toBe(false);
|
|
54
55
|
});
|
|
55
56
|
|
|
56
57
|
it('returns empty set when called with undefined', () => {
|
|
57
58
|
setAdvertisedFixtures(undefined);
|
|
58
|
-
expect(getAdvertisedFixtures()?.size).toBe(0);
|
|
59
|
+
expect(getAdvertisedFixtures()?.size, req('openwop.it.fixtures-gating.returns-empty-set-when-called-with-undefined', 'RFC 0003', 'returns empty set when called with undefined')).toBe(0);
|
|
59
60
|
});
|
|
60
61
|
});
|
|
61
62
|
|
|
62
63
|
describe('fixtures: discovery-payload parsing', () => {
|
|
63
64
|
it('populates cache from a well-formed payload', () => {
|
|
64
65
|
setAdvertisedFixtures({ fixtures: ['conformance-noop', 'conformance-delay'] });
|
|
65
|
-
expect(isFixtureAdvertised('conformance-noop')).toBe(true);
|
|
66
|
+
expect(isFixtureAdvertised('conformance-noop'), req('openwop.it.fixtures-gating.populates-cache-from-a-well-formed-payload', 'RFC 0003', 'populates cache from a well-formed payload')).toBe(true);
|
|
66
67
|
expect(isFixtureAdvertised('conformance-delay')).toBe(true);
|
|
67
68
|
expect(isFixtureAdvertised('conformance-not-advertised')).toBe(false);
|
|
68
69
|
});
|
|
69
70
|
|
|
70
71
|
it('treats absent fixtures field as "advertises none"', () => {
|
|
71
72
|
setAdvertisedFixtures({ protocolVersion: '1.0' });
|
|
72
|
-
expect(getAdvertisedFixtures()?.size).toBe(0);
|
|
73
|
+
expect(getAdvertisedFixtures()?.size, req('openwop.it.fixtures-gating.treats-absent-fixtures-field-as-advertises-none', 'RFC 0003', 'treats absent fixtures field as "advertises none"')).toBe(0);
|
|
73
74
|
expect(isFixtureAdvertised('conformance-noop')).toBe(false);
|
|
74
75
|
});
|
|
75
76
|
|
|
76
77
|
it('treats non-array fixtures field as "advertises none"', () => {
|
|
77
78
|
setAdvertisedFixtures({ fixtures: 'conformance-noop' as unknown as string[] });
|
|
78
|
-
expect(getAdvertisedFixtures()?.size).toBe(0);
|
|
79
|
+
expect(getAdvertisedFixtures()?.size, req('openwop.it.fixtures-gating.treats-non-array-fixtures-field-as-advertises-none', 'RFC 0003', 'treats non-array fixtures field as "advertises none"')).toBe(0);
|
|
79
80
|
});
|
|
80
81
|
|
|
81
82
|
it('filters out empty-string entries', () => {
|
|
82
83
|
setAdvertisedFixtures({ fixtures: ['', 'conformance-noop', ''] });
|
|
83
84
|
const set = getAdvertisedFixtures();
|
|
84
|
-
expect(set?.size).toBe(1);
|
|
85
|
+
expect(set?.size, req('openwop.it.fixtures-gating.filters-out-empty-string-entries', 'RFC 0003', 'filters out empty-string entries')).toBe(1);
|
|
85
86
|
expect(isFixtureAdvertised('conformance-noop')).toBe(true);
|
|
86
87
|
});
|
|
87
88
|
|
|
@@ -89,7 +90,7 @@ describe('fixtures: discovery-payload parsing', () => {
|
|
|
89
90
|
setAdvertisedFixtures({
|
|
90
91
|
fixtures: ['conformance-noop', 42, null, undefined] as unknown as string[],
|
|
91
92
|
});
|
|
92
|
-
expect(getAdvertisedFixtures()?.size).toBe(1);
|
|
93
|
+
expect(getAdvertisedFixtures()?.size, req('openwop.it.fixtures-gating.filters-out-non-string-entries', 'RFC 0003', 'filters out non-string entries')).toBe(1);
|
|
93
94
|
expect(isFixtureAdvertised('conformance-noop')).toBe(true);
|
|
94
95
|
});
|
|
95
96
|
|
|
@@ -97,7 +98,7 @@ describe('fixtures: discovery-payload parsing', () => {
|
|
|
97
98
|
setAdvertisedFixtures({
|
|
98
99
|
fixtures: ['conformance-noop', 'openwop.smoke.byok', 'acme.fixture.foo'],
|
|
99
100
|
});
|
|
100
|
-
expect(isFixtureAdvertised('openwop.smoke.byok')).toBe(true);
|
|
101
|
+
expect(isFixtureAdvertised('openwop.smoke.byok'), req('openwop.it.fixtures-gating.passes-vendor-prefixed-ids-through-unchanged', 'RFC 0003', 'passes vendor-prefixed ids through unchanged')).toBe(true);
|
|
101
102
|
expect(isFixtureAdvertised('acme.fixture.foo')).toBe(true);
|
|
102
103
|
});
|
|
103
104
|
|
|
@@ -105,14 +106,14 @@ describe('fixtures: discovery-payload parsing', () => {
|
|
|
105
106
|
setAdvertisedFixtures({
|
|
106
107
|
fixtures: ['conformance-noop', 'conformance-noop', 'conformance-noop'],
|
|
107
108
|
});
|
|
108
|
-
expect(getAdvertisedFixtures()?.size).toBe(1);
|
|
109
|
+
expect(getAdvertisedFixtures()?.size, req('openwop.it.fixtures-gating.deduplicates-entries-via-set-semantics', 'RFC 0003', 'deduplicates entries via Set semantics')).toBe(1);
|
|
109
110
|
});
|
|
110
111
|
});
|
|
111
112
|
|
|
112
113
|
describe('fixtures: cache replacement (not merge)', () => {
|
|
113
114
|
it('a second setAdvertisedFixtures call replaces the cache, not merges', () => {
|
|
114
115
|
setAdvertisedFixtures({ fixtures: ['conformance-noop'] });
|
|
115
|
-
expect(isFixtureAdvertised('conformance-noop')).toBe(true);
|
|
116
|
+
expect(isFixtureAdvertised('conformance-noop'), req('openwop.it.fixtures-gating.a-second-setadvertisedfixtures-call-replaces-the-cache-not-merges', 'RFC 0003', 'a second setAdvertisedFixtures call replaces the cache, not merges')).toBe(true);
|
|
116
117
|
|
|
117
118
|
setAdvertisedFixtures({ fixtures: ['conformance-delay'] });
|
|
118
119
|
expect(isFixtureAdvertised('conformance-noop')).toBe(false);
|
|
@@ -122,7 +123,7 @@ describe('fixtures: cache replacement (not merge)', () => {
|
|
|
122
123
|
it('replacing with empty array means no fixtures advertised', () => {
|
|
123
124
|
setAdvertisedFixtures({ fixtures: ['conformance-noop'] });
|
|
124
125
|
setAdvertisedFixtures({ fixtures: [] });
|
|
125
|
-
expect(getAdvertisedFixtures()?.size).toBe(0);
|
|
126
|
+
expect(getAdvertisedFixtures()?.size, req('openwop.it.fixtures-gating.replacing-with-empty-array-means-no-fixtures-advertised', 'RFC 0003', 'replacing with empty array means no fixtures advertised')).toBe(0);
|
|
126
127
|
expect(isFixtureAdvertised('conformance-noop')).toBe(false);
|
|
127
128
|
});
|
|
128
129
|
});
|
|
@@ -130,7 +131,7 @@ describe('fixtures: cache replacement (not merge)', () => {
|
|
|
130
131
|
describe('fixtures: __resetForTests', () => {
|
|
131
132
|
it('returns the cache to the pre-populated state', () => {
|
|
132
133
|
setAdvertisedFixtures({ fixtures: ['conformance-noop'] });
|
|
133
|
-
expect(isFixtureCacheReady()).toBe(true);
|
|
134
|
+
expect(isFixtureCacheReady(), req('openwop.it.fixtures-gating.returns-the-cache-to-the-pre-populated-state', 'RFC 0003', 'returns the cache to the pre-populated state')).toBe(true);
|
|
134
135
|
__resetForTests();
|
|
135
136
|
expect(isFixtureCacheReady()).toBe(false);
|
|
136
137
|
expect(getAdvertisedFixtures()).toBe(null);
|
|
@@ -153,7 +154,7 @@ describe('fixtures: OPENWOP_OPTED_OUT_FIXTURES env filtering', () => {
|
|
|
153
154
|
setAdvertisedFixtures({
|
|
154
155
|
fixtures: ['conformance-noop', 'conformance-dispatch-input-mapping'],
|
|
155
156
|
});
|
|
156
|
-
expect(isFixtureAdvertised('conformance-noop')).toBe(true);
|
|
157
|
+
expect(isFixtureAdvertised('conformance-noop'), req('openwop.it.fixtures-gating.exact-id-is-filtered-out-of-the-advertised-set', 'RFC 0003', 'exact id is filtered out of the advertised set')).toBe(true);
|
|
157
158
|
expect(isFixtureAdvertised('conformance-dispatch-input-mapping')).toBe(false);
|
|
158
159
|
});
|
|
159
160
|
|
|
@@ -167,7 +168,7 @@ describe('fixtures: OPENWOP_OPTED_OUT_FIXTURES env filtering', () => {
|
|
|
167
168
|
'conformance-dispatch-cross-worker-handoff',
|
|
168
169
|
],
|
|
169
170
|
});
|
|
170
|
-
expect(isFixtureAdvertised('conformance-noop')).toBe(true);
|
|
171
|
+
expect(isFixtureAdvertised('conformance-noop'), req('openwop.it.fixtures-gating.trailing-glob-filters-every-matching-id', 'RFC 0003', 'trailing-* glob filters every matching id')).toBe(true);
|
|
171
172
|
expect(isFixtureAdvertised('conformance-dispatch-input-mapping')).toBe(false);
|
|
172
173
|
expect(isFixtureAdvertised('conformance-dispatch-output-mapping')).toBe(false);
|
|
173
174
|
expect(isFixtureAdvertised('conformance-dispatch-cross-worker-handoff')).toBe(false);
|
|
@@ -184,7 +185,7 @@ describe('fixtures: OPENWOP_OPTED_OUT_FIXTURES env filtering', () => {
|
|
|
184
185
|
'conformance-subworkflow-parent',
|
|
185
186
|
],
|
|
186
187
|
});
|
|
187
|
-
expect(isFixtureAdvertised('conformance-noop')).toBe(true);
|
|
188
|
+
expect(isFixtureAdvertised('conformance-noop'), req('openwop.it.fixtures-gating.exact-glob-entries-mix-in-one-env-value', 'RFC 0003', 'exact + glob entries mix in one env value')).toBe(true);
|
|
188
189
|
expect(isFixtureAdvertised('conformance-dispatch-input-mapping')).toBe(false);
|
|
189
190
|
expect(isFixtureAdvertised('conformance-subworkflow-input-mapping')).toBe(false);
|
|
190
191
|
// subworkflow-parent is NOT subworkflow-input-mapping — exact match required.
|
|
@@ -194,33 +195,33 @@ describe('fixtures: OPENWOP_OPTED_OUT_FIXTURES env filtering', () => {
|
|
|
194
195
|
it('non-matching opt-out entries leave the advertised set intact', () => {
|
|
195
196
|
process.env.OPENWOP_OPTED_OUT_FIXTURES = 'conformance-nonexistent';
|
|
196
197
|
setAdvertisedFixtures({ fixtures: ['conformance-noop'] });
|
|
197
|
-
expect(isFixtureAdvertised('conformance-noop')).toBe(true);
|
|
198
|
+
expect(isFixtureAdvertised('conformance-noop'), req('openwop.it.fixtures-gating.non-matching-opt-out-entries-leave-the-advertised-set-intact', 'RFC 0003', 'non-matching opt-out entries leave the advertised set intact')).toBe(true);
|
|
198
199
|
expect(getAdvertisedFixtures()?.size).toBe(1);
|
|
199
200
|
});
|
|
200
201
|
|
|
201
202
|
it('empty / whitespace-only entries are ignored', () => {
|
|
202
203
|
process.env.OPENWOP_OPTED_OUT_FIXTURES = ', ,conformance-noop, ,';
|
|
203
204
|
setAdvertisedFixtures({ fixtures: ['conformance-noop', 'conformance-delay'] });
|
|
204
|
-
expect(isFixtureAdvertised('conformance-noop')).toBe(false);
|
|
205
|
+
expect(isFixtureAdvertised('conformance-noop'), req('openwop.it.fixtures-gating.empty-whitespace-only-entries-are-ignored', 'RFC 0003', 'empty / whitespace-only entries are ignored')).toBe(false);
|
|
205
206
|
expect(isFixtureAdvertised('conformance-delay')).toBe(true);
|
|
206
207
|
});
|
|
207
208
|
|
|
208
209
|
it('unset env behaves identically to no filtering', () => {
|
|
209
210
|
delete process.env.OPENWOP_OPTED_OUT_FIXTURES;
|
|
210
211
|
setAdvertisedFixtures({ fixtures: ['conformance-noop', 'conformance-delay'] });
|
|
211
|
-
expect(getAdvertisedFixtures()?.size).toBe(2);
|
|
212
|
+
expect(getAdvertisedFixtures()?.size, req('openwop.it.fixtures-gating.unset-env-behaves-identically-to-no-filtering', 'RFC 0003', 'unset env behaves identically to no filtering')).toBe(2);
|
|
212
213
|
});
|
|
213
214
|
|
|
214
215
|
it('whitespace-only env behaves identically to unset', () => {
|
|
215
216
|
process.env.OPENWOP_OPTED_OUT_FIXTURES = ' ';
|
|
216
217
|
setAdvertisedFixtures({ fixtures: ['conformance-noop'] });
|
|
217
|
-
expect(isFixtureAdvertised('conformance-noop')).toBe(true);
|
|
218
|
+
expect(isFixtureAdvertised('conformance-noop'), req('openwop.it.fixtures-gating.whitespace-only-env-behaves-identically-to-unset', 'RFC 0003', 'whitespace-only env behaves identically to unset')).toBe(true);
|
|
218
219
|
});
|
|
219
220
|
|
|
220
221
|
it('env is re-read on each setAdvertisedFixtures call (no memoization)', () => {
|
|
221
222
|
process.env.OPENWOP_OPTED_OUT_FIXTURES = 'conformance-noop';
|
|
222
223
|
setAdvertisedFixtures({ fixtures: ['conformance-noop', 'conformance-delay'] });
|
|
223
|
-
expect(isFixtureAdvertised('conformance-noop')).toBe(false);
|
|
224
|
+
expect(isFixtureAdvertised('conformance-noop'), req('openwop.it.fixtures-gating.env-is-re-read-on-each-setadvertisedfixtures-call-no-memoization', 'RFC 0003', 'env is re-read on each setAdvertisedFixtures call (no memoization)')).toBe(false);
|
|
224
225
|
|
|
225
226
|
// Mutate env and re-set — the new env value MUST take effect.
|
|
226
227
|
process.env.OPENWOP_OPTED_OUT_FIXTURES = 'conformance-delay';
|
|
@@ -239,19 +240,19 @@ describe('env: OPENWOP_OPTED_OUT_SCENARIOS predicate', () => {
|
|
|
239
240
|
|
|
240
241
|
it('unset env → every scenario id returns false', () => {
|
|
241
242
|
delete process.env.OPENWOP_OPTED_OUT_SCENARIOS;
|
|
242
|
-
expect(isScenarioOptedOut('otel-trace-propagation-subworkflow')).toBe(false);
|
|
243
|
+
expect(isScenarioOptedOut('otel-trace-propagation-subworkflow'), req('openwop.it.fixtures-gating.unset-env-every-scenario-id-returns-false', 'RFC 0003', 'unset env → every scenario id returns false')).toBe(false);
|
|
243
244
|
expect(isScenarioOptedOut('any-scenario')).toBe(false);
|
|
244
245
|
});
|
|
245
246
|
|
|
246
247
|
it('exact scenario id match returns true', () => {
|
|
247
248
|
process.env.OPENWOP_OPTED_OUT_SCENARIOS = 'otel-trace-propagation-subworkflow';
|
|
248
|
-
expect(isScenarioOptedOut('otel-trace-propagation-subworkflow')).toBe(true);
|
|
249
|
+
expect(isScenarioOptedOut('otel-trace-propagation-subworkflow'), req('openwop.it.fixtures-gating.exact-scenario-id-match-returns-true', 'RFC 0003', 'exact scenario id match returns true')).toBe(true);
|
|
249
250
|
expect(isScenarioOptedOut('otel-trace-propagation')).toBe(false);
|
|
250
251
|
});
|
|
251
252
|
|
|
252
253
|
it('CSV with multiple ids matches each entry exactly', () => {
|
|
253
254
|
process.env.OPENWOP_OPTED_OUT_SCENARIOS = 'scenario-a,scenario-b,scenario-c';
|
|
254
|
-
expect(isScenarioOptedOut('scenario-a')).toBe(true);
|
|
255
|
+
expect(isScenarioOptedOut('scenario-a'), req('openwop.it.fixtures-gating.csv-with-multiple-ids-matches-each-entry-exactly', 'RFC 0003', 'CSV with multiple ids matches each entry exactly')).toBe(true);
|
|
255
256
|
expect(isScenarioOptedOut('scenario-b')).toBe(true);
|
|
256
257
|
expect(isScenarioOptedOut('scenario-c')).toBe(true);
|
|
257
258
|
expect(isScenarioOptedOut('scenario-d')).toBe(false);
|
|
@@ -259,13 +260,13 @@ describe('env: OPENWOP_OPTED_OUT_SCENARIOS predicate', () => {
|
|
|
259
260
|
|
|
260
261
|
it('whitespace around entries is tolerated', () => {
|
|
261
262
|
process.env.OPENWOP_OPTED_OUT_SCENARIOS = ' scenario-a , scenario-b ';
|
|
262
|
-
expect(isScenarioOptedOut('scenario-a')).toBe(true);
|
|
263
|
+
expect(isScenarioOptedOut('scenario-a'), req('openwop.it.fixtures-gating.whitespace-around-entries-is-tolerated', 'RFC 0003', 'whitespace around entries is tolerated')).toBe(true);
|
|
263
264
|
expect(isScenarioOptedOut('scenario-b')).toBe(true);
|
|
264
265
|
});
|
|
265
266
|
|
|
266
267
|
it('env is re-read on each call (no memoization)', () => {
|
|
267
268
|
process.env.OPENWOP_OPTED_OUT_SCENARIOS = 'scenario-a';
|
|
268
|
-
expect(isScenarioOptedOut('scenario-a')).toBe(true);
|
|
269
|
+
expect(isScenarioOptedOut('scenario-a'), req('openwop.it.fixtures-gating.env-is-re-read-on-each-call-no-memoization', 'RFC 0003', 'env is re-read on each call (no memoization)')).toBe(true);
|
|
269
270
|
expect(isScenarioOptedOut('scenario-b')).toBe(false);
|
|
270
271
|
|
|
271
272
|
process.env.OPENWOP_OPTED_OUT_SCENARIOS = 'scenario-b';
|