@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
|
@@ -35,10 +35,10 @@ describe('aiEnvelope.contractRefusal: advertisement shape (FINAL v1.1)', () => {
|
|
|
35
35
|
const body = res.json as DiscoveryDoc | undefined;
|
|
36
36
|
const top = discoveryFamilies(body);
|
|
37
37
|
const block = top && typeof top === 'object' ? top['envelopeContracts'] : undefined;
|
|
38
|
-
if (block === undefined) return; // absent — skip
|
|
38
|
+
if (block === undefined) return softSkip('blocked', 'precondition not met — `block === undefined` returned early (absent — skip) (seam, prior step, or fixture unavailable)'); // absent — skip
|
|
39
39
|
expect(
|
|
40
40
|
typeof (block as Record<string, unknown>)['advertised'],
|
|
41
|
-
|
|
41
|
+
req('openwop.it.aiEnvelope.contractRefusal.opted-in-hosts-advertise-envelopecontracts-advertised-as-a-boolean',
|
|
42
42
|
'ai-envelope.md §"Capability handshake integration"',
|
|
43
43
|
'envelopeContracts.advertised MUST be a boolean when present',
|
|
44
44
|
),
|
|
@@ -69,10 +69,10 @@ describe('aiEnvelope.contractRefusal: behavioral accept-gate (FINAL v1.1)', () =
|
|
|
69
69
|
nodeAllowedKinds: ['vendor.x.foo.create'],
|
|
70
70
|
},
|
|
71
71
|
);
|
|
72
|
-
if (r.status === 404) return;
|
|
72
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
73
73
|
expect(
|
|
74
74
|
r.body.status,
|
|
75
|
-
|
|
75
|
+
req('openwop.it.aiEnvelope.contractRefusal.node-with-nodeallowedkinds-vendor-x-foo-create-emits-vendor-x-bar-create-status', 'ai-envelope.md §"Envelope Contract"', 'envelope outside node accepts[] MUST be refused'),
|
|
76
76
|
).toBe('gated');
|
|
77
77
|
});
|
|
78
78
|
|
|
@@ -91,9 +91,9 @@ describe('aiEnvelope.contractRefusal: behavioral accept-gate (FINAL v1.1)', () =
|
|
|
91
91
|
nodeAllowedKinds: ['vendor.x.foo.create'],
|
|
92
92
|
},
|
|
93
93
|
);
|
|
94
|
-
if (r.status === 404) return;
|
|
95
|
-
expect(Array.isArray(r.body.allowedKinds), 'allowedKinds MUST be an array').toBe(true);
|
|
96
|
-
expect(r.body.allowedKinds, 'allowedKinds MUST include universals + declared accepts').toEqual(
|
|
94
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
95
|
+
expect(Array.isArray(r.body.allowedKinds), req('openwop.it.aiEnvelope.contractRefusal.gated-outcome-carries-the-union-of-universals-node-declared-accepts-as-allowedki', 'spec/v1/ai-envelope.md', 'allowedKinds MUST be an array')).toBe(true);
|
|
96
|
+
expect(r.body.allowedKinds, req('openwop.it.aiEnvelope.contractRefusal.gated-outcome-carries-the-union-of-universals-node-declared-accepts-as-allowedki', 'spec/v1/ai-envelope.md', 'allowedKinds MUST include universals + declared accepts')).toEqual(
|
|
97
97
|
expect.arrayContaining(['clarification.request', 'schema.request', 'schema.response', 'error', 'vendor.x.foo.create']),
|
|
98
98
|
);
|
|
99
99
|
});
|
|
@@ -110,10 +110,10 @@ describe('aiEnvelope.contractRefusal: behavioral accept-gate (FINAL v1.1)', () =
|
|
|
110
110
|
},
|
|
111
111
|
{ nodeAllowedKinds: ['vendor.x.foo.create'] }, // doesn't include clarification.request
|
|
112
112
|
);
|
|
113
|
-
if (r.status === 404) return;
|
|
113
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
114
114
|
expect(
|
|
115
115
|
r.body.status,
|
|
116
|
-
|
|
116
|
+
req('openwop.it.aiEnvelope.contractRefusal.universals-are-accepted-regardless-of-nodeallowedkinds-always-allowed', 'ai-envelope.md §"Universal kinds"', 'universal kinds MUST be accepted regardless of node accepts[]'),
|
|
117
117
|
).toBe('accepted');
|
|
118
118
|
});
|
|
119
119
|
|
|
@@ -132,20 +132,22 @@ describe('aiEnvelope.contractRefusal: behavioral accept-gate (FINAL v1.1)', () =
|
|
|
132
132
|
nodeAllowedKinds: ['vendor.unadvertised.kind'], // node would allow but host doesn't
|
|
133
133
|
},
|
|
134
134
|
);
|
|
135
|
-
if (r.status === 404) return;
|
|
135
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
136
136
|
expect(
|
|
137
137
|
r.body.status,
|
|
138
|
-
|
|
138
|
+
req('openwop.it.aiEnvelope.contractRefusal.host-supportedenvelopes-gate-fires-before-node-accepts-gate-kind-unadvertised-ga', 'ai-envelope.md §"Capability handshake integration"', 'host gate MUST fire before node gate'),
|
|
139
139
|
).toBe('gated');
|
|
140
140
|
});
|
|
141
141
|
});
|
|
142
142
|
|
|
143
143
|
// E.1 engine-projection via the test-only event-log seam.
|
|
144
144
|
import { queryTestEvents, isEventLogSeamAvailable, resetTestSeam } from '../lib/event-log-query.js';
|
|
145
|
+
import { req } from '../lib/requirement-ids.js';
|
|
146
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
145
147
|
|
|
146
148
|
describe('aiEnvelope.contractRefusal: engine projection via event-log seam', () => {
|
|
147
149
|
it('gated (fail-node) → node.failed { error.code: "envelope_contract_violation" }', async () => {
|
|
148
|
-
if (!(await isEventLogSeamAvailable())) return;
|
|
150
|
+
if (!(await isEventLogSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isEventLogSeamAvailable())` returned early (seam, prior step, or fixture unavailable)');
|
|
149
151
|
const runId = `r-cr-fail-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
150
152
|
const r = await accept(
|
|
151
153
|
{
|
|
@@ -162,19 +164,19 @@ describe('aiEnvelope.contractRefusal: engine projection via event-log seam', ()
|
|
|
162
164
|
projectTo: { runId, nodeId: 'n', refusalMode: 'fail-node' },
|
|
163
165
|
},
|
|
164
166
|
);
|
|
165
|
-
if (r.status === 404) return;
|
|
167
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
166
168
|
expect(r.body.status).toBe('gated');
|
|
167
169
|
const events = await queryTestEvents(runId, { type: 'node.failed' });
|
|
168
|
-
if (!events.ok || events.events.length === 0) return;
|
|
170
|
+
if (!events.ok || events.events.length === 0) return softSkip('blocked', 'precondition not met — `!events.ok || events.events.length === 0` returned early (seam, prior step, or fixture unavailable)');
|
|
169
171
|
const err = events.events[0]!.payload.error as { code?: string; details?: { refusedType?: string; acceptedTypes?: string[] } };
|
|
170
172
|
expect(
|
|
171
173
|
err.code,
|
|
172
|
-
|
|
174
|
+
req('openwop.it.aiEnvelope.contractRefusal.gated-fail-node-node-failed-error-code-envelope-contract-violation', 'ai-envelope.md §"Envelope Contract"', 'gated outcome MUST project to node.failed with error.code = envelope_contract_violation'),
|
|
173
175
|
).toBe('envelope_contract_violation');
|
|
174
176
|
});
|
|
175
177
|
|
|
176
178
|
it('refused envelope: error.details.refusedType names emitted kind; acceptedTypes lists allowed kinds', async () => {
|
|
177
|
-
if (!(await isEventLogSeamAvailable())) return;
|
|
179
|
+
if (!(await isEventLogSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isEventLogSeamAvailable())` returned early (seam, prior step, or fixture unavailable)');
|
|
178
180
|
const runId = `r-cr-details-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
179
181
|
await accept(
|
|
180
182
|
{
|
|
@@ -192,17 +194,17 @@ describe('aiEnvelope.contractRefusal: engine projection via event-log seam', ()
|
|
|
192
194
|
},
|
|
193
195
|
);
|
|
194
196
|
const events = await queryTestEvents(runId, { type: 'node.failed' });
|
|
195
|
-
if (!events.ok || events.events.length === 0) return;
|
|
197
|
+
if (!events.ok || events.events.length === 0) return softSkip('blocked', 'precondition not met — `!events.ok || events.events.length === 0` returned early (seam, prior step, or fixture unavailable)');
|
|
196
198
|
const details = (events.events[0]!.payload.error as { details?: { refusedType?: string; acceptedTypes?: string[] } }).details;
|
|
197
199
|
expect(details?.refusedType).toBe('vendor.x.bar.create');
|
|
198
200
|
expect(
|
|
199
201
|
Array.isArray(details?.acceptedTypes) && details!.acceptedTypes!.includes('vendor.x.foo.create'),
|
|
200
|
-
|
|
202
|
+
req('openwop.it.aiEnvelope.contractRefusal.refused-envelope-error-details-refusedtype-names-emitted-kind-acceptedtypes-list', 'ai-envelope.md §"Envelope Contract"', 'error.details.acceptedTypes MUST list the node\'s declared accepts[] (plus universals)'),
|
|
201
203
|
).toBe(true);
|
|
202
204
|
});
|
|
203
205
|
|
|
204
206
|
it('refusalMode:"discard-and-warn" → log.appended { level: "warn" } instead of node.failed', async () => {
|
|
205
|
-
if (!(await isEventLogSeamAvailable())) return;
|
|
207
|
+
if (!(await isEventLogSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isEventLogSeamAvailable())` returned early (seam, prior step, or fixture unavailable)');
|
|
206
208
|
const runId = `r-cr-warn-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
207
209
|
await accept(
|
|
208
210
|
{
|
|
@@ -221,20 +223,20 @@ describe('aiEnvelope.contractRefusal: engine projection via event-log seam', ()
|
|
|
221
223
|
);
|
|
222
224
|
const warnEvents = await queryTestEvents(runId, { type: 'log.appended' });
|
|
223
225
|
const failEvents = await queryTestEvents(runId, { type: 'node.failed' });
|
|
224
|
-
if (!warnEvents.ok || !failEvents.ok) return;
|
|
226
|
+
if (!warnEvents.ok || !failEvents.ok) return softSkip('blocked', 'precondition not met — `!warnEvents.ok || !failEvents.ok` returned early (seam, prior step, or fixture unavailable)');
|
|
225
227
|
expect(
|
|
226
228
|
warnEvents.events.some((e) => (e.payload as { level?: string }).level === 'warn'),
|
|
227
|
-
|
|
229
|
+
req('openwop.it.aiEnvelope.contractRefusal.refusalmode-discard-and-warn-log-appended-level-warn-instead-of-node-failed', 'ai-envelope.md §"Envelope Contract"', 'discard-and-warn MUST emit log.appended at warn level'),
|
|
228
230
|
).toBe(true);
|
|
229
231
|
expect(
|
|
230
232
|
failEvents.events.length,
|
|
231
|
-
|
|
233
|
+
req('openwop.it.aiEnvelope.contractRefusal.refusalmode-discard-and-warn-log-appended-level-warn-instead-of-node-failed', 'ai-envelope.md §"Envelope Contract"', 'discard-and-warn MUST NOT emit node.failed'),
|
|
232
234
|
).toBe(0);
|
|
233
235
|
await resetTestSeam();
|
|
234
236
|
});
|
|
235
237
|
|
|
236
238
|
it('host-gate refusal (hostSupportedEnvelopes) projects to node.failed with envelope_contract_violation', async () => {
|
|
237
|
-
if (!(await isEventLogSeamAvailable())) return;
|
|
239
|
+
if (!(await isEventLogSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isEventLogSeamAvailable())` returned early (seam, prior step, or fixture unavailable)');
|
|
238
240
|
const runId = `r-cr-host-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
239
241
|
await accept(
|
|
240
242
|
{
|
|
@@ -252,10 +254,10 @@ describe('aiEnvelope.contractRefusal: engine projection via event-log seam', ()
|
|
|
252
254
|
},
|
|
253
255
|
);
|
|
254
256
|
const events = await queryTestEvents(runId, { type: 'node.failed' });
|
|
255
|
-
if (!events.ok || events.events.length === 0) return;
|
|
257
|
+
if (!events.ok || events.events.length === 0) return softSkip('blocked', 'precondition not met — `!events.ok || events.events.length === 0` returned early (seam, prior step, or fixture unavailable)');
|
|
256
258
|
expect(
|
|
257
259
|
(events.events[0]!.payload.error as { code?: string }).code,
|
|
258
|
-
|
|
260
|
+
req('openwop.it.aiEnvelope.contractRefusal.host-gate-refusal-hostsupportedenvelopes-projects-to-node-failed-with-envelope-c', 'ai-envelope.md §"Capability handshake integration"', 'host-gate refusal MUST project to node.failed envelope_contract_violation (stacks above node-gate)'),
|
|
259
261
|
).toBe('envelope_contract_violation');
|
|
260
262
|
});
|
|
261
263
|
});
|
|
@@ -277,10 +279,10 @@ describe('aiEnvelope.contractRefusal: capability-stacking (FINAL v1.1)', () => {
|
|
|
277
279
|
});
|
|
278
280
|
|
|
279
281
|
it('host.aiEnvelope.supported = false → envelope/accept refuses with capability_required BEFORE envelope contract gates', async () => {
|
|
280
|
-
if (!(await isToggleAvailable())) return; // seam not exposed — soft-skip
|
|
282
|
+
if (!(await isToggleAvailable())) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isToggleAvailable())` returned early (seam not exposed — soft-skip)'); // seam not exposed — soft-skip
|
|
281
283
|
|
|
282
284
|
const toggle = await setHostCapability('host.aiEnvelope.supported', false);
|
|
283
|
-
if (!toggle.ok) return;
|
|
285
|
+
if (!toggle.ok) return softSkip('blocked', 'precondition not met — `!toggle.ok` returned early (seam, prior step, or fixture unavailable)');
|
|
284
286
|
|
|
285
287
|
// Same envelope shape that the existing host-gate scenario uses
|
|
286
288
|
// (line 233-257 above) — the type IS in hostSupportedEnvelopes AND
|
|
@@ -301,17 +303,17 @@ describe('aiEnvelope.contractRefusal: capability-stacking (FINAL v1.1)', () => {
|
|
|
301
303
|
nodeAllowedKinds: ['vendor.advertised.kind'],
|
|
302
304
|
},
|
|
303
305
|
);
|
|
304
|
-
if (r.status === 404) return;
|
|
306
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
305
307
|
expect(
|
|
306
308
|
r.body.status,
|
|
307
|
-
|
|
309
|
+
req('openwop.it.aiEnvelope.contractRefusal.host-aienvelope-supported-false-envelope-accept-refuses-with-capability-required',
|
|
308
310
|
'ai-envelope.md §"Capability handshake integration"',
|
|
309
311
|
'capability-absent host MUST refuse envelope acceptance regardless of host-gate / node-gate match',
|
|
310
312
|
),
|
|
311
313
|
).toBe('invalid');
|
|
312
314
|
expect(
|
|
313
315
|
r.body.reason,
|
|
314
|
-
|
|
316
|
+
req('openwop.it.aiEnvelope.contractRefusal.host-aienvelope-supported-false-envelope-accept-refuses-with-capability-required',
|
|
315
317
|
'capabilities.md §"Unsupported capability — refusal contract"',
|
|
316
318
|
'refusal reason MUST be capability_required (NOT envelope_contract_violation) — capability gate stacks above the envelope-contract gate',
|
|
317
319
|
),
|
|
@@ -319,9 +321,9 @@ describe('aiEnvelope.contractRefusal: capability-stacking (FINAL v1.1)', () => {
|
|
|
319
321
|
});
|
|
320
322
|
|
|
321
323
|
it('host.aiEnvelope.supported = true → envelope/accept falls through to envelope-contract gates', async () => {
|
|
322
|
-
if (!(await isToggleAvailable())) return;
|
|
324
|
+
if (!(await isToggleAvailable())) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isToggleAvailable())` returned early');
|
|
323
325
|
const toggle = await setHostCapability('host.aiEnvelope.supported', true);
|
|
324
|
-
if (!toggle.ok) return;
|
|
326
|
+
if (!toggle.ok) return softSkip('blocked', 'precondition not met — `!toggle.ok` returned early (seam, prior step, or fixture unavailable)');
|
|
325
327
|
|
|
326
328
|
// With capability advertised, a normally-rejected envelope (type
|
|
327
329
|
// not in hostSupportedEnvelopes) reaches the envelope-contract
|
|
@@ -343,10 +345,10 @@ describe('aiEnvelope.contractRefusal: capability-stacking (FINAL v1.1)', () => {
|
|
|
343
345
|
nodeAllowedKinds: ['vendor.unadvertised.kind'],
|
|
344
346
|
},
|
|
345
347
|
);
|
|
346
|
-
if (r.status === 404) return;
|
|
348
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
347
349
|
expect(
|
|
348
350
|
r.body.status,
|
|
349
|
-
|
|
351
|
+
req('openwop.it.aiEnvelope.contractRefusal.host-aienvelope-supported-true-envelope-accept-falls-through-to-envelope-contrac',
|
|
350
352
|
'ai-envelope.md §"Capability handshake integration"',
|
|
351
353
|
'when capability IS advertised, envelope-contract gates run normally',
|
|
352
354
|
),
|
|
@@ -38,13 +38,13 @@ async function isEnvelopeContractsAdvertised(): Promise<boolean> {
|
|
|
38
38
|
|
|
39
39
|
describe('aiEnvelope.correlationReplay: advertisement shape (FINAL v1.1)', () => {
|
|
40
40
|
it('host that advertises envelopeContracts.advertised:true claims the replay-determinism contract', async () => {
|
|
41
|
-
if (!(await isEnvelopeContractsAdvertised())) return; // not opted in — skip
|
|
41
|
+
if (!(await isEnvelopeContractsAdvertised())) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isEnvelopeContractsAdvertised())` returned early (not opted in — skip)'); // not opted in — skip
|
|
42
42
|
// The contract has no separate capability flag — advertising
|
|
43
43
|
// envelopeContracts is the claim. The behavioral assertions below
|
|
44
44
|
// exercise the contract; this advertisement-shape test exists so
|
|
45
45
|
// a "no envelope contracts at all" host doesn't appear in failure
|
|
46
46
|
// reports for this scenario.
|
|
47
|
-
expect(true).toBe(true);
|
|
47
|
+
expect(true, req('openwop.it.aiEnvelope.correlationReplay.host-that-advertises-envelopecontracts-advertised-true-claims-the-replay-determi', 'spec/v1/ai-envelope.md', 'host that advertises envelopeContracts.advertised:true claims the replay-determinism contract')).toBe(true);
|
|
48
48
|
});
|
|
49
49
|
});
|
|
50
50
|
|
|
@@ -75,7 +75,7 @@ describe('aiEnvelope.correlationReplay: behavioral in-process dedup (FINAL v1.1)
|
|
|
75
75
|
meta: baseMeta,
|
|
76
76
|
};
|
|
77
77
|
const first = await accept(envelope);
|
|
78
|
-
if (first.status === 404) return;
|
|
78
|
+
if (first.status === 404) return softSkip('blocked', 'precondition not met — `first.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
79
79
|
expect(first.body.status).toBe('accepted');
|
|
80
80
|
const cachedOutcome = first.body;
|
|
81
81
|
|
|
@@ -90,7 +90,7 @@ describe('aiEnvelope.correlationReplay: behavioral in-process dedup (FINAL v1.1)
|
|
|
90
90
|
});
|
|
91
91
|
expect(
|
|
92
92
|
second.body.status,
|
|
93
|
-
|
|
93
|
+
req('openwop.it.aiEnvelope.correlationReplay.same-correlationid-re-emission-returns-the-cached-outcome-unchanged',
|
|
94
94
|
'ai-envelope.md §"Replay determinism"',
|
|
95
95
|
'second emission with same correlationId MUST return the cached outcome (handler runs at most once per correlationId)',
|
|
96
96
|
),
|
|
@@ -118,10 +118,10 @@ describe('aiEnvelope.correlationReplay: behavioral in-process dedup (FINAL v1.1)
|
|
|
118
118
|
],
|
|
119
119
|
},
|
|
120
120
|
);
|
|
121
|
-
if (r.status === 404) return;
|
|
121
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
122
122
|
expect(
|
|
123
123
|
r.body.status,
|
|
124
|
-
|
|
124
|
+
req('openwop.it.aiEnvelope.correlationReplay.same-correlationid-different-envelope-type-invalid-envelope-correlation-conflict',
|
|
125
125
|
'ai-envelope.md §"Replay determinism"',
|
|
126
126
|
'same correlationId with different type MUST refuse envelope_correlation_conflict',
|
|
127
127
|
),
|
|
@@ -157,10 +157,10 @@ describe('aiEnvelope.correlationReplay: behavioral in-process dedup (FINAL v1.1)
|
|
|
157
157
|
],
|
|
158
158
|
},
|
|
159
159
|
);
|
|
160
|
-
if (r.status === 404) return;
|
|
160
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
161
161
|
expect(
|
|
162
162
|
r.body.status,
|
|
163
|
-
|
|
163
|
+
req('openwop.it.aiEnvelope.correlationReplay.cached-outcome-of-any-status-invalid-gated-breached-replays-identically',
|
|
164
164
|
'ai-envelope.md §"Replay determinism"',
|
|
165
165
|
'cached non-accepted outcome MUST replay identically (handler at most once per correlationId)',
|
|
166
166
|
),
|
|
@@ -170,10 +170,12 @@ describe('aiEnvelope.correlationReplay: behavioral in-process dedup (FINAL v1.1)
|
|
|
170
170
|
|
|
171
171
|
// E.1 engine-projection via the test-only event-log seam.
|
|
172
172
|
import { queryTestEvents, isEventLogSeamAvailable, resetTestSeam } from '../lib/event-log-query.js';
|
|
173
|
+
import { req } from '../lib/requirement-ids.js';
|
|
174
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
173
175
|
|
|
174
176
|
describe('aiEnvelope.correlationReplay: causationId projection via event-log seam', () => {
|
|
175
177
|
it('resulting RunEventDoc.causationId MUST equal the envelope.correlationId (causal chain preserved)', async () => {
|
|
176
|
-
if (!(await isEventLogSeamAvailable())) return;
|
|
178
|
+
if (!(await isEventLogSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isEventLogSeamAvailable())` returned early (seam, prior step, or fixture unavailable)');
|
|
177
179
|
const runId = `r-cr-cause-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
178
180
|
const correlationId = `${runId}:n:0:causationId-link`;
|
|
179
181
|
await accept(
|
|
@@ -188,11 +190,11 @@ describe('aiEnvelope.correlationReplay: causationId projection via event-log sea
|
|
|
188
190
|
{ projectTo: { runId, nodeId: 'n' } },
|
|
189
191
|
);
|
|
190
192
|
const events = await queryTestEvents(runId);
|
|
191
|
-
if (!events.ok || events.events.length === 0) return;
|
|
193
|
+
if (!events.ok || events.events.length === 0) return softSkip('blocked', 'precondition not met — `!events.ok || events.events.length === 0` returned early (seam, prior step, or fixture unavailable)');
|
|
192
194
|
for (const e of events.events) {
|
|
193
195
|
expect(
|
|
194
196
|
e.causationId,
|
|
195
|
-
|
|
197
|
+
req('openwop.it.aiEnvelope.correlationReplay.resulting-runeventdoc-causationid-must-equal-the-envelope-correlationid-causal-c', 'ai-envelope.md §"Replay determinism"', 'every event projected from an envelope MUST carry causationId === envelope.correlationId'),
|
|
196
198
|
).toBe(correlationId);
|
|
197
199
|
}
|
|
198
200
|
await resetTestSeam();
|
|
@@ -238,7 +240,7 @@ describe('aiEnvelope.correlationReplay: cross-process replay via persisted dedup
|
|
|
238
240
|
};
|
|
239
241
|
// First accept persists the outcome under (runId, correlationId).
|
|
240
242
|
const first = await accept(env1, { persistedDedup: { runId } });
|
|
241
|
-
if (first.status === 404) return; // seam not exposed — soft-skip
|
|
243
|
+
if (first.status === 404) return softSkip('blocked', 'precondition not met — `first.status === 404` returned early (seam not exposed — soft-skip) (seam, prior step, or fixture unavailable)'); // seam not exposed — soft-skip
|
|
242
244
|
expect(first.body.status).toBe('accepted');
|
|
243
245
|
expect(first.body.envelopeId).toBe('env-cr-persist-1');
|
|
244
246
|
|
|
@@ -250,7 +252,7 @@ describe('aiEnvelope.correlationReplay: cross-process replay via persisted dedup
|
|
|
250
252
|
const second = await accept(env2, { persistedDedup: { runId } });
|
|
251
253
|
expect(
|
|
252
254
|
second.body.envelopeId,
|
|
253
|
-
|
|
255
|
+
req('openwop.it.aiEnvelope.correlationReplay.persisted-outcome-replays-for-the-same-correlationid-even-with-no-in-memory-prio',
|
|
254
256
|
'ai-envelope.md §"Replay determinism"',
|
|
255
257
|
'persisted outcome MUST replay across calls without an in-memory priorCorrelations map (cross-process recovery: cached envelopeId surfaces even when the inbound envelope carries a different envelopeId)',
|
|
256
258
|
),
|
|
@@ -273,7 +275,7 @@ describe('aiEnvelope.correlationReplay: cross-process replay via persisted dedup
|
|
|
273
275
|
},
|
|
274
276
|
{ persistedDedup: { runId } },
|
|
275
277
|
);
|
|
276
|
-
if (first.status === 404) return;
|
|
278
|
+
if (first.status === 404) return softSkip('blocked', 'precondition not met — `first.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
277
279
|
expect(first.body.status).toBe('accepted');
|
|
278
280
|
|
|
279
281
|
// Second accept: same correlationId, different envelope type, NO
|
|
@@ -292,7 +294,7 @@ describe('aiEnvelope.correlationReplay: cross-process replay via persisted dedup
|
|
|
292
294
|
);
|
|
293
295
|
expect(
|
|
294
296
|
second.body.status,
|
|
295
|
-
|
|
297
|
+
req('openwop.it.aiEnvelope.correlationReplay.persisted-store-enforces-envelope-correlation-conflict-across-calls',
|
|
296
298
|
'ai-envelope.md §"Replay determinism"',
|
|
297
299
|
'persisted store MUST surface envelope_correlation_conflict on type mismatch without an in-memory priorCorrelations map',
|
|
298
300
|
),
|
|
@@ -40,11 +40,11 @@ async function isBYOKAdvertised(): Promise<boolean> {
|
|
|
40
40
|
|
|
41
41
|
describe('aiEnvelope.redaction: advertisement shape (FINAL v1.1)', () => {
|
|
42
42
|
it('hosts advertising envelopeContracts AND secrets honor SR-1 carry-forward', async () => {
|
|
43
|
-
if (!(await isBYOKAdvertised())) return; // BYOK not advertised — skip
|
|
43
|
+
if (!(await isBYOKAdvertised())) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isBYOKAdvertised())` returned early (BYOK not advertised — skip)'); // BYOK not advertised — skip
|
|
44
44
|
// The contract is invariant-based, not capability-flag-based. The
|
|
45
45
|
// advertisement-shape check is just "the host claims a BYOK surface";
|
|
46
46
|
// behavioral assertions below exercise the redaction invariant.
|
|
47
|
-
expect(true).toBe(true);
|
|
47
|
+
expect(true, req('openwop.it.aiEnvelope.redaction.hosts-advertising-envelopecontracts-and-secrets-honor-sr-1-carry-forward', 'spec/v1/ai-envelope.md', 'hosts advertising envelopeContracts AND secrets honor SR-1 carry-forward')).toBe(true);
|
|
48
48
|
});
|
|
49
49
|
});
|
|
50
50
|
|
|
@@ -78,16 +78,16 @@ describe('aiEnvelope.redaction: behavioral acceptor-level scrub (FINAL v1.1)', (
|
|
|
78
78
|
},
|
|
79
79
|
{ byokCanaries: CANARIES },
|
|
80
80
|
);
|
|
81
|
-
if (r.status === 404) return;
|
|
81
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
82
82
|
expect(r.body.status).toBe('accepted');
|
|
83
|
-
expect(r.body.redactionCount, 'redactionCount MUST be > 0 when canary appears').toBeGreaterThan(0);
|
|
83
|
+
expect(r.body.redactionCount, req('openwop.it.aiEnvelope.redaction.canary-in-payload-substituted-with-canonical-sr-1-redacted-secretid-marker-per-a', 'ai-envelope.md §"Redaction (SR-1 carry-forward)"', 'redactionCount MUST be > 0 when canary appears')).toBeGreaterThan(0);
|
|
84
84
|
expect(
|
|
85
85
|
JSON.stringify(r.body.redactedPayload).includes(CANARY_VALUE),
|
|
86
|
-
|
|
86
|
+
req('openwop.it.aiEnvelope.redaction.canary-in-payload-substituted-with-canonical-sr-1-redacted-secretid-marker-per-a', 'ai-envelope.md §"Redaction (SR-1 carry-forward)"', 'canary plaintext MUST be absent from the redacted view'),
|
|
87
87
|
).toBe(false);
|
|
88
88
|
expect(
|
|
89
89
|
JSON.stringify(r.body.redactedPayload),
|
|
90
|
-
|
|
90
|
+
req('openwop.it.aiEnvelope.redaction.canary-in-payload-substituted-with-canonical-sr-1-redacted-secretid-marker-per-a', 'agent-memory.md §SR-1 line 66', 'persisted entry MUST carry [REDACTED:<secretId>] in place of the plaintext'),
|
|
91
91
|
).toContain(CANONICAL_MARKER);
|
|
92
92
|
});
|
|
93
93
|
|
|
@@ -108,11 +108,11 @@ describe('aiEnvelope.redaction: behavioral acceptor-level scrub (FINAL v1.1)', (
|
|
|
108
108
|
},
|
|
109
109
|
{ byokCanaries: CANARIES },
|
|
110
110
|
);
|
|
111
|
-
if (r.status === 404) return;
|
|
111
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
112
112
|
expect(r.body.status).toBe('accepted');
|
|
113
113
|
expect(
|
|
114
114
|
JSON.stringify(r.body.redactedPayload).includes(CANARY_VALUE),
|
|
115
|
-
'no canary plaintext remnant anywhere in the redacted view (recursive scrub)',
|
|
115
|
+
req('openwop.it.aiEnvelope.redaction.canary-across-nested-object-fields-all-occurrences-scrubbed-with-canonical-marke', 'spec/v1/ai-envelope.md', 'no canary plaintext remnant anywhere in the redacted view (recursive scrub)'),
|
|
116
116
|
).toBe(false);
|
|
117
117
|
// q1's question (1 occurrence), q2's context.trace (2 occurrences) = total 3
|
|
118
118
|
expect(r.body.redactionCount).toBe(3);
|
|
@@ -132,14 +132,14 @@ describe('aiEnvelope.redaction: behavioral acceptor-level scrub (FINAL v1.1)', (
|
|
|
132
132
|
},
|
|
133
133
|
{ byokCanaries: [C1, C2] },
|
|
134
134
|
);
|
|
135
|
-
if (r.status === 404) return;
|
|
135
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
136
136
|
expect(r.body.status).toBe('accepted');
|
|
137
137
|
const view = JSON.stringify(r.body.redactedPayload);
|
|
138
138
|
expect(view.includes(C1.value)).toBe(false);
|
|
139
139
|
expect(view.includes(C2.value)).toBe(false);
|
|
140
140
|
expect(
|
|
141
141
|
view.includes(`[REDACTED:${C1.secretId}]`) && view.includes(`[REDACTED:${C2.secretId}]`),
|
|
142
|
-
|
|
142
|
+
req('openwop.it.aiEnvelope.redaction.multiple-canaries-each-substituted-with-its-own-secretid-marker', 'agent-memory.md §SR-1', 'each canary MUST be substituted with its OWN [REDACTED:<secretId>] marker'),
|
|
143
143
|
).toBe(true);
|
|
144
144
|
});
|
|
145
145
|
|
|
@@ -157,10 +157,10 @@ describe('aiEnvelope.redaction: behavioral acceptor-level scrub (FINAL v1.1)', (
|
|
|
157
157
|
},
|
|
158
158
|
{ byokCanaries: CANARIES }, // canary NOT in payload; substitution count expected 0
|
|
159
159
|
);
|
|
160
|
-
if (r.status === 404) return;
|
|
160
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
161
161
|
expect(
|
|
162
162
|
r.body.status,
|
|
163
|
-
|
|
163
|
+
req('openwop.it.aiEnvelope.redaction.redaction-runs-after-schema-validation-payload-with-redacted-shaped-substrings-s', 'ai-envelope.md §"Redaction (SR-1 carry-forward)"', 'redaction MUST run AFTER schema validation; pre-existing markers do not affect validation'),
|
|
164
164
|
).toBe('accepted');
|
|
165
165
|
// No canary present → redactionCount absent or 0
|
|
166
166
|
expect(r.body.redactionCount ?? 0).toBe(0);
|
|
@@ -181,12 +181,12 @@ describe('aiEnvelope.redaction: behavioral acceptor-level scrub (FINAL v1.1)', (
|
|
|
181
181
|
},
|
|
182
182
|
{ byokCanaries: CANARIES },
|
|
183
183
|
);
|
|
184
|
-
if (r.status === 404) return;
|
|
184
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
185
185
|
expect(r.body.status).toBe('invalid');
|
|
186
186
|
const bodyString = JSON.stringify(r.body);
|
|
187
187
|
expect(
|
|
188
188
|
bodyString.includes(CANARY_VALUE),
|
|
189
|
-
|
|
189
|
+
req('openwop.it.aiEnvelope.redaction.canary-in-invalid-envelope-validation-refusal-error-response-must-not-echo-the-c',
|
|
190
190
|
'SECURITY/threat-model-secret-leakage.md §SR-1',
|
|
191
191
|
'error response on validation refusal MUST NOT echo BYOK canary plaintext',
|
|
192
192
|
),
|
|
@@ -197,10 +197,12 @@ describe('aiEnvelope.redaction: behavioral acceptor-level scrub (FINAL v1.1)', (
|
|
|
197
197
|
// E.2 OTel scrape + E.3 debug-bundle seams.
|
|
198
198
|
import { queryTestSpans, exportDebugBundle, isOtelSeamAvailable } from '../lib/otel-scrape.js';
|
|
199
199
|
import { resetTestSeam } from '../lib/event-log-query.js';
|
|
200
|
+
import { req } from '../lib/requirement-ids.js';
|
|
201
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
200
202
|
|
|
201
203
|
describe('aiEnvelope.redaction: OTel + debug-bundle scrape (E.2 + E.3)', () => {
|
|
202
204
|
it('redacted canary plaintext MUST be absent from OTel envelope_* span attributes', async () => {
|
|
203
|
-
if (!(await isOtelSeamAvailable())) return;
|
|
205
|
+
if (!(await isOtelSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isOtelSeamAvailable())` returned early (seam, prior step, or fixture unavailable)');
|
|
204
206
|
const runId = `r-red-otel-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
205
207
|
await accept(
|
|
206
208
|
{
|
|
@@ -214,11 +216,11 @@ describe('aiEnvelope.redaction: OTel + debug-bundle scrape (E.2 + E.3)', () => {
|
|
|
214
216
|
{ byokCanaries: CANARIES, projectTo: { runId, nodeId: 'n' } },
|
|
215
217
|
);
|
|
216
218
|
const spans = await queryTestSpans({ runId });
|
|
217
|
-
if (!spans.ok) return;
|
|
219
|
+
if (!spans.ok) return softSkip('blocked', 'precondition not met — `!spans.ok` returned early (seam, prior step, or fixture unavailable)');
|
|
218
220
|
const allAttrs = spans.data.flatMap((s) => Object.values(s.attributes).map((v) => String(v)));
|
|
219
221
|
expect(
|
|
220
222
|
allAttrs.some((v) => v.includes(CANARY_VALUE)),
|
|
221
|
-
|
|
223
|
+
req('openwop.it.aiEnvelope.redaction.redacted-canary-plaintext-must-be-absent-from-otel-envelope-span-attributes',
|
|
222
224
|
'SECURITY/threat-model-secret-leakage.md §SR-1',
|
|
223
225
|
'BYOK canary plaintext MUST NOT appear in any OTel envelope_* span attribute',
|
|
224
226
|
),
|
|
@@ -227,7 +229,7 @@ describe('aiEnvelope.redaction: OTel + debug-bundle scrape (E.2 + E.3)', () => {
|
|
|
227
229
|
});
|
|
228
230
|
|
|
229
231
|
it('redacted canary plaintext MUST be absent from debug-bundle export', async () => {
|
|
230
|
-
if (!(await isOtelSeamAvailable())) return;
|
|
232
|
+
if (!(await isOtelSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isOtelSeamAvailable())` returned early (seam, prior step, or fixture unavailable)');
|
|
231
233
|
const runId = `r-red-bundle-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
232
234
|
await accept(
|
|
233
235
|
{
|
|
@@ -241,11 +243,11 @@ describe('aiEnvelope.redaction: OTel + debug-bundle scrape (E.2 + E.3)', () => {
|
|
|
241
243
|
{ byokCanaries: CANARIES, projectTo: { runId, nodeId: 'n' } },
|
|
242
244
|
);
|
|
243
245
|
const bundle = await exportDebugBundle(runId);
|
|
244
|
-
if (!bundle.ok) return;
|
|
246
|
+
if (!bundle.ok) return softSkip('blocked', 'precondition not met — `!bundle.ok` returned early (seam, prior step, or fixture unavailable)');
|
|
245
247
|
const serialized = JSON.stringify(bundle.data);
|
|
246
248
|
expect(
|
|
247
249
|
serialized.includes(CANARY_VALUE),
|
|
248
|
-
|
|
250
|
+
req('openwop.it.aiEnvelope.redaction.redacted-canary-plaintext-must-be-absent-from-debug-bundle-export',
|
|
249
251
|
'SECURITY/threat-model-secret-leakage.md §SR-1',
|
|
250
252
|
'BYOK canary plaintext MUST NOT appear in the debug-bundle export (events + spans)',
|
|
251
253
|
),
|
|
@@ -40,10 +40,10 @@ describe('aiEnvelope.schemaDrift: advertisement shape (FINAL v1.1)', () => {
|
|
|
40
40
|
const body = res.json as DiscoveryDoc | undefined;
|
|
41
41
|
const top = discoveryFamilies(body);
|
|
42
42
|
const val = top && typeof top === 'object' ? top['envelopeStrictness'] : undefined;
|
|
43
|
-
if (val === undefined) return; // absent → treated as 'warn'; skip
|
|
43
|
+
if (val === undefined) return softSkip('blocked', 'precondition not met — `val === undefined` returned early (absent → treated as \'warn\'; skip) (seam, prior step, or fixture unavailable)'); // absent → treated as 'warn'; skip
|
|
44
44
|
expect(
|
|
45
45
|
val === 'warn' || val === 'strict',
|
|
46
|
-
|
|
46
|
+
req('openwop.it.aiEnvelope.schemaDrift.capabilities-envelopestrictness-is-either-absent-treated-as-warn-or-warn-strict',
|
|
47
47
|
'ai-envelope.md §"Capability handshake integration"',
|
|
48
48
|
'envelopeStrictness MUST be the literal string "warn" or "strict" when present',
|
|
49
49
|
),
|
|
@@ -51,13 +51,13 @@ describe('aiEnvelope.schemaDrift: advertisement shape (FINAL v1.1)', () => {
|
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
it('schemaVersions is non-empty when envelopeContracts.advertised: true', async () => {
|
|
54
|
-
if (!(await isEnvelopeContractsAdvertised())) return; // not opted in — skip
|
|
54
|
+
if (!(await isEnvelopeContractsAdvertised())) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isEnvelopeContractsAdvertised())` returned early (not opted in — skip)'); // not opted in — skip
|
|
55
55
|
const res = await driver.get('/.well-known/openwop');
|
|
56
56
|
const body = res.json as { schemaVersions?: Record<string, number>; capabilities?: { schemaVersions?: Record<string, number> } } | undefined;
|
|
57
57
|
const versions = body?.schemaVersions ?? capabilityFamily(body, 'schemaVersions') ?? {};
|
|
58
58
|
expect(
|
|
59
59
|
Object.keys(versions).length > 0,
|
|
60
|
-
|
|
60
|
+
req('openwop.it.aiEnvelope.schemaDrift.schemaversions-is-non-empty-when-envelopecontracts-advertised-true',
|
|
61
61
|
'ai-envelope.md §"Schema version advertisement"',
|
|
62
62
|
'schemaVersions MUST be non-empty when envelopeContracts.advertised is true',
|
|
63
63
|
),
|
|
@@ -93,10 +93,10 @@ describe('aiEnvelope.schemaDrift: behavioral strictness gate (FINAL v1.1)', () =
|
|
|
93
93
|
envelopeStrictness: 'warn',
|
|
94
94
|
},
|
|
95
95
|
);
|
|
96
|
-
if (r.status === 404) return;
|
|
96
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
97
97
|
expect(
|
|
98
98
|
r.body.status,
|
|
99
|
-
|
|
99
|
+
req('openwop.it.aiEnvelope.schemaDrift.schemaversion-below-advertised-floor-under-strictness-warn-accepted-warn-and-con',
|
|
100
100
|
'ai-envelope.md §"Schema discipline"',
|
|
101
101
|
'below-floor schemaVersion under strictness:warn MUST be accepted (drift projected at engine level)',
|
|
102
102
|
),
|
|
@@ -118,10 +118,10 @@ describe('aiEnvelope.schemaDrift: behavioral strictness gate (FINAL v1.1)', () =
|
|
|
118
118
|
envelopeStrictness: 'strict',
|
|
119
119
|
},
|
|
120
120
|
);
|
|
121
|
-
if (r.status === 404) return;
|
|
121
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
122
122
|
expect(
|
|
123
123
|
r.body.status,
|
|
124
|
-
|
|
124
|
+
req('openwop.it.aiEnvelope.schemaDrift.schemaversion-below-advertised-floor-under-strictness-strict-invalid-unknown-sch',
|
|
125
125
|
'ai-envelope.md §"Schema discipline"',
|
|
126
126
|
'below-floor schemaVersion under strictness:strict MUST refuse with unknown_schema_version',
|
|
127
127
|
),
|
|
@@ -145,10 +145,10 @@ describe('aiEnvelope.schemaDrift: behavioral strictness gate (FINAL v1.1)', () =
|
|
|
145
145
|
envelopeStrictness: strictness,
|
|
146
146
|
},
|
|
147
147
|
);
|
|
148
|
-
if (r.status === 404) return;
|
|
148
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
149
149
|
expect(
|
|
150
150
|
r.body.status,
|
|
151
|
-
|
|
151
|
+
req('openwop.it.aiEnvelope.schemaDrift.schemaversion-above-advertised-floor-invalid-regardless-of-strictness-host-doesn',
|
|
152
152
|
'ai-envelope.md §"Schema discipline"',
|
|
153
153
|
`above-floor schemaVersion MUST refuse regardless of strictness (got ${strictness})`,
|
|
154
154
|
),
|
|
@@ -172,13 +172,13 @@ describe('aiEnvelope.schemaDrift: behavioral strictness gate (FINAL v1.1)', () =
|
|
|
172
172
|
envelopeStrictness: 'warn', // above-floor → invalid regardless
|
|
173
173
|
},
|
|
174
174
|
);
|
|
175
|
-
if (r.status === 404) return;
|
|
175
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
176
176
|
expect(r.body.status).toBe('invalid');
|
|
177
177
|
expect(Array.isArray(r.body.details)).toBe(true);
|
|
178
178
|
const paths = (r.body.details ?? []).map((d: unknown) => (d as { instancePath?: string }).instancePath);
|
|
179
179
|
expect(
|
|
180
180
|
paths.includes('/schemaVersion'),
|
|
181
|
-
|
|
181
|
+
req('openwop.it.aiEnvelope.schemaDrift.refused-above-floor-envelope-carries-instancepath-schemaversion-in-details',
|
|
182
182
|
'ai-envelope.md §"Schema discipline"',
|
|
183
183
|
'schema-drift refusal MUST cite /schemaVersion as the violating field',
|
|
184
184
|
),
|
|
@@ -190,10 +190,12 @@ describe('aiEnvelope.schemaDrift: behavioral strictness gate (FINAL v1.1)', () =
|
|
|
190
190
|
import { queryTestSpans, isOtelSeamAvailable } from '../lib/otel-scrape.js';
|
|
191
191
|
import { resetTestSeam } from '../lib/event-log-query.js';
|
|
192
192
|
import { capabilityFamily, discoveryFamilies } from '../lib/discovery-capabilities.js';
|
|
193
|
+
import { req } from '../lib/requirement-ids.js';
|
|
194
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
193
195
|
|
|
194
196
|
describe('aiEnvelope.schemaDrift: OTel drift attribute projection (E.2)', () => {
|
|
195
197
|
it('below-floor + strictness:warn → OTel span MUST carry envelope_schema_version_drift attribute', async () => {
|
|
196
|
-
if (!(await isOtelSeamAvailable())) return;
|
|
198
|
+
if (!(await isOtelSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isOtelSeamAvailable())` returned early (seam, prior step, or fixture unavailable)');
|
|
197
199
|
const runId = `r-drift-otel-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
198
200
|
const r = await accept(
|
|
199
201
|
{
|
|
@@ -210,14 +212,14 @@ describe('aiEnvelope.schemaDrift: OTel drift attribute projection (E.2)', () =>
|
|
|
210
212
|
projectTo: { runId, nodeId: 'n' },
|
|
211
213
|
},
|
|
212
214
|
);
|
|
213
|
-
if (r.status === 404) return;
|
|
215
|
+
if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
214
216
|
expect(r.body.status).toBe('accepted');
|
|
215
217
|
|
|
216
218
|
const spans = await queryTestSpans({ runId });
|
|
217
|
-
if (!spans.ok) return;
|
|
219
|
+
if (!spans.ok) return softSkip('blocked', 'precondition not met — `!spans.ok` returned early (seam, prior step, or fixture unavailable)');
|
|
218
220
|
expect(
|
|
219
221
|
spans.data.some((s) => s.attributes.envelope_schema_version_drift === true),
|
|
220
|
-
|
|
222
|
+
req('openwop.it.aiEnvelope.schemaDrift.below-floor-strictness-warn-otel-span-must-carry-envelope-schema-version-drift-a',
|
|
221
223
|
'ai-envelope.md §"Schema discipline"',
|
|
222
224
|
'below-floor accept under strictness:warn MUST project envelope_schema_version_drift attribute on the OTel span',
|
|
223
225
|
),
|