@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
|
@@ -32,6 +32,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
32
32
|
import { softSkip } from '../lib/soft-skip.js';
|
|
33
33
|
import { driver } from '../lib/driver.js';
|
|
34
34
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
35
|
+
import { req } from '../lib/requirement-ids.js';
|
|
35
36
|
|
|
36
37
|
const ALLOWED = new Set(['single-region', 'reconciled-records', 'fenced-effects']);
|
|
37
38
|
const REQUIRED_METRICS_WHEN_MULTI_REGION = [
|
|
@@ -62,7 +63,7 @@ describe('multi-region-idempotency: capability shape', () => {
|
|
|
62
63
|
return softSkip('blocked', 'precondition not met — `!idem || idem.crossRegion === undefined` returned early (seam, prior step, or fixture unavailable)');
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
expect(ALLOWED.has(idem.crossRegion),
|
|
66
|
+
expect(ALLOWED.has(idem.crossRegion), req('openwop.it.multi-region-idempotency.idempotency-crossregion-when-advertised-must-be-one-of-the-closed-enum',
|
|
66
67
|
'idempotency.md §"Multi-region idempotency" §"Capability advertisement"',
|
|
67
68
|
'crossRegion MUST be one of {"single-region","reconciled-records","fenced-effects"}',
|
|
68
69
|
)).toBe(true);
|
|
@@ -88,7 +89,7 @@ describe('multi-region-idempotency: capability shape', () => {
|
|
|
88
89
|
|
|
89
90
|
const advertised = new Set(observability?.metrics?.names ?? []);
|
|
90
91
|
for (const name of REQUIRED_METRICS_WHEN_MULTI_REGION) {
|
|
91
|
-
expect(advertised.has(name),
|
|
92
|
+
expect(advertised.has(name), req('openwop.it.multi-region-idempotency.multi-region-hosts-should-expose-the-cross-region-conflict-counter-per-operator',
|
|
92
93
|
'idempotency.md §"Operator surface"',
|
|
93
94
|
`multi-region hosts SHOULD advertise metric "${name}" so operators can monitor conflict frequency`,
|
|
94
95
|
)).toBe(true);
|
|
@@ -122,7 +123,7 @@ describe('multi-region-idempotency: granular multiRegion advertisement shape (RF
|
|
|
122
123
|
|
|
123
124
|
expect(
|
|
124
125
|
typeof mr.supported,
|
|
125
|
-
|
|
126
|
+
req('openwop.it.multi-region-idempotency.capabilities-idempotency-multiregion-when-present-conforms-to-rfc-0036-a',
|
|
126
127
|
'RFCS/0036-multi-region-and-cross-engine-guarantees.md §A',
|
|
127
128
|
'capabilities.idempotency.multiRegion.supported MUST be boolean when present',
|
|
128
129
|
),
|
|
@@ -133,7 +134,7 @@ describe('multi-region-idempotency: granular multiRegion advertisement shape (RF
|
|
|
133
134
|
const n = mr.replicationLagBoundMs as number;
|
|
134
135
|
expect(
|
|
135
136
|
Number.isInteger(n) && n >= 0 && n <= 60000,
|
|
136
|
-
|
|
137
|
+
req('openwop.it.multi-region-idempotency.capabilities-idempotency-multiregion-when-present-conforms-to-rfc-0036-a',
|
|
137
138
|
'RFCS/0036-multi-region-and-cross-engine-guarantees.md §A',
|
|
138
139
|
'replicationLagBoundMs MUST be integer in [0, 60000] when supported is true',
|
|
139
140
|
),
|
|
@@ -145,7 +146,7 @@ describe('multi-region-idempotency: granular multiRegion advertisement shape (RF
|
|
|
145
146
|
const isExtension = /^x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*$/.test(s);
|
|
146
147
|
expect(
|
|
147
148
|
isCategorical || isExtension,
|
|
148
|
-
|
|
149
|
+
req('openwop.it.multi-region-idempotency.capabilities-idempotency-multiregion-when-present-conforms-to-rfc-0036-a',
|
|
149
150
|
'RFCS/0036-multi-region-and-cross-engine-guarantees.md §A',
|
|
150
151
|
'partitionRecoveryStrategy MUST be `lexicographic-min-run-id` OR match ^x-host-<host>-<key>$ (RFC 0150 §D removed the time-ordered rules: with no shared clock under a partition, each region believes it wrote last, so neither can produce the reproducible survivor the annex requires)',
|
|
151
152
|
),
|
|
@@ -25,6 +25,7 @@ import { driver } from '../lib/driver.js';
|
|
|
25
25
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
26
26
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
27
27
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
28
|
+
import { req } from '../lib/requirement-ids.js';
|
|
28
29
|
|
|
29
30
|
const WORKFLOW_ID = 'conformance-failure';
|
|
30
31
|
const SKIP_NO_FIXTURE = !isFixtureAdvertised(WORKFLOW_ID);
|
|
@@ -43,10 +44,10 @@ function nodeFailedValidator() {
|
|
|
43
44
|
describe.skipIf(SKIP_NO_FIXTURE)('run-event-payloads.schema.json §nodeFailed — node.failed carries a structured error object', () => {
|
|
44
45
|
it('every node.failed on the conformance-failure run validates against §nodeFailed (error: { code, message } is an object, not a string)', async () => {
|
|
45
46
|
const create = await driver.post('/v1/runs', { workflowId: WORKFLOW_ID });
|
|
46
|
-
expect(create.status,
|
|
47
|
+
expect(create.status, req('openwop.it.node-failed-payload-shape.every-node-failed-on-the-conformance-failure-run-validates-against-nodefailed-er', 'rest-endpoints.md', 'POST /v1/runs MUST return 201 for the failing fixture')).toBe(201);
|
|
47
48
|
const runId = (create.json as { runId: string }).runId;
|
|
48
49
|
const terminal = await pollUntilTerminal(runId);
|
|
49
|
-
expect(terminal.status,
|
|
50
|
+
expect(terminal.status, req('openwop.it.node-failed-payload-shape.every-node-failed-on-the-conformance-failure-run-validates-against-nodefailed-er', 'fixtures.md conformance-failure §Terminal status', 'fixture MUST reach terminal `failed`')).toBe('failed');
|
|
50
51
|
|
|
51
52
|
const res = await driver.get(`/v1/runs/${encodeURIComponent(runId)}/events`);
|
|
52
53
|
expect(res.status).toBe(200);
|
|
@@ -54,7 +55,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('run-event-payloads.schema.json §nodeFailed
|
|
|
54
55
|
const failed = events.filter((e) => e.type === 'node.failed');
|
|
55
56
|
expect(
|
|
56
57
|
failed.length,
|
|
57
|
-
|
|
58
|
+
req('openwop.it.node-failed-payload-shape.every-node-failed-on-the-conformance-failure-run-validates-against-nodefailed-er', 'rest-endpoints.md §Run events', 'a run that fails at a node MUST carry at least one node.failed event on its log'),
|
|
58
59
|
).toBeGreaterThan(0);
|
|
59
60
|
|
|
60
61
|
const validate = nodeFailedValidator();
|
|
@@ -62,7 +63,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('run-event-payloads.schema.json §nodeFailed
|
|
|
62
63
|
const ok = validate(ev.payload);
|
|
63
64
|
expect(
|
|
64
65
|
ok,
|
|
65
|
-
|
|
66
|
+
req('openwop.it.node-failed-payload-shape.every-node-failed-on-the-conformance-failure-run-validates-against-nodefailed-er',
|
|
66
67
|
'run-event-payloads.schema.json §nodeFailed',
|
|
67
68
|
`node.failed payload MUST validate — error is a REQUIRED object { code, message } (_errorObject), not a bare string or a data.code: ${JSON.stringify(validate.errors)} — payload: ${JSON.stringify(ev.payload).slice(0, 300)}`,
|
|
68
69
|
),
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
import { describe, it, expect, beforeAll } from 'vitest';
|
|
22
22
|
import { driver } from '../lib/driver.js';
|
|
23
23
|
import { discoveryFamilies } from '../lib/discovery-capabilities.js';
|
|
24
|
+
import { req } from '../lib/requirement-ids.js';
|
|
25
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
24
26
|
|
|
25
27
|
/** RFC 0031 §C — spec-reserved capability identifiers. */
|
|
26
28
|
const RESERVED_IDENTIFIERS: ReadonlySet<string> = new Set([
|
|
@@ -84,7 +86,7 @@ describe('node-module-required-capabilities-shape: authoring convention (RFC 003
|
|
|
84
86
|
if (SKIP_REASON) {
|
|
85
87
|
// eslint-disable-next-line no-console
|
|
86
88
|
console.warn(`[node-module-required-capabilities-shape] skip: ${SKIP_REASON}`);
|
|
87
|
-
return;
|
|
89
|
+
return softSkip('skipped', 'operator opted out — gate `SKIP_REASON` returned early ([node-module-required-capabilities-shape] skip: …)');
|
|
88
90
|
}
|
|
89
91
|
const aiNodes = CATALOG.filter((n) => /^core\.ai\./.test(n.typeId));
|
|
90
92
|
const missing: string[] = [];
|
|
@@ -103,7 +105,7 @@ describe('node-module-required-capabilities-shape: authoring convention (RFC 003
|
|
|
103
105
|
// node was inspected (otherwise the test is vacuous). MUST hold.
|
|
104
106
|
expect(
|
|
105
107
|
aiNodes.length,
|
|
106
|
-
|
|
108
|
+
req('openwop.it.node-module-required-capabilities-shape.every-nodemodule-with-typeid-matching-core-ai-declares-non-empty-requiredmodelca',
|
|
107
109
|
'RFC 0031 §B',
|
|
108
110
|
'host MUST advertise at least one core.ai.* NodeModule in the node catalog (otherwise the SHOULD has no surface to bind to)',
|
|
109
111
|
),
|
|
@@ -111,7 +113,7 @@ describe('node-module-required-capabilities-shape: authoring convention (RFC 003
|
|
|
111
113
|
});
|
|
112
114
|
|
|
113
115
|
it('every declared identifier MUST match the spec-reserved set OR the `x-host-<host>-<key>` extension pattern', () => {
|
|
114
|
-
if (SKIP_REASON) return;
|
|
116
|
+
if (SKIP_REASON) return softSkip('skipped', 'operator opted out — gate `SKIP_REASON` returned early');
|
|
115
117
|
const violations: Array<{ typeId: string; identifier: string }> = [];
|
|
116
118
|
for (const n of CATALOG) {
|
|
117
119
|
if (!Array.isArray(n.requiredModelCapabilities)) continue;
|
|
@@ -127,7 +129,7 @@ describe('node-module-required-capabilities-shape: authoring convention (RFC 003
|
|
|
127
129
|
}
|
|
128
130
|
expect(
|
|
129
131
|
violations,
|
|
130
|
-
|
|
132
|
+
req('openwop.it.node-module-required-capabilities-shape.every-declared-identifier-must-match-the-spec-reserved-set-or-the-x-host-host-ke',
|
|
131
133
|
'RFC 0031 §C "Reservation policy"',
|
|
132
134
|
'every requiredModelCapabilities identifier MUST be spec-reserved OR match x-host-<host>-<key>',
|
|
133
135
|
),
|
|
@@ -135,7 +137,7 @@ describe('node-module-required-capabilities-shape: authoring convention (RFC 003
|
|
|
135
137
|
});
|
|
136
138
|
|
|
137
139
|
it('NodeModule.fallbackModel.provider (when declared) MUST be in `capabilities.aiProviders.supported[]`', () => {
|
|
138
|
-
if (SKIP_REASON) return;
|
|
140
|
+
if (SKIP_REASON) return softSkip('skipped', 'operator opted out — gate `SKIP_REASON` returned early');
|
|
139
141
|
const violations: Array<{ typeId: string; provider: string }> = [];
|
|
140
142
|
for (const n of CATALOG) {
|
|
141
143
|
const fm = n.fallbackModel;
|
|
@@ -148,7 +150,7 @@ describe('node-module-required-capabilities-shape: authoring convention (RFC 003
|
|
|
148
150
|
}
|
|
149
151
|
expect(
|
|
150
152
|
violations,
|
|
151
|
-
|
|
153
|
+
req('openwop.it.node-module-required-capabilities-shape.nodemodule-fallbackmodel-provider-when-declared-must-be-in-capabilities-aiprovid',
|
|
152
154
|
'RFC 0031 §B',
|
|
153
155
|
'every fallbackModel.provider MUST appear in capabilities.aiProviders.supported[]',
|
|
154
156
|
),
|
|
@@ -156,7 +158,7 @@ describe('node-module-required-capabilities-shape: authoring convention (RFC 003
|
|
|
156
158
|
});
|
|
157
159
|
|
|
158
160
|
it('a NodeModule declaring `requiredModelCapabilities` without `fallbackModel` is conformant — refusal-only (no substitution) is the default posture', () => {
|
|
159
|
-
if (SKIP_REASON) return;
|
|
161
|
+
if (SKIP_REASON) return softSkip('skipped', 'operator opted out — gate `SKIP_REASON` returned early');
|
|
160
162
|
// The check is structural: catalog entries are not malformed when
|
|
161
163
|
// they carry requiredModelCapabilities AND lack fallbackModel. This
|
|
162
164
|
// asserts the host doesn't synthesize a default fallbackModel for
|
|
@@ -176,7 +178,7 @@ describe('node-module-required-capabilities-shape: authoring convention (RFC 003
|
|
|
176
178
|
for (const n of refusalOnly) {
|
|
177
179
|
expect(
|
|
178
180
|
n.fallbackModel,
|
|
179
|
-
|
|
181
|
+
req('openwop.it.node-module-required-capabilities-shape.a-nodemodule-declaring-requiredmodelcapabilities-without-fallbackmodel-is-confor',
|
|
180
182
|
'RFC 0031 §B',
|
|
181
183
|
`${n.typeId}: refusal-only posture MUST surface as absent fallbackModel (not as {} or null wrapper)`,
|
|
182
184
|
),
|
|
@@ -38,6 +38,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
38
38
|
import { softSkip } from '../lib/soft-skip.js';
|
|
39
39
|
import { driver } from '../lib/driver.js';
|
|
40
40
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
41
|
+
import { req } from '../lib/requirement-ids.js';
|
|
41
42
|
|
|
42
43
|
interface DiscoveryOAuth {
|
|
43
44
|
supported?: boolean;
|
|
@@ -100,7 +101,7 @@ describe('oauth-authorization-code-roundtrip: the grant dance (RFC 0047 §C)', (
|
|
|
100
101
|
|
|
101
102
|
expect(
|
|
102
103
|
res.status,
|
|
103
|
-
|
|
104
|
+
req('openwop.it.oauth-authorization-code-roundtrip.acquires-a-token-via-authorization-code-and-returns-a-reference-never-the-token',
|
|
104
105
|
'RFC 0047 §C',
|
|
105
106
|
'the authorize-code-roundtrip seam MUST perform the authorization_code grant against the synthetic provider and return the run observable surfaces',
|
|
106
107
|
),
|
|
@@ -109,7 +110,7 @@ describe('oauth-authorization-code-roundtrip: the grant dance (RFC 0047 §C)', (
|
|
|
109
110
|
const body = (res.json ?? {}) as { credentialRef?: unknown };
|
|
110
111
|
expect(
|
|
111
112
|
typeof body.credentialRef === 'string' && body.credentialRef.length > 0,
|
|
112
|
-
|
|
113
|
+
req('openwop.it.oauth-authorization-code-roundtrip.acquires-a-token-via-authorization-code-and-returns-a-reference-never-the-token',
|
|
113
114
|
'RFC 0047 §C',
|
|
114
115
|
'a successful roundtrip MUST resolve to a credential REFERENCE (token persisted as a host.credentials entry), not the raw token',
|
|
115
116
|
),
|
|
@@ -120,7 +121,7 @@ describe('oauth-authorization-code-roundtrip: the grant dance (RFC 0047 §C)', (
|
|
|
120
121
|
for (const secret of SECRET_VALUES) {
|
|
121
122
|
expect(
|
|
122
123
|
serialized.includes(secret),
|
|
123
|
-
|
|
124
|
+
req('openwop.it.oauth-authorization-code-roundtrip.acquires-a-token-via-authorization-code-and-returns-a-reference-never-the-token',
|
|
124
125
|
'RFC 0047 §C / SECURITY/invariants.yaml credential-payload-redaction',
|
|
125
126
|
`the authorization code, state, PKCE verifier, and acquired token material MUST NOT appear on any run-visible surface — leaked: ${secret.slice(0, 16)}…`,
|
|
126
127
|
),
|
|
@@ -135,7 +136,7 @@ describe('oauth-authorization-code-roundtrip: the grant dance (RFC 0047 §C)', (
|
|
|
135
136
|
const keys = Object.keys(authorized.payload);
|
|
136
137
|
expect(
|
|
137
138
|
keys.includes('credentialRef') && !keys.includes('access_token') && !keys.includes('refresh_token'),
|
|
138
|
-
|
|
139
|
+
req('openwop.it.oauth-authorization-code-roundtrip.acquires-a-token-via-authorization-code-and-returns-a-reference-never-the-token',
|
|
139
140
|
'RFC 0047 §C',
|
|
140
141
|
'connector.authorized MUST carry { provider, credentialRef, scopes } and MUST NOT carry token material',
|
|
141
142
|
),
|
|
@@ -20,6 +20,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
20
20
|
import { softSkip } from '../lib/soft-skip.js';
|
|
21
21
|
import { driver } from '../lib/driver.js';
|
|
22
22
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
23
|
+
import { req } from '../lib/requirement-ids.js';
|
|
23
24
|
|
|
24
25
|
interface DiscoveryOAuthProvider {
|
|
25
26
|
id?: string;
|
|
@@ -58,7 +59,7 @@ describe('oauth-capability-shape: advertisement shape (RFC 0047 §A)', () => {
|
|
|
58
59
|
if (oauth === null) return softSkip('inapplicable', 'host doesn\'t advertise host.oauth at all');
|
|
59
60
|
expect(
|
|
60
61
|
typeof oauth.supported,
|
|
61
|
-
|
|
62
|
+
req('openwop.it.oauth-capability-shape.capabilities-oauth-is-either-absent-or-well-formed',
|
|
62
63
|
'capabilities.schema.json §oauth',
|
|
63
64
|
'capabilities.oauth.supported MUST be a boolean when oauth is advertised',
|
|
64
65
|
),
|
|
@@ -70,12 +71,12 @@ describe('oauth-capability-shape: advertisement shape (RFC 0047 §A)', () => {
|
|
|
70
71
|
if (!oauth?.supported || oauth.grants === undefined) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!oauth?.supported || oauth.grants === undefined` returned early');
|
|
71
72
|
expect(
|
|
72
73
|
Array.isArray(oauth.grants),
|
|
73
|
-
|
|
74
|
+
req('openwop.it.oauth-capability-shape.grants-is-a-subset-of-the-canonical-grant-set-when-supported', 'RFC 0047 §A', 'capabilities.oauth.grants MUST be an array'),
|
|
74
75
|
).toBe(true);
|
|
75
76
|
for (const grant of oauth.grants) {
|
|
76
77
|
expect(
|
|
77
78
|
VALID_GRANTS.has(grant),
|
|
78
|
-
|
|
79
|
+
req('openwop.it.oauth-capability-shape.grants-is-a-subset-of-the-canonical-grant-set-when-supported',
|
|
79
80
|
'RFC 0047 §A',
|
|
80
81
|
`capabilities.oauth.grants entries MUST be one of {${[...VALID_GRANTS].join(', ')}}, got: ${grant}`,
|
|
81
82
|
),
|
|
@@ -89,7 +90,7 @@ describe('oauth-capability-shape: advertisement shape (RFC 0047 §A)', () => {
|
|
|
89
90
|
for (const provider of oauth.providers) {
|
|
90
91
|
expect(
|
|
91
92
|
typeof provider.id === 'string' && provider.id.length > 0,
|
|
92
|
-
|
|
93
|
+
req('openwop.it.oauth-capability-shape.every-advertised-provider-has-a-non-empty-id-when-supported',
|
|
93
94
|
'RFC 0047 §A',
|
|
94
95
|
'each capabilities.oauth.providers[] entry MUST declare a non-empty id',
|
|
95
96
|
),
|
|
@@ -28,6 +28,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
28
28
|
import { softSkip } from '../lib/soft-skip.js';
|
|
29
29
|
import { driver } from '../lib/driver.js';
|
|
30
30
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
31
|
+
import { req } from '../lib/requirement-ids.js';
|
|
31
32
|
|
|
32
33
|
interface DiscoveryOAuth {
|
|
33
34
|
supported?: boolean;
|
|
@@ -53,7 +54,7 @@ describe('oauth-connector-redaction: advertisement shape (RFC 0047 §A)', () =>
|
|
|
53
54
|
if (oauth === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `oauth === null` returned early');
|
|
54
55
|
expect(
|
|
55
56
|
typeof oauth.supported,
|
|
56
|
-
|
|
57
|
+
req('openwop.it.oauth-connector-redaction.capabilities-oauth-supported-is-a-boolean-when-advertised',
|
|
57
58
|
'capabilities.schema.json §oauth',
|
|
58
59
|
'capabilities.oauth.supported MUST be a boolean when oauth is advertised',
|
|
59
60
|
),
|
|
@@ -75,7 +76,7 @@ describe('oauth-connector-redaction: token material MUST NOT cross the wire (RFC
|
|
|
75
76
|
|
|
76
77
|
expect(
|
|
77
78
|
res.status,
|
|
78
|
-
|
|
79
|
+
req('openwop.it.oauth-connector-redaction.canary-token-is-absent-from-every-observable-run-surface',
|
|
79
80
|
'RFC 0047 §C',
|
|
80
81
|
'the oauth connector-echo seam MUST acquire the token and return the run observable surfaces',
|
|
81
82
|
),
|
|
@@ -84,7 +85,7 @@ describe('oauth-connector-redaction: token material MUST NOT cross the wire (RFC
|
|
|
84
85
|
const serialized = JSON.stringify(res.json ?? {});
|
|
85
86
|
expect(
|
|
86
87
|
serialized.includes(TOKEN_CANARY),
|
|
87
|
-
|
|
88
|
+
req('openwop.it.oauth-connector-redaction.canary-token-is-absent-from-every-observable-run-surface',
|
|
88
89
|
'SECURITY/invariants.yaml credential-payload-redaction',
|
|
89
90
|
'acquired OAuth token material MUST NOT appear in inputs, variables, channels, events, snapshot, or debug bundle — only the credential reference may cross the wire',
|
|
90
91
|
),
|
|
@@ -21,6 +21,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
21
21
|
import { readFileSync } from 'node:fs';
|
|
22
22
|
import { join } from 'node:path';
|
|
23
23
|
import { API_DIR } from '../lib/paths.js';
|
|
24
|
+
import { req } from '../lib/requirement-ids.js';
|
|
24
25
|
|
|
25
26
|
const OPENAPI_PATH = join(API_DIR, 'openapi.yaml');
|
|
26
27
|
|
|
@@ -86,8 +87,8 @@ describe('RFC 0149 §A — every server/path pair resolves to exactly one /v1 se
|
|
|
86
87
|
// Guards the gate itself: an extraction that silently found nothing would
|
|
87
88
|
// make every assertion below vacuously true — the exact failure mode
|
|
88
89
|
// RFC 0148 exists to prevent.
|
|
89
|
-
expect(servers.length, `${OPENAPI_PATH} MUST declare servers[]`).toBeGreaterThan(0);
|
|
90
|
-
expect(paths.length, `${OPENAPI_PATH} MUST declare paths`).toBeGreaterThan(0);
|
|
90
|
+
expect(servers.length, req('openwop.it.openapi-resolved-paths.the-document-declares-at-least-one-server-and-one-path', 'RFC 0149 §A', `${OPENAPI_PATH} MUST declare servers[]`)).toBeGreaterThan(0);
|
|
91
|
+
expect(paths.length, req('openwop.it.openapi-resolved-paths.the-document-declares-at-least-one-server-and-one-path', 'RFC 0149 §A', `${OPENAPI_PATH} MUST declare paths`)).toBeGreaterThan(0);
|
|
91
92
|
});
|
|
92
93
|
|
|
93
94
|
it('no versioned operation resolves to a duplicated /v1 prefix', () => {
|
|
@@ -102,10 +103,10 @@ describe('RFC 0149 §A — every server/path pair resolves to exactly one /v1 se
|
|
|
102
103
|
}
|
|
103
104
|
expect(
|
|
104
105
|
offenders,
|
|
105
|
-
'RFC 0149 §A: a versioned operation MUST resolve with exactly one `/v1` segment. ' +
|
|
106
|
+
req('openwop.it.openapi-resolved-paths.no-versioned-operation-resolves-to-a-duplicated-v1-prefix', 'RFC 0149 §A', 'RFC 0149 §A: a versioned operation MUST resolve with exactly one `/v1` segment. ' +
|
|
106
107
|
'Offending server/path pairs:\n ' +
|
|
107
108
|
offenders.join('\n ') +
|
|
108
|
-
'\nFix: drop `/v1` from `servers[].url` and keep it in the path keys.',
|
|
109
|
+
'\nFix: drop `/v1` from `servers[].url` and keep it in the path keys.'),
|
|
109
110
|
).toEqual([]);
|
|
110
111
|
});
|
|
111
112
|
|
|
@@ -119,7 +120,7 @@ describe('RFC 0149 §A — every server/path pair resolves to exactly one /v1 se
|
|
|
119
120
|
const resolved = resolvedPath(server, pathKey);
|
|
120
121
|
expect(
|
|
121
122
|
resolved,
|
|
122
|
-
`RFC 0149 §A: ${pathKey} MUST remain unversioned; resolved as ${resolved}
|
|
123
|
+
req('openwop.it.openapi-resolved-paths.the-unversioned-discovery-route-stays-unversioned-when-resolved', 'RFC 0149 §A', `RFC 0149 §A: ${pathKey} MUST remain unversioned; resolved as ${resolved}`),
|
|
123
124
|
).toBe(pathKey);
|
|
124
125
|
}
|
|
125
126
|
}
|
|
@@ -22,6 +22,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
22
22
|
import { driver } from '../lib/driver.js';
|
|
23
23
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
24
24
|
import { isOrchestratorSupported } from '../lib/multi-agent-capabilities.js';
|
|
25
|
+
import { req } from '../lib/requirement-ids.js';
|
|
25
26
|
|
|
26
27
|
const FIXTURE = 'conformance-orchestrator-low-confidence';
|
|
27
28
|
const SKIP = !isOrchestratorSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -51,7 +52,7 @@ describe.skipIf(SKIP)('orchestratorConservativePath: CP-1 low-confidence suspend
|
|
|
51
52
|
const decisionsBeforeResume = list.filter((e) => e.type === 'runOrchestrator.decided');
|
|
52
53
|
expect(
|
|
53
54
|
decisionsBeforeResume.length,
|
|
54
|
-
'CP-1: low-confidence holds the decision until human ratification',
|
|
55
|
+
req('openwop.it.orchestratorConservativePath.supervisor-below-threshold-suspends-with-reason-low-confidence-ratified-decision', 'RFCS/0006-orchestrator.md', 'CP-1: low-confidence holds the decision until human ratification'),
|
|
55
56
|
).toBe(0);
|
|
56
57
|
|
|
57
58
|
// node.suspended with reason=low-confidence is present.
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
isOrchestratorSupported,
|
|
28
28
|
isDispatchSupported,
|
|
29
29
|
} from '../lib/multi-agent-capabilities.js';
|
|
30
|
+
import { req } from '../lib/requirement-ids.js';
|
|
30
31
|
|
|
31
32
|
const FIXTURE = 'conformance-orchestrator-dispatch';
|
|
32
33
|
const SKIP =
|
|
@@ -55,7 +56,7 @@ describe.skipIf(SKIP)('orchestratorDispatch: supervisor → dispatch → next-wo
|
|
|
55
56
|
const d = e.payload?.decision as { kind?: string } | undefined;
|
|
56
57
|
return d?.kind === 'next-worker';
|
|
57
58
|
});
|
|
58
|
-
expect(nextWorker, 'fixture emits at least one kind:next-worker decision').toBeDefined();
|
|
59
|
+
expect(nextWorker, req('openwop.it.orchestratorDispatch.emits-runorchestrator-decided-next-worker-between-supervisor-dispatch', 'RFCS/0006-orchestrator.md', 'fixture emits at least one kind:next-worker decision')).toBeDefined();
|
|
59
60
|
|
|
60
61
|
const payload = nextWorker!.payload!;
|
|
61
62
|
expect(typeof payload.agentId).toBe('string');
|
|
@@ -20,6 +20,7 @@ import { driver } from '../lib/driver.js';
|
|
|
20
20
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
21
21
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
22
22
|
import { isOrchestratorSupported } from '../lib/multi-agent-capabilities.js';
|
|
23
|
+
import { req } from '../lib/requirement-ids.js';
|
|
23
24
|
|
|
24
25
|
const FIXTURE = 'conformance-orchestrator-terminate';
|
|
25
26
|
const SKIP = !isOrchestratorSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -27,7 +28,7 @@ const SKIP = !isOrchestratorSupported() || !isFixtureAdvertised(FIXTURE);
|
|
|
27
28
|
describe.skipIf(SKIP)('orchestratorTermination: terminate decision → run.completed (CO-3)', () => {
|
|
28
29
|
it('terminate is the final orchestrator decision; run completes cleanly', async () => {
|
|
29
30
|
const create = await driver.post('/v1/runs', { workflowId: FIXTURE });
|
|
30
|
-
expect(create.status).toBe(201);
|
|
31
|
+
expect(create.status, req('openwop.it.orchestratorTermination.terminate-is-the-final-orchestrator-decision-run-completes-cleanly', 'RFCS/0006-orchestrator.md', 'terminate is the final orchestrator decision; run completes cleanly')).toBe(201);
|
|
31
32
|
const runId = (create.json as { runId: string }).runId;
|
|
32
33
|
|
|
33
34
|
const terminal = await pollUntilTerminal(runId);
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
|
|
33
33
|
import { describe, it, expect } from 'vitest';
|
|
34
34
|
import { seamAbsent } from '../lib/soft-skip.js';
|
|
35
|
-
import { driver } from '../lib/driver.js';
|
|
36
35
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
37
36
|
import { readOrgChartCap, getOrgChart, getDepartmentView, AUTHORITY_FIELDS } from '../lib/agentOrgChart.js';
|
|
37
|
+
import { req } from '../lib/requirement-ids.js';
|
|
38
38
|
|
|
39
39
|
/** Assert an org-chart wire object carries no authority-bearing field. */
|
|
40
40
|
function expectNoAuthority(obj: Record<string, unknown> | undefined, where: string): void {
|
|
@@ -42,7 +42,7 @@ function expectNoAuthority(obj: Record<string, unknown> | undefined, where: stri
|
|
|
42
42
|
for (const f of AUTHORITY_FIELDS) {
|
|
43
43
|
expect(
|
|
44
44
|
!(f in obj),
|
|
45
|
-
|
|
45
|
+
req('openwop.it.org-position-no-authority-escalation.the-live-org-chart-wire-carries-no-authority-bearing-field-on-any-member-departm', 'RFC 0087 §B / org-position-no-authority-escalation', `${where} MUST NOT carry the authority field "${f}" — org position confers no authority`),
|
|
46
46
|
).toBe(true);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
|
|
38
38
|
import { describe, it, expect, afterEach } from 'vitest';
|
|
39
39
|
import { OtelCollector } from '../lib/otel-collector.js';
|
|
40
|
+
import { req } from '../lib/requirement-ids.js';
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
43
|
* NOT callback-shaped, despite importing the collector.
|
|
@@ -119,7 +120,7 @@ function metricsPayload(metricName: string, attrs: Record<string, string>): unkn
|
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
// NOTE: assertions here intentionally use bare `expect(...)` rather than
|
|
122
|
-
// `expect(...,
|
|
123
|
+
// `expect(..., req('openwop.it.<file>.<slug>', 'spec.md §section', 'requirement'))`. This is a
|
|
123
124
|
// HARNESS self-test — it verifies the conformance collector's own
|
|
124
125
|
// `findCanaryLeakage()` inspector, not a host's compliance with a spec
|
|
125
126
|
// requirement, so there is no spec section to cite (consistent with other
|
|
@@ -196,7 +197,7 @@ describe('otel-collector-canary-inspection: collector inspects real OTLP exports
|
|
|
196
197
|
);
|
|
197
198
|
|
|
198
199
|
const leaks = collector.findCanaryLeakage(CANARY);
|
|
199
|
-
expect(leaks.length).toBeGreaterThan(0);
|
|
200
|
+
expect(leaks.length, req('openwop.it.otel-collector-canary-inspection.catches-a-canary-embedded-in-a-span-attribute-value', 'KNOWN-LIMITS.md', 'catches a canary embedded in a span attribute value')).toBeGreaterThan(0);
|
|
200
201
|
const attrLeak = leaks.find((l) => l.surface === 'span.attribute');
|
|
201
202
|
expect(attrLeak).toBeDefined();
|
|
202
203
|
expect(attrLeak!.key).toBe('http.request.header.authorization');
|
|
@@ -216,7 +217,7 @@ describe('otel-collector-canary-inspection: collector inspects real OTLP exports
|
|
|
216
217
|
|
|
217
218
|
const leaks = collector.findCanaryLeakage(CANARY);
|
|
218
219
|
const surfaces = new Set(leaks.map((l) => l.surface));
|
|
219
|
-
expect(surfaces.has('span.name')).toBe(true);
|
|
220
|
+
expect(surfaces.has('span.name'), req('openwop.it.otel-collector-canary-inspection.catches-a-canary-in-a-resource-attribute-and-in-a-span-name', 'KNOWN-LIMITS.md', 'catches a canary in a resource attribute and in a span name')).toBe(true);
|
|
220
221
|
expect(surfaces.has('span.resourceAttribute')).toBe(true);
|
|
221
222
|
});
|
|
222
223
|
|
|
@@ -227,7 +228,7 @@ describe('otel-collector-canary-inspection: collector inspects real OTLP exports
|
|
|
227
228
|
|
|
228
229
|
const leaks = collector.findCanaryLeakage(CANARY);
|
|
229
230
|
const metricLeak = leaks.find((l) => l.surface === 'metric.attribute');
|
|
230
|
-
expect(metricLeak).toBeDefined();
|
|
231
|
+
expect(metricLeak, req('openwop.it.otel-collector-canary-inspection.catches-a-canary-in-a-metric-data-point-attribute', 'KNOWN-LIMITS.md', 'catches a canary in a metric data-point attribute')).toBeDefined();
|
|
231
232
|
expect(metricLeak!.emitterName).toBe('openwop.node.duration');
|
|
232
233
|
});
|
|
233
234
|
|
|
@@ -240,7 +241,7 @@ describe('otel-collector-canary-inspection: collector inspects real OTLP exports
|
|
|
240
241
|
|
|
241
242
|
const leaks = collector.findCanaryLeakage(CANARY);
|
|
242
243
|
const resourceLeaks = leaks.filter((l) => l.surface === 'span.resourceAttribute' && l.key === 'deployment.token');
|
|
243
|
-
expect(resourceLeaks.length).toBe(1);
|
|
244
|
+
expect(resourceLeaks.length, req('openwop.it.otel-collector-canary-inspection.dedups-a-resource-attribute-leak-to-one-hit-even-when-shared-across-many-spans', 'KNOWN-LIMITS.md', 'dedups a resource-attribute leak to ONE hit even when shared across many spans')).toBe(1);
|
|
244
245
|
});
|
|
245
246
|
|
|
246
247
|
it('reports ZERO hits when the host redacts the canary before export (positive control)', async () => {
|
|
@@ -255,7 +256,7 @@ describe('otel-collector-canary-inspection: collector inspects real OTLP exports
|
|
|
255
256
|
);
|
|
256
257
|
await postMetrics(metricsPayload('openwop.node.duration', { 'secret.echo': REDACTED }));
|
|
257
258
|
|
|
258
|
-
expect(collector.findCanaryLeakage(CANARY)).toEqual([]);
|
|
259
|
+
expect(collector.findCanaryLeakage(CANARY), req('openwop.it.otel-collector-canary-inspection.reports-zero-hits-when-the-host-redacts-the-canary-before-export-positive-contro', 'KNOWN-LIMITS.md', 'reports ZERO hits when the host redacts the canary before export (positive control)')).toEqual([]);
|
|
259
260
|
});
|
|
260
261
|
|
|
261
262
|
it('an empty or whitespace canary never produces a (vacuous) hit', async () => {
|
|
@@ -269,7 +270,7 @@ describe('otel-collector-canary-inspection: collector inspects real OTLP exports
|
|
|
269
270
|
}),
|
|
270
271
|
);
|
|
271
272
|
|
|
272
|
-
expect(collector.findCanaryLeakage('')).toEqual([]);
|
|
273
|
+
expect(collector.findCanaryLeakage(''), req('openwop.it.otel-collector-canary-inspection.an-empty-or-whitespace-canary-never-produces-a-vacuous-hit', 'KNOWN-LIMITS.md', 'an empty or whitespace canary never produces a (vacuous) hit')).toEqual([]);
|
|
273
274
|
expect(collector.findCanaryLeakage(' ')).toEqual([]);
|
|
274
275
|
});
|
|
275
276
|
});
|
|
@@ -32,6 +32,7 @@ import { discoveryFamilies } from '../lib/discovery-capabilities.js';
|
|
|
32
32
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
33
33
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
34
34
|
import { getCollector, waitForRunSpans } from '../lib/otel-collector.js';
|
|
35
|
+
import { req } from '../lib/requirement-ids.js';
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* Callback-shaped: the host exports OTLP/gRPC spans to the suite's collector.
|
|
@@ -90,13 +91,13 @@ describe('otel-emission-grpc: OTLP/gRPC export path', () => {
|
|
|
90
91
|
// at least one openwop.run span correlated by runId.
|
|
91
92
|
const runSpans = await waitForRunSpans(runId, { timeoutMs: 5_000, minCount: 1 });
|
|
92
93
|
|
|
93
|
-
expect(runSpans.length,
|
|
94
|
+
expect(runSpans.length, req('openwop.it.otel-emission-grpc.host-emits-openwop-run-spans-over-otlp-grpc-collector-captures-them-via-the-shar',
|
|
94
95
|
'observability.md §"Export protocols" + RFC 0008/0009 Track 11',
|
|
95
96
|
'host advertising exportProtocols ∋ "grpc" MUST emit openwop.* spans over OTLP/gRPC',
|
|
96
97
|
)).toBeGreaterThan(0);
|
|
97
98
|
|
|
98
99
|
const runSpan = runSpans.find((s) => s.name === 'openwop.run');
|
|
99
|
-
expect(runSpan?.attributes.get('openwop.run_id'),
|
|
100
|
+
expect(runSpan?.attributes.get('openwop.run_id'), req('openwop.it.otel-emission-grpc.host-emits-openwop-run-spans-over-otlp-grpc-collector-captures-them-via-the-shar',
|
|
100
101
|
'observability.md §"Run-level attributes"',
|
|
101
102
|
'openwop.run span MUST carry openwop.run_id attribute',
|
|
102
103
|
)).toBe(runId);
|
|
@@ -30,6 +30,7 @@ import { discoveryFamilies } from '../lib/discovery-capabilities.js';
|
|
|
30
30
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
31
31
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
32
32
|
import { getCollector, waitForRunSpans } from '../lib/otel-collector.js';
|
|
33
|
+
import { req } from '../lib/requirement-ids.js';
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
36
|
* Callback-shaped: the host exports OTLP/HTTP spans to the suite's collector.
|
|
@@ -80,7 +81,7 @@ describe('otel-emission: required run-level + node-level attributes', () => {
|
|
|
80
81
|
|
|
81
82
|
const runSpans = await waitForRunSpans(runId, { timeoutMs: 5_000, minCount: 2 });
|
|
82
83
|
|
|
83
|
-
expect(runSpans.length,
|
|
84
|
+
expect(runSpans.length, req('openwop.it.otel-emission.host-emits-openwop-run-openwop-node-spans-with-required-attributes',
|
|
84
85
|
'observability.md §"Span attributes"',
|
|
85
86
|
'host MUST emit at least one openwop.* span carrying openwop.run_id',
|
|
86
87
|
)).toBeGreaterThan(0);
|
|
@@ -90,21 +91,21 @@ describe('otel-emission: required run-level + node-level attributes', () => {
|
|
|
90
91
|
const anySpanHasWorkflowId = runSpans.some(
|
|
91
92
|
(s) => s.attributes.get('openwop.workflow_id') === FIXTURE,
|
|
92
93
|
);
|
|
93
|
-
expect(anySpanHasWorkflowId,
|
|
94
|
+
expect(anySpanHasWorkflowId, req('openwop.it.otel-emission.host-emits-openwop-run-openwop-node-spans-with-required-attributes',
|
|
94
95
|
'observability.md §"Run-level attributes"',
|
|
95
96
|
'spans MUST carry openwop.workflow_id matching the run\'s workflow',
|
|
96
97
|
)).toBe(true);
|
|
97
98
|
|
|
98
99
|
// Find an openwop.run span (lifecycle span; named per §"Span naming").
|
|
99
100
|
const runSpan = runSpans.find((s) => s.name === 'openwop.run' || s.name.startsWith('openwop.run.'));
|
|
100
|
-
expect(runSpan,
|
|
101
|
+
expect(runSpan, req('openwop.it.otel-emission.host-emits-openwop-run-openwop-node-spans-with-required-attributes',
|
|
101
102
|
'observability.md §"Span naming"',
|
|
102
103
|
'host MUST emit a span named openwop.run (or openwop.run.<phase>) per run',
|
|
103
104
|
)).toBeDefined();
|
|
104
105
|
|
|
105
106
|
// Find an openwop.node.<typeId> span; conformance-noop has one node.
|
|
106
107
|
const nodeSpan = runSpans.find((s) => s.name.startsWith('openwop.node.'));
|
|
107
|
-
expect(nodeSpan,
|
|
108
|
+
expect(nodeSpan, req('openwop.it.otel-emission.host-emits-openwop-run-openwop-node-spans-with-required-attributes',
|
|
108
109
|
'observability.md §"Span naming"',
|
|
109
110
|
'host MUST emit a span named openwop.node.<typeId> per node execution',
|
|
110
111
|
)).toBeDefined();
|
|
@@ -114,7 +115,7 @@ describe('otel-emission: required run-level + node-level attributes', () => {
|
|
|
114
115
|
expect(typeof nodeSpan.attributes.get('openwop.node_id')).toBe('string');
|
|
115
116
|
expect(typeof nodeSpan.attributes.get('openwop.node_type')).toBe('string');
|
|
116
117
|
const attempt = nodeSpan.attributes.get('openwop.node_attempt');
|
|
117
|
-
expect(typeof attempt === 'number' && attempt >= 0,
|
|
118
|
+
expect(typeof attempt === 'number' && attempt >= 0, req('openwop.it.otel-emission.host-emits-openwop-run-openwop-node-spans-with-required-attributes',
|
|
118
119
|
'observability.md §"Node-level attributes"',
|
|
119
120
|
'openwop.node_attempt MUST be a non-negative number',
|
|
120
121
|
)).toBe(true);
|
|
@@ -41,6 +41,7 @@ import { pollUntilTerminal } from '../lib/polling.js';
|
|
|
41
41
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
42
42
|
import { isScenarioOptedOut } from '../lib/env.js';
|
|
43
43
|
import { getCollector, waitForRunSpans } from '../lib/otel-collector.js';
|
|
44
|
+
import { req } from '../lib/requirement-ids.js';
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
47
|
* Callback-shaped: the host exports OTLP spans to the suite's collector.
|
|
@@ -133,13 +134,13 @@ describe('otel-trace-propagation-subworkflow: traceparent threads parent → chi
|
|
|
133
134
|
const subwfCompleted = events.find(
|
|
134
135
|
(e) => e.type === 'node.completed' && e.nodeId === 'subwf-call',
|
|
135
136
|
);
|
|
136
|
-
expect(subwfCompleted,
|
|
137
|
+
expect(subwfCompleted, req('openwop.it.otel-trace-propagation-subworkflow.child-run-spans-inherit-the-parent-run-s-inbound-traceid',
|
|
137
138
|
'node-packs.md §core.subWorkflow',
|
|
138
139
|
'parent event log MUST include node.completed for the subwf-call node',
|
|
139
140
|
)).toBeDefined();
|
|
140
141
|
|
|
141
142
|
const childRunId = subwfCompleted?.payload?.outputs?.childRunId;
|
|
142
|
-
expect(typeof childRunId,
|
|
143
|
+
expect(typeof childRunId, req('openwop.it.otel-trace-propagation-subworkflow.child-run-spans-inherit-the-parent-run-s-inbound-traceid',
|
|
143
144
|
'node-packs.md §core.subWorkflow outputSchema',
|
|
144
145
|
'subwf-call node.completed payload MUST carry outputs.childRunId',
|
|
145
146
|
)).toBe('string');
|
|
@@ -148,19 +149,19 @@ describe('otel-trace-propagation-subworkflow: traceparent threads parent → chi
|
|
|
148
149
|
const parentSpans = await waitForRunSpans(parentRunId, { timeoutMs: 10_000, minCount: 1 });
|
|
149
150
|
const childSpans = await waitForRunSpans(childRunId!, { timeoutMs: 10_000, minCount: 1 });
|
|
150
151
|
|
|
151
|
-
expect(parentSpans.length, 'collector MUST receive ≥1 span for the parent run').toBeGreaterThan(0);
|
|
152
|
-
expect(childSpans.length, 'collector MUST receive ≥1 span for the child run').toBeGreaterThan(0);
|
|
152
|
+
expect(parentSpans.length, req('openwop.it.otel-trace-propagation-subworkflow.child-run-spans-inherit-the-parent-run-s-inbound-traceid', 'node-packs.md §core.subWorkflow outputSchema', 'collector MUST receive ≥1 span for the parent run')).toBeGreaterThan(0);
|
|
153
|
+
expect(childSpans.length, req('openwop.it.otel-trace-propagation-subworkflow.child-run-spans-inherit-the-parent-run-s-inbound-traceid', 'node-packs.md §core.subWorkflow outputSchema', 'collector MUST receive ≥1 span for the child run')).toBeGreaterThan(0);
|
|
153
154
|
|
|
154
155
|
const wantTrace = traceId.toLowerCase();
|
|
155
156
|
|
|
156
157
|
const parentMatching = parentSpans.filter((s) => s.traceId.toLowerCase() === wantTrace);
|
|
157
|
-
expect(parentMatching.length,
|
|
158
|
+
expect(parentMatching.length, req('openwop.it.otel-trace-propagation-subworkflow.child-run-spans-inherit-the-parent-run-s-inbound-traceid',
|
|
158
159
|
'observability.md §"Trace context propagation"',
|
|
159
160
|
'parent-run spans MUST share the inbound traceparent traceId',
|
|
160
161
|
)).toBeGreaterThan(0);
|
|
161
162
|
|
|
162
163
|
const childMatching = childSpans.filter((s) => s.traceId.toLowerCase() === wantTrace);
|
|
163
|
-
expect(childMatching.length,
|
|
164
|
+
expect(childMatching.length, req('openwop.it.otel-trace-propagation-subworkflow.child-run-spans-inherit-the-parent-run-s-inbound-traceid',
|
|
164
165
|
'observability.md §"Trace context propagation" + node-packs.md §core.subWorkflow',
|
|
165
166
|
'child-run spans dispatched via core.subWorkflow MUST inherit the parent run\'s traceId so distributed traces stitch across the dispatch boundary',
|
|
166
167
|
)).toBeGreaterThan(0);
|
|
@@ -24,6 +24,7 @@ import { discoveryFamilies } from '../lib/discovery-capabilities.js';
|
|
|
24
24
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
25
25
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
26
26
|
import { getCollector, waitForRunSpans } from '../lib/otel-collector.js';
|
|
27
|
+
import { req } from '../lib/requirement-ids.js';
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Callback-shaped: the host exports OTLP spans to the suite's collector.
|
|
@@ -92,7 +93,7 @@ describe('otel-trace-propagation: inbound traceparent threads to emitted spans',
|
|
|
92
93
|
const wantTrace = traceId.toLowerCase();
|
|
93
94
|
const matching = runSpans.filter((s) => s.traceId.toLowerCase() === wantTrace);
|
|
94
95
|
|
|
95
|
-
expect(matching.length,
|
|
96
|
+
expect(matching.length, req('openwop.it.otel-trace-propagation.host-emitted-spans-share-the-caller-supplied-traceid',
|
|
96
97
|
'observability.md §"Trace context propagation"',
|
|
97
98
|
'spans emitted during a run started with an inbound traceparent MUST share its traceId',
|
|
98
99
|
)).toBeGreaterThan(0);
|