@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
|
@@ -46,6 +46,8 @@ import { behaviorGate } from '../lib/behavior-gate.js';
|
|
|
46
46
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
47
47
|
import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
|
|
48
48
|
import { queryTestEvents } from '../lib/event-log-query.js';
|
|
49
|
+
import { req } from '../lib/requirement-ids.js';
|
|
50
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
49
51
|
|
|
50
52
|
const FIXTURE = 'conformance-context-budget-multiturn';
|
|
51
53
|
const PROFILE = 'openwop-context-budget';
|
|
@@ -135,20 +137,20 @@ describe('context-budget-transcript-bound (RFC 0111 §"Context economy")', () =>
|
|
|
135
137
|
const cb = ma?.executionModel?.contextBudget;
|
|
136
138
|
const budget = numberOf(cb?.transcriptTokenBudget);
|
|
137
139
|
if (!behaviorGate(PROFILE, budget !== undefined)) return;
|
|
138
|
-
if (!isFixtureAdvertised(FIXTURE)) return; // fixture-gated soft-skip
|
|
140
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early (fixture-gated soft-skip)'); // fixture-gated soft-skip
|
|
139
141
|
|
|
140
142
|
const advertisedCounter = stringOf(cb?.tokenCounter);
|
|
141
143
|
expect(
|
|
142
144
|
advertisedCounter,
|
|
143
|
-
|
|
145
|
+
req('openwop.it.context-budget-transcript-bound.bounds-the-per-turn-transcript-to-transcripttokenbudget-with-an-internally-consi', 'RFC 0111', 'tokenCounter MUST be advertised when transcriptTokenBudget is present (schema if/then)'),
|
|
144
146
|
).toBeDefined();
|
|
145
147
|
|
|
146
148
|
// Drive the multi-turn orchestrator run.
|
|
147
149
|
const create = await driver.post('/v1/runs', { workflowId: FIXTURE });
|
|
148
150
|
expect(create.status).toBe(201);
|
|
149
151
|
const runId = runIdOf(create.json);
|
|
150
|
-
expect(runId, 'POST /v1/runs MUST return a runId').toBeDefined();
|
|
151
|
-
if (runId === undefined) return;
|
|
152
|
+
expect(runId, req('openwop.it.context-budget-transcript-bound.bounds-the-per-turn-transcript-to-transcripttokenbudget-with-an-internally-consi', 'RFC 0111', 'POST /v1/runs MUST return a runId')).toBeDefined();
|
|
153
|
+
if (runId === undefined) return softSkip('blocked', 'precondition not met — `runId === undefined` returned early (seam, prior step, or fixture unavailable)');
|
|
152
154
|
await pollUntilTerminal(runId);
|
|
153
155
|
|
|
154
156
|
// Probe the per-iteration transcript-window seam (OPTIONAL).
|
|
@@ -158,25 +160,25 @@ describe('context-budget-transcript-bound (RFC 0111 §"Context economy")', () =>
|
|
|
158
160
|
`/v1/host/sample/agent/transcript-window?runId=${encodeURIComponent(runId)}&iteration=${iteration}`,
|
|
159
161
|
);
|
|
160
162
|
if (res.status === 404 || res.status === 405) {
|
|
161
|
-
if (iteration === 1) return; // seam unwired — soft-skip the whole scenario
|
|
163
|
+
if (iteration === 1) return softSkip('blocked', 'precondition not met — `iteration === 1` returned early (seam unwired — soft-skip the whole scenario) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip the whole scenario
|
|
162
164
|
break; // iterations exhausted
|
|
163
165
|
}
|
|
164
166
|
if (res.status === 400 || res.status === 422) break; // iteration past the run's last turn
|
|
165
167
|
expect(
|
|
166
168
|
res.status === 200,
|
|
167
|
-
|
|
169
|
+
req('openwop.it.context-budget-transcript-bound.bounds-the-per-turn-transcript-to-transcripttokenbudget-with-an-internally-consi', 'host-sample-test-seams.md §14', 'the transcript-window seam MUST return 200 for a valid iteration'),
|
|
168
170
|
).toBe(true);
|
|
169
171
|
const window = transcriptWindowOf(res.json);
|
|
170
172
|
expect(
|
|
171
173
|
window,
|
|
172
|
-
|
|
174
|
+
req('openwop.it.context-budget-transcript-bound.bounds-the-per-turn-transcript-to-transcripttokenbudget-with-an-internally-consi', 'host-sample-test-seams.md §14', 'the seam MUST return { tokenCounter, tokenCount, eventIds, summarizedRanges }'),
|
|
173
175
|
).toBeDefined();
|
|
174
|
-
if (window === undefined) return;
|
|
176
|
+
if (window === undefined) return softSkip('blocked', 'precondition not met — `window === undefined` returned early (seam, prior step, or fixture unavailable)');
|
|
175
177
|
windows.push({ iteration, window });
|
|
176
178
|
}
|
|
177
179
|
|
|
178
180
|
// Non-vacuity: a wired seam MUST report at least one iteration.
|
|
179
|
-
expect(windows.length, 'a wired transcript-window seam MUST report at least one orchestrator iteration').toBeGreaterThan(0);
|
|
181
|
+
expect(windows.length, req('openwop.it.context-budget-transcript-bound.bounds-the-per-turn-transcript-to-transcripttokenbudget-with-an-internally-consi', 'host-sample-test-seams.md §14', 'a wired transcript-window seam MUST report at least one orchestrator iteration')).toBeGreaterThan(0);
|
|
180
182
|
|
|
181
183
|
// Independent event-log read for the cross-check (OPTIONAL seam).
|
|
182
184
|
const q = await queryTestEvents(runId);
|
|
@@ -196,14 +198,14 @@ describe('context-budget-transcript-bound (RFC 0111 §"Context economy")', () =>
|
|
|
196
198
|
// 1 — tokenCounter agreement.
|
|
197
199
|
expect(
|
|
198
200
|
window.tokenCounter,
|
|
199
|
-
|
|
201
|
+
req('openwop.it.context-budget-transcript-bound.bounds-the-per-turn-transcript-to-transcripttokenbudget-with-an-internally-consi', 'RFC 0111', `iteration ${iteration}: seam tokenCounter MUST equal the advertised contextBudget.tokenCounter`),
|
|
200
202
|
).toBe(advertisedCounter);
|
|
201
203
|
|
|
202
204
|
// 2 — the per-turn token bound.
|
|
203
205
|
if (budget !== undefined) {
|
|
204
206
|
expect(
|
|
205
207
|
window.tokenCount,
|
|
206
|
-
|
|
208
|
+
req('openwop.it.context-budget-transcript-bound.bounds-the-per-turn-transcript-to-transcripttokenbudget-with-an-internally-consi', 'RFC 0111', `iteration ${iteration}: tokenCount MUST NOT exceed transcriptTokenBudget`),
|
|
207
209
|
).toBeLessThanOrEqual(budget);
|
|
208
210
|
}
|
|
209
211
|
|
|
@@ -212,7 +214,7 @@ describe('context-budget-transcript-bound (RFC 0111 §"Context economy")', () =>
|
|
|
212
214
|
for (const id of window.eventIds) {
|
|
213
215
|
expect(
|
|
214
216
|
logEventIds.has(id),
|
|
215
|
-
|
|
217
|
+
req('openwop.it.context-budget-transcript-bound.bounds-the-per-turn-transcript-to-transcripttokenbudget-with-an-internally-consi', 'RFC 0111 §"Conformance seam"', `iteration ${iteration}: eventId "${id}" in the seam accounting MUST be a real persisted run event`),
|
|
216
218
|
).toBe(true);
|
|
217
219
|
}
|
|
218
220
|
}
|
|
@@ -221,7 +223,7 @@ describe('context-budget-transcript-bound (RFC 0111 §"Context economy")', () =>
|
|
|
221
223
|
const uniqueIds = new Set(window.eventIds);
|
|
222
224
|
expect(
|
|
223
225
|
uniqueIds.size,
|
|
224
|
-
|
|
226
|
+
req('openwop.it.context-budget-transcript-bound.bounds-the-per-turn-transcript-to-transcripttokenbudget-with-an-internally-consi', 'RFC 0111 §"Conformance seam"', `iteration ${iteration}: eventIds MUST be a tail with no repeated entry`),
|
|
225
227
|
).toBe(window.eventIds.length);
|
|
226
228
|
|
|
227
229
|
// 5 — every summarized range references a recorded context.summarized event.
|
|
@@ -229,7 +231,7 @@ describe('context-budget-transcript-bound (RFC 0111 §"Context economy")', () =>
|
|
|
229
231
|
for (const range of window.summarizedRanges) {
|
|
230
232
|
expect(
|
|
231
233
|
summarizedRefs.has(range.summaryRef),
|
|
232
|
-
|
|
234
|
+
req('openwop.it.context-budget-transcript-bound.bounds-the-per-turn-transcript-to-transcripttokenbudget-with-an-internally-consi', 'RFC 0111', `iteration ${iteration}: summarizedRanges summaryRef "${range.summaryRef}" MUST have a matching context.summarized event`),
|
|
233
235
|
).toBe(true);
|
|
234
236
|
}
|
|
235
237
|
}
|
|
@@ -245,7 +247,7 @@ describe('context-budget-transcript-bound (RFC 0111 §"Context economy")', () =>
|
|
|
245
247
|
for (const id of verbatimTail) {
|
|
246
248
|
expect(
|
|
247
249
|
summarizedIds.has(id),
|
|
248
|
-
|
|
250
|
+
req('openwop.it.context-budget-transcript-bound.bounds-the-per-turn-transcript-to-transcripttokenbudget-with-an-internally-consi', 'RFC 0111', `a kept (verbatim) turn "${id}" MUST NOT appear inside a summarized range`),
|
|
249
251
|
).toBe(false);
|
|
250
252
|
}
|
|
251
253
|
}
|
|
@@ -34,6 +34,8 @@ import { behaviorGate } from '../lib/behavior-gate.js';
|
|
|
34
34
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
35
35
|
import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
|
|
36
36
|
import { queryTestEvents, type TestEvent } from '../lib/event-log-query.js';
|
|
37
|
+
import { req } from '../lib/requirement-ids.js';
|
|
38
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
37
39
|
|
|
38
40
|
const FIXTURE = 'conformance-context-budget-multiturn';
|
|
39
41
|
const PROFILE = 'openwop-context-summarization';
|
|
@@ -98,55 +100,55 @@ describe('context-summarization-replay (RFC 0111 §"Replay determinism")', () =>
|
|
|
98
100
|
const ma = await readCapabilityFamily<MultiAgentCap>('multiAgent');
|
|
99
101
|
const summarizationSupported = ma?.executionModel?.contextBudget?.summarization?.supported === true;
|
|
100
102
|
if (!behaviorGate(PROFILE, summarizationSupported)) return;
|
|
101
|
-
if (!isFixtureAdvertised(FIXTURE)) return; // fixture-gated soft-skip
|
|
103
|
+
if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early (fixture-gated soft-skip)'); // fixture-gated soft-skip
|
|
102
104
|
|
|
103
105
|
// Drive the multi-turn orchestrator run.
|
|
104
106
|
const create = await driver.post('/v1/runs', { workflowId: FIXTURE });
|
|
105
107
|
expect(create.status).toBe(201);
|
|
106
108
|
const sourceRunId = runIdOf(create.json);
|
|
107
|
-
expect(sourceRunId, 'POST /v1/runs MUST return a runId').toBeDefined();
|
|
108
|
-
if (sourceRunId === undefined) return;
|
|
109
|
+
expect(sourceRunId, req('openwop.it.context-summarization-replay.replay-reuses-the-recorded-context-summarized-summaryref-never-re-summarizes', 'rest-endpoints.md POST /v1/runs/{runId}:fork', 'POST /v1/runs MUST return a runId')).toBeDefined();
|
|
110
|
+
if (sourceRunId === undefined) return softSkip('blocked', 'precondition not met — `sourceRunId === undefined` returned early (seam, prior step, or fixture unavailable)');
|
|
109
111
|
await pollUntilTerminal(sourceRunId);
|
|
110
112
|
|
|
111
113
|
// Read the recorded summarization records (OPTIONAL event-log seam).
|
|
112
114
|
const sourceQ = await queryTestEvents(sourceRunId, { type: 'context.summarized' });
|
|
113
|
-
if (!sourceQ.ok) return; // event-log seam unwired — soft-skip
|
|
115
|
+
if (!sourceQ.ok) return softSkip('blocked', 'precondition not met — `!sourceQ.ok` returned early (event-log seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // event-log seam unwired — soft-skip
|
|
114
116
|
const sourceFingerprints = summaryFingerprints(sourceQ.events);
|
|
115
117
|
if (sourceFingerprints.length === 0) {
|
|
116
118
|
// The run did not summarize (budget not exceeded on this host) — nothing
|
|
117
119
|
// to prove about reuse. Honest soft-skip; not a vacuous pass of the MUST.
|
|
118
120
|
// eslint-disable-next-line no-console
|
|
119
121
|
console.warn(`[${PROFILE}] run produced no context.summarized events; replay-reuse leg soft-skipped`);
|
|
120
|
-
return;
|
|
122
|
+
return softSkip('blocked', 'precondition not met — `sourceFingerprints.length === 0` returned early ([…] run produced no context.summarized events; replay-reuse leg soft-skipped) (seam, prior step, or fixture unavailable)');
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
// Only attempt replay when the host advertises the replay fork mode.
|
|
124
126
|
const wellKnown = await driver.get('/.well-known/openwop');
|
|
125
|
-
if (!replayModesOf(wellKnown.json).includes('replay')) return;
|
|
127
|
+
if (!replayModesOf(wellKnown.json).includes('replay')) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!replayModesOf(wellKnown.json).includes(\'replay\')` returned early');
|
|
126
128
|
|
|
127
129
|
const fork = await driver.post(
|
|
128
130
|
`/v1/runs/${encodeURIComponent(sourceRunId)}:fork`,
|
|
129
131
|
{ fromSeq: 0, mode: 'replay' },
|
|
130
132
|
);
|
|
131
|
-
if (fork.status === 501 || fork.status === 404) return; // replay not implemented for this run — soft-skip
|
|
133
|
+
if (fork.status === 501 || fork.status === 404) return softSkip('blocked', 'precondition not met — `fork.status === 501 || fork.status === 404` returned early (replay not implemented for this run — soft-skip) (seam, prior step, or fixture unavailable)'); // replay not implemented for this run — soft-skip
|
|
132
134
|
expect(
|
|
133
135
|
fork.status,
|
|
134
|
-
|
|
136
|
+
req('openwop.it.context-summarization-replay.replay-reuses-the-recorded-context-summarized-summaryref-never-re-summarizes', 'rest-endpoints.md POST /v1/runs/{runId}:fork', 'replay fork MUST return 201'),
|
|
135
137
|
).toBe(201);
|
|
136
138
|
const forkRunId = runIdOf(fork.json);
|
|
137
|
-
expect(forkRunId, 'replay fork MUST return a runId').toBeDefined();
|
|
138
|
-
if (forkRunId === undefined) return;
|
|
139
|
+
expect(forkRunId, req('openwop.it.context-summarization-replay.replay-reuses-the-recorded-context-summarized-summaryref-never-re-summarizes', 'rest-endpoints.md POST /v1/runs/{runId}:fork', 'replay fork MUST return a runId')).toBeDefined();
|
|
140
|
+
if (forkRunId === undefined) return softSkip('blocked', 'precondition not met — `forkRunId === undefined` returned early (seam, prior step, or fixture unavailable)');
|
|
139
141
|
await pollUntilTerminal(forkRunId);
|
|
140
142
|
|
|
141
143
|
const forkQ = await queryTestEvents(forkRunId, { type: 'context.summarized' });
|
|
142
|
-
if (!forkQ.ok) return; // event-log seam unwired for the fork — soft-skip
|
|
144
|
+
if (!forkQ.ok) return softSkip('blocked', 'precondition not met — `!forkQ.ok` returned early (event-log seam unwired for the fork — soft-skip) (seam, prior step, or fixture unavailable)'); // event-log seam unwired for the fork — soft-skip
|
|
143
145
|
const forkFingerprints = summaryFingerprints(forkQ.events);
|
|
144
146
|
|
|
145
147
|
// The replay MUST reuse the recorded summaries (same summaryRef + replacedTurns),
|
|
146
148
|
// NOT regenerate them — the direct analogue of RFC 0041 envelope-refusal recovery.
|
|
147
149
|
expect(
|
|
148
150
|
forkFingerprints,
|
|
149
|
-
|
|
151
|
+
req('openwop.it.context-summarization-replay.replay-reuses-the-recorded-context-summarized-summaryref-never-re-summarizes',
|
|
150
152
|
'RFC 0111 §"Replay determinism"',
|
|
151
153
|
'a replay fork MUST reuse the recorded context.summarized summaryRef (never re-summarize to a different transcript)',
|
|
152
154
|
),
|
|
@@ -49,8 +49,8 @@ import Ajv2020 from 'ajv/dist/2020.js';
|
|
|
49
49
|
import addFormats from 'ajv-formats';
|
|
50
50
|
import { driver } from '../lib/driver.js';
|
|
51
51
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
import { req } from '../lib/requirement-ids.js';
|
|
53
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
54
54
|
|
|
55
55
|
function provenanceSubschema(): Record<string, unknown> {
|
|
56
56
|
const caps = JSON.parse(
|
|
@@ -73,11 +73,11 @@ describe('contract-provenance (RFC 0146, always-on)', () => {
|
|
|
73
73
|
|
|
74
74
|
expect(
|
|
75
75
|
caps.properties['contractProvenance'],
|
|
76
|
-
|
|
76
|
+
req('openwop.it.contract-provenance.a1-declared-at-the-document-root-and-optional', 'capabilities.schema.json', 'declared as a root property — families live at the document root per capabilities.md §"Document-root layout", never under the deprecated wrapper'),
|
|
77
77
|
).toBeDefined();
|
|
78
78
|
expect(
|
|
79
79
|
(caps.required ?? []).includes('contractProvenance'),
|
|
80
|
-
|
|
80
|
+
req('openwop.it.contract-provenance.a1-declared-at-the-document-root-and-optional', 'RFC 0146 req 1', 'OPTIONAL — absent means UNSPECIFIED provenance, not "current" and not "stale"; a host must not be non-conformant for staying silent'),
|
|
81
81
|
).toBe(false);
|
|
82
82
|
});
|
|
83
83
|
|
|
@@ -86,32 +86,32 @@ describe('contract-provenance (RFC 0146, always-on)', () => {
|
|
|
86
86
|
|
|
87
87
|
expect(
|
|
88
88
|
validate({ suiteVersion: '1.72.0', corpusCommit: '93d4692eb1e28244b860da6ddcb6521b57a712b3' }),
|
|
89
|
-
|
|
89
|
+
req('openwop.it.contract-provenance.a2-a-full-40-hex-commit-validates-a-short-sha-or-a-vendor-build-string-does-not', 'RFC 0146 req 4', `a real stamp validates: ${JSON.stringify(validate.errors)}`),
|
|
90
90
|
).toBe(true);
|
|
91
91
|
// This is what keeps the field from decaying into a free-text version box. A short SHA is
|
|
92
92
|
// ambiguous across a growing history; a vendor build id belongs in `implementation`, which
|
|
93
93
|
// already exists for exactly that.
|
|
94
94
|
expect(
|
|
95
95
|
validate({ corpusCommit: '93d4692' }),
|
|
96
|
-
|
|
96
|
+
req('openwop.it.contract-provenance.a2-a-full-40-hex-commit-validates-a-short-sha-or-a-vendor-build-string-does-not', 'RFC 0146 req 4', 'a SHORT sha is REJECTED — abbreviated commits are ambiguous and this field is an identity, not a hint'),
|
|
97
97
|
).toBe(false);
|
|
98
98
|
expect(
|
|
99
99
|
validate({ corpusCommit: 'build-4711' }),
|
|
100
|
-
|
|
100
|
+
req('openwop.it.contract-provenance.a2-a-full-40-hex-commit-validates-a-short-sha-or-a-vendor-build-string-does-not', 'RFC 0146 req 4', 'a vendor build identifier is REJECTED — `implementation` is the field for that'),
|
|
101
101
|
).toBe(false);
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
it('A3 — both members optional, and unknown members rejected', () => {
|
|
105
105
|
const validate = compiled();
|
|
106
106
|
|
|
107
|
-
expect(validate({}),
|
|
107
|
+
expect(validate({}), req('openwop.it.contract-provenance.a3-both-members-optional-and-unknown-members-rejected', 'RFC 0146 req 1', 'an empty object validates — a host may know neither')).toBe(true);
|
|
108
108
|
expect(
|
|
109
109
|
validate({ suiteVersion: '1.72.0' }),
|
|
110
|
-
|
|
110
|
+
req('openwop.it.contract-provenance.a3-both-members-optional-and-unknown-members-rejected', 'RFC 0146 req 1', 'a host that knows only its suite version advertises only that'),
|
|
111
111
|
).toBe(true);
|
|
112
112
|
expect(
|
|
113
113
|
validate({ suiteVersion: '1.72.0', schemaDigest: 'abc' }),
|
|
114
|
-
|
|
114
|
+
req('openwop.it.contract-provenance.a3-both-members-optional-and-unknown-members-rejected', 'RFC 0146 §Proposal', 'the object is closed — a digest is a DIFFERENT artifact answering a different question (tamper vs identity) and is deliberately not part of this shape'),
|
|
115
115
|
).toBe(false);
|
|
116
116
|
});
|
|
117
117
|
|
|
@@ -135,7 +135,7 @@ describe('contract-provenance (RFC 0146, always-on)', () => {
|
|
|
135
135
|
const rfc = rfcText ?? '';
|
|
136
136
|
expect(
|
|
137
137
|
/MUST NOT reject a request, refuse interop, or fail a run solely because/.test(rfc),
|
|
138
|
-
|
|
138
|
+
req('openwop.it.contract-provenance.a4-the-rfc-states-the-advisory-rule-which-is-what-stops-this-becoming-an-upgrade', 'RFC 0146 req 3', 'a consumer MUST NOT reject on a mismatch — v1.x revisions are additive, so a host on an older revision is CONFORMANT and the field detects drift rather than creating an error'),
|
|
139
139
|
).toBe(true);
|
|
140
140
|
});
|
|
141
141
|
});
|
|
@@ -156,14 +156,14 @@ function suiteStamp(): { suiteVersion?: string; corpusCommit?: string } | null {
|
|
|
156
156
|
describe('contract-provenance: the suite READS the advert — the consumer half (RFC 0146 G3)', () => {
|
|
157
157
|
it('compares the advertised revision against the suite\'s own, and reports drift', async () => {
|
|
158
158
|
const mine = suiteStamp();
|
|
159
|
-
if (mine === null) return; // repo layout — inapplicable, see the docblock
|
|
159
|
+
if (mine === null) return softSkip('blocked', 'precondition not met — `mine === null` returned early (repo layout — inapplicable, see the docblock) (seam, prior step, or fixture unavailable)'); // repo layout — inapplicable, see the docblock
|
|
160
160
|
|
|
161
161
|
const res = await driver.get('/.well-known/openwop');
|
|
162
|
-
if (res.status !== 200 || res.json === null || res.json === undefined) return;
|
|
162
|
+
if (res.status !== 200 || res.json === null || res.json === undefined) return softSkip('blocked', 'precondition not met — `res.status !== 200 || res.json === null || res.json === undefined` returned early (seam, prior step, or fixture unavailable)');
|
|
163
163
|
const adv = (res.json as Record<string, unknown>)['contractProvenance'] as
|
|
164
164
|
| { suiteVersion?: string; corpusCommit?: string }
|
|
165
165
|
| undefined;
|
|
166
|
-
if (adv === undefined) return; // silent host — absent means UNSPECIFIED (req 1), not stale
|
|
166
|
+
if (adv === undefined) return softSkip('blocked', 'precondition not met — `adv === undefined` returned early (silent host — absent means UNSPECIFIED (req 1), not stale) (seam, prior step, or fixture unavailable)'); // silent host — absent means UNSPECIFIED (req 1), not stale
|
|
167
167
|
|
|
168
168
|
const same = adv.corpusCommit !== undefined && adv.corpusCommit === mine.corpusCommit;
|
|
169
169
|
console.log(
|
|
@@ -178,7 +178,7 @@ describe('contract-provenance: the suite READS the advert — the consumer half
|
|
|
178
178
|
// because an unparseable provenance is useless to every consumer, not just this one.
|
|
179
179
|
expect(
|
|
180
180
|
typeof adv.corpusCommit === 'string' || typeof adv.suiteVersion === 'string',
|
|
181
|
-
|
|
181
|
+
req('openwop.it.contract-provenance.compares-the-advertised-revision-against-the-suite-s-own-and-reports-drift',
|
|
182
182
|
'RFC 0146 req 1 + req 4',
|
|
183
183
|
'an advertised contractProvenance carries at least one of suiteVersion / corpusCommit — an object conveying neither is indistinguishable from silence while looking like an answer',
|
|
184
184
|
),
|
|
@@ -189,18 +189,18 @@ describe('contract-provenance: the suite READS the advert — the consumer half
|
|
|
189
189
|
describe('contract-provenance: a host advertising it makes a well-formed claim (RFC 0146)', () => {
|
|
190
190
|
it('the advertised provenance validates against the declared shape', async () => {
|
|
191
191
|
const res = await driver.get('/.well-known/openwop');
|
|
192
|
-
if (res.status !== 200 || res.json === null || res.json === undefined) return;
|
|
192
|
+
if (res.status !== 200 || res.json === null || res.json === undefined) return softSkip('blocked', 'precondition not met — `res.status !== 200 || res.json === null || res.json === undefined` returned early (seam, prior step, or fixture unavailable)');
|
|
193
193
|
|
|
194
194
|
const doc = res.json as Record<string, unknown>;
|
|
195
195
|
const adv = doc['contractProvenance'];
|
|
196
196
|
// INAPPLICABLE, not gated. The field is OPTIONAL (req 1) and strict mode must not coerce a
|
|
197
197
|
// host into advertising — the same call RFC 0142 makes for `store` and RFC 0145 for
|
|
198
198
|
// `registrationSource`. Silence is an honest answer here.
|
|
199
|
-
if (adv === undefined) return;
|
|
199
|
+
if (adv === undefined) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `adv === undefined` returned early (INAPPLICABLE, not gated. The field is OPTIONAL (req 1) and strict mode must not coerce a host into advertising — the same ca…');
|
|
200
200
|
|
|
201
201
|
expect(
|
|
202
202
|
compiled()(adv),
|
|
203
|
-
|
|
203
|
+
req('openwop.it.contract-provenance.the-advertised-provenance-validates-against-the-declared-shape',
|
|
204
204
|
'capabilities.schema.json §contractProvenance',
|
|
205
205
|
`an advertised contractProvenance MUST match the declared shape — a full 40-hex corpusCommit and a published suiteVersion, nothing else: ${JSON.stringify(compiled().errors)}`,
|
|
206
206
|
),
|
|
@@ -35,8 +35,7 @@ import { join } from 'node:path';
|
|
|
35
35
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
36
36
|
import addFormats from 'ajv-formats';
|
|
37
37
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
38
|
-
|
|
39
|
-
const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
|
|
38
|
+
import { req } from '../lib/requirement-ids.js';
|
|
40
39
|
|
|
41
40
|
function loadSchema(name: string): Record<string, unknown> {
|
|
42
41
|
return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
|
|
@@ -60,36 +59,36 @@ describe('conversation-turn-model-provenance-shape: agent.model on a role:agent
|
|
|
60
59
|
it('an agent turn carrying a conforming agent.model { provider, model } validates', () => {
|
|
61
60
|
expect(
|
|
62
61
|
turn({ ...agentBase, agent: { agentId: 'advisor-cfo', model: { provider: 'anthropic', model: 'claude-opus-4-8' } } }),
|
|
63
|
-
|
|
62
|
+
req('openwop.it.conversation-turn-model-provenance-shape.an-agent-turn-carrying-a-conforming-agent-model-provider-model-validates', 'RFC 0109 §Proposal', "a role:'agent' turn with agent.model { provider, model } MUST validate"),
|
|
64
63
|
).toBe(true);
|
|
65
64
|
});
|
|
66
65
|
|
|
67
66
|
it('agent.model REQUIRES both provider and model', () => {
|
|
68
67
|
expect(
|
|
69
68
|
turn({ ...agentBase, agent: { model: { provider: 'anthropic' } } }),
|
|
70
|
-
|
|
69
|
+
req('openwop.it.conversation-turn-model-provenance-shape.agent-model-requires-both-provider-and-model', 'RFC 0109 §Proposal', 'agent.model without `model` MUST be rejected'),
|
|
71
70
|
).toBe(false);
|
|
72
71
|
expect(
|
|
73
72
|
turn({ ...agentBase, agent: { model: { model: 'claude-opus-4-8' } } }),
|
|
74
|
-
|
|
73
|
+
req('openwop.it.conversation-turn-model-provenance-shape.agent-model-requires-both-provider-and-model', 'RFC 0109 §Proposal', 'agent.model without `provider` MUST be rejected'),
|
|
75
74
|
).toBe(false);
|
|
76
75
|
});
|
|
77
76
|
|
|
78
77
|
it('agent.model is CLOSED — an extra key (a secret/endpoint/prompt) MUST be rejected (the SR-1 guard)', () => {
|
|
79
78
|
expect(
|
|
80
79
|
turn({ ...agentBase, agent: { model: { provider: 'anthropic', model: 'claude-opus-4-8', apiKey: 'sk-secret' } } }),
|
|
81
|
-
|
|
80
|
+
req('openwop.it.conversation-turn-model-provenance-shape.agent-model-is-closed-an-extra-key-a-secret-endpoint-prompt-must-be-rejected-the', 'RFC 0109 §Proposal', 'agent.model MUST forbid extra keys — no credential/endpoint/prompt rides the provenance stamp'),
|
|
82
81
|
).toBe(false);
|
|
83
82
|
});
|
|
84
83
|
|
|
85
84
|
it('agent.model is OPTIONAL — an agent turn that omits it still validates (additive, back-compat)', () => {
|
|
86
85
|
expect(
|
|
87
86
|
turn({ ...agentBase, agent: { agentId: 'advisor-cfo' } }),
|
|
88
|
-
|
|
87
|
+
req('openwop.it.conversation-turn-model-provenance-shape.agent-model-is-optional-an-agent-turn-that-omits-it-still-validates-additive-bac', 'RFC 0109 §Compatibility', 'agent.model is additive — a turn without it MUST still validate'),
|
|
89
88
|
).toBe(true);
|
|
90
89
|
expect(
|
|
91
90
|
turn(agentBase),
|
|
92
|
-
|
|
91
|
+
req('openwop.it.conversation-turn-model-provenance-shape.agent-model-is-optional-an-agent-turn-that-omits-it-still-validates-additive-bac', 'RFC 0109 §Compatibility', 'a turn with no agent object at all MUST still validate'),
|
|
93
92
|
).toBe(true);
|
|
94
93
|
});
|
|
95
94
|
});
|
|
@@ -101,10 +100,10 @@ describe('conversation-turn-model-provenance-shape: capability advertisement (RF
|
|
|
101
100
|
const block = props.conversationTurnModelProvenance as
|
|
102
101
|
| { properties?: Record<string, unknown>; required?: string[]; additionalProperties?: boolean }
|
|
103
102
|
| undefined;
|
|
104
|
-
expect(block,
|
|
105
|
-
expect(block?.properties?.supported,
|
|
106
|
-
expect(block?.required,
|
|
107
|
-
expect(block?.additionalProperties,
|
|
103
|
+
expect(block, req('openwop.it.conversation-turn-model-provenance-shape.capabilities-schema-json-declares-conversationturnmodelprovenance-with-supported', 'RFC 0109 §Conformance', 'capabilities.conversationTurnModelProvenance MUST be declared')).toBeDefined();
|
|
104
|
+
expect(block?.properties?.supported, req('openwop.it.conversation-turn-model-provenance-shape.capabilities-schema-json-declares-conversationturnmodelprovenance-with-supported', 'RFC 0109 §Conformance', 'conversationTurnModelProvenance.supported MUST be declared')).toBeDefined();
|
|
105
|
+
expect(block?.required, req('openwop.it.conversation-turn-model-provenance-shape.capabilities-schema-json-declares-conversationturnmodelprovenance-with-supported', 'RFC 0109 §Conformance', 'supported MUST be required on the block')).toContain('supported');
|
|
106
|
+
expect(block?.additionalProperties, req('openwop.it.conversation-turn-model-provenance-shape.capabilities-schema-json-declares-conversationturnmodelprovenance-with-supported', 'RFC 0109 §Conformance', 'the block MUST be closed')).toBe(false);
|
|
108
107
|
});
|
|
109
108
|
|
|
110
109
|
it('the conversationTurnModelProvenance block validates a conforming advertisement and rejects extras', () => {
|
|
@@ -113,8 +112,8 @@ describe('conversation-turn-model-provenance-shape: capability advertisement (RF
|
|
|
113
112
|
const ajv = new Ajv2020({ strict: false, allErrors: true });
|
|
114
113
|
addFormats(ajv);
|
|
115
114
|
const validate = ajv.compile(block);
|
|
116
|
-
expect(validate({ supported: true }),
|
|
117
|
-
expect(validate({}),
|
|
118
|
-
expect(validate({ supported: true, unexpected: 1 }),
|
|
115
|
+
expect(validate({ supported: true }), req('openwop.it.conversation-turn-model-provenance-shape.the-conversationturnmodelprovenance-block-validates-a-conforming-advertisement-a', 'RFC 0109 §Conformance', 'a conforming advertisement MUST validate')).toBe(true);
|
|
116
|
+
expect(validate({}), req('openwop.it.conversation-turn-model-provenance-shape.the-conversationturnmodelprovenance-block-validates-a-conforming-advertisement-a', 'RFC 0109 §Conformance', 'supported is required')).toBe(false);
|
|
117
|
+
expect(validate({ supported: true, unexpected: 1 }), req('openwop.it.conversation-turn-model-provenance-shape.the-conversationturnmodelprovenance-block-validates-a-conforming-advertisement-a', 'RFC 0109 §Conformance', 'an extra key MUST be rejected (closed block)')).toBe(false);
|
|
119
118
|
});
|
|
120
119
|
});
|
|
@@ -21,6 +21,7 @@ import { readErrorCode } from '../lib/error-envelope.js';
|
|
|
21
21
|
import { driver } from '../lib/driver.js';
|
|
22
22
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
23
23
|
import { isConversationPrimitiveSupported } from '../lib/multi-agent-capabilities.js';
|
|
24
|
+
import { req } from '../lib/requirement-ids.js';
|
|
24
25
|
|
|
25
26
|
const FIXTURE = 'conformance-conversation-capability-negotiation';
|
|
26
27
|
// Inverted gate: this scenario runs when host does NOT advertise the
|
|
@@ -33,7 +34,7 @@ describe.skipIf(SKIP)('conversationCapabilityNegotiation: refusal contract', ()
|
|
|
33
34
|
// The host MUST reject — either at workflow registration (404/400)
|
|
34
35
|
// or at run-create (400). What MUST NOT happen is a successful
|
|
35
36
|
// 201 followed by silent fallback.
|
|
36
|
-
expect([400, 404, 422]).toContain(create.status);
|
|
37
|
+
expect([400, 404, 422], req('openwop.it.conversationCapabilityNegotiation.host-without-conversationprimitive-capability-refuses-conversation-bearing-workf', 'RFCS/0005-conversation.md', 'host without conversationPrimitive capability refuses conversation-bearing workflow')).toContain(create.status);
|
|
37
38
|
const body = create.json as { code?: string };
|
|
38
39
|
const code = readErrorCode(create.json) ?? body.code ?? '';
|
|
39
40
|
expect(typeof code).toBe('string');
|
|
@@ -22,6 +22,7 @@ import { driver } from '../lib/driver.js';
|
|
|
22
22
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
23
23
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
24
24
|
import { isConversationPrimitiveSupported } from '../lib/multi-agent-capabilities.js';
|
|
25
|
+
import { req } from '../lib/requirement-ids.js';
|
|
25
26
|
|
|
26
27
|
const FIXTURE = 'conformance-conversation-lifecycle';
|
|
27
28
|
const SKIP = !isConversationPrimitiveSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -29,7 +30,7 @@ const SKIP = !isConversationPrimitiveSupported() || !isFixtureAdvertised(FIXTURE
|
|
|
29
30
|
describe.skipIf(SKIP)('conversationLifecycle: open → exchange → close round-trip', () => {
|
|
30
31
|
it('emits all three lifecycle events with matching conversationId; no exchanges after close', async () => {
|
|
31
32
|
const create = await driver.post('/v1/runs', { workflowId: FIXTURE });
|
|
32
|
-
expect(create.status).toBe(201);
|
|
33
|
+
expect(create.status, req('openwop.it.conversationLifecycle.emits-all-three-lifecycle-events-with-matching-conversationid-no-exchanges-after', 'RFCS/0005-conversation.md', 'emits all three lifecycle events with matching conversationId; no exchanges after close')).toBe(201);
|
|
33
34
|
const runId = (create.json as { runId: string }).runId;
|
|
34
35
|
|
|
35
36
|
// The fixture's exchange step requires resume input. Host-internal
|
|
@@ -19,6 +19,8 @@ import { driver } from '../lib/driver.js';
|
|
|
19
19
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
20
20
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
21
21
|
import { isConversationPrimitiveSupported } from '../lib/multi-agent-capabilities.js';
|
|
22
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
23
|
+
import { req } from '../lib/requirement-ids.js';
|
|
22
24
|
|
|
23
25
|
const FIXTURE = 'conformance-conversation-replay';
|
|
24
26
|
const SKIP = !isConversationPrimitiveSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -26,7 +28,7 @@ const SKIP = !isConversationPrimitiveSupported() || !isFixtureAdvertised(FIXTURE
|
|
|
26
28
|
describe.skipIf(SKIP)('conversationReplayDeterminism: replay-fork preserves conversation log', () => {
|
|
27
29
|
it('forked run yields byte-equal conversation channel projection', async () => {
|
|
28
30
|
const create = await driver.post('/v1/runs', { workflowId: FIXTURE });
|
|
29
|
-
expect(create.status).toBe(201);
|
|
31
|
+
expect(create.status, req('openwop.it.conversationReplayDeterminism.forked-run-yields-byte-equal-conversation-channel-projection', 'RFCS/0005-conversation.md', 'forked run yields byte-equal conversation channel projection')).toBe(201);
|
|
30
32
|
const sourceRunId = (create.json as { runId: string }).runId;
|
|
31
33
|
|
|
32
34
|
const terminal = await pollUntilTerminal(sourceRunId);
|
|
@@ -38,7 +40,7 @@ describe.skipIf(SKIP)('conversationReplayDeterminism: replay-fork preserves conv
|
|
|
38
40
|
const fork = await driver.post(`/v1/runs/${encodeURIComponent(sourceRunId)}:fork`, {
|
|
39
41
|
mode: 'replay',
|
|
40
42
|
});
|
|
41
|
-
if (fork.status === 404 || fork.status === 501) return; // host doesn't support replay-fork
|
|
43
|
+
if (fork.status === 404 || fork.status === 501) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `fork.status === 404 || fork.status === 501` returned early (host doesn\'t support replay-fork)'); // host doesn't support replay-fork
|
|
42
44
|
expect([200, 201]).toContain(fork.status);
|
|
43
45
|
|
|
44
46
|
const forkedRunId = (fork.json as { runId: string }).runId;
|
|
@@ -20,6 +20,7 @@ import { driver } from '../lib/driver.js';
|
|
|
20
20
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
21
21
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
22
22
|
import { isConversationPrimitiveSupported } from '../lib/multi-agent-capabilities.js';
|
|
23
|
+
import { req } from '../lib/requirement-ids.js';
|
|
23
24
|
|
|
24
25
|
const FIXTURE = 'conformance-conversation-vs-clarification';
|
|
25
26
|
const SKIP = !isConversationPrimitiveSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -41,7 +42,7 @@ describe.skipIf(SKIP)('conversationVsLegacySuspend: distinct event surfaces', ()
|
|
|
41
42
|
expect(conversationEvents.length).toBeGreaterThan(0);
|
|
42
43
|
expect(
|
|
43
44
|
clarificationEvents.length,
|
|
44
|
-
'conversation.exchange MUST NOT emit clarification.* events',
|
|
45
|
+
req('openwop.it.conversationVsLegacySuspend.conversation-suspend-emits-conversation-events-not-clarification', 'RFCS/0005-conversation.md', 'conversation.exchange MUST NOT emit clarification.* events'),
|
|
45
46
|
).toBe(0);
|
|
46
47
|
});
|
|
47
48
|
});
|
|
@@ -24,8 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
import { describe, it, expect } from 'vitest';
|
|
26
26
|
import { isCoreStandard, isCore, deriveProfiles } from '../lib/profiles.js';
|
|
27
|
-
|
|
28
|
-
const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
|
|
27
|
+
import { req } from '../lib/requirement-ids.js';
|
|
29
28
|
|
|
30
29
|
const CORE = {
|
|
31
30
|
protocolVersion: '1.0',
|
|
@@ -38,29 +37,29 @@ describe('core-standard-profile: floor predicate (RFC 0088 §B, server-free)', (
|
|
|
38
37
|
it('a host meeting core + interrupts + a default transport is core-standard', () => {
|
|
39
38
|
// No supportedTransports ⇒ both stream predicates default-true (profiles.md).
|
|
40
39
|
const c = { ...CORE };
|
|
41
|
-
expect(isCoreStandard(c),
|
|
40
|
+
expect(isCoreStandard(c), req('openwop.it.core-standard-profile.a-host-meeting-core-interrupts-a-default-transport-is-core-standard', 'core-standard-profile.md §B', 'core + interrupts + transport ⇒ core-standard')).toBe(true);
|
|
42
41
|
});
|
|
43
42
|
|
|
44
43
|
it('a bare openwop-core host without interrupts is NOT core-standard', () => {
|
|
45
44
|
// openwop-core minimum, but no clarification.request ⇒ fails openwop-interrupts.
|
|
46
45
|
const c = { ...CORE, supportedEnvelopes: ['schema.request'] };
|
|
47
|
-
expect(isCore(c),
|
|
48
|
-
expect(isCoreStandard(c),
|
|
46
|
+
expect(isCore(c), req('openwop.it.core-standard-profile.a-bare-openwop-core-host-without-interrupts-is-not-core-standard', 'profiles.md §openwop-core', 'still a valid openwop-core host')).toBe(true);
|
|
47
|
+
expect(isCoreStandard(c), req('openwop.it.core-standard-profile.a-bare-openwop-core-host-without-interrupts-is-not-core-standard', 'core-standard-profile.md §B', 'the floor is stricter than the v1 minimum')).toBe(false);
|
|
49
48
|
});
|
|
50
49
|
|
|
51
50
|
it('a host advertising no event transport fails the floor', () => {
|
|
52
51
|
const c = { ...CORE, supportedTransports: [] as string[] };
|
|
53
|
-
expect(isCoreStandard(c),
|
|
52
|
+
expect(isCoreStandard(c), req('openwop.it.core-standard-profile.a-host-advertising-no-event-transport-fails-the-floor', 'core-standard-profile.md §B', 'at least one event transport is required')).toBe(false);
|
|
54
53
|
});
|
|
55
54
|
|
|
56
55
|
it('a host advertising the rest transport satisfies the transport term', () => {
|
|
57
56
|
const c = { ...CORE, supportedTransports: ['rest'] };
|
|
58
|
-
expect(isCoreStandard(c),
|
|
57
|
+
expect(isCoreStandard(c), req('openwop.it.core-standard-profile.a-host-advertising-the-rest-transport-satisfies-the-transport-term', 'core-standard-profile.md §B', 'rest transport ⇒ stream term satisfied')).toBe(true);
|
|
59
58
|
});
|
|
60
59
|
|
|
61
60
|
it('a non-1.x host is not core-standard', () => {
|
|
62
61
|
const c = { ...CORE, protocolVersion: '2.0' };
|
|
63
|
-
expect(isCoreStandard(c),
|
|
62
|
+
expect(isCoreStandard(c), req('openwop.it.core-standard-profile.a-non-1-x-host-is-not-core-standard', 'profiles.md §openwop-core', 'core-standard implies openwop-core (1.x)')).toBe(false);
|
|
64
63
|
});
|
|
65
64
|
});
|
|
66
65
|
|
|
@@ -69,7 +68,7 @@ describe('core-standard-profile: composes, does not redefine (RFC 0088 §A, serv
|
|
|
69
68
|
const c = { ...CORE };
|
|
70
69
|
expect(
|
|
71
70
|
(deriveProfiles(c) as readonly string[]).includes('openwop-core-standard'),
|
|
72
|
-
|
|
71
|
+
req('openwop.it.core-standard-profile.openwop-core-standard-is-an-annex-not-a-closed-catalog-profile-absent-from-deriv', 'core-standard-profile.md §A', 'the annex is not a closed-catalog predicate'),
|
|
73
72
|
).toBe(false);
|
|
74
73
|
});
|
|
75
74
|
});
|