@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
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
import { describe, it, expect } from 'vitest';
|
|
13
13
|
import { softSkip } from '../lib/soft-skip.js';
|
|
14
|
-
import { driver } from '../lib/driver.js';
|
|
15
14
|
import { readSubRunAttestationCap, invokeSubRunAttest } from '../lib/subRunAttestation.js';
|
|
15
|
+
import { req } from '../lib/requirement-ids.js';
|
|
16
16
|
|
|
17
17
|
describe('subrun-approval-gate (RFC 0063 §C)', () => {
|
|
18
18
|
it('accept merges the child outputs; reject does not', async () => {
|
|
@@ -23,14 +23,14 @@ describe('subrun-approval-gate (RFC 0063 §C)', () => {
|
|
|
23
23
|
if (accepted === null) return softSkip('blocked', 'seam absent — soft-skip');
|
|
24
24
|
expect(
|
|
25
25
|
accepted.merged,
|
|
26
|
-
|
|
26
|
+
req('openwop.it.subrun-approval-gate.accept-merges-the-child-outputs-reject-does-not', 'RFC 0063 §C', 'an `accept` approval MUST merge the child outputs'),
|
|
27
27
|
).toBe(true);
|
|
28
28
|
|
|
29
29
|
const rejected = await invokeSubRunAttest({ ...base, approvalAction: 'reject' });
|
|
30
30
|
if (rejected === null) return softSkip('blocked', 'precondition not met — `rejected === null` returned early (seam, prior step, or fixture unavailable)');
|
|
31
31
|
expect(
|
|
32
32
|
rejected.merged,
|
|
33
|
-
|
|
33
|
+
req('openwop.it.subrun-approval-gate.accept-merges-the-child-outputs-reject-does-not', 'RFC 0063 §C', 'a `reject` approval MUST NOT merge the child outputs'),
|
|
34
34
|
).toBe(false);
|
|
35
35
|
});
|
|
36
36
|
});
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
import { describe, it, expect } from 'vitest';
|
|
14
14
|
import { softSkip } from '../lib/soft-skip.js';
|
|
15
|
-
import { driver } from '../lib/driver.js';
|
|
16
15
|
import { readSubRunAttestationCap } from '../lib/subRunAttestation.js';
|
|
16
|
+
import { req } from '../lib/requirement-ids.js';
|
|
17
17
|
|
|
18
18
|
describe('subrun-attestation-shape: advertisement (RFC 0063 §A)', () => {
|
|
19
19
|
it('capabilities.agents.subRunAttestation is absent or a boolean', async () => {
|
|
@@ -22,7 +22,7 @@ describe('subrun-attestation-shape: advertisement (RFC 0063 §A)', () => {
|
|
|
22
22
|
if (cap === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === null` returned early');
|
|
23
23
|
expect(
|
|
24
24
|
typeof cap,
|
|
25
|
-
|
|
25
|
+
req('openwop.it.subrun-attestation-shape.capabilities-agents-subrunattestation-is-absent-or-a-boolean',
|
|
26
26
|
'capabilities.schema.json §agents.subRunAttestation',
|
|
27
27
|
'agents.subRunAttestation MUST be a boolean when present',
|
|
28
28
|
),
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
import { describe, it, expect } from 'vitest';
|
|
14
14
|
import { softSkip } from '../lib/soft-skip.js';
|
|
15
|
-
import { driver } from '../lib/driver.js';
|
|
16
15
|
import { readSubRunAttestationCap, invokeSubRunAttest } from '../lib/subRunAttestation.js';
|
|
16
|
+
import { req } from '../lib/requirement-ids.js';
|
|
17
17
|
|
|
18
18
|
describe('subrun-checksum-stable (RFC 0063 §B)', () => {
|
|
19
19
|
it('identical child outputs produce an identical sha256 attestation checksum', async () => {
|
|
@@ -30,15 +30,15 @@ describe('subrun-checksum-stable (RFC 0063 §B)', () => {
|
|
|
30
30
|
const att = a.attestation ?? {};
|
|
31
31
|
expect(
|
|
32
32
|
typeof att.checksum === 'string' && (att.checksum as string).length > 0,
|
|
33
|
-
|
|
33
|
+
req('openwop.it.subrun-checksum-stable.identical-child-outputs-produce-an-identical-sha256-attestation-checksum', 'RFC 0063 §B', 'output.harvested MUST carry a non-empty attestation.checksum when checksum:true'),
|
|
34
34
|
).toBe(true);
|
|
35
35
|
expect(
|
|
36
36
|
att.algorithm,
|
|
37
|
-
|
|
37
|
+
req('openwop.it.subrun-checksum-stable.identical-child-outputs-produce-an-identical-sha256-attestation-checksum', 'RFC 0063 §B', 'attestation.algorithm MUST be "sha256" (the v1 recipe)'),
|
|
38
38
|
).toBe('sha256');
|
|
39
39
|
expect(
|
|
40
40
|
(b.attestation ?? {}).checksum,
|
|
41
|
-
|
|
41
|
+
req('openwop.it.subrun-checksum-stable.identical-child-outputs-produce-an-identical-sha256-attestation-checksum', 'RFC 0063 §B', 'JCS canonicalization MUST make the checksum invariant to key order — same content, same hash'),
|
|
42
42
|
).toBe(att.checksum);
|
|
43
43
|
});
|
|
44
44
|
});
|
|
@@ -23,6 +23,8 @@ import { driver } from '../lib/driver.js';
|
|
|
23
23
|
import { pollUntilTerminal, pollUntilStatus } from '../lib/polling.js';
|
|
24
24
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
25
25
|
import { setHostCapability, resetHostCapabilities, isToggleAvailable } from '../lib/host-toggle.js';
|
|
26
|
+
import { req } from '../lib/requirement-ids.js';
|
|
27
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
26
28
|
|
|
27
29
|
const PARENT = 'conformance-subworkflow-input-mapping';
|
|
28
30
|
const CHILD = 'conformance-subworkflow-input-mapping-child';
|
|
@@ -51,7 +53,7 @@ describe.skipIf(SKIP)('subworkflow-input-mapping: parent → child variable seed
|
|
|
51
53
|
const parentRunId = (create.json as { runId: string }).runId;
|
|
52
54
|
|
|
53
55
|
const parentTerminal = (await pollUntilTerminal(parentRunId)) as RunSnapshot;
|
|
54
|
-
expect(parentTerminal.status,
|
|
56
|
+
expect(parentTerminal.status, req('openwop.it.subworkflow-input-mapping.hvmap-2-inputmapping-seeds-child-variables-overrides-defaultvalue-child-reads-pa',
|
|
55
57
|
'RFCS/0022-dispatch-input-output-mapping.md §B',
|
|
56
58
|
'parent run MUST reach terminal `completed` once the child finishes',
|
|
57
59
|
)).toBe('completed');
|
|
@@ -63,7 +65,7 @@ describe.skipIf(SKIP)('subworkflow-input-mapping: parent → child variable seed
|
|
|
63
65
|
const subwfCompleted = events.find(
|
|
64
66
|
(e) => e.type === 'node.completed' && e.nodeId === 'subwf-call',
|
|
65
67
|
);
|
|
66
|
-
expect(subwfCompleted,
|
|
68
|
+
expect(subwfCompleted, req('openwop.it.subworkflow-input-mapping.hvmap-2-inputmapping-seeds-child-variables-overrides-defaultvalue-child-reads-pa',
|
|
67
69
|
'spec/v1/node-packs.md §"`core.subWorkflow` contract"',
|
|
68
70
|
'parent event log MUST contain `node.completed` for the subwf-call node',
|
|
69
71
|
)).toBeDefined();
|
|
@@ -76,12 +78,12 @@ describe.skipIf(SKIP)('subworkflow-input-mapping: parent → child variable seed
|
|
|
76
78
|
const childSnapshotRes = await driver.get(`/v1/runs/${encodeURIComponent(childRunId!)}`);
|
|
77
79
|
expect(childSnapshotRes.status).toBe(200);
|
|
78
80
|
const childSnapshot = childSnapshotRes.json as RunSnapshot;
|
|
79
|
-
expect(childSnapshot.status,
|
|
81
|
+
expect(childSnapshot.status, req('openwop.it.subworkflow-input-mapping.hvmap-2-inputmapping-seeds-child-variables-overrides-defaultvalue-child-reads-pa',
|
|
80
82
|
'spec/v1/node-packs.md §"`core.subWorkflow` contract"',
|
|
81
83
|
'child run MUST reach terminal `completed`',
|
|
82
84
|
)).toBe('completed');
|
|
83
85
|
const childVars = childSnapshot.variables ?? {};
|
|
84
|
-
expect(childVars.receivedPrdId,
|
|
86
|
+
expect(childVars.receivedPrdId, req('openwop.it.subworkflow-input-mapping.hvmap-2-inputmapping-seeds-child-variables-overrides-defaultvalue-child-reads-pa',
|
|
85
87
|
'RFCS/0022-dispatch-input-output-mapping.md §B',
|
|
86
88
|
'child `receivedPrdId` MUST be parent\'s `currentPrdId` projection ("prd-1"), overriding the child\'s defaultValue "baked-in"',
|
|
87
89
|
)).toBe('prd-1');
|
|
@@ -89,7 +91,7 @@ describe.skipIf(SKIP)('subworkflow-input-mapping: parent → child variable seed
|
|
|
89
91
|
|
|
90
92
|
it('HVMAP-2-unset: parent.currentPrdId unset → child receivedPrdId MUST surface as `undefined`', async () => {
|
|
91
93
|
const PARENT_NO_DEFAULT = 'conformance-subworkflow-input-mapping-no-default';
|
|
92
|
-
if (!isFixtureAdvertised(PARENT_NO_DEFAULT) || !isFixtureAdvertised(CHILD)) return; // soft-skip
|
|
94
|
+
if (!isFixtureAdvertised(PARENT_NO_DEFAULT) || !isFixtureAdvertised(CHILD)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(PARENT_NO_DEFAULT) || !isFixtureAdvertised(CHILD)` returned early (soft-skip)'); // soft-skip
|
|
93
95
|
const create = await driver.post('/v1/runs', { workflowId: PARENT_NO_DEFAULT });
|
|
94
96
|
expect(create.status).toBe(201);
|
|
95
97
|
const parentRunId = (create.json as { runId: string }).runId;
|
|
@@ -100,7 +102,7 @@ describe.skipIf(SKIP)('subworkflow-input-mapping: parent → child variable seed
|
|
|
100
102
|
const subwfCompleted = events.find(
|
|
101
103
|
(e) => e.type === 'node.completed' && e.nodeId === 'subwf-call',
|
|
102
104
|
);
|
|
103
|
-
if (!subwfCompleted) return;
|
|
105
|
+
if (!subwfCompleted) return softSkip('blocked', 'precondition not met — `!subwfCompleted` returned early (seam, prior step, or fixture unavailable)');
|
|
104
106
|
const childRunId = subwfCompleted.payload?.outputs?.childRunId;
|
|
105
107
|
|
|
106
108
|
const childRes = await driver.get(`/v1/runs/${encodeURIComponent(childRunId!)}`);
|
|
@@ -114,7 +116,7 @@ describe.skipIf(SKIP)('subworkflow-input-mapping: parent → child variable seed
|
|
|
114
116
|
// undefined the child's defaultValue should remain.
|
|
115
117
|
expect(
|
|
116
118
|
v === 'baked-in' || v === undefined || !('receivedPrdId' in vars),
|
|
117
|
-
|
|
119
|
+
req('openwop.it.subworkflow-input-mapping.hvmap-2-unset-parent-currentprdid-unset-child-receivedprdid-must-surface-as-unde',
|
|
118
120
|
'RFCS/0022-dispatch-input-output-mapping.md §B',
|
|
119
121
|
'unset parent variable MUST surface as undefined-or-defaultValue-fallback (NOT null)',
|
|
120
122
|
),
|
|
@@ -137,8 +139,8 @@ describe.skipIf(SKIP)('subworkflow-input-mapping: parent → child variable seed
|
|
|
137
139
|
const CHILD_GATE_NODE = 'child-gate';
|
|
138
140
|
|
|
139
141
|
it('HVMAP-2-no-midrun-propagation: parent mid-run mutation MUST NOT propagate into the seeded child', async () => {
|
|
140
|
-
if (!isFixtureAdvertised(MID_RUN_PARENT) || !isFixtureAdvertised(MID_RUN_CHILD)) return; // fixture not seeded — soft-skip
|
|
141
|
-
if (!(await isToggleAvailable())) return; // sample test seam not exposed — soft-skip
|
|
142
|
+
if (!isFixtureAdvertised(MID_RUN_PARENT) || !isFixtureAdvertised(MID_RUN_CHILD)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(MID_RUN_PARENT) || !isFixtureAdvertised(MID_RUN_CHILD)` returned early (fixture not seeded — soft-skip)'); // fixture not seeded — soft-skip
|
|
143
|
+
if (!(await isToggleAvailable())) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isToggleAvailable())` returned early (sample test seam not exposed — soft-skip)'); // sample test seam not exposed — soft-skip
|
|
142
144
|
|
|
143
145
|
const create = await driver.post('/v1/runs', { workflowId: MID_RUN_PARENT });
|
|
144
146
|
expect(create.status).toBe(201);
|
|
@@ -156,7 +158,7 @@ describe.skipIf(SKIP)('subworkflow-input-mapping: parent → child variable seed
|
|
|
156
158
|
const parentSnap = await driver.get(`/v1/runs/${encodeURIComponent(parentRunId)}`);
|
|
157
159
|
const parentJson = parentSnap.json as { childRuns?: Array<{ runId: string; status: string }> };
|
|
158
160
|
const childRunId = parentJson.childRuns?.[0]?.runId;
|
|
159
|
-
expect(childRunId,
|
|
161
|
+
expect(childRunId, req('openwop.it.subworkflow-input-mapping.hvmap-2-no-midrun-propagation-parent-mid-run-mutation-must-not-propagate-into-th',
|
|
160
162
|
'fixtures.md conformance-subworkflow-mid-run-mutation',
|
|
161
163
|
'parent snapshot MUST surface the spawned child runId via childRuns[]',
|
|
162
164
|
)).toBeDefined();
|
|
@@ -185,7 +187,7 @@ describe.skipIf(SKIP)('subworkflow-input-mapping: parent → child variable seed
|
|
|
185
187
|
// (`seeded-id`), NOT the post-mutation parent value (`mutated-id`).
|
|
186
188
|
expect(
|
|
187
189
|
childTerminal.variables?.receivedPrdId,
|
|
188
|
-
|
|
190
|
+
req('openwop.it.subworkflow-input-mapping.hvmap-2-no-midrun-propagation-parent-mid-run-mutation-must-not-propagate-into-th',
|
|
189
191
|
'RFCS/0022-dispatch-input-output-mapping.md §B',
|
|
190
192
|
'mid-run parent mutation MUST NOT propagate; child receivedPrdId stays at dispatch-time fold',
|
|
191
193
|
),
|
|
@@ -196,7 +198,7 @@ describe.skipIf(SKIP)('subworkflow-input-mapping: parent → child variable seed
|
|
|
196
198
|
|
|
197
199
|
describe('subworkflow-input-mapping: registration refusal (RFC 0022 §C HVMAP-2-refusal)', () => {
|
|
198
200
|
it('host with subWorkflow.inputMapping toggled OFF MUST refuse non-empty inputMapping at registration', async () => {
|
|
199
|
-
if (!(await isToggleAvailable())) return; // seam not exposed — soft-skip
|
|
201
|
+
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
|
|
200
202
|
await setHostCapability('subWorkflow.inputMapping', false);
|
|
201
203
|
try {
|
|
202
204
|
const workflow = {
|
|
@@ -215,7 +217,7 @@ describe('subworkflow-input-mapping: registration refusal (RFC 0022 §C HVMAP-2-
|
|
|
215
217
|
const res = await driver.post('/v1/host/sample/workflows', workflow);
|
|
216
218
|
expect(
|
|
217
219
|
res.status,
|
|
218
|
-
|
|
220
|
+
req('openwop.it.subworkflow-input-mapping.host-with-subworkflow-inputmapping-toggled-off-must-refuse-non-empty-inputmappin',
|
|
219
221
|
'RFCS/0022-dispatch-input-output-mapping.md §C',
|
|
220
222
|
'workflow with non-empty subWorkflow.inputMapping MUST be refused when capability is not advertised',
|
|
221
223
|
),
|
|
@@ -224,7 +226,7 @@ describe('subworkflow-input-mapping: registration refusal (RFC 0022 §C HVMAP-2-
|
|
|
224
226
|
expect(body.error).toBe('validation_error');
|
|
225
227
|
expect(
|
|
226
228
|
body.details?.requiredCapability,
|
|
227
|
-
|
|
229
|
+
req('openwop.it.subworkflow-input-mapping.host-with-subworkflow-inputmapping-toggled-off-must-refuse-non-empty-inputmappin',
|
|
228
230
|
'RFCS/0022-dispatch-input-output-mapping.md §C',
|
|
229
231
|
'refusal MUST surface requiredCapability: "subWorkflow.inputMapping"',
|
|
230
232
|
),
|
|
@@ -20,6 +20,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
20
20
|
import { driver } from '../lib/driver.js';
|
|
21
21
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
22
22
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
23
|
+
import { req } from '../lib/requirement-ids.js';
|
|
23
24
|
|
|
24
25
|
const PARENT_WORKFLOW_ID = 'conformance-subworkflow-parent';
|
|
25
26
|
const CHILD_WORKFLOW_ID = 'conformance-subworkflow-child';
|
|
@@ -50,7 +51,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('subworkflow: conformance-subworkflow-parent di
|
|
|
50
51
|
const parentRunId = (create.json as { runId: string }).runId;
|
|
51
52
|
|
|
52
53
|
const parentTerminal = await pollUntilTerminal(parentRunId);
|
|
53
|
-
expect(parentTerminal.status,
|
|
54
|
+
expect(parentTerminal.status, req('openwop.it.subworkflow.parent-run-reaches-terminal-completed-and-child-variable-is-propagated-via-outpu',
|
|
54
55
|
'fixtures.md conformance-subworkflow-parent §Terminal status',
|
|
55
56
|
'parent fixture MUST reach terminal `completed` after child finishes',
|
|
56
57
|
)).toBe('completed');
|
|
@@ -59,7 +60,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('subworkflow: conformance-subworkflow-parent di
|
|
|
59
60
|
// parent's `childOutcome`. The variable should appear on the parent's
|
|
60
61
|
// final variables.
|
|
61
62
|
const parentVars = (parentTerminal as RunSnapshot).variables ?? {};
|
|
62
|
-
expect(parentVars.childOutcome,
|
|
63
|
+
expect(parentVars.childOutcome, req('openwop.it.subworkflow.parent-run-reaches-terminal-completed-and-child-variable-is-propagated-via-outpu',
|
|
63
64
|
'node-packs.md §core.subWorkflow outputMapping',
|
|
64
65
|
'parent variables MUST include `childOutcome` mapped from child `childResult`',
|
|
65
66
|
)).toBeDefined();
|
|
@@ -84,7 +85,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('subworkflow: conformance-subworkflow-parent di
|
|
|
84
85
|
const subwfCompleted = events.find(
|
|
85
86
|
(e) => e.type === 'node.completed' && e.nodeId === 'subwf-call',
|
|
86
87
|
);
|
|
87
|
-
expect(subwfCompleted,
|
|
88
|
+
expect(subwfCompleted, req('openwop.it.subworkflow.child-run-is-created-with-parent-linkage-fields-and-reaches-terminal-completed',
|
|
88
89
|
'node-packs.md §core.subWorkflow',
|
|
89
90
|
'parent event log MUST contain node.completed for the subwf-call node',
|
|
90
91
|
)).toBeDefined();
|
|
@@ -93,32 +94,32 @@ describe.skipIf(SKIP_NO_FIXTURE)('subworkflow: conformance-subworkflow-parent di
|
|
|
93
94
|
| { outputs?: { childRunId?: string; childStatus?: string; skipped?: boolean } }
|
|
94
95
|
| undefined;
|
|
95
96
|
const childRunId = subwfPayload?.outputs?.childRunId;
|
|
96
|
-
expect(typeof childRunId,
|
|
97
|
+
expect(typeof childRunId, req('openwop.it.subworkflow.child-run-is-created-with-parent-linkage-fields-and-reaches-terminal-completed',
|
|
97
98
|
'node-packs.md §core.subWorkflow outputSchema',
|
|
98
99
|
'core.subWorkflow output MUST include childRunId as a string',
|
|
99
100
|
)).toBe('string');
|
|
100
101
|
|
|
101
|
-
expect(subwfPayload?.outputs?.childStatus,
|
|
102
|
+
expect(subwfPayload?.outputs?.childStatus, req('openwop.it.subworkflow.child-run-is-created-with-parent-linkage-fields-and-reaches-terminal-completed',
|
|
102
103
|
'node-packs.md §core.subWorkflow outputSchema',
|
|
103
104
|
'core.subWorkflow output MUST include childStatus="completed" on success',
|
|
104
105
|
)).toBe('completed');
|
|
105
106
|
|
|
106
107
|
// Fetch the child run snapshot and verify parent linkage.
|
|
107
108
|
const childRes = await driver.get(`/v1/runs/${encodeURIComponent(childRunId!)}`);
|
|
108
|
-
expect(childRes.status, 'child run snapshot MUST be retrievable').toBe(200);
|
|
109
|
+
expect(childRes.status, req('openwop.it.subworkflow.child-run-is-created-with-parent-linkage-fields-and-reaches-terminal-completed', 'node-packs.md §core.subWorkflow outputSchema', 'child run snapshot MUST be retrievable')).toBe(200);
|
|
109
110
|
const child = childRes.json as RunSnapshot;
|
|
110
111
|
|
|
111
|
-
expect(child.status,
|
|
112
|
+
expect(child.status, req('openwop.it.subworkflow.child-run-is-created-with-parent-linkage-fields-and-reaches-terminal-completed',
|
|
112
113
|
'fixtures.md conformance-subworkflow-child §Terminal status',
|
|
113
114
|
'child MUST reach terminal `completed`',
|
|
114
115
|
)).toBe('completed');
|
|
115
116
|
|
|
116
|
-
expect(child.parentRunId,
|
|
117
|
+
expect(child.parentRunId, req('openwop.it.subworkflow.child-run-is-created-with-parent-linkage-fields-and-reaches-terminal-completed',
|
|
117
118
|
'spec gap G3 parent linkage',
|
|
118
119
|
'child run MUST carry parentRunId pointing back to dispatcher',
|
|
119
120
|
)).toBe(parentRunId);
|
|
120
121
|
|
|
121
|
-
expect(child.parentNodeId,
|
|
122
|
+
expect(child.parentNodeId, req('openwop.it.subworkflow.child-run-is-created-with-parent-linkage-fields-and-reaches-terminal-completed',
|
|
122
123
|
'spec gap G3 parent linkage',
|
|
123
124
|
'child run MUST carry parentNodeId pointing back to the subwf-call node',
|
|
124
125
|
)).toBe('subwf-call');
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
import { describe, it, expect } from 'vitest';
|
|
12
12
|
import { driver } from '../lib/driver.js';
|
|
13
13
|
import { discoveryFamilies } from '../lib/discovery-capabilities.js';
|
|
14
|
+
import { req } from '../lib/requirement-ids.js';
|
|
15
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
14
16
|
|
|
15
17
|
interface DiscoveryDoc {
|
|
16
18
|
capabilities?: Record<string, unknown>;
|
|
@@ -31,10 +33,10 @@ async function call(tenantId: string, op: string, args: Record<string, unknown>)
|
|
|
31
33
|
describe('table-cross-tenant-isolation: advertisement shape (RFC 0016)', () => {
|
|
32
34
|
it('capabilities.tableStorage is either absent or a well-formed object', async () => {
|
|
33
35
|
const cap = await readCap();
|
|
34
|
-
if (cap === null) return;
|
|
36
|
+
if (cap === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === null` returned early');
|
|
35
37
|
expect(
|
|
36
38
|
typeof cap.supported,
|
|
37
|
-
|
|
39
|
+
req('openwop.it.table-cross-tenant-isolation.capabilities-tablestorage-is-either-absent-or-a-well-formed-object',
|
|
38
40
|
'capabilities.schema.json §tableStorage',
|
|
39
41
|
'capabilities.tableStorage.supported MUST be a boolean when present',
|
|
40
42
|
),
|
|
@@ -45,22 +47,22 @@ describe('table-cross-tenant-isolation: advertisement shape (RFC 0016)', () => {
|
|
|
45
47
|
describe('table-cross-tenant-isolation: behavioral (RFC 0016 §B point 1)', () => {
|
|
46
48
|
it('insert under tenant A → query under tenant B returns 0 rows', async () => {
|
|
47
49
|
const cap = await readCap();
|
|
48
|
-
if (!cap || cap.supported !== true) return;
|
|
50
|
+
if (!cap || cap.supported !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!cap || cap.supported !== true` returned early');
|
|
49
51
|
const table = `xtenant_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
|
|
50
52
|
|
|
51
53
|
const insertRes = await call('tenant-a', 'insert', {
|
|
52
54
|
table,
|
|
53
55
|
row: { id: 'r1', body: 'from-A' },
|
|
54
56
|
});
|
|
55
|
-
if (insertRes.status === 404) return; // seam not exposed
|
|
56
|
-
expect(insertRes.status, 'insert MUST succeed').toBe(200);
|
|
57
|
+
if (insertRes.status === 404) return softSkip('blocked', 'precondition not met — `insertRes.status === 404` returned early (seam not exposed) (seam, prior step, or fixture unavailable)'); // seam not exposed
|
|
58
|
+
expect(insertRes.status, req('openwop.it.table-cross-tenant-isolation.insert-under-tenant-a-query-under-tenant-b-returns-0-rows', 'RFC 0016 §B point 1', 'insert MUST succeed')).toBe(200);
|
|
57
59
|
|
|
58
60
|
const queryRes = await call('tenant-b', 'query', { table, filter: {} });
|
|
59
61
|
expect(queryRes.status).toBe(200);
|
|
60
62
|
const body = queryRes.json as { rows?: unknown[] };
|
|
61
63
|
expect(
|
|
62
64
|
Array.isArray(body.rows) ? body.rows.length : -1,
|
|
63
|
-
|
|
65
|
+
req('openwop.it.table-cross-tenant-isolation.insert-under-tenant-a-query-under-tenant-b-returns-0-rows', 'RFC 0016 §B point 1', 'tenant B MUST see 0 rows in tenant A table'),
|
|
64
66
|
).toBe(0);
|
|
65
67
|
});
|
|
66
68
|
});
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
import { describe, it, expect } from 'vitest';
|
|
17
17
|
import { driver } from '../lib/driver.js';
|
|
18
18
|
import { discoveryFamilies } from '../lib/discovery-capabilities.js';
|
|
19
|
+
import { req } from '../lib/requirement-ids.js';
|
|
20
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
19
21
|
|
|
20
22
|
interface DiscoveryDoc {
|
|
21
23
|
capabilities?: Record<string, unknown>;
|
|
@@ -32,10 +34,10 @@ async function readCap(): Promise<Record<string, unknown> | null> {
|
|
|
32
34
|
describe('table-cursor-pagination: advertisement shape (RFC 0016)', () => {
|
|
33
35
|
it('capabilities.tableStorage is either absent or a well-formed object', async () => {
|
|
34
36
|
const cap = await readCap();
|
|
35
|
-
if (cap === null) return; // host doesn't advertise — skip
|
|
37
|
+
if (cap === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === null` returned early (host doesn\'t advertise — skip)'); // host doesn't advertise — skip
|
|
36
38
|
expect(
|
|
37
39
|
typeof cap.supported,
|
|
38
|
-
|
|
40
|
+
req('openwop.it.table-cursor-pagination.capabilities-tablestorage-is-either-absent-or-a-well-formed-object',
|
|
39
41
|
'capabilities.schema.json §tableStorage',
|
|
40
42
|
'capabilities.tableStorage.supported MUST be a boolean when present',
|
|
41
43
|
),
|
|
@@ -50,7 +52,7 @@ async function call(op: string, args: Record<string, unknown>) {
|
|
|
50
52
|
describe('table-cursor-pagination: behavioral (RFC 0016 §B point 3)', () => {
|
|
51
53
|
it('first page returns N rows + nextCursor; second page resumes; final page returns nextCursor:null', async () => {
|
|
52
54
|
const probe = await call('query', { table: '__probe__', limit: 1 });
|
|
53
|
-
if (probe.status === 404) return; // seam not exposed
|
|
55
|
+
if (probe.status === 404) return softSkip('blocked', 'precondition not met — `probe.status === 404` returned early (seam not exposed) (seam, prior step, or fixture unavailable)'); // seam not exposed
|
|
54
56
|
const table = `pag-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
55
57
|
// Seed 5 rows with deterministic ids so cursor ordering is testable.
|
|
56
58
|
for (let i = 1; i <= 5; i++) {
|
|
@@ -62,7 +64,7 @@ describe('table-cursor-pagination: behavioral (RFC 0016 §B point 3)', () => {
|
|
|
62
64
|
expect(Array.isArray(b1.rows) && b1.rows.length === 2).toBe(true);
|
|
63
65
|
expect(
|
|
64
66
|
typeof b1.nextCursor === 'string' && b1.nextCursor.length > 0,
|
|
65
|
-
|
|
67
|
+
req('openwop.it.table-cursor-pagination.first-page-returns-n-rows-nextcursor-second-page-resumes-final-page-returns-next', 'RFC 0016 §B point 3', 'first page MUST surface nextCursor when more results remain'),
|
|
66
68
|
).toBe(true);
|
|
67
69
|
|
|
68
70
|
// Page 2: cursor from page 1, limit=2
|
|
@@ -71,7 +73,7 @@ describe('table-cursor-pagination: behavioral (RFC 0016 §B point 3)', () => {
|
|
|
71
73
|
expect(b2.rows?.length).toBe(2);
|
|
72
74
|
expect(
|
|
73
75
|
b2.rows![0]!.id > b1.rows![1]!.id,
|
|
74
|
-
|
|
76
|
+
req('openwop.it.table-cursor-pagination.first-page-returns-n-rows-nextcursor-second-page-resumes-final-page-returns-next', 'RFC 0016 §B point 3', 'second page MUST resume AFTER the last id of the previous page'),
|
|
75
77
|
).toBe(true);
|
|
76
78
|
|
|
77
79
|
// Page 3: final page — only 1 row left, nextCursor MUST be null
|
|
@@ -80,7 +82,7 @@ describe('table-cursor-pagination: behavioral (RFC 0016 §B point 3)', () => {
|
|
|
80
82
|
expect(b3.rows?.length).toBe(1);
|
|
81
83
|
expect(
|
|
82
84
|
b3.nextCursor,
|
|
83
|
-
|
|
85
|
+
req('openwop.it.table-cursor-pagination.first-page-returns-n-rows-nextcursor-second-page-resumes-final-page-returns-next', 'RFC 0016 §B point 3', 'final page (no more results) MUST surface nextCursor: null'),
|
|
84
86
|
).toBe(null);
|
|
85
87
|
});
|
|
86
88
|
});
|
|
@@ -17,6 +17,8 @@ import { describe, it, expect } from 'vitest';
|
|
|
17
17
|
import { readErrorCode } from '../lib/error-envelope.js';
|
|
18
18
|
import { driver } from '../lib/driver.js';
|
|
19
19
|
import { discoveryFamilies } from '../lib/discovery-capabilities.js';
|
|
20
|
+
import { req } from '../lib/requirement-ids.js';
|
|
21
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
20
22
|
|
|
21
23
|
interface DiscoveryDoc {
|
|
22
24
|
capabilities?: Record<string, unknown>;
|
|
@@ -33,10 +35,10 @@ async function readCap(): Promise<Record<string, unknown> | null> {
|
|
|
33
35
|
describe('table-schema-enforcement: advertisement shape (RFC 0016)', () => {
|
|
34
36
|
it('capabilities.tableStorage is either absent or a well-formed object', async () => {
|
|
35
37
|
const cap = await readCap();
|
|
36
|
-
if (cap === null) return; // host doesn't advertise — skip
|
|
38
|
+
if (cap === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === null` returned early (host doesn\'t advertise — skip)'); // host doesn't advertise — skip
|
|
37
39
|
expect(
|
|
38
40
|
typeof cap.supported,
|
|
39
|
-
|
|
41
|
+
req('openwop.it.table-schema-enforcement.capabilities-tablestorage-is-either-absent-or-a-well-formed-object',
|
|
40
42
|
'capabilities.schema.json §tableStorage',
|
|
41
43
|
'capabilities.tableStorage.supported MUST be a boolean when present',
|
|
42
44
|
),
|
|
@@ -51,7 +53,7 @@ async function call(op: string, args: Record<string, unknown>) {
|
|
|
51
53
|
describe('table-schema-enforcement: behavioral (RFC 0016 §B point 2)', () => {
|
|
52
54
|
it('first insert declares schema; subsequent insert with wrong column type is rejected', async () => {
|
|
53
55
|
const probe = await call('insert', { table: '__probe__', row: { id: 'probe-0' } });
|
|
54
|
-
if (probe.status === 404) return; // seam not exposed
|
|
56
|
+
if (probe.status === 404) return softSkip('blocked', 'precondition not met — `probe.status === 404` returned early (seam not exposed) (seam, prior step, or fixture unavailable)'); // seam not exposed
|
|
55
57
|
const table = `sch-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
56
58
|
// First insert — declares the schema from this row's columns.
|
|
57
59
|
const first = await call('insert', {
|
|
@@ -74,12 +76,12 @@ describe('table-schema-enforcement: behavioral (RFC 0016 §B point 2)', () => {
|
|
|
74
76
|
});
|
|
75
77
|
expect(
|
|
76
78
|
bad.status >= 400 && bad.status < 500,
|
|
77
|
-
|
|
79
|
+
req('openwop.it.table-schema-enforcement.first-insert-declares-schema-subsequent-insert-with-wrong-column-type-is-rejecte', 'RFC 0016 §B point 2', 'type-divergent insert MUST be rejected with 4xx'),
|
|
78
80
|
).toBe(true);
|
|
79
81
|
const code = readErrorCode(bad.json);
|
|
80
82
|
expect(
|
|
81
83
|
code,
|
|
82
|
-
|
|
84
|
+
req('openwop.it.table-schema-enforcement.first-insert-declares-schema-subsequent-insert-with-wrong-column-type-is-rejecte', 'RFC 0016 §B point 2', 'rejection MUST carry the table_schema_violation error code'),
|
|
83
85
|
).toBe('table_schema_violation');
|
|
84
86
|
});
|
|
85
87
|
});
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
*/
|
|
50
50
|
|
|
51
51
|
import { describe, it, expect } from 'vitest';
|
|
52
|
-
import { driver } from '../lib/driver.js';
|
|
53
52
|
import { loadEnv } from '../lib/env.js';
|
|
53
|
+
import { req } from '../lib/requirement-ids.js';
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Canonical seam paths from `host-sample-test-seams.md`. A host that exposes
|
|
@@ -160,7 +160,7 @@ describe('test-seam-unauthenticated: an enabled seam still authenticates', () =>
|
|
|
160
160
|
|
|
161
161
|
expect(
|
|
162
162
|
answered,
|
|
163
|
-
|
|
163
|
+
req('openwop.it.test-seam-unauthenticated.no-v1-host-sample-seam-answers-an-unauthenticated-request-with-200', 'host-sample-test-seams.md §"Production safety (normative)"', `${diagnosis}\n ${answered.join('\n ')}`),
|
|
164
164
|
).toEqual([]);
|
|
165
165
|
});
|
|
166
166
|
});
|
|
@@ -46,6 +46,8 @@ import {
|
|
|
46
46
|
findBannedInputSchemaKeyword,
|
|
47
47
|
type CompactToolDescriptor,
|
|
48
48
|
} from '../lib/toolCatalog.js';
|
|
49
|
+
import { req } from '../lib/requirement-ids.js';
|
|
50
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
49
51
|
|
|
50
52
|
function loadSchema(name: string): Record<string, unknown> {
|
|
51
53
|
return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
|
|
@@ -80,18 +82,18 @@ describe('tool-catalog-compact-projection (RFC 0112 §compact)', () => {
|
|
|
80
82
|
|
|
81
83
|
// ---- Leg 1: the compact envelope (§compact) -------------------------
|
|
82
84
|
const compact = await listToolsCompact();
|
|
83
|
-
if (compact === null) return; // advertises the cap but doesn't serve the read — soft-skip the rest
|
|
85
|
+
if (compact === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `compact === null` returned early (advertises the cap but doesn\'t serve the read — soft-skip the rest)'); // advertises the cap but doesn't serve the read — soft-skip the rest
|
|
84
86
|
|
|
85
87
|
for (const t of compact) {
|
|
86
88
|
// ---- Leg 2: schema validity + heavy fields dropped ----------------
|
|
87
89
|
expect(
|
|
88
90
|
validate(t),
|
|
89
|
-
|
|
91
|
+
req('openwop.it.tool-catalog-compact-projection.serves-the-tools-compacttooldescriptor-projection-closed-shape-bounded-inputsche', 'compact-tool-descriptor.schema.json', `each CompactToolDescriptor MUST validate (${ajv.errorsText(validate.errors)})`),
|
|
90
92
|
).toBe(true);
|
|
91
93
|
for (const f of COMPACT_DROPPED_FIELDS) {
|
|
92
94
|
expect(
|
|
93
95
|
!(f in t),
|
|
94
|
-
|
|
96
|
+
req('openwop.it.tool-catalog-compact-projection.serves-the-tools-compacttooldescriptor-projection-closed-shape-bounded-inputsche', 'tool-catalog.md §compact', `CompactToolDescriptor MUST drop the heavy field "${f}"`),
|
|
95
97
|
).toBe(true);
|
|
96
98
|
}
|
|
97
99
|
|
|
@@ -100,14 +102,14 @@ describe('tool-catalog-compact-projection (RFC 0112 §compact)', () => {
|
|
|
100
102
|
if (input !== undefined) {
|
|
101
103
|
expect(
|
|
102
104
|
input.type === 'object' && typeof input.properties === 'object' && input.properties !== null,
|
|
103
|
-
|
|
105
|
+
req('openwop.it.tool-catalog-compact-projection.serves-the-tools-compacttooldescriptor-projection-closed-shape-bounded-inputsche', 'tool-catalog.md §compact', 'compact inputSchema MUST be top-level type:"object" with a properties map'),
|
|
104
106
|
).toBe(true);
|
|
105
107
|
// Total (any-depth), schema-aware: a nested oneOf/$ref under a property
|
|
106
108
|
// schema is exactly the verbosity the compact view exists to drop.
|
|
107
109
|
const banned = findBannedInputSchemaKeyword(input);
|
|
108
110
|
expect(
|
|
109
111
|
banned,
|
|
110
|
-
|
|
112
|
+
req('openwop.it.tool-catalog-compact-projection.serves-the-tools-compacttooldescriptor-projection-closed-shape-bounded-inputsche', 'tool-catalog.md §compact', `compact inputSchema MUST NOT use $ref/oneOf/allOf/anyOf/not/patternProperties/dependentSchemas at any nesting depth (found "${banned ?? 'none'}")`),
|
|
111
113
|
).toBe(null);
|
|
112
114
|
}
|
|
113
115
|
}
|
|
@@ -123,7 +125,7 @@ describe('tool-catalog-compact-projection (RFC 0112 §compact)', () => {
|
|
|
123
125
|
standardIds.size === compactIds.size && [...standardIds].every((id) => compactIds.has(id));
|
|
124
126
|
expect(
|
|
125
127
|
sameSet,
|
|
126
|
-
|
|
128
|
+
req('openwop.it.tool-catalog-compact-projection.serves-the-tools-compacttooldescriptor-projection-closed-shape-bounded-inputsche',
|
|
127
129
|
'tool-catalog.md §compact',
|
|
128
130
|
`compact tools[] MUST carry the same toolId set as the standard view (standard=${[...standardIds].sort().join(',')} compact=${[...compactIds].sort().join(',')})`,
|
|
129
131
|
),
|
|
@@ -136,12 +138,12 @@ describe('tool-catalog-compact-projection (RFC 0112 §compact)', () => {
|
|
|
136
138
|
if (one.status === 200) {
|
|
137
139
|
expect(
|
|
138
140
|
validate(one.json),
|
|
139
|
-
|
|
141
|
+
req('openwop.it.tool-catalog-compact-projection.serves-the-tools-compacttooldescriptor-projection-closed-shape-bounded-inputsche', 'compact-tool-descriptor.schema.json', `GET /v1/tools/{toolId}?view=compact MUST return a valid CompactToolDescriptor (${ajv.errorsText(validate.errors)})`),
|
|
140
142
|
).toBe(true);
|
|
141
143
|
const got = one.json;
|
|
142
144
|
expect(
|
|
143
145
|
got && typeof got === 'object' && (got as { toolId?: unknown }).toolId === id,
|
|
144
|
-
|
|
146
|
+
req('openwop.it.tool-catalog-compact-projection.serves-the-tools-compacttooldescriptor-projection-closed-shape-bounded-inputsche', 'tool-catalog.md §compact', 'GET /v1/tools/{toolId}?view=compact MUST return the requested descriptor'),
|
|
145
147
|
).toBe(true);
|
|
146
148
|
}
|
|
147
149
|
}
|
|
@@ -40,6 +40,8 @@ import {
|
|
|
40
40
|
SAFETY_TIERS,
|
|
41
41
|
TOOL_CONTENT_FORBIDDEN,
|
|
42
42
|
} from '../lib/toolCatalog.js';
|
|
43
|
+
import { req } from '../lib/requirement-ids.js';
|
|
44
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
43
45
|
|
|
44
46
|
function loadSchema(name: string): Record<string, unknown> {
|
|
45
47
|
return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
|
|
@@ -49,7 +51,7 @@ function expectContentFree(d: Record<string, unknown>, where: string): void {
|
|
|
49
51
|
for (const f of TOOL_CONTENT_FORBIDDEN) {
|
|
50
52
|
expect(
|
|
51
53
|
!(f in d),
|
|
52
|
-
|
|
54
|
+
req('openwop.it.tool-catalog-projection.lists-schema-valid-tooldescriptors-serves-by-id-404s-is-auth-gated-and-never-dis', 'RFC 0078 §F (SR-1)', `${where} MUST be content-free (no ${f})`),
|
|
53
55
|
).toBe(true);
|
|
54
56
|
}
|
|
55
57
|
}
|
|
@@ -67,25 +69,25 @@ describe('tool-catalog-projection (RFC 0078 §B/§F)', () => {
|
|
|
67
69
|
const unauth = await driver.get('/v1/tools', { authenticated: false });
|
|
68
70
|
expect(
|
|
69
71
|
unauth.status === 401,
|
|
70
|
-
|
|
72
|
+
req('openwop.it.tool-catalog-projection.lists-schema-valid-tooldescriptors-serves-by-id-404s-is-auth-gated-and-never-dis', 'tool-catalog.md §B', 'GET /v1/tools MUST require authentication (401 unauthenticated)'),
|
|
71
73
|
).toBe(true);
|
|
72
74
|
|
|
73
75
|
// ---- Leg 1: the list (§B) -------------------------------------------
|
|
74
76
|
const tools = await listTools();
|
|
75
|
-
if (tools === null) return; // host advertises the cap but doesn't serve the read — soft-skip the rest
|
|
77
|
+
if (tools === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `tools === null` returned early (host advertises the cap but doesn\'t serve the read — soft-skip the rest)'); // host advertises the cap but doesn't serve the read — soft-skip the rest
|
|
76
78
|
|
|
77
79
|
for (const t of tools) {
|
|
78
80
|
expect(
|
|
79
81
|
validate(t),
|
|
80
|
-
|
|
82
|
+
req('openwop.it.tool-catalog-projection.lists-schema-valid-tooldescriptors-serves-by-id-404s-is-auth-gated-and-never-dis', 'tool-descriptor.schema.json', `each ToolDescriptor MUST validate (${ajv.errorsText(validate.errors)})`),
|
|
81
83
|
).toBe(true);
|
|
82
84
|
expect(
|
|
83
85
|
typeof t.source === 'string' && TOOL_SOURCES.includes(t.source as string),
|
|
84
|
-
|
|
86
|
+
req('openwop.it.tool-catalog-projection.lists-schema-valid-tooldescriptors-serves-by-id-404s-is-auth-gated-and-never-dis', 'tool-catalog.md §C', 'ToolDescriptor.source MUST be in the closed vocabulary'),
|
|
85
87
|
).toBe(true);
|
|
86
88
|
expect(
|
|
87
89
|
typeof t.safetyTier === 'string' && SAFETY_TIERS.includes(t.safetyTier as string),
|
|
88
|
-
|
|
90
|
+
req('openwop.it.tool-catalog-projection.lists-schema-valid-tooldescriptors-serves-by-id-404s-is-auth-gated-and-never-dis', 'tool-catalog.md §C', 'ToolDescriptor.safetyTier MUST be pure|read|write|exec'),
|
|
89
91
|
).toBe(true);
|
|
90
92
|
expectContentFree(t, 'ToolDescriptor');
|
|
91
93
|
}
|
|
@@ -97,14 +99,14 @@ describe('tool-catalog-projection (RFC 0078 §B/§F)', () => {
|
|
|
97
99
|
if (one.status === 200) {
|
|
98
100
|
expect(
|
|
99
101
|
one.descriptor?.toolId === id,
|
|
100
|
-
|
|
102
|
+
req('openwop.it.tool-catalog-projection.lists-schema-valid-tooldescriptors-serves-by-id-404s-is-auth-gated-and-never-dis', 'tool-catalog.md §B', 'GET /v1/tools/{toolId} MUST return the requested descriptor'),
|
|
101
103
|
).toBe(true);
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
106
|
const unknown = await getTool('__conformance_nonexistent_tool__');
|
|
105
107
|
expect(
|
|
106
108
|
unknown.status === 404,
|
|
107
|
-
|
|
109
|
+
req('openwop.it.tool-catalog-projection.lists-schema-valid-tooldescriptors-serves-by-id-404s-is-auth-gated-and-never-dis', 'tool-catalog.md §B', 'GET /v1/tools/{unknown} MUST 404'),
|
|
108
110
|
).toBe(true);
|
|
109
111
|
|
|
110
112
|
// ---- Leg 4: §F-2 cross-principal non-disclosure (env-gated) ---------
|
|
@@ -113,7 +115,7 @@ describe('tool-catalog-projection (RFC 0078 §B/§F)', () => {
|
|
|
113
115
|
const cross = await getTool(crossId);
|
|
114
116
|
expect(
|
|
115
117
|
cross.status === 404,
|
|
116
|
-
|
|
118
|
+
req('openwop.it.tool-catalog-projection.lists-schema-valid-tooldescriptors-serves-by-id-404s-is-auth-gated-and-never-dis', 'tool-catalog.md §F-2', 'a tool owned by a different principal MUST 404 (non-disclosure)'),
|
|
117
119
|
).toBe(true);
|
|
118
120
|
}
|
|
119
121
|
});
|