@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
|
@@ -34,6 +34,8 @@ import { describe, it, expect } from 'vitest';
|
|
|
34
34
|
import { driver } from '../lib/driver.js';
|
|
35
35
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
36
36
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
37
|
+
import { req } from '../lib/requirement-ids.js';
|
|
38
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
37
39
|
|
|
38
40
|
interface DiscoveryDoc {
|
|
39
41
|
capabilities?: {
|
|
@@ -97,8 +99,8 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-secret-redaction: composed body reda
|
|
|
97
99
|
},
|
|
98
100
|
observability: 'full',
|
|
99
101
|
});
|
|
100
|
-
if (res.status === 404) return; // host doesn't expose the seam
|
|
101
|
-
expect(res.status, 'compose seam MUST return 200').toBe(200);
|
|
102
|
+
if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (host doesn\'t expose the seam) (seam, prior step, or fixture unavailable)'); // host doesn't expose the seam
|
|
103
|
+
expect(res.status, req('openwop.it.prompt-composed-secret-redaction.emits-prompt-composed-with-redacted-id-in-place-of-secret-sourced-variable-value', 'spec/v1/prompts.md §Composition + observability', 'compose seam MUST return 200')).toBe(200);
|
|
102
104
|
|
|
103
105
|
const payload = res.json as PromptComposedPayload;
|
|
104
106
|
|
|
@@ -108,14 +110,14 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-secret-redaction: composed body reda
|
|
|
108
110
|
const userBody = payload.userPrompt ?? '';
|
|
109
111
|
expect(
|
|
110
112
|
systemBody.includes(CANARY_FRAGMENT),
|
|
111
|
-
|
|
113
|
+
req('openwop.it.prompt-composed-secret-redaction.emits-prompt-composed-with-redacted-id-in-place-of-secret-sourced-variable-value',
|
|
112
114
|
'spec/v1/prompts.md §Composition + observability',
|
|
113
115
|
'prompt.composed.systemPrompt MUST NOT contain plaintext secret value',
|
|
114
116
|
),
|
|
115
117
|
).toBe(false);
|
|
116
118
|
expect(
|
|
117
119
|
userBody.includes(CANARY_FRAGMENT),
|
|
118
|
-
|
|
120
|
+
req('openwop.it.prompt-composed-secret-redaction.emits-prompt-composed-with-redacted-id-in-place-of-secret-sourced-variable-value',
|
|
119
121
|
'spec/v1/prompts.md §Composition + observability',
|
|
120
122
|
'prompt.composed.userPrompt MUST NOT contain plaintext secret value',
|
|
121
123
|
),
|
|
@@ -127,7 +129,7 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-secret-redaction: composed body reda
|
|
|
127
129
|
const combined = systemBody + userBody;
|
|
128
130
|
expect(
|
|
129
131
|
/\[REDACTED:[a-zA-Z0-9._-]+\]/.test(combined),
|
|
130
|
-
|
|
132
|
+
req('openwop.it.prompt-composed-secret-redaction.emits-prompt-composed-with-redacted-id-in-place-of-secret-sourced-variable-value',
|
|
131
133
|
'spec/v1/prompts.md §Composition + observability',
|
|
132
134
|
'composed body MUST carry [REDACTED:<secretId>] marker where secret-sourced variables appear',
|
|
133
135
|
),
|
|
@@ -140,7 +142,7 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-secret-redaction: composed body reda
|
|
|
140
142
|
if (typeof value === 'string') {
|
|
141
143
|
expect(
|
|
142
144
|
value.includes(CANARY_FRAGMENT),
|
|
143
|
-
|
|
145
|
+
req('openwop.it.prompt-composed-secret-redaction.emits-prompt-composed-with-redacted-id-in-place-of-secret-sourced-variable-value',
|
|
144
146
|
'spec/v1/prompts.md §Composition + observability',
|
|
145
147
|
`variableBindings[${name}] MUST NOT contain plaintext secret value`,
|
|
146
148
|
),
|
|
@@ -158,19 +160,19 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-secret-redaction: composed body reda
|
|
|
158
160
|
bindings: { apiKey: 'openwop-conformance-canary-secret' },
|
|
159
161
|
observability: 'full',
|
|
160
162
|
});
|
|
161
|
-
if (res.status === 404) return;
|
|
163
|
+
if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
162
164
|
expect(res.status).toBe(200);
|
|
163
165
|
const payload = res.json as PromptComposedPayload;
|
|
164
166
|
expect(
|
|
165
167
|
payload.hash && /^sha256:[0-9a-f]{64}$/.test(payload.hash),
|
|
166
|
-
|
|
168
|
+
req('openwop.it.prompt-composed-secret-redaction.emits-variablehashes-for-the-secret-sourced-binding-regardless-of-observability',
|
|
167
169
|
'spec/v1/prompts.md §Composition + observability',
|
|
168
170
|
'prompt.composed.hash MUST be present and match sha256:<hex64>',
|
|
169
171
|
),
|
|
170
172
|
).toBe(true);
|
|
171
173
|
expect(
|
|
172
174
|
payload.variableHashes !== undefined,
|
|
173
|
-
|
|
175
|
+
req('openwop.it.prompt-composed-secret-redaction.emits-variablehashes-for-the-secret-sourced-binding-regardless-of-observability',
|
|
174
176
|
'spec/v1/prompts.md §Composition + observability',
|
|
175
177
|
'prompt.composed.variableHashes MUST be present under all non-off observability modes',
|
|
176
178
|
),
|
|
@@ -33,6 +33,8 @@ import { describe, it, expect } from 'vitest';
|
|
|
33
33
|
import { driver } from '../lib/driver.js';
|
|
34
34
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
35
35
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
36
|
+
import { req } from '../lib/requirement-ids.js';
|
|
37
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
36
38
|
|
|
37
39
|
interface DiscoveryDoc {
|
|
38
40
|
capabilities?: {
|
|
@@ -81,13 +83,13 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-trust-marker: untrusted input wrappe
|
|
|
81
83
|
bindingTrust: { userPayload: 'untrusted' },
|
|
82
84
|
observability: 'full',
|
|
83
85
|
});
|
|
84
|
-
if (res.status === 404) return;
|
|
86
|
+
if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
85
87
|
expect(res.status).toBe(200);
|
|
86
88
|
|
|
87
89
|
const payload = res.json as PromptComposedPayload;
|
|
88
90
|
expect(
|
|
89
91
|
payload.contentTrust,
|
|
90
|
-
|
|
92
|
+
req('openwop.it.prompt-composed-trust-marker.sets-contenttrust-untrusted-when-any-contributing-input-is-untrusted',
|
|
91
93
|
'spec/v1/prompts.md §Composition + observability',
|
|
92
94
|
'prompt.composed.contentTrust MUST be "untrusted" when ANY contributing input is untrusted',
|
|
93
95
|
),
|
|
@@ -104,7 +106,7 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-trust-marker: untrusted input wrappe
|
|
|
104
106
|
bindingTrust: { userPayload: 'untrusted' },
|
|
105
107
|
observability: 'full',
|
|
106
108
|
});
|
|
107
|
-
if (res.status === 404) return;
|
|
109
|
+
if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
108
110
|
expect(res.status).toBe(200);
|
|
109
111
|
|
|
110
112
|
const payload = res.json as PromptComposedPayload;
|
|
@@ -112,7 +114,7 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-trust-marker: untrusted input wrappe
|
|
|
112
114
|
|
|
113
115
|
expect(
|
|
114
116
|
combined.includes('<UNTRUSTED>') && combined.includes('</UNTRUSTED>'),
|
|
115
|
-
|
|
117
|
+
req('openwop.it.prompt-composed-trust-marker.wraps-untrusted-segments-in-untrusted-untrusted-markers-within-composed-bodies',
|
|
116
118
|
'spec/v1/prompts.md §Composition + observability',
|
|
117
119
|
'composed body MUST wrap untrusted segments with <UNTRUSTED>...</UNTRUSTED> markers',
|
|
118
120
|
),
|
|
@@ -127,14 +129,14 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-trust-marker: untrusted input wrappe
|
|
|
127
129
|
const outsideMarkers = markerRegions.filter((_, i) => i % 2 === 0).join(' ');
|
|
128
130
|
expect(
|
|
129
131
|
insideMarkers.includes(UNTRUSTED_PAYLOAD),
|
|
130
|
-
|
|
132
|
+
req('openwop.it.prompt-composed-trust-marker.wraps-untrusted-segments-in-untrusted-untrusted-markers-within-composed-bodies',
|
|
131
133
|
'spec/v1/prompts.md §Composition + observability',
|
|
132
134
|
'untrusted payload content MUST appear inside <UNTRUSTED>...</UNTRUSTED> markers',
|
|
133
135
|
),
|
|
134
136
|
).toBe(true);
|
|
135
137
|
expect(
|
|
136
138
|
outsideMarkers.includes(UNTRUSTED_PAYLOAD),
|
|
137
|
-
|
|
139
|
+
req('openwop.it.prompt-composed-trust-marker.wraps-untrusted-segments-in-untrusted-untrusted-markers-within-composed-bodies',
|
|
138
140
|
'spec/v1/prompts.md §Composition + observability',
|
|
139
141
|
'untrusted payload content MUST NOT appear outside the markers',
|
|
140
142
|
),
|
|
@@ -151,13 +153,13 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-trust-marker: untrusted input wrappe
|
|
|
151
153
|
bindingTrust: { userPayload: 'trusted' },
|
|
152
154
|
observability: 'full',
|
|
153
155
|
});
|
|
154
|
-
if (res.status === 404) return;
|
|
156
|
+
if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
155
157
|
expect(res.status).toBe(200);
|
|
156
158
|
|
|
157
159
|
const payload = res.json as PromptComposedPayload;
|
|
158
160
|
expect(
|
|
159
161
|
payload.contentTrust,
|
|
160
|
-
|
|
162
|
+
req('openwop.it.prompt-composed-trust-marker.keeps-contenttrust-trusted-when-all-contributing-inputs-are-trusted',
|
|
161
163
|
'spec/v1/prompts.md §Composition + observability',
|
|
162
164
|
'prompt.composed.contentTrust MUST be "trusted" when no contributing input is untrusted',
|
|
163
165
|
),
|
|
@@ -35,6 +35,8 @@ import { pollUntilTerminal } from '../lib/polling.js';
|
|
|
35
35
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
36
36
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
37
37
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
38
|
+
import { req } from '../lib/requirement-ids.js';
|
|
39
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
38
40
|
|
|
39
41
|
const WORKFLOW_ID = 'conformance-prompt-end-to-end';
|
|
40
42
|
const SKIP_NO_FIXTURE = !isFixtureAdvertised(WORKFLOW_ID);
|
|
@@ -88,7 +90,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
|
|
|
88
90
|
const create = await driver.post('/v1/runs', { workflowId: WORKFLOW_ID });
|
|
89
91
|
expect(
|
|
90
92
|
create.status,
|
|
91
|
-
|
|
93
|
+
req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro',
|
|
92
94
|
'spec/v1/rest-endpoints.md',
|
|
93
95
|
'POST /v1/runs MUST return 201 on accepted creation',
|
|
94
96
|
),
|
|
@@ -98,7 +100,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
|
|
|
98
100
|
const terminal = await pollUntilTerminal(runId);
|
|
99
101
|
expect(
|
|
100
102
|
terminal.status,
|
|
101
|
-
|
|
103
|
+
req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro',
|
|
102
104
|
'fixtures.md conformance-prompt-end-to-end §Terminal status',
|
|
103
105
|
'fixture MUST reach terminal `completed`',
|
|
104
106
|
),
|
|
@@ -108,7 +110,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
|
|
|
108
110
|
const resolved = events.find((e) => e.type === 'agent.promptResolved');
|
|
109
111
|
expect(
|
|
110
112
|
resolved,
|
|
111
|
-
|
|
113
|
+
req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro',
|
|
112
114
|
'spec/v1/prompts.md §"Resolution chain (normative)"',
|
|
113
115
|
'host MUST emit `agent.promptResolved` when a node carries a `*PromptRef` and prompts.supported is advertised',
|
|
114
116
|
),
|
|
@@ -120,12 +122,12 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
|
|
|
120
122
|
chain?: Array<{ layer?: string; applied?: boolean; source?: string }>;
|
|
121
123
|
resolved?: string | null;
|
|
122
124
|
};
|
|
123
|
-
expect(payload.nodeId, 'agent.promptResolved.nodeId MUST be set').toBe('writer');
|
|
124
|
-
expect(payload.kind, 'agent.promptResolved.kind MUST match the resolved kind').toBe('system');
|
|
125
|
+
expect(payload.nodeId, req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro', 'spec/v1/prompts.md §"Resolution chain (normative)"', 'agent.promptResolved.nodeId MUST be set')).toBe('writer');
|
|
126
|
+
expect(payload.kind, req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro', 'spec/v1/prompts.md §"Resolution chain (normative)"', 'agent.promptResolved.kind MUST match the resolved kind')).toBe('system');
|
|
125
127
|
const applied = (payload.chain ?? []).find((c) => c.applied === true);
|
|
126
128
|
expect(
|
|
127
129
|
applied?.layer,
|
|
128
|
-
|
|
130
|
+
req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro',
|
|
129
131
|
'spec/v1/prompts.md §"Resolution chain (normative)" — Layer 1',
|
|
130
132
|
'node-config ref MUST win when no higher-precedence run-configurable layer is configured',
|
|
131
133
|
),
|
|
@@ -138,7 +140,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
|
|
|
138
140
|
if (!behaviorGate('prompts-supported', promptsSupported(d))) return;
|
|
139
141
|
|
|
140
142
|
const create = await driver.post('/v1/runs', { workflowId: WORKFLOW_ID });
|
|
141
|
-
if (create.status !== 201) return;
|
|
143
|
+
if (create.status !== 201) return softSkip('blocked', 'precondition not met — `create.status !== 201` returned early (seam, prior step, or fixture unavailable)');
|
|
142
144
|
const { runId } = create.json as { runId: string };
|
|
143
145
|
await pollUntilTerminal(runId);
|
|
144
146
|
const events = await readAllEvents(runId);
|
|
@@ -146,7 +148,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
|
|
|
146
148
|
const composed = events.find((e) => e.type === 'prompt.composed');
|
|
147
149
|
expect(
|
|
148
150
|
composed,
|
|
149
|
-
|
|
151
|
+
req('openwop.it.prompt-end-to-end-events.emits-prompt-composed-with-sha256-hex64-hash-non-empty-composed-body-for-system',
|
|
150
152
|
'spec/v1/prompts.md §"Composition + observability"',
|
|
151
153
|
'host MUST emit `prompt.composed` after `agent.promptResolved` when a ref resolves and observability !== off',
|
|
152
154
|
),
|
|
@@ -162,15 +164,15 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
|
|
|
162
164
|
};
|
|
163
165
|
expect(
|
|
164
166
|
payload.hash && /^sha256:[0-9a-f]{64}$/.test(payload.hash),
|
|
165
|
-
|
|
167
|
+
req('openwop.it.prompt-end-to-end-events.emits-prompt-composed-with-sha256-hex64-hash-non-empty-composed-body-for-system',
|
|
166
168
|
'schemas/run-event-payloads.schema.json §promptComposed.hash',
|
|
167
169
|
'hash MUST match `^sha256:[0-9a-f]{64}$`',
|
|
168
170
|
),
|
|
169
171
|
).toBe(true);
|
|
170
|
-
expect(payload.kind, 'system-only kind composition').toBe('system-only');
|
|
172
|
+
expect(payload.kind, req('openwop.it.prompt-end-to-end-events.emits-prompt-composed-with-sha256-hex64-hash-non-empty-composed-body-for-system', 'schemas/run-event-payloads.schema.json §promptComposed.hash', 'system-only kind composition')).toBe('system-only');
|
|
171
173
|
expect(
|
|
172
174
|
typeof payload.composed === 'string' && payload.composed.length > 0,
|
|
173
|
-
|
|
175
|
+
req('openwop.it.prompt-end-to-end-events.emits-prompt-composed-with-sha256-hex64-hash-non-empty-composed-body-for-system',
|
|
174
176
|
'spec/v1/prompts.md §"Composition + observability"',
|
|
175
177
|
'composed body MUST be non-empty for system-kind under observability: full',
|
|
176
178
|
),
|
|
@@ -183,18 +185,18 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
|
|
|
183
185
|
const d = await readDiscovery();
|
|
184
186
|
if (!behaviorGate('prompts-supported', promptsSupported(d))) return;
|
|
185
187
|
const create = await driver.post('/v1/runs', { workflowId: WORKFLOW_ID });
|
|
186
|
-
if (create.status !== 201) return;
|
|
188
|
+
if (create.status !== 201) return softSkip('blocked', 'precondition not met — `create.status !== 201` returned early (seam, prior step, or fixture unavailable)');
|
|
187
189
|
const { runId } = create.json as { runId: string };
|
|
188
190
|
await pollUntilTerminal(runId);
|
|
189
191
|
const events = await readAllEvents(runId);
|
|
190
192
|
|
|
191
193
|
const resolvedIdx = events.findIndex((e) => e.type === 'agent.promptResolved');
|
|
192
194
|
const composedIdx = events.findIndex((e) => e.type === 'prompt.composed');
|
|
193
|
-
expect(resolvedIdx, 'agent.promptResolved MUST appear in the event log').toBeGreaterThanOrEqual(0);
|
|
194
|
-
expect(composedIdx, 'prompt.composed MUST appear in the event log').toBeGreaterThanOrEqual(0);
|
|
195
|
+
expect(resolvedIdx, req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-before-prompt-composed-causal-ordering', 'spec/v1/prompts.md §"Resolution chain (normative)"', 'agent.promptResolved MUST appear in the event log')).toBeGreaterThanOrEqual(0);
|
|
196
|
+
expect(composedIdx, req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-before-prompt-composed-causal-ordering', 'spec/v1/prompts.md §"Resolution chain (normative)"', 'prompt.composed MUST appear in the event log')).toBeGreaterThanOrEqual(0);
|
|
195
197
|
expect(
|
|
196
198
|
resolvedIdx,
|
|
197
|
-
|
|
199
|
+
req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-before-prompt-composed-causal-ordering',
|
|
198
200
|
'spec/v1/prompts.md §"Resolution chain (normative)"',
|
|
199
201
|
'agent.promptResolved MUST emit BEFORE the corresponding prompt.composed (resolution precedes composition)',
|
|
200
202
|
),
|
|
@@ -35,6 +35,8 @@ import { driver } from '../lib/driver.js';
|
|
|
35
35
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
36
36
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
37
37
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
38
|
+
import { req } from '../lib/requirement-ids.js';
|
|
39
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
38
40
|
|
|
39
41
|
interface DiscoveryDoc {
|
|
40
42
|
capabilities?: {
|
|
@@ -86,17 +88,17 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
|
|
|
86
88
|
if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
|
|
87
89
|
|
|
88
90
|
const res = await driver.get('/v1/prompts');
|
|
89
|
-
expect(res.status,
|
|
91
|
+
expect(res.status, req('openwop.it.prompt-list-and-fetch.get-v1-prompts-returns-items-prompttemplate-nextcursor-when-endpointssupported-i', 'spec/v1/prompts.md §Discovery & distribution', 'GET /v1/prompts MUST return 200 when endpointsSupported: true')).toBe(200);
|
|
90
92
|
const body = res.json as ListResponse;
|
|
91
93
|
expect(
|
|
92
94
|
Array.isArray(body.items),
|
|
93
|
-
|
|
95
|
+
req('openwop.it.prompt-list-and-fetch.get-v1-prompts-returns-items-prompttemplate-nextcursor-when-endpointssupported-i', 'spec/v1/prompts.md §Discovery & distribution', 'response MUST contain an `items` array'),
|
|
94
96
|
).toBe(true);
|
|
95
97
|
for (const item of body.items) {
|
|
96
98
|
const ok = validate(item);
|
|
97
99
|
expect(
|
|
98
100
|
ok,
|
|
99
|
-
|
|
101
|
+
req('openwop.it.prompt-list-and-fetch.get-v1-prompts-returns-items-prompttemplate-nextcursor-when-endpointssupported-i',
|
|
100
102
|
'spec/v1/prompts.md §PromptTemplate',
|
|
101
103
|
`every list item MUST validate against prompt-template.schema.json; errors: ${JSON.stringify(validate.errors)}`,
|
|
102
104
|
),
|
|
@@ -113,7 +115,7 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
|
|
|
113
115
|
for (const item of body.items) {
|
|
114
116
|
expect(
|
|
115
117
|
item.meta?.source,
|
|
116
|
-
|
|
118
|
+
req('openwop.it.prompt-list-and-fetch.get-v1-prompts-source-host-narrows-to-host-built-in-templates',
|
|
117
119
|
'spec/v1/prompts.md §Discovery & distribution',
|
|
118
120
|
'source filter MUST narrow to templates whose meta.source matches',
|
|
119
121
|
),
|
|
@@ -125,7 +127,7 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
|
|
|
125
127
|
const d = await readDiscovery();
|
|
126
128
|
if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
|
|
127
129
|
const res = await driver.get('/v1/prompts?kind=system');
|
|
128
|
-
expect(res.status).toBe(200);
|
|
130
|
+
expect(res.status, req('openwop.it.prompt-list-and-fetch.get-v1-prompts-kind-system-narrows-to-system-kind-templates', 'RFC 0028 §A', 'GET /v1/prompts?kind=system narrows to system-kind templates')).toBe(200);
|
|
129
131
|
const body = res.json as ListResponse;
|
|
130
132
|
for (const item of body.items) {
|
|
131
133
|
expect(item.kind).toBe('system');
|
|
@@ -138,9 +140,9 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
|
|
|
138
140
|
|
|
139
141
|
// List first to discover a known templateId we can fetch.
|
|
140
142
|
const list = await driver.get('/v1/prompts?source=host&limit=1');
|
|
141
|
-
if (list.status !== 200) return;
|
|
143
|
+
if (list.status !== 200) return softSkip('blocked', 'precondition not met — `list.status !== 200` returned early (seam, prior step, or fixture unavailable)');
|
|
142
144
|
const body = list.json as ListResponse;
|
|
143
|
-
if (body.items.length === 0) return; // host advertises endpoints but ships no fixtures — tolerable
|
|
145
|
+
if (body.items.length === 0) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `body.items.length === 0` returned early (host advertises endpoints but ships no fixtures — tolerable)'); // host advertises endpoints but ships no fixtures — tolerable
|
|
144
146
|
const known = body.items[0]!;
|
|
145
147
|
|
|
146
148
|
const fetched = await driver.get(`/v1/prompts/${encodeURIComponent(known.templateId)}`);
|
|
@@ -153,7 +155,7 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
|
|
|
153
155
|
const etag = fetched.headers?.get('etag');
|
|
154
156
|
expect(
|
|
155
157
|
typeof etag === 'string' && etag.length > 0,
|
|
156
|
-
|
|
158
|
+
req('openwop.it.prompt-list-and-fetch.get-v1-prompts-templateid-returns-the-template-etag-header-for-a-known-fixture',
|
|
157
159
|
'spec/v1/prompts.md §Discovery & distribution',
|
|
158
160
|
'GET /v1/prompts/{templateId} SHOULD set an ETag header (RFC 0028 §A cache semantics)',
|
|
159
161
|
),
|
|
@@ -164,22 +166,22 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
|
|
|
164
166
|
const d = await readDiscovery();
|
|
165
167
|
if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
|
|
166
168
|
const list = await driver.get('/v1/prompts?source=host&limit=1');
|
|
167
|
-
if (list.status !== 200) return;
|
|
169
|
+
if (list.status !== 200) return softSkip('blocked', 'precondition not met — `list.status !== 200` returned early (seam, prior step, or fixture unavailable)');
|
|
168
170
|
const body = list.json as ListResponse;
|
|
169
|
-
if (body.items.length === 0) return;
|
|
171
|
+
if (body.items.length === 0) return softSkip('blocked', 'precondition not met — `body.items.length === 0` returned early (seam, prior step, or fixture unavailable)');
|
|
170
172
|
const known = body.items[0]!;
|
|
171
173
|
|
|
172
174
|
const first = await driver.get(`/v1/prompts/${encodeURIComponent(known.templateId)}`);
|
|
173
|
-
if (first.status !== 200) return;
|
|
175
|
+
if (first.status !== 200) return softSkip('blocked', 'precondition not met — `first.status !== 200` returned early (seam, prior step, or fixture unavailable)');
|
|
174
176
|
const etag = first.headers?.get('etag') ?? undefined;
|
|
175
|
-
if (!etag) return; // ETag is SHOULD, not MUST — soft-skip when absent
|
|
177
|
+
if (!etag) return softSkip('blocked', 'precondition not met — `!etag` returned early (ETag is SHOULD, not MUST — soft-skip when absent) (seam, prior step, or fixture unavailable)'); // ETag is SHOULD, not MUST — soft-skip when absent
|
|
176
178
|
|
|
177
179
|
const second = await driver.get(`/v1/prompts/${encodeURIComponent(known.templateId)}`, {
|
|
178
180
|
headers: { 'If-None-Match': etag },
|
|
179
181
|
});
|
|
180
182
|
expect(
|
|
181
183
|
second.status,
|
|
182
|
-
|
|
184
|
+
req('openwop.it.prompt-list-and-fetch.get-v1-prompts-templateid-with-if-none-match-returns-304-when-etag-matches',
|
|
183
185
|
'spec/v1/prompts.md §Discovery & distribution',
|
|
184
186
|
'conditional revalidation MUST return 304 when ETag matches',
|
|
185
187
|
),
|
|
@@ -198,7 +200,7 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
|
|
|
198
200
|
const body = res.json as { error?: unknown; message?: unknown };
|
|
199
201
|
expect(
|
|
200
202
|
typeof body.error,
|
|
201
|
-
|
|
203
|
+
req('openwop.it.prompt-list-and-fetch.get-v1-prompts-unknown-template-returns-404-with-errorenvelope',
|
|
202
204
|
'schemas/error-envelope.schema.json',
|
|
203
205
|
'404 response MUST carry canonical ErrorEnvelope: `error` is a machine-readable code STRING (flat shape per the schema, not nested)',
|
|
204
206
|
),
|
|
@@ -36,6 +36,8 @@ import { describe, it, expect } from 'vitest';
|
|
|
36
36
|
import { driver } from '../lib/driver.js';
|
|
37
37
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
38
38
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
39
|
+
import { req } from '../lib/requirement-ids.js';
|
|
40
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
39
41
|
|
|
40
42
|
interface DiscoveryDoc {
|
|
41
43
|
capabilities?: {
|
|
@@ -83,7 +85,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
|
|
|
83
85
|
const res = await driver.post('/v1/prompts', body);
|
|
84
86
|
expect(
|
|
85
87
|
res.status,
|
|
86
|
-
|
|
88
|
+
req('openwop.it.prompt-mutable-lifecycle.post-v1-prompts-creates-a-user-source-template-201-location',
|
|
87
89
|
'spec/v1/prompts.md §Discovery & distribution',
|
|
88
90
|
'POST /v1/prompts MUST return 201 on successful user-source create',
|
|
89
91
|
),
|
|
@@ -91,7 +93,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
|
|
|
91
93
|
const location = res.headers?.get?.('location');
|
|
92
94
|
expect(
|
|
93
95
|
typeof location === 'string' && location.includes(TEMPLATE_ID),
|
|
94
|
-
|
|
96
|
+
req('openwop.it.prompt-mutable-lifecycle.post-v1-prompts-creates-a-user-source-template-201-location',
|
|
95
97
|
'spec/v1/prompts.md §Discovery & distribution',
|
|
96
98
|
'201 response MUST set a Location header referencing the new templateId',
|
|
97
99
|
),
|
|
@@ -107,7 +109,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
|
|
|
107
109
|
expect(tpl.templateId).toBe(TEMPLATE_ID);
|
|
108
110
|
expect(
|
|
109
111
|
tpl.meta?.source,
|
|
110
|
-
|
|
112
|
+
req('openwop.it.prompt-mutable-lifecycle.get-v1-prompts-templateid-returns-the-new-template-with-meta-source-user',
|
|
111
113
|
'spec/v1/prompts.md §PromptTemplate',
|
|
112
114
|
'host MUST stamp meta.source: "user" on POST-created templates',
|
|
113
115
|
),
|
|
@@ -126,7 +128,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
|
|
|
126
128
|
const res = await driver.post('/v1/prompts', body);
|
|
127
129
|
expect(
|
|
128
130
|
res.status,
|
|
129
|
-
|
|
131
|
+
req('openwop.it.prompt-mutable-lifecycle.post-v1-prompts-with-same-templateid-version-returns-409',
|
|
130
132
|
'spec/v1/prompts.md §Discovery & distribution',
|
|
131
133
|
'POST /v1/prompts MUST return 409 on (templateId, version) duplicate',
|
|
132
134
|
),
|
|
@@ -145,7 +147,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
|
|
|
145
147
|
const res = await driver.put(`/v1/prompts/${encodeURIComponent(TEMPLATE_ID)}`, body);
|
|
146
148
|
expect(
|
|
147
149
|
res.status,
|
|
148
|
-
|
|
150
|
+
req('openwop.it.prompt-mutable-lifecycle.put-v1-prompts-templateid-with-strictly-greater-semver-replaces-the-template',
|
|
149
151
|
'spec/v1/prompts.md §Discovery & distribution',
|
|
150
152
|
'PUT /v1/prompts/{templateId} MUST return 200 on monotonic-SemVer update',
|
|
151
153
|
),
|
|
@@ -167,7 +169,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
|
|
|
167
169
|
const res = await driver.put(`/v1/prompts/${encodeURIComponent(TEMPLATE_ID)}`, body);
|
|
168
170
|
expect(
|
|
169
171
|
res.status,
|
|
170
|
-
|
|
172
|
+
req('openwop.it.prompt-mutable-lifecycle.put-v1-prompts-templateid-with-non-monotonic-semver-returns-409',
|
|
171
173
|
'spec/v1/prompts.md §Discovery & distribution',
|
|
172
174
|
'PUT MUST return 409 when submitted version does not exceed stored',
|
|
173
175
|
),
|
|
@@ -180,7 +182,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
|
|
|
180
182
|
const del = await driver.delete(`/v1/prompts/${encodeURIComponent(TEMPLATE_ID)}`);
|
|
181
183
|
expect(
|
|
182
184
|
del.status,
|
|
183
|
-
|
|
185
|
+
req('openwop.it.prompt-mutable-lifecycle.delete-v1-prompts-templateid-returns-204-and-subsequent-get-returns-404',
|
|
184
186
|
'spec/v1/prompts.md §Discovery & distribution',
|
|
185
187
|
'DELETE /v1/prompts/{templateId} MUST return 204 on successful delete',
|
|
186
188
|
),
|
|
@@ -188,7 +190,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
|
|
|
188
190
|
const after = await driver.get(`/v1/prompts/${encodeURIComponent(TEMPLATE_ID)}`);
|
|
189
191
|
expect(
|
|
190
192
|
after.status,
|
|
191
|
-
|
|
193
|
+
req('openwop.it.prompt-mutable-lifecycle.delete-v1-prompts-templateid-returns-204-and-subsequent-get-returns-404',
|
|
192
194
|
'spec/v1/prompts.md §Discovery & distribution',
|
|
193
195
|
'GET after DELETE MUST return 404',
|
|
194
196
|
),
|
|
@@ -201,14 +203,14 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
|
|
|
201
203
|
// Find a host-built-in to probe; the conformance-fixture set
|
|
202
204
|
// is the standard source for this test.
|
|
203
205
|
const list = await driver.get('/v1/prompts?source=host&limit=1');
|
|
204
|
-
if (list.status !== 200) return;
|
|
206
|
+
if (list.status !== 200) return softSkip('blocked', 'precondition not met — `list.status !== 200` returned early (seam, prior step, or fixture unavailable)');
|
|
205
207
|
const body = list.json as { items: PromptTemplate[] };
|
|
206
|
-
if (body.items.length === 0) return;
|
|
208
|
+
if (body.items.length === 0) return softSkip('blocked', 'precondition not met — `body.items.length === 0` returned early (seam, prior step, or fixture unavailable)');
|
|
207
209
|
const hostTemplate = body.items[0]!;
|
|
208
210
|
const res = await driver.delete(`/v1/prompts/${encodeURIComponent(hostTemplate.templateId)}`);
|
|
209
211
|
expect(
|
|
210
212
|
res.status,
|
|
211
|
-
|
|
213
|
+
req('openwop.it.prompt-mutable-lifecycle.delete-on-a-host-built-in-template-returns-403',
|
|
212
214
|
'spec/v1/prompts.md §Discovery & distribution',
|
|
213
215
|
'DELETE on a host-built-in template MUST return 403 (read-only)',
|
|
214
216
|
),
|
|
@@ -42,6 +42,8 @@ import { describe, it, expect } from 'vitest';
|
|
|
42
42
|
import { randomUUID } from 'node:crypto';
|
|
43
43
|
import { driver } from '../lib/driver.js';
|
|
44
44
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
45
|
+
import { req } from '../lib/requirement-ids.js';
|
|
46
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
45
47
|
|
|
46
48
|
const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
|
|
47
49
|
|
|
@@ -70,12 +72,12 @@ describe.skipIf(HTTP_SKIP)(
|
|
|
70
72
|
const d = await readDiscovery();
|
|
71
73
|
if (d === null) {
|
|
72
74
|
ctx.skip();
|
|
73
|
-
return;
|
|
75
|
+
return softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
|
|
74
76
|
}
|
|
75
77
|
const mutableLibrary = capabilityFamily(d, 'prompts')?.mutableLibrary;
|
|
76
78
|
if (mutableLibrary !== true) {
|
|
77
79
|
ctx.skip();
|
|
78
|
-
return;
|
|
80
|
+
return softSkip('blocked', 'precondition not met — `mutableLibrary !== true` returned early (seam, prior step, or fixture unavailable)');
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
const nonMemberWorkspaceId =
|
|
@@ -96,7 +98,7 @@ describe.skipIf(HTTP_SKIP)(
|
|
|
96
98
|
// 0028 Tier-2 self-disclosed vulnerability demonstrated.
|
|
97
99
|
expect(
|
|
98
100
|
res.status,
|
|
99
|
-
|
|
101
|
+
req('openwop.it.prompt-mutation-workspace-membership-enforced.post-v1-prompts-with-a-workspaceid-the-principal-is-not-a-member-of-must-not-suc',
|
|
100
102
|
'spec/v1/prompts.md §Workspace membership on workspace-scoped reads and writes',
|
|
101
103
|
`mutating /v1/prompts MUST refuse a write to a non-member workspace; ` +
|
|
102
104
|
`got ${res.status} ${res.text.slice(0, 200)}`,
|
|
@@ -116,7 +118,7 @@ describe.skipIf(HTTP_SKIP)(
|
|
|
116
118
|
const body = res.json as { error?: unknown } | null;
|
|
117
119
|
expect(
|
|
118
120
|
body?.error,
|
|
119
|
-
|
|
121
|
+
req('openwop.it.prompt-mutation-workspace-membership-enforced.post-v1-prompts-with-a-workspaceid-the-principal-is-not-a-member-of-must-not-suc',
|
|
120
122
|
'spec/v1/rest-endpoints.md §Common error codes — workspace_membership_required',
|
|
121
123
|
`403 refusal of a workspace-scoped mutation MUST carry error: "workspace_membership_required"; got error: ${JSON.stringify(body?.error)}`,
|
|
122
124
|
),
|
|
@@ -47,6 +47,8 @@ import { describe, it, expect } from 'vitest';
|
|
|
47
47
|
import { driver } from '../lib/driver.js';
|
|
48
48
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
49
49
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
50
|
+
import { req } from '../lib/requirement-ids.js';
|
|
51
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
50
52
|
|
|
51
53
|
interface DiscoveryDoc {
|
|
52
54
|
capabilities?: {
|
|
@@ -94,7 +96,7 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
|
|
|
94
96
|
const res = await driver.get('/v1/prompts?source=pack');
|
|
95
97
|
expect(
|
|
96
98
|
res.status,
|
|
97
|
-
|
|
99
|
+
req('openwop.it.prompt-pack-install.get-v1-prompts-source-pack-returns-200-an-array-of-prompttemplate-objects-when-e',
|
|
98
100
|
'spec/v1/prompts.md §"Discovery & distribution"',
|
|
99
101
|
'GET /v1/prompts MUST return 200 when prompts.endpointsSupported is advertised',
|
|
100
102
|
),
|
|
@@ -103,7 +105,7 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
|
|
|
103
105
|
const body = res.json as ListResponse;
|
|
104
106
|
expect(
|
|
105
107
|
Array.isArray(body.items),
|
|
106
|
-
|
|
108
|
+
req('openwop.it.prompt-pack-install.get-v1-prompts-source-pack-returns-200-an-array-of-prompttemplate-objects-when-e',
|
|
107
109
|
'RFCS/0028-prompt-library-endpoints.md §A',
|
|
108
110
|
'`items` MUST be an array of PromptTemplate objects',
|
|
109
111
|
),
|
|
@@ -117,7 +119,7 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
|
|
|
117
119
|
const packItems = body.items.filter((t) => t.meta?.source === 'pack');
|
|
118
120
|
expect(
|
|
119
121
|
packItems.length,
|
|
120
|
-
|
|
122
|
+
req('openwop.it.prompt-pack-install.get-v1-prompts-source-pack-returns-200-an-array-of-prompttemplate-objects-when-e',
|
|
121
123
|
'RFCS/0028-prompt-library-endpoints.md §B',
|
|
122
124
|
'OPENWOP_TEST_PROMPT_PACK_INSTALLED=true asserts the boot-time loader installed at least one pack',
|
|
123
125
|
),
|
|
@@ -130,29 +132,29 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
|
|
|
130
132
|
if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
|
|
131
133
|
|
|
132
134
|
const res = await driver.get('/v1/prompts?source=pack');
|
|
133
|
-
if (res.status !== 200) return;
|
|
135
|
+
if (res.status !== 200) return softSkip('blocked', 'precondition not met — `res.status !== 200` returned early (seam, prior step, or fixture unavailable)');
|
|
134
136
|
const body = res.json as ListResponse;
|
|
135
137
|
const packItems = body.items.filter((t) => t.meta?.source === 'pack');
|
|
136
|
-
if (packItems.length === 0) return; // gated above
|
|
138
|
+
if (packItems.length === 0) return softSkip('blocked', 'precondition not met — `packItems.length === 0` returned early (gated above) (seam, prior step, or fixture unavailable)'); // gated above
|
|
137
139
|
|
|
138
140
|
for (const t of packItems) {
|
|
139
141
|
expect(
|
|
140
142
|
t.meta?.source,
|
|
141
|
-
|
|
143
|
+
req('openwop.it.prompt-pack-install.each-pack-source-template-carries-meta-source-packname-packversion-stamps-per-rf',
|
|
142
144
|
'schemas/prompt-template.schema.json §meta.source',
|
|
143
145
|
'pack-installed templates MUST stamp `meta.source: "pack"`',
|
|
144
146
|
),
|
|
145
147
|
).toBe('pack');
|
|
146
148
|
expect(
|
|
147
149
|
typeof t.meta?.packName === 'string' && (t.meta?.packName?.length ?? 0) > 0,
|
|
148
|
-
|
|
150
|
+
req('openwop.it.prompt-pack-install.each-pack-source-template-carries-meta-source-packname-packversion-stamps-per-rf',
|
|
149
151
|
'RFCS/0028-prompt-library-endpoints.md §B',
|
|
150
152
|
'pack-installed templates MUST stamp `meta.packName`',
|
|
151
153
|
),
|
|
152
154
|
).toBe(true);
|
|
153
155
|
expect(
|
|
154
156
|
typeof t.meta?.packVersion === 'string' && /^\d+\.\d+\.\d+/.test(t.meta?.packVersion ?? ''),
|
|
155
|
-
|
|
157
|
+
req('openwop.it.prompt-pack-install.each-pack-source-template-carries-meta-source-packname-packversion-stamps-per-rf',
|
|
156
158
|
'RFCS/0028-prompt-library-endpoints.md §B',
|
|
157
159
|
'pack-installed templates MUST stamp a semver `meta.packVersion`',
|
|
158
160
|
),
|
|
@@ -165,15 +167,15 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
|
|
|
165
167
|
if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
|
|
166
168
|
|
|
167
169
|
const list = await driver.get('/v1/prompts?source=pack');
|
|
168
|
-
if (list.status !== 200) return;
|
|
170
|
+
if (list.status !== 200) return softSkip('blocked', 'precondition not met — `list.status !== 200` returned early (seam, prior step, or fixture unavailable)');
|
|
169
171
|
const body = list.json as ListResponse;
|
|
170
172
|
const writer = body.items.find((t) => t.templateId === 'writer-system' && t.meta?.source === 'pack');
|
|
171
|
-
if (!writer) return; // host may have installed a different reference pack; skip silently
|
|
173
|
+
if (!writer) return softSkip('blocked', 'precondition not met — `!writer` returned early (host may have installed a different reference pack; skip silently) (seam, prior step, or fixture unavailable)'); // host may have installed a different reference pack; skip silently
|
|
172
174
|
|
|
173
175
|
const fetched = await driver.get(`/v1/prompts/${encodeURIComponent('writer-system')}`);
|
|
174
176
|
expect(
|
|
175
177
|
fetched.status,
|
|
176
|
-
|
|
178
|
+
req('openwop.it.prompt-pack-install.get-v1-prompts-templateid-returns-a-pack-source-template-by-id-reference-pack-wr',
|
|
177
179
|
'RFCS/0028-prompt-library-endpoints.md §A',
|
|
178
180
|
'GET /v1/prompts/{templateId} MUST return 200 for a known pack-source template id',
|
|
179
181
|
),
|
|
@@ -182,7 +184,7 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
|
|
|
182
184
|
expect(t.templateId).toBe('writer-system');
|
|
183
185
|
expect(
|
|
184
186
|
t.meta?.source,
|
|
185
|
-
'fetched template MUST preserve `meta.source: "pack"` provenance',
|
|
187
|
+
req('openwop.it.prompt-pack-install.get-v1-prompts-templateid-returns-a-pack-source-template-by-id-reference-pack-wr', 'RFCS/0028-prompt-library-endpoints.md §A', 'fetched template MUST preserve `meta.source: "pack"` provenance'),
|
|
186
188
|
).toBe('pack');
|
|
187
189
|
});
|
|
188
190
|
});
|