@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
|
@@ -23,6 +23,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
23
23
|
import { softSkip } from '../lib/soft-skip.js';
|
|
24
24
|
import { driver } from '../lib/driver.js';
|
|
25
25
|
import { capabilityFamily, discoveryFamilies } from '../lib/discovery-capabilities.js';
|
|
26
|
+
import { req } from '../lib/requirement-ids.js';
|
|
26
27
|
|
|
27
28
|
async function isMcpClientSupported(): Promise<boolean> {
|
|
28
29
|
const disco = await driver.get('/.well-known/openwop');
|
|
@@ -44,12 +45,12 @@ describe('mcp-toolcall-redaction: capability advertisement contract', () => {
|
|
|
44
45
|
};
|
|
45
46
|
}), 'mcpClient');
|
|
46
47
|
|
|
47
|
-
expect(cap?.supported,
|
|
48
|
+
expect(cap?.supported, req('openwop.it.mcp-toolcall-redaction.host-advertising-mcpclient-must-declare-trustboundary-untrusted',
|
|
48
49
|
'host-capabilities.md §host.mcp',
|
|
49
50
|
'mcpClient.supported MUST be a boolean',
|
|
50
51
|
)).toBe(true);
|
|
51
52
|
|
|
52
|
-
expect(Array.isArray(cap?.transports),
|
|
53
|
+
expect(Array.isArray(cap?.transports), req('openwop.it.mcp-toolcall-redaction.host-advertising-mcpclient-must-declare-trustboundary-untrusted',
|
|
53
54
|
'host-capabilities.md §host.mcp',
|
|
54
55
|
'mcpClient.transports MUST be an array of transport identifiers',
|
|
55
56
|
)).toBe(true);
|
|
@@ -59,7 +60,7 @@ describe('mcp-toolcall-redaction: capability advertisement contract', () => {
|
|
|
59
60
|
// Hosts advertising mcpClient MUST encode the boundary in the
|
|
60
61
|
// capability so downstream consumers (LLM nodes) treat the
|
|
61
62
|
// content accordingly.
|
|
62
|
-
expect(cap?.trustBoundary,
|
|
63
|
+
expect(cap?.trustBoundary, req('openwop.it.mcp-toolcall-redaction.host-advertising-mcpclient-must-declare-trustboundary-untrusted',
|
|
63
64
|
'SECURITY/threat-model-prompt-injection.md §"UNTRUSTED marker"',
|
|
64
65
|
'mcpClient.trustBoundary MUST be "untrusted" — downstream LLM nodes treat tool content as user data',
|
|
65
66
|
)).toBe('untrusted');
|
|
@@ -27,10 +27,11 @@
|
|
|
27
27
|
import { describe, it, expect } from 'vitest';
|
|
28
28
|
import { driver } from '../lib/driver.js';
|
|
29
29
|
import { readErrorCode } from '../lib/error-envelope.js';
|
|
30
|
-
import { seamAbsent } from '../lib/soft-skip.js';
|
|
30
|
+
import { seamAbsent, softSkip } from '../lib/soft-skip.js';
|
|
31
31
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
32
32
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
33
33
|
import { getMcpFakeServer } from '../lib/mcp-fake-server.js';
|
|
34
|
+
import { req } from '../lib/requirement-ids.js';
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* Callback-shaped: the host issues MCP calls to the suite's fake server, which records the revision header.
|
|
@@ -67,7 +68,7 @@ describe('RFC 0153 §A/§B — MCP revision negotiation', () => {
|
|
|
67
68
|
for (const v of caps?.protocolVersions ?? []) {
|
|
68
69
|
expect(
|
|
69
70
|
DATE_FORM.test(v),
|
|
70
|
-
|
|
71
|
+
req('openwop.it.mcp-version-negotiation.advertised-revisions-use-mcp-date-form-and-include-the-preferred-one',
|
|
71
72
|
'RFCS/0153-mcp-2026-07-28-versioned-composition.md §A',
|
|
72
73
|
`'${v}' is not MCP's date form. MCP revisions ARE dates, and 'latest' or an unpadded ` +
|
|
73
74
|
'month lets two hosts disagree about which revision they share while both look valid.',
|
|
@@ -76,39 +77,39 @@ describe('RFC 0153 §A/§B — MCP revision negotiation', () => {
|
|
|
76
77
|
}
|
|
77
78
|
expect(
|
|
78
79
|
caps?.protocolVersions ?? [],
|
|
79
|
-
|
|
80
|
+
req('openwop.it.mcp-version-negotiation.advertised-revisions-use-mcp-date-form-and-include-the-preferred-one', 'RFCS/0153 §A', '`preferredVersion` MUST be one the host actually lists'),
|
|
80
81
|
).toContain(caps?.preferredVersion);
|
|
81
82
|
});
|
|
82
83
|
|
|
83
84
|
it('outbound calls carry MCP-Protocol-Version in date form', async () => {
|
|
84
85
|
if (!behaviorGate(PROFILE, await negotiationAdvertised())) return;
|
|
85
86
|
const server = getMcpFakeServer();
|
|
86
|
-
if (server === null) return;
|
|
87
|
+
if (server === null) return softSkip('blocked', 'precondition not met — `server === null` returned early (seam, prior step, or fixture unavailable)');
|
|
87
88
|
server.reset();
|
|
88
89
|
const drive = await driver.post('/v1/host/sample/mcp/invoke', { serverUrl: server.endpoint() });
|
|
89
90
|
if (drive.status === 404 || drive.status === 403) {
|
|
90
91
|
expect(
|
|
91
92
|
drive.status,
|
|
92
|
-
|
|
93
|
+
req('openwop.it.mcp-version-negotiation.outbound-calls-carry-mcp-protocol-version-in-date-form',
|
|
93
94
|
'RFCS/0153 §B',
|
|
94
95
|
'a host advertising MCP revisions MUST expose an invoke seam so the negotiated revision ' +
|
|
95
96
|
'is observable. Without it the requirement resolves to `blocked` per RFC 0148 §A — not ' +
|
|
96
97
|
'to a pass.',
|
|
97
98
|
),
|
|
98
99
|
).not.toBe(404);
|
|
99
|
-
return;
|
|
100
|
+
return softSkip('blocked', 'precondition not met — `drive.status === 404 || drive.status === 403` returned early (seam, prior step, or fixture unavailable)');
|
|
100
101
|
}
|
|
101
102
|
const calls = server.invocations();
|
|
102
|
-
expect(calls.length, 'the host MUST have called the server').toBeGreaterThan(0);
|
|
103
|
+
expect(calls.length, req('openwop.it.mcp-version-negotiation.outbound-calls-carry-mcp-protocol-version-in-date-form', 'RFCS/0153 §B', 'the host MUST have called the server')).toBeGreaterThan(0);
|
|
103
104
|
for (const c of calls) {
|
|
104
105
|
const v = c.headers['mcp-protocol-version'];
|
|
105
106
|
expect(
|
|
106
107
|
v,
|
|
107
|
-
|
|
108
|
+
req('openwop.it.mcp-version-negotiation.outbound-calls-carry-mcp-protocol-version-in-date-form', 'RFCS/0153 §A', 'every MCP call MUST declare its revision'),
|
|
108
109
|
).toBeTruthy();
|
|
109
110
|
expect(
|
|
110
111
|
DATE_FORM.test(v ?? ''),
|
|
111
|
-
|
|
112
|
+
req('openwop.it.mcp-version-negotiation.outbound-calls-carry-mcp-protocol-version-in-date-form',
|
|
112
113
|
'RFCS/0153 §A',
|
|
113
114
|
`the revision on the wire MUST be MCP's date form; got '${v}'. A malformed revision is ` +
|
|
114
115
|
'unmatchable against a pinned peer, and the failure then surfaces at the peer rather ' +
|
|
@@ -121,7 +122,7 @@ describe('RFC 0153 §A/§B — MCP revision negotiation', () => {
|
|
|
121
122
|
it('the negotiated revision is one the host advertises', async () => {
|
|
122
123
|
if (!behaviorGate(PROFILE, await negotiationAdvertised())) return;
|
|
123
124
|
const server = getMcpFakeServer();
|
|
124
|
-
if (server === null) return;
|
|
125
|
+
if (server === null) return softSkip('blocked', 'precondition not met — `server === null` returned early (seam, prior step, or fixture unavailable)');
|
|
125
126
|
const caps = await mcp();
|
|
126
127
|
server.reset();
|
|
127
128
|
const drive = await driver.post('/v1/host/sample/mcp/invoke', { serverUrl: server.endpoint() });
|
|
@@ -132,7 +133,7 @@ describe('RFC 0153 §A/§B — MCP revision negotiation', () => {
|
|
|
132
133
|
for (const c of server.invocations()) {
|
|
133
134
|
expect(
|
|
134
135
|
caps?.protocolVersions ?? [],
|
|
135
|
-
|
|
136
|
+
req('openwop.it.mcp-version-negotiation.the-negotiated-revision-is-one-the-host-advertises',
|
|
136
137
|
'RFCS/0153 §A/§B',
|
|
137
138
|
'the revision sent on the wire MUST appear in `protocolVersions`. Negotiating an ' +
|
|
138
139
|
'unadvertised revision makes the discovery document unreliable for every consumer ' +
|
|
@@ -145,7 +146,7 @@ describe('RFC 0153 §A/§B — MCP revision negotiation', () => {
|
|
|
145
146
|
it('an unsupported revision fails through the canonical interop envelope', async () => {
|
|
146
147
|
if (!behaviorGate(PROFILE, await negotiationAdvertised())) return;
|
|
147
148
|
const server = getMcpFakeServer();
|
|
148
|
-
if (server === null) return;
|
|
149
|
+
if (server === null) return softSkip('blocked', 'precondition not met — `server === null` returned early (seam, prior step, or fixture unavailable)');
|
|
149
150
|
const drive = await driver.post('/v1/host/sample/mcp/invoke', {
|
|
150
151
|
serverUrl: server.endpoint(),
|
|
151
152
|
requestVersion: '1999-01-01',
|
|
@@ -153,13 +154,13 @@ describe('RFC 0153 §A/§B — MCP revision negotiation', () => {
|
|
|
153
154
|
if (drive.status === 404 || drive.status === 403) return seamAbsent(`host advertises mcp version negotiation but the invoke seam /v1/host/sample/mcp/invoke answered ${drive.status} — the host-as-client legs are unobservable (host-sample-test-seams.md)`);
|
|
154
155
|
expect(
|
|
155
156
|
drive.status >= 400,
|
|
156
|
-
|
|
157
|
+
req('openwop.it.mcp-version-negotiation.an-unsupported-revision-fails-through-the-canonical-interop-envelope', 'RFCS/0153 §B', 'an unsupported revision MUST fail rather than silently proceed'),
|
|
157
158
|
).toBe(true);
|
|
158
159
|
// S28: canonical envelope is FLAT (`error: "<code>"`, error-envelope.schema.json);
|
|
159
160
|
// the nested `error.code` is tolerated by the lib only through the deprecation window.
|
|
160
161
|
expect(
|
|
161
162
|
readErrorCode(drive.json),
|
|
162
|
-
|
|
163
|
+
req('openwop.it.mcp-version-negotiation.an-unsupported-revision-fails-through-the-canonical-interop-envelope',
|
|
163
164
|
'RFCS/0153 §B',
|
|
164
165
|
'the upstream error MUST be projected through the canonical OpenWOP interop envelope — a ' +
|
|
165
166
|
'raw JSON-RPC error body leaves the caller parsing a foreign protocol to learn its own ' +
|
|
@@ -33,6 +33,8 @@ import { join } from 'node:path';
|
|
|
33
33
|
import { driver } from '../lib/driver.js';
|
|
34
34
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
35
35
|
import { capabilityFamily, discoveryFamilies } from '../lib/discovery-capabilities.js';
|
|
36
|
+
import { req } from '../lib/requirement-ids.js';
|
|
37
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
36
38
|
|
|
37
39
|
const MEDIA_KINDS = ['media.image', 'media.audio', 'media.file'] as const;
|
|
38
40
|
const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
|
|
@@ -51,7 +53,7 @@ describe('media-url-inline-cap: media payload schemas compile + round-trip (RFC
|
|
|
51
53
|
it(`envelopes/${kind}.schema.json compiles under Ajv2020`, () => {
|
|
52
54
|
expect(
|
|
53
55
|
compile(kind),
|
|
54
|
-
`ai-envelope.md §"Media reference payloads": ${kind} payload schema MUST compile
|
|
56
|
+
req('openwop.it.media-url-inline-cap.envelopes-schema-json-compiles-under-ajv2020', 'RFC 0055 §C', `ai-envelope.md §"Media reference payloads": ${kind} payload schema MUST compile`),
|
|
55
57
|
).toBeTypeOf('function');
|
|
56
58
|
});
|
|
57
59
|
}
|
|
@@ -62,22 +64,22 @@ describe('media-url-inline-cap: media payload schemas compile + round-trip (RFC
|
|
|
62
64
|
bytes: 184320,
|
|
63
65
|
mimeType: 'image/png',
|
|
64
66
|
});
|
|
65
|
-
expect(ok, 'URL-reference media payload MUST validate').toBe(true);
|
|
67
|
+
expect(ok, req('openwop.it.media-url-inline-cap.accepts-a-url-reference-image-payload', 'RFC 0055 §C', 'URL-reference media payload MUST validate')).toBe(true);
|
|
66
68
|
});
|
|
67
69
|
|
|
68
70
|
it('accepts an inline-base64 audio payload', () => {
|
|
69
71
|
const ok = compile('media.audio')({ base64: 'AAAA', bytes: 3, mimeType: 'audio/ogg', durationSeconds: 1.2 });
|
|
70
|
-
expect(ok, 'inline-base64 media payload MUST validate').toBe(true);
|
|
72
|
+
expect(ok, req('openwop.it.media-url-inline-cap.accepts-an-inline-base64-audio-payload', 'RFC 0055 §C', 'inline-base64 media payload MUST validate')).toBe(true);
|
|
71
73
|
});
|
|
72
74
|
|
|
73
75
|
it('rejects a payload missing required bytes', () => {
|
|
74
76
|
const ok = compile('media.file')({ url: 'https://host.example/v1/runs/run_1/assets/report.pdf' });
|
|
75
|
-
expect(ok, 'ai-envelope.md §"Media reference payloads": `bytes` is required').toBe(false);
|
|
77
|
+
expect(ok, req('openwop.it.media-url-inline-cap.rejects-a-payload-missing-required-bytes', 'RFC 0055 §C', 'ai-envelope.md §"Media reference payloads": `bytes` is required')).toBe(false);
|
|
76
78
|
});
|
|
77
79
|
|
|
78
80
|
it('rejects an unknown property (additionalProperties:false)', () => {
|
|
79
81
|
const ok = compile('media.image')({ bytes: 1, wat: true });
|
|
80
|
-
expect(ok, 'media payload is additionalProperties:false').toBe(false);
|
|
82
|
+
expect(ok, req('openwop.it.media-url-inline-cap.rejects-an-unknown-property-additionalproperties-false', 'RFC 0055 §C', 'media payload is additionalProperties:false')).toBe(false);
|
|
81
83
|
});
|
|
82
84
|
});
|
|
83
85
|
|
|
@@ -88,12 +90,12 @@ interface DiscoveryDoc {
|
|
|
88
90
|
describe.skipIf(HTTP_SKIP)('media-url-inline-cap: advertisement shape (RFC 0055 §C rule 2)', () => {
|
|
89
91
|
it('aiProviders.maxInlineMediaBytes is a non-negative integer when advertised', async () => {
|
|
90
92
|
const res = await driver.get('/.well-known/openwop');
|
|
91
|
-
if (res.status !== 200) return;
|
|
93
|
+
if (res.status !== 200) return softSkip('blocked', 'precondition not met — `res.status !== 200` returned early (seam, prior step, or fixture unavailable)');
|
|
92
94
|
const cap = capabilityFamily((res.json as DiscoveryDoc), 'aiProviders')?.maxInlineMediaBytes;
|
|
93
|
-
if (cap === undefined) return; // optional — soft-skip when absent
|
|
95
|
+
if (cap === undefined) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === undefined` returned early (optional — soft-skip when absent)'); // optional — soft-skip when absent
|
|
94
96
|
expect(
|
|
95
97
|
Number.isInteger(cap) && (cap as number) >= 0,
|
|
96
|
-
|
|
98
|
+
req('openwop.it.media-url-inline-cap.aiproviders-maxinlinemediabytes-is-a-non-negative-integer-when-advertised', 'capabilities.md §aiProviders.maxInlineMediaBytes', 'cap MUST be a non-negative integer'),
|
|
97
99
|
).toBe(true);
|
|
98
100
|
});
|
|
99
101
|
|
|
@@ -106,24 +108,24 @@ describe.skipIf(HTTP_SKIP)('media-url-inline-cap: advertisement shape (RFC 0055
|
|
|
106
108
|
|
|
107
109
|
it('a stored media asset is served by a tenant-scoped URL, not inlined', async () => {
|
|
108
110
|
const stored = await driver.post('/v1/host/sample/media/put', { contentBase64: PNG_1x1, contentType: 'image/png' });
|
|
109
|
-
if (stored.status === 404) return; // store seam disabled — soft-skip
|
|
110
|
-
expect(stored.status, 'media store MUST return 201').toBe(201);
|
|
111
|
+
if (stored.status === 404) return softSkip('blocked', 'precondition not met — `stored.status === 404` returned early (store seam disabled — soft-skip) (seam, prior step, or fixture unavailable)'); // store seam disabled — soft-skip
|
|
112
|
+
expect(stored.status, req('openwop.it.media-url-inline-cap.a-stored-media-asset-is-served-by-a-tenant-scoped-url-not-inlined', 'ai-envelope.md §"Media reference payloads"', 'media store MUST return 201')).toBe(201);
|
|
111
113
|
const body = stored.json as { url?: string; bytes?: number };
|
|
112
114
|
expect(
|
|
113
115
|
typeof body.url === 'string' && /\/v1\/host\/sample\/assets\//.test(body.url!),
|
|
114
|
-
|
|
116
|
+
req('openwop.it.media-url-inline-cap.a-stored-media-asset-is-served-by-a-tenant-scoped-url-not-inlined', 'ai-envelope.md §"Media reference payloads"', 'asset MUST be served by a URL reference, not inlined'),
|
|
115
117
|
).toBe(true);
|
|
116
118
|
const served = await driver.get(body.url!);
|
|
117
|
-
expect(served.status, 'the asset URL MUST resolve').toBe(200);
|
|
119
|
+
expect(served.status, req('openwop.it.media-url-inline-cap.a-stored-media-asset-is-served-by-a-tenant-scoped-url-not-inlined', 'ai-envelope.md §"Media reference payloads"', 'the asset URL MUST resolve')).toBe(200);
|
|
118
120
|
});
|
|
119
121
|
|
|
120
122
|
it('an unminted/guessed asset token does not resolve (media-asset-url-tenant-scoped)', async () => {
|
|
121
123
|
// Probe whether the serve route exists at all; soft-skip if not.
|
|
122
124
|
const probe = await driver.get('/v1/host/sample/assets/probe-never-minted-token');
|
|
123
|
-
if (probe.status === 404 && !process.env.OPENWOP_BASE_URL) return;
|
|
125
|
+
if (probe.status === 404 && !process.env.OPENWOP_BASE_URL) return softSkip('blocked', 'precondition not met — `probe.status === 404 && !process.env.OPENWOP_BASE_URL` returned early (seam, prior step, or fixture unavailable)');
|
|
124
126
|
expect(
|
|
125
127
|
probe.status,
|
|
126
|
-
|
|
128
|
+
req('openwop.it.media-url-inline-cap.an-unminted-guessed-asset-token-does-not-resolve-media-asset-url-tenant-scoped', 'SECURITY/invariants.yaml#media-asset-url-tenant-scoped', 'a token not held by the caller (unguessable 256-bit) MUST NOT resolve'),
|
|
127
129
|
).toBe(404);
|
|
128
130
|
});
|
|
129
131
|
|
|
@@ -135,14 +137,14 @@ describe.skipIf(HTTP_SKIP)('media-url-inline-cap: advertisement shape (RFC 0055
|
|
|
135
137
|
// — and on the reference host, which exports debug bundles but has no node
|
|
136
138
|
// that emits a media.* envelope into a run (so no media payload appears).
|
|
137
139
|
const disc = await driver.get('/.well-known/openwop');
|
|
138
|
-
if (disc.status !== 200) return;
|
|
140
|
+
if (disc.status !== 200) return softSkip('blocked', 'precondition not met — `disc.status !== 200` returned early (seam, prior step, or fixture unavailable)');
|
|
139
141
|
const caps = discoveryFamilies(disc.json) as { aiProviders?: { maxInlineMediaBytes?: unknown }; debugBundle?: { supported?: unknown } };
|
|
140
142
|
if (caps.aiProviders?.maxInlineMediaBytes === undefined || caps.debugBundle?.supported !== true) {
|
|
141
|
-
return; // host doesn't serve media + export debug bundles — contract not exercisable
|
|
143
|
+
return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `caps.aiProviders?.maxInlineMediaBytes === undefined || caps.debugBundle?.supported !== true` returned early (host doesn\'t serve media + export debug bundles — …'); // host doesn't serve media + export debug bundles — contract not exercisable
|
|
142
144
|
}
|
|
143
145
|
// Find a recent run and inspect its debug bundle for any media.* event.
|
|
144
146
|
const runs = await driver.get('/v1/runs?limit=20');
|
|
145
|
-
if (runs.status !== 200) return;
|
|
147
|
+
if (runs.status !== 200) return softSkip('blocked', 'precondition not met — `runs.status !== 200` returned early (seam, prior step, or fixture unavailable)');
|
|
146
148
|
const runIds = ((runs.json as { runs?: { runId?: string }[] }).runs ?? [])
|
|
147
149
|
.map((r) => r.runId)
|
|
148
150
|
.filter((id): id is string => typeof id === 'string');
|
|
@@ -155,9 +157,9 @@ describe.skipIf(HTTP_SKIP)('media-url-inline-cap: advertisement shape (RFC 0055
|
|
|
155
157
|
// The §C rule-3 contract: served by URL, not inlined binary.
|
|
156
158
|
expect(
|
|
157
159
|
typeof ev.payload?.url === 'string' && ev.payload?.base64 === undefined,
|
|
158
|
-
|
|
160
|
+
req('openwop.it.media-url-inline-cap.a-media-payload-in-a-run-debug-bundle-is-referenced-by-url-not-inlined-rfc-0055', 'ai-envelope.md §"Media reference payloads"', 'a media.* payload in a debug bundle MUST be a URL reference, never inlined binary'),
|
|
159
161
|
).toBe(true);
|
|
160
|
-
return; // asserted one — contract proven
|
|
162
|
+
return softSkip('blocked', 'precondition not met — `typeof ev.type === \'string\' && ev.type.startsWith(\'media.\')` returned early (asserted one — contract proven) (seam, prior step, or fixture unavailable)'); // asserted one — contract proven
|
|
161
163
|
}
|
|
162
164
|
}
|
|
163
165
|
}
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
import { describe, it, expect } from 'vitest';
|
|
12
12
|
import { softSkip } from '../lib/soft-skip.js';
|
|
13
|
-
import { driver } from '../lib/driver.js';
|
|
14
13
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
15
14
|
import { readMemoryAttributionCap, emitsWriteEvents, seedRun, memoryWrittenEvents } from '../lib/memoryAttribution.js';
|
|
15
|
+
import { req } from '../lib/requirement-ids.js';
|
|
16
16
|
|
|
17
17
|
describe('memory-attribution-emits-on-write (RFC 0057 §A/§B)', () => {
|
|
18
18
|
it('an advertised host emits memory.written carrying a stable memoryId', async () => {
|
|
@@ -23,7 +23,7 @@ describe('memory-attribution-emits-on-write (RFC 0057 §A/§B)', () => {
|
|
|
23
23
|
try {
|
|
24
24
|
await pollUntilTerminal(runId, { timeoutMs: 10_000 });
|
|
25
25
|
} catch {
|
|
26
|
-
return;
|
|
26
|
+
return softSkip('blocked', 'precondition not met — an earlier step threw (seam, prior step, or fixture unavailable)');
|
|
27
27
|
}
|
|
28
28
|
const events = await memoryWrittenEvents(runId);
|
|
29
29
|
if (events.length === 0) return softSkip('blocked', 'run wrote no memory — soft-skip (events.length === 0)');
|
|
@@ -31,7 +31,7 @@ describe('memory-attribution-emits-on-write (RFC 0057 §A/§B)', () => {
|
|
|
31
31
|
const memoryId = (e.payload as { memoryId?: unknown } | undefined)?.memoryId;
|
|
32
32
|
expect(
|
|
33
33
|
typeof memoryId === 'string' && memoryId.length > 0,
|
|
34
|
-
|
|
34
|
+
req('openwop.it.memory-attribution-emits-on-write.an-advertised-host-emits-memory-written-carrying-a-stable-memoryid', 'RFC 0057 §B', 'memory.written.memoryId MUST be a stable, non-empty identifier'),
|
|
35
35
|
).toBe(true);
|
|
36
36
|
}
|
|
37
37
|
});
|
|
@@ -44,12 +44,12 @@ describe('memory-attribution-emits-on-write (RFC 0057 §A/§B)', () => {
|
|
|
44
44
|
try {
|
|
45
45
|
await pollUntilTerminal(runId, { timeoutMs: 10_000 });
|
|
46
46
|
} catch {
|
|
47
|
-
return;
|
|
47
|
+
return softSkip('blocked', 'precondition not met — an earlier step threw (seam, prior step, or fixture unavailable)');
|
|
48
48
|
}
|
|
49
49
|
const events = await memoryWrittenEvents(runId);
|
|
50
50
|
expect(
|
|
51
51
|
events.length,
|
|
52
|
-
|
|
52
|
+
req('openwop.it.memory-attribution-emits-on-write.a-host-without-the-capability-emits-no-memory-written', 'RFC 0057 §A', 'a host not advertising memory.attribution MUST NOT emit memory.written'),
|
|
53
53
|
).toBe(0);
|
|
54
54
|
});
|
|
55
55
|
});
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
|
|
14
14
|
import { describe, it, expect } from 'vitest';
|
|
15
15
|
import { softSkip } from '../lib/soft-skip.js';
|
|
16
|
-
import { driver } from '../lib/driver.js';
|
|
17
16
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
18
17
|
import { readMemoryAttributionCap, emitsWriteEvents, seedRun, memoryWrittenEvents } from '../lib/memoryAttribution.js';
|
|
18
|
+
import { req } from '../lib/requirement-ids.js';
|
|
19
19
|
|
|
20
20
|
describe('memory-attribution-no-content (RFC 0057 §C)', () => {
|
|
21
21
|
it('memory.written payloads carry no entry content', async () => {
|
|
@@ -26,7 +26,7 @@ describe('memory-attribution-no-content (RFC 0057 §C)', () => {
|
|
|
26
26
|
try {
|
|
27
27
|
await pollUntilTerminal(runId, { timeoutMs: 10_000 });
|
|
28
28
|
} catch {
|
|
29
|
-
return;
|
|
29
|
+
return softSkip('blocked', 'precondition not met — an earlier step threw (seam, prior step, or fixture unavailable)');
|
|
30
30
|
}
|
|
31
31
|
const events = await memoryWrittenEvents(runId);
|
|
32
32
|
if (events.length === 0) return softSkip('blocked', 'run wrote no memory — soft-skip (events.length === 0)');
|
|
@@ -34,12 +34,12 @@ describe('memory-attribution-no-content (RFC 0057 §C)', () => {
|
|
|
34
34
|
const payload = e.payload ?? {};
|
|
35
35
|
expect(
|
|
36
36
|
'content' in payload,
|
|
37
|
-
|
|
37
|
+
req('openwop.it.memory-attribution-no-content.memory-written-payloads-carry-no-entry-content', 'RFC 0057 §C', 'memory.written MUST NOT carry the entry content field'),
|
|
38
38
|
).toBe(false);
|
|
39
39
|
expect(
|
|
40
40
|
typeof (payload as { memoryRef?: unknown }).memoryRef === 'string' &&
|
|
41
41
|
typeof (payload as { memoryId?: unknown }).memoryId === 'string',
|
|
42
|
-
|
|
42
|
+
req('openwop.it.memory-attribution-no-content.memory-written-payloads-carry-no-entry-content', 'RFC 0057 §B', 'memory.written MUST carry memoryRef + memoryId identifiers'),
|
|
43
43
|
).toBe(true);
|
|
44
44
|
}
|
|
45
45
|
});
|
|
@@ -41,6 +41,7 @@ import { softSkip } from '../lib/soft-skip.js';
|
|
|
41
41
|
import { driver } from '../lib/driver.js';
|
|
42
42
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
43
43
|
import { readMemoryAttributionCap, emitsWriteEvents, seedRun, memoryWrittenEvents } from '../lib/memoryAttribution.js';
|
|
44
|
+
import { req } from '../lib/requirement-ids.js';
|
|
44
45
|
|
|
45
46
|
function memoryIdOf(payload: Record<string, unknown> | undefined): string | null {
|
|
46
47
|
const id = (payload ?? {})['memoryId'];
|
|
@@ -56,7 +57,7 @@ describe('memory-attribution-replay-stable (RFC 0057 §D)', () => {
|
|
|
56
57
|
try {
|
|
57
58
|
await pollUntilTerminal(runId, { timeoutMs: 10_000 });
|
|
58
59
|
} catch {
|
|
59
|
-
return;
|
|
60
|
+
return softSkip('blocked', 'precondition not met — an earlier step threw (seam, prior step, or fixture unavailable)');
|
|
60
61
|
}
|
|
61
62
|
const original = await memoryWrittenEvents(runId);
|
|
62
63
|
if (original.length === 0) return softSkip('blocked', 'run wrote no memory — nothing to test');
|
|
@@ -83,7 +84,7 @@ describe('memory-attribution-replay-stable (RFC 0057 §D)', () => {
|
|
|
83
84
|
const missing = [...recordedIds].filter((id) => !replayedIds.has(id));
|
|
84
85
|
expect(
|
|
85
86
|
missing,
|
|
86
|
-
|
|
87
|
+
req('openwop.it.memory-attribution-replay-stable.a-replay-mode-fork-introduces-no-memory-written-with-a-new-memoryid',
|
|
87
88
|
'replay.md §"Determinism guarantees" caveat 5',
|
|
88
89
|
'recorded-fact events are fixed history: a replay MUST re-emit the source run\'s ' +
|
|
89
90
|
'`memory.written` events from the log. A replay whose log is SHORT of the source\'s is not ' +
|
|
@@ -97,7 +98,7 @@ describe('memory-attribution-replay-stable (RFC 0057 §D)', () => {
|
|
|
97
98
|
const id = memoryIdOf(e.payload);
|
|
98
99
|
expect(
|
|
99
100
|
id !== null && recordedIds.has(id),
|
|
100
|
-
|
|
101
|
+
req('openwop.it.memory-attribution-replay-stable.a-replay-mode-fork-introduces-no-memory-written-with-a-new-memoryid', 'RFC 0057 §D', 'a replay MUST NOT regenerate memoryId — every replayed memory.written reuses a recorded id'),
|
|
101
102
|
).toBe(true);
|
|
102
103
|
}
|
|
103
104
|
});
|
|
@@ -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 { readMemoryAttributionCap } from '../lib/memoryAttribution.js';
|
|
14
|
+
import { req } from '../lib/requirement-ids.js';
|
|
15
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
15
16
|
|
|
16
17
|
describe('memory-attribution-shape: advertisement (RFC 0057 §A)', () => {
|
|
17
18
|
it('capabilities.memory.attribution is absent or a well-formed object', async () => {
|
|
18
19
|
const cap = await readMemoryAttributionCap();
|
|
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
|
cap.supported,
|
|
22
|
-
|
|
23
|
+
req('openwop.it.memory-attribution-shape.capabilities-memory-attribution-is-absent-or-a-well-formed-object', 'capabilities.schema.json §memory.attribution', 'memory.attribution.supported MUST be the literal true when the block is present'),
|
|
23
24
|
).toBe(true);
|
|
24
25
|
if (cap.emitsWriteEvents !== undefined) {
|
|
25
26
|
expect(typeof cap.emitsWriteEvents).toBe('boolean');
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
import { describe, it, expect } from 'vitest';
|
|
16
16
|
import { softSkip } from '../lib/soft-skip.js';
|
|
17
|
-
import { driver } from '../lib/driver.js';
|
|
18
17
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
19
18
|
import { readMemoryAttributionCap, emitsWriteEvents, seedRun, memoryWrittenEvents } from '../lib/memoryAttribution.js';
|
|
19
|
+
import { req } from '../lib/requirement-ids.js';
|
|
20
20
|
|
|
21
21
|
describe('memory-attribution-tenant-scoped (RFC 0057 §C)', () => {
|
|
22
22
|
it("a run's memory.written events appear only on that run's stream", async () => {
|
|
@@ -27,7 +27,7 @@ describe('memory-attribution-tenant-scoped (RFC 0057 §C)', () => {
|
|
|
27
27
|
try {
|
|
28
28
|
await pollUntilTerminal(runId, { timeoutMs: 10_000 });
|
|
29
29
|
} catch {
|
|
30
|
-
return;
|
|
30
|
+
return softSkip('blocked', 'precondition not met — an earlier step threw (seam, prior step, or fixture unavailable)');
|
|
31
31
|
}
|
|
32
32
|
const events = await memoryWrittenEvents(runId);
|
|
33
33
|
if (events.length === 0) return softSkip('blocked', 'precondition not met — `events.length === 0` returned early (seam, prior step, or fixture unavailable)');
|
|
@@ -37,7 +37,7 @@ describe('memory-attribution-tenant-scoped (RFC 0057 §C)', () => {
|
|
|
37
37
|
if (typeof e.runId === 'string') {
|
|
38
38
|
expect(
|
|
39
39
|
e.runId,
|
|
40
|
-
|
|
40
|
+
req('openwop.it.memory-attribution-tenant-scoped.a-run-s-memory-written-events-appear-only-on-that-run-s-stream', 'RFC 0057 §C', "a memory.written event MUST belong to its own run's stream (CTI-1)"),
|
|
41
41
|
).toBe(runId);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -36,8 +36,7 @@ import Ajv2020 from 'ajv/dist/2020.js';
|
|
|
36
36
|
import addFormats from 'ajv-formats';
|
|
37
37
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
38
38
|
import { deriveProfiles } from '../lib/profiles.js';
|
|
39
|
-
|
|
40
|
-
const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
|
|
39
|
+
import { req } from '../lib/requirement-ids.js';
|
|
41
40
|
|
|
42
41
|
function loadSchema(name: string): Record<string, unknown> {
|
|
43
42
|
return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
|
|
@@ -63,7 +62,7 @@ describe('memory-capability-model-shape: reconciled dimensions (RFC 0080 §A, se
|
|
|
63
62
|
for (const dim of ['writable', 'search', 'retention']) {
|
|
64
63
|
expect(
|
|
65
64
|
memory?.properties?.[dim],
|
|
66
|
-
|
|
65
|
+
req('openwop.it.memory-capability-model-shape.capabilities-memory-declares-the-additive-writable-search-retention-dimensions', 'agent-memory.md §"Memory capability model"', `capabilities.memory.${dim} MUST be declared (RFC 0080 §A)`),
|
|
67
66
|
).toBeDefined();
|
|
68
67
|
}
|
|
69
68
|
});
|
|
@@ -72,7 +71,7 @@ describe('memory-capability-model-shape: reconciled dimensions (RFC 0080 §A, se
|
|
|
72
71
|
for (const dim of ['supported', 'compaction', 'distillation', 'attribution']) {
|
|
73
72
|
expect(
|
|
74
73
|
memory?.properties?.[dim],
|
|
75
|
-
|
|
74
|
+
req('openwop.it.memory-capability-model-shape.the-pre-existing-memory-fields-are-untouched-additive-no-relocation', 'COMPATIBILITY.md §2.1', `capabilities.memory.${dim} MUST remain (RFC 0080 is additive)`),
|
|
76
75
|
).toBeDefined();
|
|
77
76
|
}
|
|
78
77
|
});
|
|
@@ -89,22 +88,22 @@ describe('memory-capability-model-shape: reconciled dimensions (RFC 0080 §A, se
|
|
|
89
88
|
|
|
90
89
|
expect(
|
|
91
90
|
validate({ memory: { supported: true, writable: false, search: { supported: true, modes: ['semantic', 'filter'] }, retention: { ttl: true, forget: true } } }),
|
|
92
|
-
|
|
91
|
+
req('openwop.it.memory-capability-model-shape.memory-search-memory-retention-validate-conforming-instances-and-reject-malforme', 'capabilities.md §memory', 'a full reconciled-memory advertisement MUST validate'),
|
|
93
92
|
).toBe(true);
|
|
94
93
|
|
|
95
94
|
expect(
|
|
96
95
|
validate({ memory: { retention: { ttl: 'yes' } } }),
|
|
97
|
-
|
|
96
|
+
req('openwop.it.memory-capability-model-shape.memory-search-memory-retention-validate-conforming-instances-and-reject-malforme', 'RFC 0080 §A', 'retention.ttl MUST be boolean'),
|
|
98
97
|
).toBe(false);
|
|
99
98
|
|
|
100
99
|
expect(
|
|
101
100
|
validate({ memory: { search: { supported: true, modes: ['fuzzy'] } } }),
|
|
102
|
-
|
|
101
|
+
req('openwop.it.memory-capability-model-shape.memory-search-memory-retention-validate-conforming-instances-and-reject-malforme', 'RFC 0080 §A', 'search.modes MUST be the closed enum [semantic, filter]'),
|
|
103
102
|
).toBe(false);
|
|
104
103
|
|
|
105
104
|
expect(
|
|
106
105
|
validate({ memory: { search: { supported: true, unknownField: 1 } } }),
|
|
107
|
-
|
|
106
|
+
req('openwop.it.memory-capability-model-shape.memory-search-memory-retention-validate-conforming-instances-and-reject-malforme', 'RFC 0080 §A', 'memory.search MUST be additionalProperties:false'),
|
|
108
107
|
).toBe(false);
|
|
109
108
|
});
|
|
110
109
|
});
|
|
@@ -117,11 +116,11 @@ describe('memory-capability-model-shape: degraded projection (RFC 0080 §C, serv
|
|
|
117
116
|
.AgentInventoryEntry).properties;
|
|
118
117
|
expect(
|
|
119
118
|
entry?.memoryDegraded,
|
|
120
|
-
|
|
119
|
+
req('openwop.it.memory-capability-model-shape.agent-inventory-response-declares-memorydegraded-degradedmemorydimensions', 'agent-memory.md §C-1', 'memoryDegraded MUST be declared on the inventory entry'),
|
|
121
120
|
).toBeDefined();
|
|
122
121
|
expect(
|
|
123
122
|
entry?.degradedMemoryDimensions,
|
|
124
|
-
|
|
123
|
+
req('openwop.it.memory-capability-model-shape.agent-inventory-response-declares-memorydegraded-degradedmemorydimensions', 'agent-memory.md §C-1', 'degradedMemoryDimensions MUST be declared on the inventory entry'),
|
|
125
124
|
).toBeDefined();
|
|
126
125
|
});
|
|
127
126
|
|
|
@@ -131,7 +130,7 @@ describe('memory-capability-model-shape: degraded projection (RFC 0080 §C, serv
|
|
|
131
130
|
const enumVals = entry?.degradedMemoryDimensions?.items?.enum ?? [];
|
|
132
131
|
expect(
|
|
133
132
|
[...enumVals].sort(),
|
|
134
|
-
|
|
133
|
+
req('openwop.it.memory-capability-model-shape.degradedmemorydimensions-enumerates-exactly-the-eight-a-dimension-names', 'agent-memory.md §A', 'the degraded-dimension enum MUST be the eight reconciled dimensions'),
|
|
135
134
|
).toEqual([...DIMENSIONS].sort());
|
|
136
135
|
});
|
|
137
136
|
|
|
@@ -144,11 +143,11 @@ describe('memory-capability-model-shape: degraded projection (RFC 0080 §C, serv
|
|
|
144
143
|
};
|
|
145
144
|
expect(
|
|
146
145
|
validate({ total: 1, agents: [{ ...base, memoryDegraded: true, degradedMemoryDimensions: ['write', 'long-term-durability'] }] }),
|
|
147
|
-
|
|
146
|
+
req('openwop.it.memory-capability-model-shape.the-inventory-schema-round-trips-a-degraded-entry-and-rejects-an-out-of-enum-dim', 'agent-memory.md §C-1', 'a degraded inventory entry MUST validate'),
|
|
148
147
|
).toBe(true);
|
|
149
148
|
expect(
|
|
150
149
|
validate({ total: 1, agents: [{ ...base, memoryDegraded: true, degradedMemoryDimensions: ['telepathy'] }] }),
|
|
151
|
-
|
|
150
|
+
req('openwop.it.memory-capability-model-shape.the-inventory-schema-round-trips-a-degraded-entry-and-rejects-an-out-of-enum-dim', 'agent-memory.md §C-1', 'an out-of-enum degraded dimension MUST be rejected'),
|
|
152
151
|
).toBe(false);
|
|
153
152
|
});
|
|
154
153
|
});
|
|
@@ -165,7 +164,7 @@ describe('memory-capability-model-shape: openwop-memory derivation (RFC 0080 §D
|
|
|
165
164
|
} as Record<string, unknown>;
|
|
166
165
|
expect(
|
|
167
166
|
deriveProfiles(c).includes('openwop-memory'),
|
|
168
|
-
|
|
167
|
+
req('openwop.it.memory-capability-model-shape.deriveprofiles-surfaces-openwop-memory-for-a-read-write-long-term-host', 'profiles.md §openwop-memory', 'a read/write + long-term host MUST derive openwop-memory'),
|
|
169
168
|
).toBe(true);
|
|
170
169
|
});
|
|
171
170
|
|
|
@@ -180,7 +179,7 @@ describe('memory-capability-model-shape: openwop-memory derivation (RFC 0080 §D
|
|
|
180
179
|
} as Record<string, unknown>;
|
|
181
180
|
expect(
|
|
182
181
|
deriveProfiles(c).includes('openwop-memory'),
|
|
183
|
-
|
|
182
|
+
req('openwop.it.memory-capability-model-shape.deriveprofiles-withholds-openwop-memory-from-a-read-only-writable-false-host', 'profiles.md §openwop-memory', 'a read-only host MUST NOT derive openwop-memory'),
|
|
184
183
|
).toBe(false);
|
|
185
184
|
});
|
|
186
185
|
});
|
|
@@ -28,6 +28,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
28
28
|
import { softSkip } from '../lib/soft-skip.js';
|
|
29
29
|
import { driver } from '../lib/driver.js';
|
|
30
30
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
31
|
+
import { req } from '../lib/requirement-ids.js';
|
|
31
32
|
|
|
32
33
|
const MEMORY_REF = 'mem_tenant:default_agent:conformance-rfc0012-event_longTerm';
|
|
33
34
|
|
|
@@ -79,26 +80,26 @@ describe('memory-compaction-event-emitted: canonical memory.compacted payload sh
|
|
|
79
80
|
payload?: Record<string, unknown>;
|
|
80
81
|
};
|
|
81
82
|
|
|
82
|
-
expect(event.type,
|
|
83
|
+
expect(event.type, req('openwop.it.memory-compaction-event-emitted.compaction-run-returns-a-canonical-memorycompacted-payload',
|
|
83
84
|
'observability.md §"Canonical run lifecycle event names"',
|
|
84
85
|
'event MUST be type=memory.compacted',
|
|
85
86
|
)).toBe('memory.compacted');
|
|
86
87
|
|
|
87
88
|
const payload = event.payload ?? {};
|
|
88
89
|
|
|
89
|
-
expect(typeof payload.memoryRef,
|
|
90
|
+
expect(typeof payload.memoryRef, req('openwop.it.memory-compaction-event-emitted.compaction-run-returns-a-canonical-memorycompacted-payload',
|
|
90
91
|
'RFC 0012 §B / run-event-payloads.schema.json §memoryCompacted',
|
|
91
92
|
'memoryRef MUST be a non-empty string',
|
|
92
93
|
)).toBe('string');
|
|
93
94
|
expect((payload.memoryRef as string).length).toBeGreaterThan(0);
|
|
94
95
|
|
|
95
|
-
expect(typeof payload.outputId,
|
|
96
|
+
expect(typeof payload.outputId, req('openwop.it.memory-compaction-event-emitted.compaction-run-returns-a-canonical-memorycompacted-payload',
|
|
96
97
|
'RFC 0012 §B',
|
|
97
98
|
'outputId MUST be a string identifying the distilled entry',
|
|
98
99
|
)).toBe('string');
|
|
99
100
|
expect((payload.outputId as string).length).toBeGreaterThan(0);
|
|
100
101
|
|
|
101
|
-
expect(Number.isInteger(payload.sourceCount),
|
|
102
|
+
expect(Number.isInteger(payload.sourceCount), req('openwop.it.memory-compaction-event-emitted.compaction-run-returns-a-canonical-memorycompacted-payload',
|
|
102
103
|
'RFC 0012 §B',
|
|
103
104
|
'sourceCount MUST be an integer',
|
|
104
105
|
)).toBe(true);
|
|
@@ -106,7 +107,7 @@ describe('memory-compaction-event-emitted: canonical memory.compacted payload sh
|
|
|
106
107
|
|
|
107
108
|
expect(['host-managed', 'client-requested', 'both']).toContain(payload.trigger);
|
|
108
109
|
|
|
109
|
-
expect(Number.isInteger(payload.byteSize),
|
|
110
|
+
expect(Number.isInteger(payload.byteSize), req('openwop.it.memory-compaction-event-emitted.compaction-run-returns-a-canonical-memorycompacted-payload',
|
|
110
111
|
'RFC 0012 §B',
|
|
111
112
|
'byteSize MUST be an integer',
|
|
112
113
|
)).toBe(true);
|
|
@@ -115,7 +116,7 @@ describe('memory-compaction-event-emitted: canonical memory.compacted payload sh
|
|
|
115
116
|
if (payload.sourceIds !== undefined) {
|
|
116
117
|
expect(Array.isArray(payload.sourceIds)).toBe(true);
|
|
117
118
|
for (const id of payload.sourceIds as unknown[]) {
|
|
118
|
-
expect(typeof id, 'sourceIds entries MUST be strings').toBe('string');
|
|
119
|
+
expect(typeof id, req('openwop.it.memory-compaction-event-emitted.compaction-run-returns-a-canonical-memorycompacted-payload', 'RFC 0012 §B', 'sourceIds entries MUST be strings')).toBe('string');
|
|
119
120
|
expect((id as string).length).toBeGreaterThan(0);
|
|
120
121
|
}
|
|
121
122
|
}
|
|
@@ -22,6 +22,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
22
22
|
import { softSkip } from '../lib/soft-skip.js';
|
|
23
23
|
import { driver } from '../lib/driver.js';
|
|
24
24
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
25
|
+
import { req } from '../lib/requirement-ids.js';
|
|
25
26
|
|
|
26
27
|
const MEMORY_REF = 'mem_tenant:default_agent:conformance-rfc0012-tag_longTerm';
|
|
27
28
|
const COMPACTED_FROM_RE = /^compacted-from:[^\s:][^\s]*$/;
|
|
@@ -91,7 +92,7 @@ describe('memory-compaction-provenance-tag: compacted-from:<id> tag follows §C
|
|
|
91
92
|
console.warn('[rfc0012-tag] host does not expose memory:list at /v1/memory/{ref}; skipping tag inspection (canonical provenance signal remains the memory.compacted event itself)');
|
|
92
93
|
return softSkip('blocked', '[rfc0012-tag] host does not expose memory:list at /v1/memory/{ref}; skipping tag inspection (canonical provenance signal remains the memory.compacted event itself)');
|
|
93
94
|
}
|
|
94
|
-
expect(listRes.status, 'memory:list MUST return 200 when reachable').toBe(200);
|
|
95
|
+
expect(listRes.status, req('openwop.it.memory-compaction-provenance-tag.compacted-entry-carries-a-well-formed-compacted-from-tag-or-omits-it-cleanly-no', 'RFC 0012 §C', 'memory:list MUST return 200 when reachable')).toBe(200);
|
|
95
96
|
|
|
96
97
|
const body = (listRes.json as MemoryListResponse) ?? {};
|
|
97
98
|
const entries = body.entries ?? [];
|
|
@@ -110,7 +111,7 @@ describe('memory-compaction-provenance-tag: compacted-from:<id> tag follows §C
|
|
|
110
111
|
console.warn('[rfc0012-tag] output entry has no compacted-from:<id> tag — RFC 0012 §C is SHOULD, not MUST; pass with warning');
|
|
111
112
|
return softSkip('inapplicable', '[rfc0012-tag] output entry has no compacted-from:<id> tag — RFC 0012 §C is SHOULD, not MUST; pass with warning');
|
|
112
113
|
}
|
|
113
|
-
expect(provenance,
|
|
114
|
+
expect(provenance, req('openwop.it.memory-compaction-provenance-tag.compacted-entry-carries-a-well-formed-compacted-from-tag-or-omits-it-cleanly-no',
|
|
114
115
|
'RFC 0012 §C',
|
|
115
116
|
'compacted-from tag MUST match `compacted-from:<id>` shape (non-empty id, no whitespace) when present',
|
|
116
117
|
)).toMatch(COMPACTED_FROM_RE);
|