@openwop/openwop-conformance 1.162.0 → 2.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/dist/cli.js +54 -1
- package/dist/lib/paths.js +25 -3
- package/dist/lib/requirement-ids.js +34 -4
- package/dist/lib/scenario-disposition.js +1 -0
- package/dist/lib/spec-coherence.js +13 -32
- package/dist/spec-artifacts.lock.json +5 -0
- package/package.json +11 -33
- package/requirements.json +20303 -11809
- package/scenario-majors.json +1343 -0
- package/schemas/CORPUS-STAMP.json +138 -6
- package/src/cli.ts +47 -1
- package/src/global-setup.ts +3 -2
- package/src/lib/corpus-stamp.ts +29 -1
- package/src/lib/paths.ts +25 -3
- package/src/lib/requirement-ids.ts +33 -4
- package/src/lib/scenario-disposition.ts +1 -0
- package/src/lib/spec-coherence.ts +15 -32
- package/src/scenarios/a2a-1-0-agent-card.test.ts +17 -16
- package/src/scenarios/a2a-1-0-task-roundtrip.test.ts +11 -10
- package/src/scenarios/a2a-card-runtime-consistency.test.ts +18 -17
- package/src/scenarios/a2a-peer-authority.test.ts +7 -6
- package/src/scenarios/a2a-task-roundtrip.test.ts +30 -29
- package/src/scenarios/a2a-version-negotiation.test.ts +16 -14
- package/src/scenarios/a2ui-surface-degrades.test.ts +5 -3
- package/src/scenarios/a2ui-surface-delta-transport.test.ts +35 -33
- package/src/scenarios/a2ui-surface-replay.test.ts +6 -4
- package/src/scenarios/a2ui-surface-shape.test.ts +11 -10
- package/src/scenarios/a2ui-surface-version-refusal.test.ts +6 -4
- package/src/scenarios/a2ui-untrusted-blocks-approval.test.ts +5 -3
- package/src/scenarios/agent-capability-degraded-projection.test.ts +12 -11
- package/src/scenarios/agent-channel-dispatch.test.ts +18 -16
- package/src/scenarios/agent-deployment-lifecycle.test.ts +20 -19
- package/src/scenarios/agent-deployment-shape.test.ts +22 -24
- package/src/scenarios/agent-eval-run.test.ts +19 -18
- package/src/scenarios/agent-eval-suite-shape.test.ts +20 -22
- package/src/scenarios/agent-live-allowlist-enforced.test.ts +6 -5
- package/src/scenarios/agent-live-invocation-bracket.test.ts +13 -12
- package/src/scenarios/agent-live-runtime-shape.test.ts +10 -12
- package/src/scenarios/agent-live-structured-output.test.ts +7 -6
- package/src/scenarios/agent-loop-iteration-monotonic.test.ts +3 -3
- package/src/scenarios/agent-loop-stateful-resume.test.ts +2 -2
- package/src/scenarios/agent-loop-version5-shape.test.ts +4 -4
- package/src/scenarios/agent-loop-workspace-snapshot.test.ts +3 -3
- package/src/scenarios/agent-manifest-role-profile.test.ts +9 -9
- package/src/scenarios/agent-manifest-runtime.test.ts +13 -12
- package/src/scenarios/agent-org-chart-scoping.test.ts +14 -13
- package/src/scenarios/agent-org-chart-shape.test.ts +11 -13
- package/src/scenarios/agent-platform-aggregate-evidence.test.ts +5 -4
- package/src/scenarios/agent-platform-profile.test.ts +18 -19
- package/src/scenarios/agent-requires-capabilities-shape.test.ts +4 -4
- package/src/scenarios/agent-roster-attribution.test.ts +18 -17
- package/src/scenarios/agent-roster-shape.test.ts +17 -19
- package/src/scenarios/agent-verifier-shape.test.ts +11 -11
- package/src/scenarios/agentConfidenceEscalation.test.ts +2 -1
- package/src/scenarios/agentMemoryCrossTenantIsolation.test.ts +6 -5
- package/src/scenarios/agentMemoryRedactionContract.test.ts +2 -1
- package/src/scenarios/agentMemoryRoundTrip.test.ts +2 -1
- package/src/scenarios/agentMemoryTtlExpiry.test.ts +4 -3
- package/src/scenarios/agentMessageReducer.test.ts +2 -1
- package/src/scenarios/agentMetadata.test.ts +2 -1
- package/src/scenarios/agentPackCatalog.test.ts +23 -21
- package/src/scenarios/agentPackExport.test.ts +4 -2
- package/src/scenarios/agentPackHandoffSchemaValidation.test.ts +5 -4
- package/src/scenarios/agentPackInstall.test.ts +4 -2
- package/src/scenarios/agentPackProvenance.test.ts +2 -1
- package/src/scenarios/agentReasoningEvents.test.ts +3 -2
- package/src/scenarios/agentReasoningStreaming.test.ts +11 -10
- package/src/scenarios/agents-run-tool-allowlist.test.ts +14 -12
- package/src/scenarios/ai-envelope-shape.test.ts +31 -29
- package/src/scenarios/aiEnvelope.capBreached.test.ts +26 -24
- package/src/scenarios/aiEnvelope.contractRefusal.test.ts +36 -34
- package/src/scenarios/aiEnvelope.correlationReplay.test.ts +17 -15
- package/src/scenarios/aiEnvelope.redaction.test.ts +22 -20
- package/src/scenarios/aiEnvelope.schemaDrift.test.ts +18 -16
- package/src/scenarios/aiEnvelope.trustBoundaryPropagation.test.ts +38 -36
- package/src/scenarios/aiEnvelope.universalKinds.test.ts +31 -29
- package/src/scenarios/aiproviders-input-shape.test.ts +5 -5
- package/src/scenarios/aiproviders-realtimevoice-shape.test.ts +14 -16
- package/src/scenarios/aiproviders-selfhosted-honesty.test.ts +6 -4
- package/src/scenarios/aiproviders-selfhosted-shape.test.ts +15 -17
- package/src/scenarios/aiproviders-speechsynth-shape.test.ts +6 -8
- package/src/scenarios/aiproviders-subscription-scope.test.ts +7 -8
- package/src/scenarios/anonymous-actor-audit-opaque.test.ts +9 -8
- package/src/scenarios/anonymous-actor-default-deny.test.ts +10 -9
- package/src/scenarios/anonymous-actor-egress-guarded.test.ts +6 -5
- package/src/scenarios/anonymous-actor-no-secret-reach.test.ts +7 -6
- package/src/scenarios/anonymous-actor-shape.test.ts +17 -19
- package/src/scenarios/anonymous-actor-write-gated.test.ts +9 -8
- package/src/scenarios/append-ordering.test.ts +7 -5
- package/src/scenarios/approval-gate-events.test.ts +4 -3
- package/src/scenarios/approval-gate-flow.test.ts +4 -3
- package/src/scenarios/approval-payload.test.ts +5 -4
- package/src/scenarios/artifact-auth.test.ts +7 -6
- package/src/scenarios/artifact-type-pack-install.test.ts +6 -6
- package/src/scenarios/artifact-type-pack-manifest-validation.test.ts +9 -8
- package/src/scenarios/artifact-type-registration-source.test.ts +20 -20
- package/src/scenarios/artifact-type-store-emission.test.ts +15 -18
- package/src/scenarios/artifact-type-store-without-render.test.ts +4 -4
- package/src/scenarios/audit-log-integrity.test.ts +8 -6
- package/src/scenarios/auth-api-key-rotation.test.ts +11 -9
- package/src/scenarios/auth-mtls.test.ts +22 -20
- package/src/scenarios/auth-oauth2-client-credentials.test.ts +16 -14
- package/src/scenarios/auth-oidc-user-bearer.test.ts +26 -24
- package/src/scenarios/auth-saml-profile.test.ts +14 -12
- package/src/scenarios/auth-scim-profile.test.ts +3 -2
- package/src/scenarios/auth-subject-link-key-class.test.ts +8 -7
- package/src/scenarios/auth-subject-link.test.ts +11 -10
- package/src/scenarios/auth.test.ts +5 -4
- package/src/scenarios/authorization-fail-closed.test.ts +3 -2
- package/src/scenarios/authorization-roles-shape.test.ts +9 -7
- package/src/scenarios/blob-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/blob-presign-expiry.test.ts +12 -10
- package/src/scenarios/blob-roundtrip.test.ts +0 -0
- package/src/scenarios/budget-enforcement.test.ts +15 -14
- package/src/scenarios/budget-policy-shape.test.ts +18 -19
- package/src/scenarios/bulk-cancel.test.ts +9 -8
- package/src/scenarios/byok-auth-modes.test.ts +13 -14
- package/src/scenarios/byok-roundtrip.test.ts +12 -10
- package/src/scenarios/cache-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/cache-ttl-expiry.test.ts +7 -5
- package/src/scenarios/callai-multimodal.test.ts +5 -3
- package/src/scenarios/cancellation.test.ts +6 -5
- package/src/scenarios/cap-breach.test.ts +15 -14
- package/src/scenarios/capability-arm-witness.test.ts +5 -3
- package/src/scenarios/certification-bundle-non-vacuous.test.ts +20 -19
- package/src/scenarios/certification-bundle-redaction.test.ts +11 -10
- package/src/scenarios/certification-bundle-v2.test.ts +11 -10
- package/src/scenarios/chain-compensation-expansion.test.ts +14 -13
- package/src/scenarios/chain-produced-var-roundtrip.test.ts +13 -14
- package/src/scenarios/chain-subchain-cycle-rejected.test.ts +9 -10
- package/src/scenarios/chain-subchain-fanout.test.ts +8 -9
- package/src/scenarios/chain-subchain-sibling.test.ts +14 -16
- package/src/scenarios/channel-presence-behavioral.test.ts +9 -7
- package/src/scenarios/channel-presence-shape.test.ts +11 -12
- package/src/scenarios/channel-ttl.test.ts +6 -5
- package/src/scenarios/chat-card-pack-execution.test.ts +4 -4
- package/src/scenarios/chat-card-pack-manifest-validation.test.ts +9 -8
- package/src/scenarios/commitment-fired.test.ts +6 -5
- package/src/scenarios/compensation-behavior.test.ts +24 -23
- package/src/scenarios/compensation-recovery.test.ts +28 -27
- package/src/scenarios/configurable-schema.test.ts +8 -6
- package/src/scenarios/conformance-advertised-seam-required.test.ts +6 -5
- package/src/scenarios/conformance-execution-witness.test.ts +9 -8
- package/src/scenarios/connection-pack-apihosts.test.ts +19 -17
- package/src/scenarios/connection-pack-manifest-valid.test.ts +12 -11
- package/src/scenarios/connection-pack-no-credential-material.test.ts +8 -6
- package/src/scenarios/connection-pack-reach-exclusive.test.ts +5 -4
- package/src/scenarios/connection-pack-write-reconsent.test.ts +6 -4
- package/src/scenarios/connection-provider-resolution.test.ts +18 -16
- package/src/scenarios/connector-manifest-validity.test.ts +8 -7
- package/src/scenarios/context-budget-transcript-bound.test.ts +17 -15
- package/src/scenarios/context-summarization-replay.test.ts +14 -12
- package/src/scenarios/contract-provenance.test.ts +18 -18
- package/src/scenarios/conversation-turn-model-provenance-shape.test.ts +14 -15
- package/src/scenarios/conversationCapabilityNegotiation.test.ts +2 -1
- package/src/scenarios/conversationLifecycle.test.ts +2 -1
- package/src/scenarios/conversationReplayDeterminism.test.ts +4 -2
- package/src/scenarios/conversationVsLegacySuspend.test.ts +2 -1
- package/src/scenarios/core-standard-profile.test.ts +8 -9
- package/src/scenarios/cost-attribution.test.ts +23 -21
- package/src/scenarios/credential-payload-redaction.test.ts +4 -3
- package/src/scenarios/credentials-capability-shape.test.ts +5 -4
- package/src/scenarios/cross-engine-append-behavior.test.ts +11 -10
- package/src/scenarios/cross-engine-append-ordering.test.ts +4 -3
- package/src/scenarios/cross-host-ancestry-endpoint.test.ts +11 -10
- package/src/scenarios/cross-host-causation-shape.test.ts +7 -6
- package/src/scenarios/cross-workspace-isolation.test.ts +4 -3
- package/src/scenarios/data-residency-admission.test.ts +15 -14
- package/src/scenarios/deadletter-capability-shape.test.ts +6 -4
- package/src/scenarios/deadletter-retry-exhaustion.test.ts +4 -3
- package/src/scenarios/debug-bundle-truncation.test.ts +9 -7
- package/src/scenarios/debugBundle.test.ts +25 -23
- package/src/scenarios/discovery-families-view.test.ts +5 -4
- package/src/scenarios/discovery.test.ts +30 -29
- package/src/scenarios/dispatch-cross-worker-handoff.test.ts +10 -8
- package/src/scenarios/dispatch-fanout-parallel.test.ts +24 -22
- package/src/scenarios/dispatch-input-mapping.test.ts +12 -10
- package/src/scenarios/dispatch-output-mapping.test.ts +9 -7
- package/src/scenarios/dispatch-per-item-input.test.ts +22 -20
- package/src/scenarios/dispatchLoop.test.ts +3 -2
- package/src/scenarios/distillation-index-roundtrip.test.ts +3 -3
- package/src/scenarios/distillation-secret-carryforward.test.ts +2 -2
- package/src/scenarios/distillation-shape.test.ts +4 -4
- package/src/scenarios/distillation-stable-archive.test.ts +6 -6
- package/src/scenarios/distillation-token-budget.test.ts +5 -5
- package/src/scenarios/durability-poison-exhaustion.test.ts +7 -6
- package/src/scenarios/egress-audience-binding.test.ts +11 -10
- package/src/scenarios/egress-decision-content-free.test.ts +6 -5
- package/src/scenarios/egress-provenance-shape.test.ts +17 -18
- package/src/scenarios/envelope-completion-distinguishes-truncation.test.ts +27 -25
- package/src/scenarios/envelope-nl-to-format-engaged.test.ts +19 -17
- package/src/scenarios/envelope-reasoning-secret-redaction.test.ts +28 -26
- package/src/scenarios/envelope-reasoning-shape.test.ts +19 -17
- package/src/scenarios/envelope-recovery-applied.test.ts +24 -22
- package/src/scenarios/envelope-refusal-shape.test.ts +31 -29
- package/src/scenarios/envelope-rendering-hint.test.ts +5 -4
- package/src/scenarios/envelope-retry-attempted.test.ts +33 -31
- package/src/scenarios/envelope-retry-exhausted.test.ts +22 -20
- package/src/scenarios/envelope-tier-one-subset-static.test.ts +9 -7
- package/src/scenarios/envelope-truncated.test.ts +19 -17
- package/src/scenarios/envelope-truncation-cap-exhaustion.test.ts +19 -17
- package/src/scenarios/envelope-variant-discriminator-static.test.ts +4 -3
- package/src/scenarios/errors.test.ts +20 -19
- package/src/scenarios/eventOrdering.test.ts +16 -14
- package/src/scenarios/exec-not-protocol-tier.test.ts +5 -7
- package/src/scenarios/experimental-tier-shape.test.ts +17 -15
- package/src/scenarios/export-bundle-portability.test.ts +17 -17
- package/src/scenarios/failure-path.test.ts +7 -6
- package/src/scenarios/feedback-capability-shape.test.ts +4 -3
- package/src/scenarios/feedback-correction-redaction.test.ts +2 -1
- package/src/scenarios/feedback-cross-tenant-isolation.test.ts +2 -1
- package/src/scenarios/feedback-fork-not-copied.test.ts +3 -2
- package/src/scenarios/feedback-on-terminal-run.test.ts +3 -2
- package/src/scenarios/feedback-record-and-list.test.ts +2 -1
- package/src/scenarios/feedback-unsupported-501.test.ts +2 -1
- package/src/scenarios/fixtures-gating.test.ts +29 -28
- package/src/scenarios/fixtures-valid.test.ts +16 -15
- package/src/scenarios/form-content-instantiation.test.ts +15 -14
- package/src/scenarios/frontend-plugin-packs.test.ts +29 -27
- package/src/scenarios/fs-path-traversal.test.ts +14 -12
- package/src/scenarios/goal-standing-continuation.test.ts +21 -21
- package/src/scenarios/grpc-transport.test.ts +9 -7
- package/src/scenarios/heartbeat-capability-shape.test.ts +3 -3
- package/src/scenarios/heartbeat-fires-once-per-tick.test.ts +2 -2
- package/src/scenarios/heartbeat-idempotent-no-spam.test.ts +3 -3
- package/src/scenarios/heartbeat-runtime-bound.test.ts +2 -2
- package/src/scenarios/highConcurrency.test.ts +14 -13
- package/src/scenarios/host-callback-declaration.test.ts +8 -7
- package/src/scenarios/http-client-ssrf.test.ts +7 -5
- package/src/scenarios/i18n-negotiation.test.ts +14 -12
- package/src/scenarios/idempotency-concurrent-claim.test.ts +14 -13
- package/src/scenarios/idempotency-key-determinism.test.ts +20 -18
- package/src/scenarios/idempotency.test.ts +8 -7
- package/src/scenarios/idempotencyRetry.test.ts +13 -11
- package/src/scenarios/identity-owner-shape.test.ts +6 -5
- package/src/scenarios/identity-passthrough.test.ts +4 -3
- package/src/scenarios/interrupt-approval.test.ts +6 -5
- package/src/scenarios/interrupt-approver-routing.test.ts +15 -15
- package/src/scenarios/interrupt-auth-required-resume.test.ts +5 -3
- package/src/scenarios/interrupt-clarification.test.ts +4 -3
- package/src/scenarios/interrupt-external-event-correlation.test.ts +6 -5
- package/src/scenarios/interrupt-parent-child-cascade.test.ts +4 -3
- package/src/scenarios/interrupt-quorum-resolution.test.ts +5 -4
- package/src/scenarios/interrupt-token-matrix.test.ts +8 -6
- package/src/scenarios/interruptRace.test.ts +12 -10
- package/src/scenarios/kv-atomic-increment.test.ts +11 -9
- package/src/scenarios/kv-cas.test.ts +14 -12
- package/src/scenarios/kv-cross-tenant-isolation.test.ts +12 -10
- package/src/scenarios/kv-ttl-expiry.test.ts +7 -5
- package/src/scenarios/localized-content-delivery.test.ts +24 -26
- package/src/scenarios/maliciousManifest.test.ts +10 -8
- package/src/scenarios/mcp-2026-07-28-discover.test.ts +15 -14
- package/src/scenarios/mcp-cache-tenant-scope.test.ts +6 -5
- package/src/scenarios/mcp-current-auth-boundary.test.ts +7 -6
- package/src/scenarios/mcp-discoverability.test.ts +9 -7
- package/src/scenarios/mcp-extension-opacity.test.ts +7 -6
- package/src/scenarios/mcp-mrtr-roundtrip.test.ts +18 -17
- package/src/scenarios/mcp-server-elicitation-bridge.test.ts +13 -12
- package/src/scenarios/mcp-server-prompt-roundtrip.test.ts +11 -10
- package/src/scenarios/mcp-server-resource-roundtrip.test.ts +11 -10
- package/src/scenarios/mcp-server-sampling-bridge.test.ts +12 -11
- package/src/scenarios/mcp-server-tool-roundtrip.test.ts +14 -13
- package/src/scenarios/mcp-server-untrusted-args.test.ts +14 -13
- package/src/scenarios/mcp-stateless-request.test.ts +11 -10
- package/src/scenarios/mcp-tool-roundtrip.test.ts +4 -3
- package/src/scenarios/mcp-toolcall-redaction.test.ts +4 -3
- package/src/scenarios/mcp-version-negotiation.test.ts +15 -14
- package/src/scenarios/media-url-inline-cap.test.ts +21 -19
- package/src/scenarios/memory-attribution-emits-on-write.test.ts +5 -5
- package/src/scenarios/memory-attribution-no-content.test.ts +4 -4
- package/src/scenarios/memory-attribution-replay-stable.test.ts +4 -3
- package/src/scenarios/memory-attribution-shape.test.ts +4 -3
- package/src/scenarios/memory-attribution-tenant-scoped.test.ts +3 -3
- package/src/scenarios/memory-capability-model-shape.test.ts +14 -15
- package/src/scenarios/memory-compaction-event-emitted.test.ts +7 -6
- package/src/scenarios/memory-compaction-provenance-tag.test.ts +3 -2
- package/src/scenarios/memory-compaction-sr1-carry-forward.test.ts +7 -6
- package/src/scenarios/memory-consolidation-idempotent.test.ts +5 -4
- package/src/scenarios/memory-consolidation-shape.test.ts +9 -11
- package/src/scenarios/memory-degraded-projection.test.ts +10 -9
- package/src/scenarios/memory-injection-budget.test.ts +15 -14
- package/src/scenarios/metric-emission.test.ts +4 -3
- package/src/scenarios/model-capability-insufficient.test.ts +19 -17
- package/src/scenarios/model-capability-substituted.test.ts +20 -18
- package/src/scenarios/multi-agent-confidence-escalation.test.ts +12 -11
- package/src/scenarios/multi-agent-handoff-state-machine.test.ts +10 -9
- package/src/scenarios/multi-agent-memory-lifecycle.test.ts +11 -10
- package/src/scenarios/multi-node-ordering.test.ts +4 -3
- package/src/scenarios/multi-party-conversation-behavioral.test.ts +6 -6
- package/src/scenarios/multi-party-conversation-shape.test.ts +21 -23
- package/src/scenarios/multi-region-idempotency-behavior.test.ts +16 -15
- package/src/scenarios/multi-region-idempotency.test.ts +6 -5
- package/src/scenarios/node-failed-payload-shape.test.ts +5 -4
- package/src/scenarios/node-module-required-capabilities-shape.test.ts +10 -8
- package/src/scenarios/oauth-authorization-code-roundtrip.test.ts +5 -4
- package/src/scenarios/oauth-capability-shape.test.ts +5 -4
- package/src/scenarios/oauth-connector-redaction.test.ts +4 -3
- package/src/scenarios/openapi-resolved-paths.test.ts +6 -5
- package/src/scenarios/orchestratorConservativePath.test.ts +2 -1
- package/src/scenarios/orchestratorDispatch.test.ts +2 -1
- package/src/scenarios/orchestratorTermination.test.ts +2 -1
- package/src/scenarios/org-position-no-authority-escalation.test.ts +2 -2
- package/src/scenarios/otel-collector-canary-inspection.test.ts +8 -7
- package/src/scenarios/otel-emission-grpc.test.ts +3 -2
- package/src/scenarios/otel-emission.test.ts +6 -5
- package/src/scenarios/otel-trace-propagation-subworkflow.test.ts +7 -6
- package/src/scenarios/otel-trace-propagation.test.ts +2 -1
- package/src/scenarios/owner-subject-echo.test.ts +13 -12
- package/src/scenarios/owner-subject-shape.test.ts +11 -10
- package/src/scenarios/pack-manifest-extension-opacity.test.ts +8 -8
- package/src/scenarios/pack-registry-isolation.test.ts +4 -3
- package/src/scenarios/pack-registry-publish.test.ts +65 -63
- package/src/scenarios/pack-registry.test.ts +38 -36
- package/src/scenarios/pause-resume.test.ts +18 -16
- package/src/scenarios/policies.test.ts +20 -18
- package/src/scenarios/production-backpressure.test.ts +18 -16
- package/src/scenarios/production-retention-expiry.test.ts +8 -6
- package/src/scenarios/profile-discovery-core-alias.test.ts +13 -11
- package/src/scenarios/profileDerivation.test.ts +34 -33
- package/src/scenarios/prompt-all-four-kinds-events.test.ts +11 -9
- package/src/scenarios/prompt-composed-secret-redaction.test.ts +11 -9
- package/src/scenarios/prompt-composed-trust-marker.test.ts +10 -8
- package/src/scenarios/prompt-end-to-end-events.test.ts +17 -15
- package/src/scenarios/prompt-list-and-fetch.test.ts +16 -14
- package/src/scenarios/prompt-mutable-lifecycle.test.ts +13 -11
- package/src/scenarios/prompt-mutation-workspace-membership-enforced.test.ts +6 -4
- package/src/scenarios/prompt-pack-install.test.ts +14 -12
- package/src/scenarios/prompt-prefix-cache.test.ts +19 -17
- package/src/scenarios/prompt-read-workspace-membership-enforced.test.ts +11 -9
- package/src/scenarios/prompt-render-deterministic.test.ts +19 -17
- package/src/scenarios/prompt-resolution-chain-agent-intrinsic.test.ts +7 -5
- package/src/scenarios/prompt-resolution-chain-event.test.ts +12 -10
- package/src/scenarios/prompt-resolution-chain-fallback-cascade.test.ts +10 -8
- package/src/scenarios/prompt-resolution-chain-node-wins.test.ts +8 -6
- package/src/scenarios/prompt-template-shape.test.ts +30 -28
- package/src/scenarios/proposal-reviewable-learning.test.ts +19 -19
- package/src/scenarios/protocol-versions-array.test.ts +10 -9
- package/src/scenarios/provider-usage.test.ts +17 -15
- package/src/scenarios/providerPolicyEnforcement.test.ts +16 -14
- package/src/scenarios/purpose-propagation.test.ts +23 -21
- package/src/scenarios/queue-ack-nack-dlq.test.ts +12 -10
- package/src/scenarios/queue-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/queue-publish-consume-roundtrip.test.ts +10 -8
- package/src/scenarios/rate-limit-envelope.test.ts +6 -5
- package/src/scenarios/redaction.test.ts +13 -11
- package/src/scenarios/redactionAdversarial.test.ts +11 -9
- package/src/scenarios/registry-public.test.ts +12 -11
- package/src/scenarios/replay-divergence-at-refusal.test.ts +16 -15
- package/src/scenarios/replay-fanout-suppression.test.ts +16 -15
- package/src/scenarios/replay-fork-arbitrary.test.ts +24 -23
- package/src/scenarios/replay-fork.test.ts +20 -19
- package/src/scenarios/replay-llm-cache-key-portable.test.ts +11 -9
- package/src/scenarios/replay-llm-cache-key.test.ts +22 -21
- package/src/scenarios/replay-observable-sequence-determinism.test.ts +4 -3
- package/src/scenarios/replay-retention-expiry.test.ts +11 -9
- package/src/scenarios/replay-side-effect-suppression.test.ts +21 -19
- package/src/scenarios/replayDeterminism.test.ts +13 -12
- package/src/scenarios/requirement-ledger.test.ts +15 -14
- package/src/scenarios/restart-during-run.test.ts +3 -2
- package/src/scenarios/route-coverage.test.ts +20 -19
- package/src/scenarios/run-diff.test.ts +22 -20
- package/src/scenarios/run-execution-bounds-shape.test.ts +14 -12
- package/src/scenarios/run-transport-economy.test.ts +13 -11
- package/src/scenarios/runner-ledger.test.ts +17 -16
- package/src/scenarios/runs-lifecycle.test.ts +7 -6
- package/src/scenarios/runtime-capabilities.test.ts +12 -10
- package/src/scenarios/runtime-requires-install-gate.test.ts +8 -8
- package/src/scenarios/runtime-requires-shape.test.ts +7 -6
- package/src/scenarios/safefetch-behavior.test.ts +22 -21
- package/src/scenarios/safefetch-live-audit.test.ts +14 -13
- package/src/scenarios/sandbox-memory-cap.test.ts +2 -1
- package/src/scenarios/sandbox-mvp-behavior.test.ts +24 -23
- package/src/scenarios/sandbox-no-host-fs-escape.test.ts +3 -2
- package/src/scenarios/sandbox-timeout-cap.test.ts +2 -1
- package/src/scenarios/sandbox-wasm-isolation.test.ts +14 -15
- package/src/scenarios/sandbox-wasm-timeout.test.ts +5 -6
- package/src/scenarios/scheduling-capability-shape.test.ts +8 -6
- package/src/scenarios/scheduling-cron-fires-once.test.ts +8 -6
- package/src/scenarios/search-bm25-roundtrip.test.ts +8 -6
- package/src/scenarios/secret-leakage-otel-attribute.test.ts +22 -20
- package/src/scenarios/self-hosted-runner.test.ts +26 -24
- package/src/scenarios/semantic-digest-vectors.test.ts +8 -7
- package/src/scenarios/speech-synthesis-roundtrip.test.ts +9 -7
- package/src/scenarios/speech-synthesis-unadvertised.test.ts +5 -3
- package/src/scenarios/sql-injection-rejection.test.ts +8 -6
- package/src/scenarios/sql-transaction-atomicity.test.ts +10 -8
- package/src/scenarios/staleClaim.test.ts +5 -4
- package/src/scenarios/stream-modes-buffer.test.ts +8 -7
- package/src/scenarios/stream-modes-mixed.test.ts +10 -9
- package/src/scenarios/stream-modes.test.ts +12 -11
- package/src/scenarios/stream-subscribe-from-beginning.test.ts +11 -9
- package/src/scenarios/stream-text-fixture.test.ts +14 -13
- package/src/scenarios/streamReconnect.test.ts +13 -11
- package/src/scenarios/strict-behavior-gate.test.ts +9 -8
- package/src/scenarios/subrun-approval-fail-closed.test.ts +2 -2
- package/src/scenarios/subrun-approval-gate.test.ts +3 -3
- package/src/scenarios/subrun-attestation-shape.test.ts +2 -2
- package/src/scenarios/subrun-checksum-stable.test.ts +4 -4
- package/src/scenarios/subworkflow-input-mapping.test.ts +16 -14
- package/src/scenarios/subworkflow.test.ts +10 -9
- package/src/scenarios/table-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/table-cursor-pagination.test.ts +8 -6
- package/src/scenarios/table-schema-enforcement.test.ts +7 -5
- package/src/scenarios/test-seam-unauthenticated.test.ts +2 -2
- package/src/scenarios/tool-catalog-compact-projection.test.ts +10 -8
- package/src/scenarios/tool-catalog-projection.test.ts +11 -9
- package/src/scenarios/tool-descriptor-shape.test.ts +14 -15
- package/src/scenarios/tool-hooks-authorization-fail-closed.test.ts +3 -3
- package/src/scenarios/tool-hooks-content-free.test.ts +4 -4
- package/src/scenarios/tool-hooks-failure-honesty.test.ts +4 -4
- package/src/scenarios/tool-hooks-rate-limit.test.ts +2 -2
- package/src/scenarios/tool-hooks-secret-redaction.test.ts +2 -2
- package/src/scenarios/tool-hooks-shape.test.ts +3 -3
- package/src/scenarios/tool-session-lifecycle.test.ts +14 -13
- package/src/scenarios/trigger-bridge-delivery.test.ts +14 -14
- package/src/scenarios/trigger-bridge-shape.test.ts +19 -20
- package/src/scenarios/trigger-ingestion.test.ts +19 -17
- package/src/scenarios/trigger-stream-cdc-sources.test.ts +16 -14
- package/src/scenarios/vector-knn-roundtrip.test.ts +9 -7
- package/src/scenarios/verifier-gating.test.ts +8 -6
- package/src/scenarios/version-fold.test.ts +9 -8
- package/src/scenarios/version-negotiation.test.ts +12 -11
- package/src/scenarios/voice-bargein-no-partial-leak.test.ts +8 -6
- package/src/scenarios/voice-event-payloads-shape.test.ts +10 -11
- package/src/scenarios/voice-interim-not-durable.test.ts +7 -5
- package/src/scenarios/voice-streamref-tenant-bound.test.ts +5 -3
- package/src/scenarios/voice-synthesis-streaming.test.ts +11 -9
- package/src/scenarios/voice-transcription-streaming.test.ts +8 -6
- package/src/scenarios/voice-transcription-unadvertised.test.ts +5 -3
- package/src/scenarios/wasm-pack-abi-version-rejection.test.ts +3 -2
- package/src/scenarios/wasm-pack-invoke-completed.test.ts +3 -2
- package/src/scenarios/wasm-pack-invoke-suspended.test.ts +3 -2
- package/src/scenarios/wasm-pack-load.test.ts +4 -3
- package/src/scenarios/wasm-pack-memory-cap.test.ts +5 -4
- package/src/scenarios/wasm-pack-replay-determinism.test.ts +2 -1
- package/src/scenarios/webhook-negative.test.ts +11 -9
- package/src/scenarios/webhook-receiver-adversarial.test.ts +8 -7
- package/src/scenarios/webhook-sig-algorithm.test.ts +5 -3
- package/src/scenarios/webhook-signed-delivery.test.ts +16 -15
- package/src/scenarios/webhook-tenant-isolation.test.ts +16 -14
- package/src/scenarios/workflow-chain-deferred-parameters.test.ts +28 -30
- package/src/scenarios/workflow-chain-expansion.test.ts +21 -20
- package/src/scenarios/workflow-chain-host-expansion.test.ts +21 -20
- package/src/scenarios/workflow-chain-pack-manifest-validation.test.ts +14 -12
- package/src/scenarios/workflow-chain-pack-signature-verification.test.ts +5 -4
- package/src/scenarios/workflow-chain-unresolvable-typeid.test.ts +9 -8
- package/src/scenarios/workflow-primary-output-annotation.test.ts +7 -6
- package/src/scenarios/workflow-variable-format.test.ts +24 -24
- package/src/scenarios/workload-identity-behavior.test.ts +15 -13
- package/src/scenarios/workload-identity-chain-bounds.test.ts +18 -17
- package/src/scenarios/workspace-behavior.test.ts +19 -18
- package/src/scenarios/workspace-capability-shape.test.ts +3 -2
- package/src/scenarios/workspace-cross-tenant-isolation-blackbox.test.ts +6 -5
- package/src/scenarios/workspace-cross-tenant-isolation.test.ts +7 -6
- package/src/scenarios/x-openwop-form-pack-manifest.test.ts +8 -7
- package/src/setup.ts +4 -2
- package/vitest.config.ts +5 -1
- package/api/.redocly.lint-ignore.yaml +0 -22
- package/api/asyncapi.yaml +0 -834
- package/api/grpc/openwop.proto +0 -251
- package/api/openapi.yaml +0 -2693
- package/api/redocly.yaml +0 -23
- package/schemas/README.md +0 -144
- package/schemas/a2a-task-state.schema.json +0 -78
- package/schemas/a2ui-surface-delta-frame.schema.json +0 -48
- package/schemas/agent-deployment-transition.schema.json +0 -49
- package/schemas/agent-deployment.schema.json +0 -54
- package/schemas/agent-eval-suite.schema.json +0 -140
- package/schemas/agent-inventory-response.schema.json +0 -115
- package/schemas/agent-manifest.schema.json +0 -156
- package/schemas/agent-org-chart.schema.json +0 -82
- package/schemas/agent-ref.schema.json +0 -63
- package/schemas/agent-roster-entry.schema.json +0 -81
- package/schemas/agent-roster-response.schema.json +0 -21
- package/schemas/ai-envelope.schema.json +0 -134
- package/schemas/annotation-create.schema.json +0 -37
- package/schemas/annotation.schema.json +0 -56
- package/schemas/artifact-type-pack-manifest.schema.json +0 -244
- package/schemas/audit-verify-result.schema.json +0 -90
- package/schemas/budget-policy.schema.json +0 -18
- package/schemas/capabilities.schema.json +0 -4124
- package/schemas/certification-bundle-v2.schema.json +0 -118
- package/schemas/channel-presence-payload.schema.json +0 -41
- package/schemas/channel-written-payload.schema.json +0 -55
- package/schemas/chat-card-pack-manifest.schema.json +0 -253
- package/schemas/compact-tool-descriptor.schema.json +0 -51
- package/schemas/compensation-policy.schema.json +0 -64
- package/schemas/conformance-certification-bundle.schema.json +0 -86
- package/schemas/connection-pack-manifest.schema.json +0 -353
- package/schemas/conversation-event.schema.json +0 -168
- package/schemas/conversation-turn.schema.json +0 -117
- package/schemas/core-conformance-mock-agent-config.schema.json +0 -152
- package/schemas/credential-provenance.schema.json +0 -18
- package/schemas/credential-reference.schema.json +0 -21
- package/schemas/debug-bundle.schema.json +0 -196
- package/schemas/dispatch-config.schema.json +0 -112
- package/schemas/envelopes/clarification.request.schema.json +0 -52
- package/schemas/envelopes/error.schema.json +0 -30
- package/schemas/envelopes/media.audio.schema.json +0 -38
- package/schemas/envelopes/media.file.schema.json +0 -37
- package/schemas/envelopes/media.image.schema.json +0 -33
- package/schemas/envelopes/schema.request.schema.json +0 -26
- package/schemas/envelopes/schema.response.schema.json +0 -22
- package/schemas/envelopes/ui.a2ui-surface.schema.json +0 -154
- package/schemas/error-envelope.schema.json +0 -25
- package/schemas/eval-summary.schema.json +0 -92
- package/schemas/export-bundle.schema.json +0 -66
- package/schemas/form-content-pack-manifest.schema.json +0 -243
- package/schemas/frontend-plugin-manifest.schema.json +0 -109
- package/schemas/goal.schema.json +0 -104
- package/schemas/heartbeat-evaluated.schema.json +0 -14
- package/schemas/heartbeat-state-changed.schema.json +0 -14
- package/schemas/localized-content-language-settings.schema.json +0 -26
- package/schemas/localized-content-page-response.schema.json +0 -60
- package/schemas/localized-content-page.schema.json +0 -62
- package/schemas/localized-content-section.schema.json +0 -51
- package/schemas/memory-entry.schema.json +0 -36
- package/schemas/memory-list-options.schema.json +0 -37
- package/schemas/node-pack-manifest.schema.json +0 -654
- package/schemas/orchestrator-decision.schema.json +0 -90
- package/schemas/org-chart-responsibility-view.schema.json +0 -26
- package/schemas/pack-lockfile.schema.json +0 -108
- package/schemas/prompt-kind.schema.json +0 -8
- package/schemas/prompt-pack-manifest.schema.json +0 -117
- package/schemas/prompt-ref.schema.json +0 -40
- package/schemas/prompt-template.schema.json +0 -149
- package/schemas/proposal.schema.json +0 -84
- package/schemas/registry-version-manifest.schema.json +0 -208
- package/schemas/residency.schema.json +0 -16
- package/schemas/run-ancestry-response.schema.json +0 -54
- package/schemas/run-diff-response.schema.json +0 -64
- package/schemas/run-event-payloads.schema.json +0 -4452
- package/schemas/run-event.schema.json +0 -211
- package/schemas/run-options.schema.json +0 -80
- package/schemas/run-orchestrator-decided-event.schema.json +0 -20
- package/schemas/run-snapshot.schema.json +0 -148
- package/schemas/security-advisory.schema.json +0 -109
- package/schemas/self-hosted-runner-dispatch-frame.schema.json +0 -79
- package/schemas/self-hosted-runner-registration.schema.json +0 -53
- package/schemas/self-hosted-runner-result-frame.schema.json +0 -38
- package/schemas/subject.schema.json +0 -56
- package/schemas/suspend-request.schema.json +0 -207
- package/schemas/tool-descriptor.schema.json +0 -63
- package/schemas/trigger-event.schema.json +0 -222
- package/schemas/trigger-subscription-registration.schema.json +0 -67
- package/schemas/trigger-subscription.schema.json +0 -26
- package/schemas/ui-plugin-message.schema.json +0 -90
- package/schemas/workflow-chain-pack-manifest.schema.json +0 -615
- package/schemas/workflow-definition.schema.json +0 -850
- package/schemas/workload-identity.schema.json +0 -79
- package/schemas/workspace-file-create.schema.json +0 -20
- package/schemas/workspace-file.schema.json +0 -39
|
@@ -35,9 +35,7 @@ import { join } from 'node:path';
|
|
|
35
35
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
36
36
|
import addFormats from 'ajv-formats';
|
|
37
37
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
38
|
-
|
|
39
|
-
/** Server-free assertion-message helper. */
|
|
40
|
-
const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
|
|
38
|
+
import { req } from '../lib/requirement-ids.js';
|
|
41
39
|
|
|
42
40
|
function loadSchema(name: string): Record<string, unknown> {
|
|
43
41
|
return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
|
|
@@ -48,9 +46,9 @@ describe('agent-roster-shape: capability advertisement (RFC 0086, server-free)',
|
|
|
48
46
|
const caps = loadSchema('capabilities.schema.json');
|
|
49
47
|
const agents = (caps.properties as Record<string, { properties?: Record<string, { properties?: Record<string, unknown> }> }>).agents;
|
|
50
48
|
const roster = agents?.properties?.roster;
|
|
51
|
-
expect(roster,
|
|
49
|
+
expect(roster, req('openwop.it.agent-roster-shape.the-capabilities-schema-declares-agents-roster-with-its-sub-flags', 'capabilities.md §agents', 'agents.roster MUST be declared')).toBeDefined();
|
|
52
50
|
for (const flag of ['supported', 'installScope', 'portfolioTriggerSources']) {
|
|
53
|
-
expect(roster?.properties?.[flag],
|
|
51
|
+
expect(roster?.properties?.[flag], req('openwop.it.agent-roster-shape.the-capabilities-schema-declares-agents-roster-with-its-sub-flags', 'agent-roster.md §F', `agents.roster.${flag} MUST be declared`)).toBeDefined();
|
|
54
52
|
}
|
|
55
53
|
});
|
|
56
54
|
});
|
|
@@ -69,7 +67,7 @@ describe('agent-roster-shape: roster entry (RFC 0086 §A, server-free)', () => {
|
|
|
69
67
|
owner: { tenantId: 'acme', workspaceId: 'growth' },
|
|
70
68
|
enabled: true,
|
|
71
69
|
};
|
|
72
|
-
expect(entry(good),
|
|
70
|
+
expect(entry(good), req('openwop.it.agent-roster-shape.agentrosterentry-validates-a-conforming-entry', 'RFC 0086 §A', 'a conforming roster entry MUST validate')).toBe(true);
|
|
73
71
|
});
|
|
74
72
|
|
|
75
73
|
it('rejects a non-host: rosterId and an agentRef carrying both version and channel', () => {
|
|
@@ -79,12 +77,12 @@ describe('agent-roster-shape: roster entry (RFC 0086 §A, server-free)', () => {
|
|
|
79
77
|
agentRef: { agentId: 'core.openwop.agents.brief-writer' },
|
|
80
78
|
owner: { tenantId: 'acme' },
|
|
81
79
|
};
|
|
82
|
-
expect(entry({ ...base, rosterId: 'core.openwop.agents.sally' }),
|
|
80
|
+
expect(entry({ ...base, rosterId: 'core.openwop.agents.sally' }), req('openwop.it.agent-roster-shape.rejects-a-non-host-rosterid-and-an-agentref-carrying-both-version-and-channel', 'RFC 0086 §A', 'a non-`host:` rosterId MUST be rejected')).toBe(false);
|
|
83
81
|
expect(
|
|
84
82
|
entry({ ...base, agentRef: { agentId: 'core.x.y.z', version: '1.0.0', channel: 'stable' } }),
|
|
85
|
-
|
|
83
|
+
req('openwop.it.agent-roster-shape.rejects-a-non-host-rosterid-and-an-agentref-carrying-both-version-and-channel', 'RFC 0082 §A', 'an agentRef with BOTH version and channel MUST be rejected'),
|
|
86
84
|
).toBe(false);
|
|
87
|
-
expect(entry({ persona: 'x', agentRef: { agentId: 'core.x.y.z' }, owner: { tenantId: 'acme' } }),
|
|
85
|
+
expect(entry({ persona: 'x', agentRef: { agentId: 'core.x.y.z' }, owner: { tenantId: 'acme' } }), req('openwop.it.agent-roster-shape.rejects-a-non-host-rosterid-and-an-agentref-carrying-both-version-and-channel', 'RFC 0086 §A', 'a roster entry without rosterId MUST be rejected')).toBe(false);
|
|
88
86
|
});
|
|
89
87
|
});
|
|
90
88
|
|
|
@@ -96,23 +94,23 @@ describe('agent-roster-shape: roster.run.initiated event (RFC 0086 §C, server-f
|
|
|
96
94
|
const initiated = ajv.getSchema('payloads#/$defs/rosterRunInitiated');
|
|
97
95
|
|
|
98
96
|
it('roster.run.initiated validates a content-free attribution record and requires its ids', () => {
|
|
99
|
-
expect(initiated, 'the rosterRunInitiated $def MUST exist').toBeTruthy();
|
|
97
|
+
expect(initiated, req('openwop.it.agent-roster-shape.roster-run-initiated-validates-a-content-free-attribution-record-and-requires-it', 'RFC 0086', 'the rosterRunInitiated $def MUST exist')).toBeTruthy();
|
|
100
98
|
expect(
|
|
101
99
|
initiated!({ rosterId: 'host:sally-marketing', persona: 'Sally', agentId: 'core.openwop.agents.brief-writer', workflowId: 'marketing-email-campaign', triggerSource: 'schedule' }),
|
|
102
|
-
|
|
100
|
+
req('openwop.it.agent-roster-shape.roster-run-initiated-validates-a-content-free-attribution-record-and-requires-it', 'RFC 0086 §C', 'a conforming roster.run.initiated payload MUST validate'),
|
|
103
101
|
).toBe(true);
|
|
104
|
-
expect(initiated!({ rosterId: 'host:s', persona: 'S' }),
|
|
102
|
+
expect(initiated!({ rosterId: 'host:s', persona: 'S' }), req('openwop.it.agent-roster-shape.roster-run-initiated-validates-a-content-free-attribution-record-and-requires-it', 'RFC 0086 §C', 'roster.run.initiated without agentId/workflowId/triggerSource MUST be rejected')).toBe(false);
|
|
105
103
|
});
|
|
106
104
|
|
|
107
105
|
it('roster.run.initiated is content-free — a work-item body and a prompt are rejected (roster-attribution-no-content)', () => {
|
|
108
106
|
const base = { rosterId: 'host:s', persona: 'S', agentId: 'a.b.c.d', workflowId: 'wf', triggerSource: 'queue' };
|
|
109
107
|
expect(
|
|
110
108
|
initiated!({ ...base, body: 'the card description' }),
|
|
111
|
-
|
|
109
|
+
req('openwop.it.agent-roster-shape.roster-run-initiated-is-content-free-a-work-item-body-and-a-prompt-are-rejected', 'SECURITY invariant roster-attribution-no-content', 'roster.run.initiated MUST NOT carry the work-item body'),
|
|
112
110
|
).toBe(false);
|
|
113
111
|
expect(
|
|
114
112
|
initiated!({ ...base, prompt: 'system: …' }),
|
|
115
|
-
|
|
113
|
+
req('openwop.it.agent-roster-shape.roster-run-initiated-is-content-free-a-work-item-body-and-a-prompt-are-rejected', 'SECURITY invariant roster-attribution-no-content', 'roster.run.initiated MUST NOT carry prompt content'),
|
|
116
114
|
).toBe(false);
|
|
117
115
|
});
|
|
118
116
|
});
|
|
@@ -121,13 +119,13 @@ describe('agent-roster-shape: inventory projection + enum (RFC 0086 §B, server-
|
|
|
121
119
|
it('AgentInventoryEntry carries the additive optional roster portfolio projection', () => {
|
|
122
120
|
const inv = loadSchema('agent-inventory-response.schema.json');
|
|
123
121
|
const entry = (inv.$defs as Record<string, { properties?: Record<string, unknown> }>).AgentInventoryEntry?.properties ?? {};
|
|
124
|
-
expect(entry.roster,
|
|
122
|
+
expect(entry.roster, req('openwop.it.agent-roster-shape.agentinventoryentry-carries-the-additive-optional-roster-portfolio-projection', 'RFC 0086 §B', 'AgentInventoryEntry.roster (the portfolio projection) MUST be declared')).toBeDefined();
|
|
125
123
|
});
|
|
126
124
|
|
|
127
125
|
it('roster.run.initiated appears in the RunEventType enum', () => {
|
|
128
126
|
const runEvent = loadSchema('run-event.schema.json');
|
|
129
127
|
const enumVals = (runEvent.$defs as Record<string, { enum?: string[] }>).RunEventType?.enum ?? [];
|
|
130
|
-
expect(enumVals).toContain('roster.run.initiated');
|
|
128
|
+
expect(enumVals, req('openwop.it.agent-roster-shape.roster-run-initiated-appears-in-the-runeventtype-enum', 'RFC 0086', 'roster.run.initiated appears in the RunEventType enum')).toContain('roster.run.initiated');
|
|
131
129
|
});
|
|
132
130
|
|
|
133
131
|
it('the GET /v1/agents/roster response schema validates + rejects extras (RFC 0086 §B)', () => {
|
|
@@ -139,8 +137,8 @@ describe('agent-roster-shape: inventory projection + enum (RFC 0086 §B, server-
|
|
|
139
137
|
roster: [{ rosterId: 'host:sally', persona: 'Sally', agentRef: { agentId: 'core.x.y.z' }, owner: { tenantId: 'acme' } }],
|
|
140
138
|
total: 1,
|
|
141
139
|
};
|
|
142
|
-
expect(resp(good),
|
|
143
|
-
expect(resp({ ...good, unexpected: true }),
|
|
144
|
-
expect(resp({ roster: [] }),
|
|
140
|
+
expect(resp(good), req('openwop.it.agent-roster-shape.the-get-v1-agents-roster-response-schema-validates-rejects-extras-rfc-0086-b', 'RFC 0086 §B', 'a conforming GET /v1/agents/roster response MUST validate')).toBe(true);
|
|
141
|
+
expect(resp({ ...good, unexpected: true }), req('openwop.it.agent-roster-shape.the-get-v1-agents-roster-response-schema-validates-rejects-extras-rfc-0086-b', 'RFC 0086 §B', 'an extra top-level property MUST be rejected')).toBe(false);
|
|
142
|
+
expect(resp({ roster: [] }), req('openwop.it.agent-roster-shape.the-get-v1-agents-roster-response-schema-validates-rejects-extras-rfc-0086-b', 'RFC 0086 §B', 'the response MUST require `total`')).toBe(false);
|
|
145
143
|
});
|
|
146
144
|
});
|
|
@@ -25,9 +25,9 @@ import { join } from 'node:path';
|
|
|
25
25
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
26
26
|
import addFormats from 'ajv-formats';
|
|
27
27
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
28
|
+
import { req } from '../lib/requirement-ids.js';
|
|
28
29
|
|
|
29
30
|
const BASE = 'https://openwop.dev/spec/v1/';
|
|
30
|
-
const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
|
|
31
31
|
function loadSchema(name: string): Record<string, unknown> {
|
|
32
32
|
return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
|
|
33
33
|
}
|
|
@@ -52,21 +52,21 @@ describe('agent-verifier-shape: agent.verified payload (RFC 0090 §A, server-fre
|
|
|
52
52
|
const verified = ajv.getSchema(`${BASE}run-event-payloads.schema.json#/$defs/agentVerified`);
|
|
53
53
|
|
|
54
54
|
it('a conforming content-free verdict validates', () => {
|
|
55
|
-
expect(verified, 'the agentVerified $def MUST exist').toBeTruthy();
|
|
55
|
+
expect(verified, req('openwop.it.agent-verifier-shape.a-conforming-content-free-verdict-validates', 'RFC 0090', 'the agentVerified $def MUST exist')).toBeTruthy();
|
|
56
56
|
expect(
|
|
57
57
|
verified!({ agentId: 'core.openwop.verifier', target: 'evt-42', verdict: 'pass', criteria: ['grounded'], confidence: 0.9 }),
|
|
58
|
-
|
|
58
|
+
req('openwop.it.agent-verifier-shape.a-conforming-content-free-verdict-validates', 'RFC 0090 §A', 'a conforming agent.verified payload MUST validate'),
|
|
59
59
|
).toBe(true);
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
it('rejects an out-of-enum verdict', () => {
|
|
63
|
-
expect(verified!({ agentId: 'c', target: 'e', verdict: 'ok' }),
|
|
63
|
+
expect(verified!({ agentId: 'c', target: 'e', verdict: 'ok' }), req('openwop.it.agent-verifier-shape.rejects-an-out-of-enum-verdict', 'RFC 0090 §A', 'verdict MUST be pass|fail|revise')).toBe(false);
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
it('rejects a content-carrying payload (verifier-no-content-leak)', () => {
|
|
67
67
|
expect(
|
|
68
68
|
verified!({ agentId: 'c', target: 'e', verdict: 'fail', result: 'the secret answer' }),
|
|
69
|
-
|
|
69
|
+
req('openwop.it.agent-verifier-shape.rejects-a-content-carrying-payload-verifier-no-content-leak', 'RFC 0090 §SECURITY', 'agent.verified MUST be content-free (additionalProperties:false)'),
|
|
70
70
|
).toBe(false);
|
|
71
71
|
});
|
|
72
72
|
});
|
|
@@ -78,7 +78,7 @@ describe('agent-verifier-shape: RunEventType + terminate + capability (RFC 0090)
|
|
|
78
78
|
const runEvent = loadSchema('run-event.schema.json') as { $defs?: { RunEventType?: { enum?: string[] } } };
|
|
79
79
|
expect(
|
|
80
80
|
runEvent.$defs?.RunEventType?.enum?.includes('agent.verified'),
|
|
81
|
-
|
|
81
|
+
req('openwop.it.agent-verifier-shape.agent-verified-is-registered-in-the-runeventtype-enum', 'RFC 0090 §A', 'agent.verified MUST appear in the RunEventType enum'),
|
|
82
82
|
).toBe(true);
|
|
83
83
|
});
|
|
84
84
|
|
|
@@ -86,21 +86,21 @@ describe('agent-verifier-shape: RunEventType + terminate + capability (RFC 0090)
|
|
|
86
86
|
const decision = ajv.getSchema(`${BASE}orchestrator-decision.schema.json`)!;
|
|
87
87
|
expect(
|
|
88
88
|
decision({ kind: 'terminate', reason: 'goal-reached', successCriteria: [{ key: 'goal-answered', met: true }] }),
|
|
89
|
-
|
|
89
|
+
req('openwop.it.agent-verifier-shape.the-terminate-decision-accepts-the-additive-successcriteria', 'RFC 0090 §C', 'terminate MUST accept successCriteria[{key,met}]'),
|
|
90
90
|
).toBe(true);
|
|
91
91
|
expect(
|
|
92
92
|
decision({ kind: 'terminate', successCriteria: [{ key: 'x' }] }),
|
|
93
|
-
|
|
93
|
+
req('openwop.it.agent-verifier-shape.the-terminate-decision-accepts-the-additive-successcriteria', 'RFC 0090 §C', 'a successCriteria entry MUST require both key and met'),
|
|
94
94
|
).toBe(false);
|
|
95
95
|
});
|
|
96
96
|
|
|
97
97
|
it('capabilities accepts executionModel.version 6 + verifier sub-block', () => {
|
|
98
98
|
const execModel = ajv.getSchema(`${BASE}capabilities.schema.json#/properties/multiAgent/properties/executionModel`);
|
|
99
|
-
expect(execModel, 'the executionModel sub-schema MUST exist').toBeTruthy();
|
|
99
|
+
expect(execModel, req('openwop.it.agent-verifier-shape.capabilities-accepts-executionmodel-version-6-verifier-sub-block', 'RFC 0090', 'the executionModel sub-schema MUST exist')).toBeTruthy();
|
|
100
100
|
expect(
|
|
101
101
|
execModel!({ supported: true, version: 6, verifier: { supported: true, gating: true } }),
|
|
102
|
-
|
|
102
|
+
req('openwop.it.agent-verifier-shape.capabilities-accepts-executionmodel-version-6-verifier-sub-block', 'RFC 0090 §D', 'version:6 + verifier{supported,gating} MUST validate'),
|
|
103
103
|
).toBe(true);
|
|
104
|
-
expect(execModel!({ supported: true, version: 7 }),
|
|
104
|
+
expect(execModel!({ supported: true, version: 7 }), req('openwop.it.agent-verifier-shape.capabilities-accepts-executionmodel-version-6-verifier-sub-block', 'RFC 0090 §D', 'version above the ceiling MUST be rejected')).toBe(false);
|
|
105
105
|
});
|
|
106
106
|
});
|
|
@@ -21,6 +21,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
21
21
|
import { driver } from '../lib/driver.js';
|
|
22
22
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
23
23
|
import { isAgentSupported } from '../lib/multi-agent-capabilities.js';
|
|
24
|
+
import { req } from '../lib/requirement-ids.js';
|
|
24
25
|
|
|
25
26
|
const FIXTURE = 'conformance-agent-low-confidence';
|
|
26
27
|
const SKIP = !isAgentSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -51,7 +52,7 @@ describe.skipIf(SKIP)('agentConfidenceEscalation: confidence < threshold → low
|
|
|
51
52
|
const lowConfSuspend = list.find(
|
|
52
53
|
(e) => e.type === 'node.suspended' && e.payload?.reason === 'low-confidence',
|
|
53
54
|
);
|
|
54
|
-
expect(lowConfSuspend, 'CP-1: low-confidence agent.decided MUST emit node.suspended { reason: low-confidence }').toBeDefined();
|
|
55
|
+
expect(lowConfSuspend, req('openwop.it.agentConfidenceEscalation.low-confidence-agent-decided-suspends-with-reason-low-confidence-and-run-reaches', 'RFCS/0002-agent-identity-and-reasoning-events.md', 'CP-1: low-confidence agent.decided MUST emit node.suspended { reason: low-confidence }')).toBeDefined();
|
|
55
56
|
|
|
56
57
|
const payload = lowConfSuspend!.payload as Record<string, unknown>;
|
|
57
58
|
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 { hasLongTermMemory } from '../lib/multi-agent-capabilities.js';
|
|
23
|
+
import { req } from '../lib/requirement-ids.js';
|
|
23
24
|
|
|
24
25
|
const FIXTURE = 'conformance-agent-memory-cross-tenant';
|
|
25
26
|
const SKIP = !hasLongTermMemory() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -50,13 +51,13 @@ describe.skipIf(SKIP)('agentMemoryCrossTenantIsolation: CTI-1 invariant', () =>
|
|
|
50
51
|
const ownerProbe = vars.ownerProbe;
|
|
51
52
|
expect(
|
|
52
53
|
Array.isArray(ownerProbe) && ownerProbe.length > 0,
|
|
53
|
-
|
|
54
|
+
req('openwop.it.agentMemoryCrossTenantIsolation.cross-tenant-memoryref-returns-empty-null-no-leak-across-tenant-boundary', 'agent-memory.md §CTI-1 / fixtures.md conformance-agent-memory-cross-tenant', 'ownerProbe MUST be a NON-EMPTY array — the run\'s own tenant can read the entry it just wrote (positive control; an unset or empty ownerProbe means the probe never ran)'),
|
|
54
55
|
).toBe(true);
|
|
55
56
|
const ownerEntryId = vars.ownerEntryId;
|
|
56
57
|
if (typeof ownerEntryId === 'string' && ownerEntryId.length > 0) {
|
|
57
58
|
expect(
|
|
58
59
|
(ownerProbe as Array<{ id?: unknown }>).some((e) => e && typeof e === 'object' && e.id === ownerEntryId),
|
|
59
|
-
|
|
60
|
+
req('openwop.it.agentMemoryCrossTenantIsolation.cross-tenant-memoryref-returns-empty-null-no-leak-across-tenant-boundary', 'agent-memory.md §CTI-1', `ownerProbe MUST contain the entry the host reports writing (ownerEntryId=${ownerEntryId})`),
|
|
60
61
|
).toBe(true);
|
|
61
62
|
}
|
|
62
63
|
|
|
@@ -65,12 +66,12 @@ describe.skipIf(SKIP)('agentMemoryCrossTenantIsolation: CTI-1 invariant', () =>
|
|
|
65
66
|
const crossTenantResult = vars.crossTenantProbe;
|
|
66
67
|
expect(
|
|
67
68
|
crossTenantResult !== undefined,
|
|
68
|
-
|
|
69
|
+
req('openwop.it.agentMemoryCrossTenantIsolation.cross-tenant-memoryref-returns-empty-null-no-leak-across-tenant-boundary', 'agent-memory.md §CTI-1', 'crossTenantProbe MUST be set — an unset variable means the cross-tenant probe was never issued, which proves nothing'),
|
|
69
70
|
).toBe(true);
|
|
70
71
|
if (Array.isArray(crossTenantResult)) {
|
|
71
|
-
expect(crossTenantResult.length,
|
|
72
|
+
expect(crossTenantResult.length, req('openwop.it.agentMemoryCrossTenantIsolation.cross-tenant-memoryref-returns-empty-null-no-leak-across-tenant-boundary', 'agent-memory.md §CTI-1', 'a cross-tenant memoryRef probe MUST return [] — no entries of another tenant')).toBe(0);
|
|
72
73
|
} else {
|
|
73
|
-
expect(crossTenantResult,
|
|
74
|
+
expect(crossTenantResult, req('openwop.it.agentMemoryCrossTenantIsolation.cross-tenant-memoryref-returns-empty-null-no-leak-across-tenant-boundary', 'agent-memory.md §CTI-1', 'a non-array cross-tenant probe result MUST be null')).toBeNull();
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
});
|
|
@@ -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 { hasLongTermMemory } from '../lib/multi-agent-capabilities.js';
|
|
23
|
+
import { req } from '../lib/requirement-ids.js';
|
|
23
24
|
|
|
24
25
|
const FIXTURE = 'conformance-agent-memory-redaction';
|
|
25
26
|
const SKIP = !hasLongTermMemory() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -27,7 +28,7 @@ const SKIP = !hasLongTermMemory() || !isFixtureAdvertised(FIXTURE);
|
|
|
27
28
|
describe.skipIf(SKIP)('agentMemoryRedactionContract: SR-1 invariant', () => {
|
|
28
29
|
it('BYOK plaintext is redacted to [REDACTED:<secretId>] at the read surface', 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.agentMemoryRedactionContract.byok-plaintext-is-redacted-to-redacted-secretid-at-the-read-surface', 'RFCS/0004-memory-layer.md', 'BYOK plaintext is redacted to [REDACTED:<secretId>] at the read surface')).toBe(201);
|
|
31
32
|
const runId = (create.json as { runId: string }).runId;
|
|
32
33
|
|
|
33
34
|
const terminal = await pollUntilTerminal(runId);
|
|
@@ -19,6 +19,7 @@ import { driver } from '../lib/driver.js';
|
|
|
19
19
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
20
20
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
21
21
|
import { hasLongTermMemory } from '../lib/multi-agent-capabilities.js';
|
|
22
|
+
import { req } from '../lib/requirement-ids.js';
|
|
22
23
|
|
|
23
24
|
const FIXTURE = 'conformance-agent-memory-roundtrip';
|
|
24
25
|
const SKIP = !hasLongTermMemory() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -26,7 +27,7 @@ const SKIP = !hasLongTermMemory() || !isFixtureAdvertised(FIXTURE);
|
|
|
26
27
|
describe.skipIf(SKIP)('agentMemoryRoundTrip: write → read via MemoryAdapter', () => {
|
|
27
28
|
it('memory entries written during a run are readable via the resolved memoryRef', async () => {
|
|
28
29
|
const create = await driver.post('/v1/runs', { workflowId: FIXTURE });
|
|
29
|
-
expect(create.status).toBe(201);
|
|
30
|
+
expect(create.status, req('openwop.it.agentMemoryRoundTrip.memory-entries-written-during-a-run-are-readable-via-the-resolved-memoryref', 'RFCS/0004-memory-layer.md', 'memory entries written during a run are readable via the resolved memoryRef')).toBe(201);
|
|
30
31
|
const runId = (create.json as { runId: string }).runId;
|
|
31
32
|
|
|
32
33
|
const terminal = await pollUntilTerminal(runId);
|
|
@@ -18,6 +18,7 @@ import { driver } from '../lib/driver.js';
|
|
|
18
18
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
19
19
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
20
20
|
import { hasLongTermMemory } from '../lib/multi-agent-capabilities.js';
|
|
21
|
+
import { req } from '../lib/requirement-ids.js';
|
|
21
22
|
|
|
22
23
|
const FIXTURE = 'conformance-agent-memory-ttl';
|
|
23
24
|
const SKIP = !hasLongTermMemory() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -52,15 +53,15 @@ describe.skipIf(SKIP)('agentMemoryTtlExpiry: expired entries are excluded from l
|
|
|
52
53
|
const expiredId = body.variables?.expiredId;
|
|
53
54
|
expect(
|
|
54
55
|
typeof freshId === 'string' && freshId.length > 0 && typeof expiredId === 'string' && expiredId.length > 0,
|
|
55
|
-
|
|
56
|
+
req('openwop.it.agentMemoryTtlExpiry.list-excludes-entries-whose-expiresat-is-in-the-past', 'fixtures.md conformance-agent-memory-ttl', 'the host MUST land freshId and expiredId (the ids of the two entries it wrote) so the list can be checked on both sides'),
|
|
56
57
|
).toBe(true);
|
|
57
58
|
expect(
|
|
58
59
|
listResult!.some((e) => e.id === freshId),
|
|
59
|
-
|
|
60
|
+
req('openwop.it.agentMemoryTtlExpiry.list-excludes-entries-whose-expiresat-is-in-the-past', 'agent-memory.md §TTL', `list() MUST include the fresh entry (freshId=${String(freshId)})`),
|
|
60
61
|
).toBe(true);
|
|
61
62
|
expect(
|
|
62
63
|
listResult!.some((e) => e.id === expiredId),
|
|
63
|
-
|
|
64
|
+
req('openwop.it.agentMemoryTtlExpiry.list-excludes-entries-whose-expiresat-is-in-the-past', 'agent-memory.md §TTL', `list() MUST NOT include the expired entry (expiredId=${String(expiredId)})`),
|
|
64
65
|
).toBe(false);
|
|
65
66
|
});
|
|
66
67
|
});
|
|
@@ -23,6 +23,7 @@ import { driver } from '../lib/driver.js';
|
|
|
23
23
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
24
24
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
25
25
|
import { isAgentSupported } from '../lib/multi-agent-capabilities.js';
|
|
26
|
+
import { req } from '../lib/requirement-ids.js';
|
|
26
27
|
|
|
27
28
|
const FIXTURE = 'conformance-message-reducer';
|
|
28
29
|
const SKIP = !isAgentSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -44,7 +45,7 @@ describe.skipIf(SKIP)('agentMessageReducer: message reducer idempotency + append
|
|
|
44
45
|
// fixture convention is `conversation` or `messages`).
|
|
45
46
|
const channelEntries = Object.entries(body.channels ?? {});
|
|
46
47
|
const messageChannel = channelEntries.find(([, val]) => Array.isArray(val));
|
|
47
|
-
expect(messageChannel, 'fixture MUST expose at least one message-reducer channel').toBeDefined();
|
|
48
|
+
expect(messageChannel, req('openwop.it.agentMessageReducer.duplicate-messageid-emissions-fold-to-a-single-channel-entry', 'RFCS/0002-agent-identity-and-reasoning-events.md', 'fixture MUST expose at least one message-reducer channel')).toBeDefined();
|
|
48
49
|
|
|
49
50
|
const messages = messageChannel![1] as Array<{ messageId?: string }>;
|
|
50
51
|
const messageIds = messages
|
|
@@ -23,6 +23,7 @@ import { driver } from '../lib/driver.js';
|
|
|
23
23
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
24
24
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
25
25
|
import { isAgentSupported } from '../lib/multi-agent-capabilities.js';
|
|
26
|
+
import { req } from '../lib/requirement-ids.js';
|
|
26
27
|
|
|
27
28
|
const FIXTURE = 'conformance-agent-identity';
|
|
28
29
|
const SKIP = !isAgentSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -44,7 +45,7 @@ describe.skipIf(SKIP)('agentMetadata: RunSnapshot.agent + runOrchestrator wire-s
|
|
|
44
45
|
const hasOrch = body.runOrchestrator && typeof body.runOrchestrator.agentId === 'string';
|
|
45
46
|
expect(
|
|
46
47
|
hasAgent || hasOrch,
|
|
47
|
-
'fixture-runs MUST populate at least one of RunSnapshot.agent / runOrchestrator',
|
|
48
|
+
req('openwop.it.agentMetadata.host-populates-agentref-shaped-agent-identity-on-runsnapshot', 'RFCS/0002-agent-identity-and-reasoning-events.md', 'fixture-runs MUST populate at least one of RunSnapshot.agent / runOrchestrator'),
|
|
48
49
|
).toBe(true);
|
|
49
50
|
|
|
50
51
|
if (hasAgent) {
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
import { describe, it, expect } from 'vitest';
|
|
32
32
|
import { driver } from '../lib/driver.js';
|
|
33
33
|
import { isAgentSupported } from '../lib/multi-agent-capabilities.js';
|
|
34
|
+
import { req } from '../lib/requirement-ids.js';
|
|
35
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
34
36
|
|
|
35
37
|
interface PackList {
|
|
36
38
|
packs?: Array<{
|
|
@@ -68,7 +70,7 @@ async function findPack(name: string): Promise<PackList['packs'] extends Array<i
|
|
|
68
70
|
return (found ?? null) as never;
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
function assertAgentManifestShape(
|
|
73
|
+
function assertAgentManifestShape(requirementId: string,
|
|
72
74
|
agent: NonNullable<NonNullable<PackList['packs']>[number]['agents']>[number],
|
|
73
75
|
expectations: { agentIdEndsWith?: string; modelClass?: string; minTools?: number },
|
|
74
76
|
): void {
|
|
@@ -80,7 +82,7 @@ function assertAgentManifestShape(
|
|
|
80
82
|
// agentId pattern (RFCS/0003 §A namespace tiers).
|
|
81
83
|
expect(
|
|
82
84
|
AGENT_ID_PATTERN.test(agent.agentId ?? ''),
|
|
83
|
-
|
|
85
|
+
req(requirementId,
|
|
84
86
|
'schemas/agent-manifest.schema.json §agentId',
|
|
85
87
|
`agentId "${agent.agentId}" MUST match the namespace-tier pattern`,
|
|
86
88
|
),
|
|
@@ -133,10 +135,10 @@ const SKIP = !isAgentSupported();
|
|
|
133
135
|
describe.skipIf(SKIP)('core.openwop.agents.deep-research — pack catalog evidence', () => {
|
|
134
136
|
it('host pack-list includes deep-research with a well-formed AgentManifest', async () => {
|
|
135
137
|
const pack = await findPack('core.openwop.agents.deep-research');
|
|
136
|
-
if (pack === null) return; // host doesn't expose /v1/packs or doesn't have this pack
|
|
137
|
-
expect(pack.version, 'pack version MUST be present').toBeDefined();
|
|
138
|
-
expect(Array.isArray(pack.agents) && pack.agents.length === 1, 'deep-research ships exactly one agent').toBe(true);
|
|
139
|
-
assertAgentManifestShape(pack.agents![0]!, {
|
|
138
|
+
if (pack === null) return softSkip('blocked', 'precondition not met — `pack === null` returned early (host doesn\'t expose /v1/packs or doesn\'t have this pack) (seam, prior step, or fixture unavailable)'); // host doesn't expose /v1/packs or doesn't have this pack
|
|
139
|
+
expect(pack.version, req('openwop.it.agentPackCatalog.host-pack-list-includes-deep-research-with-a-well-formed-agentmanifest', 'RFCS/0003-agent-packs.md', 'pack version MUST be present')).toBeDefined();
|
|
140
|
+
expect(Array.isArray(pack.agents) && pack.agents.length === 1, req('openwop.it.agentPackCatalog.host-pack-list-includes-deep-research-with-a-well-formed-agentmanifest', 'RFCS/0003-agent-packs.md', 'deep-research ships exactly one agent')).toBe(true);
|
|
141
|
+
assertAgentManifestShape('openwop.it.agentPackCatalog.host-pack-list-includes-deep-research-with-a-well-formed-agentmanifest', pack.agents![0]!, {
|
|
140
142
|
agentIdEndsWith: 'deep-research',
|
|
141
143
|
modelClass: 'research',
|
|
142
144
|
minTools: 1,
|
|
@@ -145,11 +147,11 @@ describe.skipIf(SKIP)('core.openwop.agents.deep-research — pack catalog eviden
|
|
|
145
147
|
const tools = pack.agents![0]!.toolAllowlist ?? [];
|
|
146
148
|
expect(
|
|
147
149
|
tools.some((t) => t.includes('rag') || t.includes('retriever')),
|
|
148
|
-
'deep-research SHOULD allow at least one rag/retriever tool',
|
|
150
|
+
req('openwop.it.agentPackCatalog.host-pack-list-includes-deep-research-with-a-well-formed-agentmanifest', 'RFCS/0003-agent-packs.md', 'deep-research SHOULD allow at least one rag/retriever tool'),
|
|
149
151
|
).toBe(true);
|
|
150
152
|
expect(
|
|
151
153
|
pack.agents![0]!.memoryShape?.longTerm,
|
|
152
|
-
'deep-research MUST request longTerm memory (it persists facts across runs)',
|
|
154
|
+
req('openwop.it.agentPackCatalog.host-pack-list-includes-deep-research-with-a-well-formed-agentmanifest', 'RFCS/0003-agent-packs.md', 'deep-research MUST request longTerm memory (it persists facts across runs)'),
|
|
153
155
|
).toBe(true);
|
|
154
156
|
});
|
|
155
157
|
});
|
|
@@ -157,27 +159,27 @@ describe.skipIf(SKIP)('core.openwop.agents.deep-research — pack catalog eviden
|
|
|
157
159
|
describe.skipIf(SKIP)('core.openwop.agents.react — pack catalog evidence', () => {
|
|
158
160
|
it('host pack-list includes react with a well-formed AgentManifest', async () => {
|
|
159
161
|
const pack = await findPack('core.openwop.agents.react');
|
|
160
|
-
if (pack === null) return;
|
|
162
|
+
if (pack === null) return softSkip('blocked', 'precondition not met — `pack === null` returned early (seam, prior step, or fixture unavailable)');
|
|
161
163
|
expect(pack.version).toBeDefined();
|
|
162
|
-
expect(Array.isArray(pack.agents) && pack.agents.length >= 1, 'react ships at least one agent').toBe(true);
|
|
163
|
-
assertAgentManifestShape(pack.agents![0]!, {
|
|
164
|
+
expect(Array.isArray(pack.agents) && pack.agents.length >= 1, req('openwop.it.agentPackCatalog.host-pack-list-includes-react-with-a-well-formed-agentmanifest', 'RFCS/0003-agent-packs.md', 'react ships at least one agent')).toBe(true);
|
|
165
|
+
assertAgentManifestShape('openwop.it.agentPackCatalog.host-pack-list-includes-react-with-a-well-formed-agentmanifest', pack.agents![0]!, {
|
|
164
166
|
agentIdEndsWith: 'react',
|
|
165
167
|
});
|
|
166
168
|
// ReAct pattern requires handoff schemas (task + return).
|
|
167
169
|
const handoff = pack.agents![0]!.handoff;
|
|
168
|
-
expect(handoff, 'react AgentManifest MUST include a handoff block').toBeDefined();
|
|
169
|
-
expect(typeof handoff?.taskSchemaRef, 'handoff.taskSchemaRef MUST be a string').toBe('string');
|
|
170
|
-
expect(typeof handoff?.returnSchemaRef, 'handoff.returnSchemaRef MUST be a string').toBe('string');
|
|
170
|
+
expect(handoff, req('openwop.it.agentPackCatalog.host-pack-list-includes-react-with-a-well-formed-agentmanifest', 'RFCS/0003-agent-packs.md', 'react AgentManifest MUST include a handoff block')).toBeDefined();
|
|
171
|
+
expect(typeof handoff?.taskSchemaRef, req('openwop.it.agentPackCatalog.host-pack-list-includes-react-with-a-well-formed-agentmanifest', 'RFCS/0003-agent-packs.md', 'handoff.taskSchemaRef MUST be a string')).toBe('string');
|
|
172
|
+
expect(typeof handoff?.returnSchemaRef, req('openwop.it.agentPackCatalog.host-pack-list-includes-react-with-a-well-formed-agentmanifest', 'RFCS/0003-agent-packs.md', 'handoff.returnSchemaRef MUST be a string')).toBe('string');
|
|
171
173
|
});
|
|
172
174
|
});
|
|
173
175
|
|
|
174
176
|
describe.skipIf(SKIP)('core.openwop.agents.supervisor — pack catalog evidence', () => {
|
|
175
177
|
it('host pack-list includes supervisor with a well-formed AgentManifest', async () => {
|
|
176
178
|
const pack = await findPack('core.openwop.agents.supervisor');
|
|
177
|
-
if (pack === null) return;
|
|
179
|
+
if (pack === null) return softSkip('blocked', 'precondition not met — `pack === null` returned early (seam, prior step, or fixture unavailable)');
|
|
178
180
|
expect(pack.version).toBeDefined();
|
|
179
|
-
expect(Array.isArray(pack.agents) && pack.agents.length >= 1, 'supervisor ships at least one agent').toBe(true);
|
|
180
|
-
assertAgentManifestShape(pack.agents![0]!, {
|
|
181
|
+
expect(Array.isArray(pack.agents) && pack.agents.length >= 1, req('openwop.it.agentPackCatalog.host-pack-list-includes-supervisor-with-a-well-formed-agentmanifest', 'RFCS/0003-agent-packs.md', 'supervisor ships at least one agent')).toBe(true);
|
|
182
|
+
assertAgentManifestShape('openwop.it.agentPackCatalog.host-pack-list-includes-supervisor-with-a-well-formed-agentmanifest', pack.agents![0]!, {
|
|
181
183
|
agentIdEndsWith: 'supervisor',
|
|
182
184
|
});
|
|
183
185
|
// Supervisor pattern delegates to crew members; its modelClass should
|
|
@@ -185,10 +187,10 @@ describe.skipIf(SKIP)('core.openwop.agents.supervisor — pack catalog evidence'
|
|
|
185
187
|
const mc = pack.agents![0]!.modelClass;
|
|
186
188
|
expect(
|
|
187
189
|
mc === 'delegate' || mc === 'reasoning',
|
|
188
|
-
`supervisor SHOULD have modelClass=delegate|reasoning, got "${mc}"
|
|
190
|
+
req('openwop.it.agentPackCatalog.host-pack-list-includes-supervisor-with-a-well-formed-agentmanifest', 'RFCS/0003-agent-packs.md', `supervisor SHOULD have modelClass=delegate|reasoning, got "${mc}"`),
|
|
189
191
|
).toBe(true);
|
|
190
192
|
// Supervisor needs handoff schemas to dispatch work.
|
|
191
|
-
expect(pack.agents![0]!.handoff, 'supervisor MUST include handoff schemas').toBeDefined();
|
|
193
|
+
expect(pack.agents![0]!.handoff, req('openwop.it.agentPackCatalog.host-pack-list-includes-supervisor-with-a-well-formed-agentmanifest', 'RFCS/0003-agent-packs.md', 'supervisor MUST include handoff schemas')).toBeDefined();
|
|
192
194
|
});
|
|
193
195
|
});
|
|
194
196
|
|
|
@@ -207,10 +209,10 @@ describe.skipIf(SKIP)('agent-pack catalog summary', () => {
|
|
|
207
209
|
// Either none are present (host doesn't ship these — skip) OR all are
|
|
208
210
|
// present (host ships the full reference batch). Half-shipping is a
|
|
209
211
|
// configuration error worth flagging.
|
|
210
|
-
if (found.length === 0) return;
|
|
212
|
+
if (found.length === 0) return softSkip('blocked', 'precondition not met — `found.length === 0` returned early (Either none are present (host doesn\'t ship these — skip) OR all are present (host ships the full reference batch). Half-shipping is a configuration error wor…');
|
|
211
213
|
expect(
|
|
212
214
|
found.length,
|
|
213
|
-
'host SHOULD ship the reference agent packs as a coherent batch (none, or all three)',
|
|
215
|
+
req('openwop.it.agentPackCatalog.all-three-2026-05-17-reference-agent-packs-are-catalog-reachable', 'RFCS/0003-agent-packs.md', 'host SHOULD ship the reference agent packs as a coherent batch (none, or all three)'),
|
|
214
216
|
).toBe(names.length);
|
|
215
217
|
});
|
|
216
218
|
});
|
|
@@ -18,6 +18,8 @@ import { describe, it, expect } from 'vitest';
|
|
|
18
18
|
import { driver } from '../lib/driver.js';
|
|
19
19
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
20
20
|
import { isAgentSupported } from '../lib/multi-agent-capabilities.js';
|
|
21
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
22
|
+
import { req } from '../lib/requirement-ids.js';
|
|
21
23
|
|
|
22
24
|
const FIXTURE = 'conformance-agent-pack-export';
|
|
23
25
|
const SKIP = !isAgentSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -27,9 +29,9 @@ describe.skipIf(SKIP)('agentPackExport: workspace agents project to AgentManifes
|
|
|
27
29
|
const res = await driver.get('/v1/packs/export');
|
|
28
30
|
if (res.status === 404 || res.status === 501) {
|
|
29
31
|
// Host doesn't expose pack-export over REST; treated as skip.
|
|
30
|
-
return;
|
|
32
|
+
return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 501` returned early (Host doesn\'t expose pack-export over REST; treated as skip.) (seam, prior step, or fixture unavailable)');
|
|
31
33
|
}
|
|
32
|
-
expect(res.status).toBe(200);
|
|
34
|
+
expect(res.status, req('openwop.it.agentPackExport.exported-manifests-contain-required-agentmanifest-fields', 'RFCS/0003-agent-packs.md', 'exported manifests contain required AgentManifest fields')).toBe(200);
|
|
33
35
|
|
|
34
36
|
const body = res.json as {
|
|
35
37
|
manifests?: Array<{ agentId?: string; modelClass?: string; sourceManifestId?: string }>;
|
|
@@ -51,6 +51,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
51
51
|
import { driver } from '../lib/driver.js';
|
|
52
52
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
53
53
|
import { isAgentSupported, hasHandoffValidation } from '../lib/multi-agent-capabilities.js';
|
|
54
|
+
import { req } from '../lib/requirement-ids.js';
|
|
54
55
|
|
|
55
56
|
const FIXTURE = 'conformance-agent-pack-handoff-schema-validation';
|
|
56
57
|
const SKIP = !isAgentSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -82,7 +83,7 @@ describe.skipIf(SKIP)('agentPackHandoffSchemaValidation: handoff schema enforcem
|
|
|
82
83
|
const runId = (create.json as { runId: string }).runId;
|
|
83
84
|
|
|
84
85
|
const snap = await settle(runId);
|
|
85
|
-
expect(snap?.status, 'HV-1a: valid task payload should NOT be rejected by handoff-schema validation').toBe('completed');
|
|
86
|
+
expect(snap?.status, req('openwop.it.agentPackHandoffSchemaValidation.hv-1a-valid-task-payload-that-matches-taskschemaref-is-dispatched-and-completes', 'RFCS/0003-agent-packs.md §D', 'HV-1a: valid task payload should NOT be rejected by handoff-schema validation')).toBe('completed');
|
|
86
87
|
});
|
|
87
88
|
|
|
88
89
|
// HV-1b / HV-1c assert a REJECTION, which only a host performing handoff
|
|
@@ -101,7 +102,7 @@ describe.skipIf(SKIP)('agentPackHandoffSchemaValidation: handoff schema enforcem
|
|
|
101
102
|
const snap = await settle(runId, ['completed', 'failed']);
|
|
102
103
|
expect(
|
|
103
104
|
snap?.status,
|
|
104
|
-
'HV-1b: invalid task payload MUST cause the run to fail rather than silently dispatch off-contract',
|
|
105
|
+
req('openwop.it.agentPackHandoffSchemaValidation.hv-1b-invalid-task-payload-missing-required-field-fails-before-dispatch-with-a-s', 'RFCS/0003-agent-packs.md §D', 'HV-1b: invalid task payload MUST cause the run to fail rather than silently dispatch off-contract'),
|
|
105
106
|
).toBe('failed');
|
|
106
107
|
|
|
107
108
|
const events = await driver.get(`/v1/runs/${encodeURIComponent(runId)}/events`);
|
|
@@ -115,7 +116,7 @@ describe.skipIf(SKIP)('agentPackHandoffSchemaValidation: handoff schema enforcem
|
|
|
115
116
|
);
|
|
116
117
|
expect(
|
|
117
118
|
validationFailure,
|
|
118
|
-
'HV-1b: failure event payload MUST carry a recognizable handoff-validation error code',
|
|
119
|
+
req('openwop.it.agentPackHandoffSchemaValidation.hv-1b-invalid-task-payload-missing-required-field-fails-before-dispatch-with-a-s', 'RFCS/0003-agent-packs.md §D', 'HV-1b: failure event payload MUST carry a recognizable handoff-validation error code'),
|
|
119
120
|
).toBeDefined();
|
|
120
121
|
});
|
|
121
122
|
|
|
@@ -148,7 +149,7 @@ describe.skipIf(SKIP)('agentPackHandoffSchemaValidation: handoff schema enforcem
|
|
|
148
149
|
);
|
|
149
150
|
expect(
|
|
150
151
|
returnViolation,
|
|
151
|
-
'HV-1c: off-schema return payload MUST surface a structured violation event before persistence',
|
|
152
|
+
req('openwop.it.agentPackHandoffSchemaValidation.hv-1c-agent-return-payload-that-fails-returnschemaref-surfaces-a-structured-viol', 'RFCS/0003-agent-packs.md §D', 'HV-1c: off-schema return payload MUST surface a structured violation event before persistence'),
|
|
152
153
|
).toBeDefined();
|
|
153
154
|
});
|
|
154
155
|
});
|
|
@@ -19,6 +19,8 @@ import { describe, it, expect } from 'vitest';
|
|
|
19
19
|
import { driver } from '../lib/driver.js';
|
|
20
20
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
21
21
|
import { isAgentSupported } from '../lib/multi-agent-capabilities.js';
|
|
22
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
23
|
+
import { req } from '../lib/requirement-ids.js';
|
|
22
24
|
|
|
23
25
|
const FIXTURE = 'conformance-agent-pack-install';
|
|
24
26
|
const SKIP = !isAgentSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -32,9 +34,9 @@ describe.skipIf(SKIP)('agentPackInstall: pack agents[] entries surface as AgentM
|
|
|
32
34
|
if (res.status === 404 || res.status === 501) {
|
|
33
35
|
// Host doesn't expose pack registry over REST; scenario assertion is
|
|
34
36
|
// skipped (capability surface is host-internal).
|
|
35
|
-
return;
|
|
37
|
+
return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 501` returned early (Host doesn\'t expose pack registry over REST; scenario assertion is skipped (capability surface is host-internal).) (seam, prior step, o…');
|
|
36
38
|
}
|
|
37
|
-
expect(res.status).toBe(200);
|
|
39
|
+
expect(res.status, req('openwop.it.agentPackInstall.host-exposes-installed-agent-manifests-with-required-agentmanifest-fields', 'RFCS/0003-agent-packs.md', 'host exposes installed agent manifests with required AgentManifest fields')).toBe(200);
|
|
38
40
|
|
|
39
41
|
const body = res.json as {
|
|
40
42
|
packs?: Array<{ agents?: Array<{ agentId?: string; modelClass?: 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 { isAgentSupported } from '../lib/multi-agent-capabilities.js';
|
|
23
|
+
import { req } from '../lib/requirement-ids.js';
|
|
23
24
|
|
|
24
25
|
const FIXTURE = 'conformance-agent-pack-provenance';
|
|
25
26
|
const SKIP = !isAgentSupported() || !isFixtureAdvertised(FIXTURE);
|
|
@@ -48,7 +49,7 @@ describe.skipIf(SKIP)('agentPackProvenance: sourceManifestId survives install +
|
|
|
48
49
|
const withProvenance = refs.filter((r) => typeof r.sourceManifestId === 'string');
|
|
49
50
|
expect(
|
|
50
51
|
withProvenance.length,
|
|
51
|
-
'pack-installed agents MUST surface sourceManifestId on their runtime AgentRef projection',
|
|
52
|
+
req('openwop.it.agentPackProvenance.run-level-agentref-carries-sourcemanifestid-pointing-back-to-the-install-source', 'RFCS/0003-agent-packs.md', 'pack-installed agents MUST surface sourceManifestId on their runtime AgentRef projection'),
|
|
52
53
|
).toBeGreaterThan(0);
|
|
53
54
|
});
|
|
54
55
|
});
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
isAgentSupported,
|
|
23
23
|
getReasoningVerbosity,
|
|
24
24
|
} from '../lib/multi-agent-capabilities.js';
|
|
25
|
+
import { req } from '../lib/requirement-ids.js';
|
|
25
26
|
|
|
26
27
|
const FIXTURE = 'conformance-agent-reasoning';
|
|
27
28
|
const SKIP =
|
|
@@ -103,7 +104,7 @@ describe.skipIf(SKIP)('agentReasoningEvents: agent.* event family emission', ()
|
|
|
103
104
|
const matched = calls.find((c) => c.payload?.callId === callId);
|
|
104
105
|
expect(
|
|
105
106
|
matched,
|
|
106
|
-
`agent.toolReturned.callId=${callId} MUST pair with a prior agent.toolCalled
|
|
107
|
+
req('openwop.it.agentReasoningEvents.host-emits-at-least-one-canonical-agent-event-during-a-reasoning-fixture-run', 'schemas/run-event-payloads.schema.json', `agent.toolReturned.callId=${callId} MUST pair with a prior agent.toolCalled`),
|
|
107
108
|
).toBeDefined();
|
|
108
109
|
|
|
109
110
|
// Strict causationId chain — only assert when the host actually
|
|
@@ -115,7 +116,7 @@ describe.skipIf(SKIP)('agentReasoningEvents: agent.* event family emission', ()
|
|
|
115
116
|
if (typeof matchedEventId === 'string' && matchedEventId.length > 0) {
|
|
116
117
|
expect(
|
|
117
118
|
ret.causationId,
|
|
118
|
-
`agent.toolReturned (callId=${callId}) MUST carry causationId === paired agent.toolCalled.eventId per RFC 0002 §B
|
|
119
|
+
req('openwop.it.agentReasoningEvents.host-emits-at-least-one-canonical-agent-event-during-a-reasoning-fixture-run', 'schemas/run-event-payloads.schema.json', `agent.toolReturned (callId=${callId}) MUST carry causationId === paired agent.toolCalled.eventId per RFC 0002 §B`),
|
|
119
120
|
).toBe(matchedEventId);
|
|
120
121
|
}
|
|
121
122
|
}
|