@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
|
@@ -33,9 +33,7 @@ import { join } from 'node:path';
|
|
|
33
33
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
34
34
|
import addFormats from 'ajv-formats';
|
|
35
35
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
36
|
-
|
|
37
|
-
/** Server-free assertion-message helper (mirrors driver.describe's "spec — requirement" shape without requiring OPENWOP_BASE_URL). */
|
|
38
|
-
const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
|
|
36
|
+
import { req } from '../lib/requirement-ids.js';
|
|
39
37
|
|
|
40
38
|
function loadSchema(name: string): Record<string, unknown> {
|
|
41
39
|
return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
|
|
@@ -48,12 +46,12 @@ describe('agent-eval-suite-shape: capability advertisement (RFC 0081, server-fre
|
|
|
48
46
|
const evalSuite = agents?.properties?.evalSuite;
|
|
49
47
|
expect(
|
|
50
48
|
evalSuite,
|
|
51
|
-
|
|
49
|
+
req('openwop.it.agent-eval-suite-shape.the-capabilities-schema-declares-agents-evalsuite-with-its-sub-flags', 'capabilities.md §agents', 'agents.evalSuite MUST be declared'),
|
|
52
50
|
).toBeDefined();
|
|
53
51
|
for (const flag of ['supported', 'modes']) {
|
|
54
52
|
expect(
|
|
55
53
|
evalSuite?.properties?.[flag],
|
|
56
|
-
|
|
54
|
+
req('openwop.it.agent-eval-suite-shape.the-capabilities-schema-declares-agents-evalsuite-with-its-sub-flags', 'agent-evaluation.md §Capability advertisement', `agents.evalSuite.${flag} MUST be declared`),
|
|
57
55
|
).toBeDefined();
|
|
58
56
|
}
|
|
59
57
|
});
|
|
@@ -75,11 +73,11 @@ describe('agent-eval-suite-shape: AgentEvalSuite + EvalSummary schemas (RFC 0081
|
|
|
75
73
|
{ taskId: 'refund-window', input: { q: 'refund policy?' }, expected: { kind: 'golden', match: { strategy: 'contains', value: '30 days' } } },
|
|
76
74
|
],
|
|
77
75
|
};
|
|
78
|
-
expect(suite(good),
|
|
76
|
+
expect(suite(good), req('openwop.it.agent-eval-suite-shape.agentevalsuite-validates-a-conforming-suite-and-rejects-a-malformed-suiteid-out', 'RFC 0081 §A', 'a conforming AgentEvalSuite MUST validate')).toBe(true);
|
|
79
77
|
// Negative: suiteId must carry the `.evals.` infix.
|
|
80
|
-
expect(suite({ ...good, suiteId: 'core.openwop.support-resolver' }),
|
|
78
|
+
expect(suite({ ...good, suiteId: 'core.openwop.support-resolver' }), req('openwop.it.agent-eval-suite-shape.agentevalsuite-validates-a-conforming-suite-and-rejects-a-malformed-suiteid-out', 'RFC 0081 §A', 'a suiteId without the `.evals.` infix MUST be rejected')).toBe(false);
|
|
81
79
|
// Negative: passScore out of 0..1.
|
|
82
|
-
expect(suite({ ...good, thresholds: { passScore: 1.5 } }),
|
|
80
|
+
expect(suite({ ...good, thresholds: { passScore: 1.5 } }), req('openwop.it.agent-eval-suite-shape.agentevalsuite-validates-a-conforming-suite-and-rejects-a-malformed-suiteid-out', 'RFC 0081 §A', 'thresholds.passScore > 1 MUST be rejected')).toBe(false);
|
|
83
81
|
});
|
|
84
82
|
|
|
85
83
|
it('EvalSummary validates a conforming scorecard and rejects an out-of-range score', () => {
|
|
@@ -92,8 +90,8 @@ describe('agent-eval-suite-shape: AgentEvalSuite + EvalSummary schemas (RFC 0081
|
|
|
92
90
|
passedCount: 2,
|
|
93
91
|
tasks: [{ taskId: 'refund-window', score: 0.9, passed: true, safetyFindings: [{ kind: 'jailbreak', severity: 'low' }] }],
|
|
94
92
|
};
|
|
95
|
-
expect(summary(good),
|
|
96
|
-
expect(summary({ ...good, aggregateScore: 1.4 }),
|
|
93
|
+
expect(summary(good), req('openwop.it.agent-eval-suite-shape.evalsummary-validates-a-conforming-scorecard-and-rejects-an-out-of-range-score', 'RFC 0081 §C', 'a conforming EvalSummary MUST validate')).toBe(true);
|
|
94
|
+
expect(summary({ ...good, aggregateScore: 1.4 }), req('openwop.it.agent-eval-suite-shape.evalsummary-validates-a-conforming-scorecard-and-rejects-an-out-of-range-score', 'RFC 0081 §C', 'aggregateScore > 1 MUST be rejected')).toBe(false);
|
|
97
95
|
});
|
|
98
96
|
|
|
99
97
|
it('EvalSummary is content-free — a task-output body and a safety-finding excerpt are rejected (eval-summary-no-content-leak)', () => {
|
|
@@ -101,12 +99,12 @@ describe('agent-eval-suite-shape: AgentEvalSuite + EvalSummary schemas (RFC 0081
|
|
|
101
99
|
// Negative: a per-task entry carrying the output body.
|
|
102
100
|
expect(
|
|
103
101
|
summary({ ...base, tasks: [{ taskId: 't1', score: 0.5, passed: false, taskOutput: 'the model said …' }] }),
|
|
104
|
-
|
|
102
|
+
req('openwop.it.agent-eval-suite-shape.evalsummary-is-content-free-a-task-output-body-and-a-safety-finding-excerpt-are', 'SECURITY invariant eval-summary-no-content-leak', 'an EvalSummary task entry MUST NOT carry an output body'),
|
|
105
103
|
).toBe(false);
|
|
106
104
|
// Negative: a safety finding carrying excerpted content rather than a {kind, severity} descriptor.
|
|
107
105
|
expect(
|
|
108
106
|
summary({ ...base, tasks: [{ taskId: 't1', score: 0.5, passed: false, safetyFindings: [{ kind: 'pii-leak', severity: 'high', excerpt: 'SSN 123-45-6789' }] }] }),
|
|
109
|
-
|
|
107
|
+
req('openwop.it.agent-eval-suite-shape.evalsummary-is-content-free-a-task-output-body-and-a-safety-finding-excerpt-are', 'SECURITY invariant eval-summary-no-content-leak', 'a safetyFinding MUST NOT carry excerpted content'),
|
|
110
108
|
).toBe(false);
|
|
111
109
|
});
|
|
112
110
|
});
|
|
@@ -122,45 +120,45 @@ describe('agent-eval-suite-shape: eval event payloads (RFC 0081, server-free)',
|
|
|
122
120
|
const completed = ajv.getSchema('payloads#/$defs/evalCompleted');
|
|
123
121
|
|
|
124
122
|
it('eval.started validates a content-free start record and requires the suite provenance', () => {
|
|
125
|
-
expect(started, 'the evalStarted $def MUST exist').toBeTruthy();
|
|
123
|
+
expect(started, req('openwop.it.agent-eval-suite-shape.eval-started-validates-a-content-free-start-record-and-requires-the-suite-proven', 'RFC 0081', 'the evalStarted $def MUST exist')).toBeTruthy();
|
|
126
124
|
expect(
|
|
127
125
|
started!({ suiteId: 'core.openwop.evals.support-resolver', suiteVersion: '1.0.0', taskCount: 12, modes: ['golden'] }),
|
|
128
|
-
|
|
126
|
+
req('openwop.it.agent-eval-suite-shape.eval-started-validates-a-content-free-start-record-and-requires-the-suite-proven', 'RFC 0081 §C', 'a conforming eval.started payload MUST validate'),
|
|
129
127
|
).toBe(true);
|
|
130
128
|
expect(
|
|
131
129
|
started!({ suiteId: 'core.openwop.evals.x' }),
|
|
132
|
-
|
|
130
|
+
req('openwop.it.agent-eval-suite-shape.eval-started-validates-a-content-free-start-record-and-requires-the-suite-proven', 'RFC 0081 §C', 'eval.started without suiteVersion/taskCount/modes MUST be rejected'),
|
|
133
131
|
).toBe(false);
|
|
134
132
|
});
|
|
135
133
|
|
|
136
134
|
it('eval.scored validates a content-free per-task score and requires score + passed', () => {
|
|
137
|
-
expect(scored, 'the evalScored $def MUST exist').toBeTruthy();
|
|
135
|
+
expect(scored, req('openwop.it.agent-eval-suite-shape.eval-scored-validates-a-content-free-per-task-score-and-requires-score-passed', 'RFC 0081', 'the evalScored $def MUST exist')).toBeTruthy();
|
|
138
136
|
expect(
|
|
139
137
|
scored!({ taskId: 'refund-window', score: 0.9, passed: true, costUsd: 0.012 }),
|
|
140
|
-
|
|
138
|
+
req('openwop.it.agent-eval-suite-shape.eval-scored-validates-a-content-free-per-task-score-and-requires-score-passed', 'RFC 0081 §C', 'a conforming eval.scored payload MUST validate'),
|
|
141
139
|
).toBe(true);
|
|
142
140
|
expect(
|
|
143
141
|
scored!({ taskId: 'refund-window' }),
|
|
144
|
-
|
|
142
|
+
req('openwop.it.agent-eval-suite-shape.eval-scored-validates-a-content-free-per-task-score-and-requires-score-passed', 'RFC 0081 §C', 'eval.scored without score/passed MUST be rejected'),
|
|
145
143
|
).toBe(false);
|
|
146
144
|
});
|
|
147
145
|
|
|
148
146
|
it('eval.completed validates a content-free aggregate record', () => {
|
|
149
|
-
expect(completed, 'the evalCompleted $def MUST exist').toBeTruthy();
|
|
147
|
+
expect(completed, req('openwop.it.agent-eval-suite-shape.eval-completed-validates-a-content-free-aggregate-record', 'RFC 0081', 'the evalCompleted $def MUST exist')).toBeTruthy();
|
|
150
148
|
expect(
|
|
151
149
|
completed!({ aggregateScore: 0.86, passed: true, taskCount: 12, passedCount: 11, regressionVsBaseline: 0.04 }),
|
|
152
|
-
|
|
150
|
+
req('openwop.it.agent-eval-suite-shape.eval-completed-validates-a-content-free-aggregate-record', 'RFC 0081 §C', 'a conforming eval.completed payload MUST validate'),
|
|
153
151
|
).toBe(true);
|
|
154
152
|
expect(
|
|
155
153
|
completed!({ aggregateScore: 2 }),
|
|
156
|
-
|
|
154
|
+
req('openwop.it.agent-eval-suite-shape.eval-completed-validates-a-content-free-aggregate-record', 'RFC 0081 §C', 'eval.completed with an out-of-range aggregateScore MUST be rejected'),
|
|
157
155
|
).toBe(false);
|
|
158
156
|
});
|
|
159
157
|
|
|
160
158
|
it('all three eval event names appear in the RunEventType enum', () => {
|
|
161
159
|
const runEvent = loadSchema('run-event.schema.json');
|
|
162
160
|
const enumVals = (runEvent.$defs as Record<string, { enum?: string[] }>).RunEventType?.enum ?? [];
|
|
163
|
-
expect(enumVals).toContain('eval.started');
|
|
161
|
+
expect(enumVals, req('openwop.it.agent-eval-suite-shape.all-three-eval-event-names-appear-in-the-runeventtype-enum', 'RFC 0081', 'all three eval event names appear in the RunEventType enum')).toContain('eval.started');
|
|
164
162
|
expect(enumVals).toContain('eval.scored');
|
|
165
163
|
expect(enumVals).toContain('eval.completed');
|
|
166
164
|
});
|
|
@@ -20,10 +20,11 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import { describe, it, expect } from 'vitest';
|
|
23
|
-
import { driver } from '../lib/driver.js';
|
|
24
23
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
25
24
|
import { readLiveRuntimeCap, invokeLive } from '../lib/liveRuntime.js';
|
|
26
25
|
import { queryTestEvents, isEventLogSeamAvailable, resetTestSeam } from '../lib/event-log-query.js';
|
|
26
|
+
import { req } from '../lib/requirement-ids.js';
|
|
27
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
27
28
|
|
|
28
29
|
const DISALLOWED_TOOL = 'conformance-disallowed-tool';
|
|
29
30
|
|
|
@@ -32,12 +33,12 @@ describe('agent-live-allowlist-enforced (RFC 0077 §F-1)', () => {
|
|
|
32
33
|
const cap = await readLiveRuntimeCap();
|
|
33
34
|
if (!behaviorGate('openwop-live-allowlist-enforced', cap?.supported === true)) return;
|
|
34
35
|
|
|
35
|
-
if (!(await isEventLogSeamAvailable())) return; // soft-skip
|
|
36
|
+
if (!(await isEventLogSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isEventLogSeamAvailable())` returned early (soft-skip) (seam, prior step, or fixture unavailable)'); // soft-skip
|
|
36
37
|
const res = await invokeLive({ source: 'run-api', attemptTool: DISALLOWED_TOOL });
|
|
37
|
-
if (res === null || !res.runId) return; // seam/hook absent — soft-skip
|
|
38
|
+
if (res === null || !res.runId) return softSkip('blocked', 'precondition not met — `res === null || !res.runId` returned early (seam/hook absent — soft-skip) (seam, prior step, or fixture unavailable)'); // seam/hook absent — soft-skip
|
|
38
39
|
|
|
39
40
|
const q = await queryTestEvents(res.runId, { type: 'agent.toolCalled' });
|
|
40
|
-
if (!q.ok) return;
|
|
41
|
+
if (!q.ok) return softSkip('blocked', 'precondition not met — `!q.ok` returned early (seam, prior step, or fixture unavailable)');
|
|
41
42
|
|
|
42
43
|
const calledDisallowed = q.events.some((e) => {
|
|
43
44
|
const tool = e.payload.tool ?? e.payload.toolId ?? e.payload.name;
|
|
@@ -45,7 +46,7 @@ describe('agent-live-allowlist-enforced (RFC 0077 §F-1)', () => {
|
|
|
45
46
|
});
|
|
46
47
|
expect(
|
|
47
48
|
calledDisallowed === false,
|
|
48
|
-
|
|
49
|
+
req('openwop.it.agent-live-allowlist-enforced.does-not-call-a-tool-outside-the-agent-toolallowlist', 'RFC 0077 §F-1 / RFC 0002 §A14', 'a live invocation MUST NOT call a tool outside the agent toolAllowlist'),
|
|
49
50
|
).toBe(true);
|
|
50
51
|
|
|
51
52
|
await resetTestSeam();
|
|
@@ -21,10 +21,11 @@
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import { describe, it, expect } from 'vitest';
|
|
24
|
-
import { driver } from '../lib/driver.js';
|
|
25
24
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
26
25
|
import { readLiveRuntimeCap, invokeLive } from '../lib/liveRuntime.js';
|
|
27
26
|
import { queryTestEvents, isEventLogSeamAvailable, resetTestSeam } from '../lib/event-log-query.js';
|
|
27
|
+
import { req } from '../lib/requirement-ids.js';
|
|
28
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
28
29
|
|
|
29
30
|
const SOURCES = ['workflow-node', 'run-api', 'chat-mention'];
|
|
30
31
|
const OUTCOMES = ['completed', 'handed-off', 'escalated', 'refused', 'failed'];
|
|
@@ -35,21 +36,21 @@ describe('agent-live-invocation-bracket (RFC 0077 §E)', () => {
|
|
|
35
36
|
const cap = await readLiveRuntimeCap();
|
|
36
37
|
if (!behaviorGate('openwop-live-invocation-bracket', cap?.supported === true)) return;
|
|
37
38
|
|
|
38
|
-
if (!(await isEventLogSeamAvailable())) return; // event-log seam absent — soft-skip
|
|
39
|
+
if (!(await isEventLogSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isEventLogSeamAvailable())` returned early (event-log seam absent — soft-skip) (seam, prior step, or fixture unavailable)'); // event-log seam absent — soft-skip
|
|
39
40
|
const res = await invokeLive({ source: 'run-api' });
|
|
40
|
-
if (res === null || !res.runId) return; // live-invoke seam absent — soft-skip
|
|
41
|
+
if (res === null || !res.runId) return softSkip('blocked', 'precondition not met — `res === null || !res.runId` returned early (live-invoke seam absent — soft-skip) (seam, prior step, or fixture unavailable)'); // live-invoke seam absent — soft-skip
|
|
41
42
|
|
|
42
43
|
const q = await queryTestEvents(res.runId);
|
|
43
|
-
if (!q.ok) return;
|
|
44
|
+
if (!q.ok) return softSkip('blocked', 'precondition not met — `!q.ok` returned early (seam, prior step, or fixture unavailable)');
|
|
44
45
|
const events = q.events.slice().sort((a, b) => a.sequence - b.sequence);
|
|
45
46
|
|
|
46
47
|
const started = events.filter((e) => e.type === 'agent.invocation.started');
|
|
47
48
|
const completed = events.filter((e) => e.type === 'agent.invocation.completed');
|
|
48
49
|
expect(
|
|
49
50
|
started.length >= 1 && completed.length >= 1,
|
|
50
|
-
|
|
51
|
+
req('openwop.it.agent-live-invocation-bracket.brackets-a-live-invocation-with-started-first-completed-last-matching-invocation', 'multi-agent-execution.md §"Live manifest dispatch"', 'a live invocation MUST emit agent.invocation.started + agent.invocation.completed'),
|
|
51
52
|
).toBe(true);
|
|
52
|
-
if (started.length === 0 || completed.length === 0) return;
|
|
53
|
+
if (started.length === 0 || completed.length === 0) return softSkip('blocked', 'precondition not met — `started.length === 0 || completed.length === 0` returned early (seam, prior step, or fixture unavailable)');
|
|
53
54
|
|
|
54
55
|
const start = started[0]!;
|
|
55
56
|
const end = completed[completed.length - 1]!;
|
|
@@ -58,11 +59,11 @@ describe('agent-live-invocation-bracket (RFC 0077 §E)', () => {
|
|
|
58
59
|
const agentScoped = events.filter((e) => AGENT_SCOPED(e.type));
|
|
59
60
|
expect(
|
|
60
61
|
agentScoped[0]?.type === 'agent.invocation.started',
|
|
61
|
-
|
|
62
|
+
req('openwop.it.agent-live-invocation-bracket.brackets-a-live-invocation-with-started-first-completed-last-matching-invocation', 'RFC 0077 §E', 'agent.invocation.started MUST be the first agent-scoped event of the invocation'),
|
|
62
63
|
).toBe(true);
|
|
63
64
|
expect(
|
|
64
65
|
agentScoped[agentScoped.length - 1]?.type === 'agent.invocation.completed',
|
|
65
|
-
|
|
66
|
+
req('openwop.it.agent-live-invocation-bracket.brackets-a-live-invocation-with-started-first-completed-last-matching-invocation', 'RFC 0077 §E', 'agent.invocation.completed MUST be the last agent-scoped event of the invocation'),
|
|
66
67
|
).toBe(true);
|
|
67
68
|
|
|
68
69
|
// Matching invocationId across the bracket.
|
|
@@ -70,17 +71,17 @@ describe('agent-live-invocation-bracket (RFC 0077 §E)', () => {
|
|
|
70
71
|
const endId = end.payload.invocationId;
|
|
71
72
|
expect(
|
|
72
73
|
typeof startId === 'string' && startId === endId,
|
|
73
|
-
|
|
74
|
+
req('openwop.it.agent-live-invocation-bracket.brackets-a-live-invocation-with-started-first-completed-last-matching-invocation', 'run-event-payloads.schema.json#agentInvocation*', 'the bracket MUST share one invocationId'),
|
|
74
75
|
).toBe(true);
|
|
75
76
|
|
|
76
77
|
// Enum discipline.
|
|
77
78
|
expect(
|
|
78
79
|
typeof start.payload.source === 'string' && SOURCES.includes(start.payload.source as string),
|
|
79
|
-
|
|
80
|
+
req('openwop.it.agent-live-invocation-bracket.brackets-a-live-invocation-with-started-first-completed-last-matching-invocation', 'run-event-payloads.schema.json#agentInvocationStarted', 'source MUST be workflow-node|run-api|chat-mention'),
|
|
80
81
|
).toBe(true);
|
|
81
82
|
expect(
|
|
82
83
|
typeof end.payload.outcome === 'string' && OUTCOMES.includes(end.payload.outcome as string),
|
|
83
|
-
|
|
84
|
+
req('openwop.it.agent-live-invocation-bracket.brackets-a-live-invocation-with-started-first-completed-last-matching-invocation', 'run-event-payloads.schema.json#agentInvocationCompleted', 'outcome MUST be in the closed enum'),
|
|
84
85
|
).toBe(true);
|
|
85
86
|
|
|
86
87
|
// Content-free: identifiers + metadata only, never prompt/result body.
|
|
@@ -88,7 +89,7 @@ describe('agent-live-invocation-bracket (RFC 0077 §E)', () => {
|
|
|
88
89
|
for (const forbidden of ['prompt', 'result', 'body', 'input', 'output', 'apiKey', 'secret', 'credentials', 'token']) {
|
|
89
90
|
expect(
|
|
90
91
|
!(forbidden in evt.payload),
|
|
91
|
-
|
|
92
|
+
req('openwop.it.agent-live-invocation-bracket.brackets-a-live-invocation-with-started-first-completed-last-matching-invocation', 'RFC 0077', `agent.invocation.* MUST be content-free (no ${forbidden})`),
|
|
92
93
|
).toBe(true);
|
|
93
94
|
}
|
|
94
95
|
}
|
|
@@ -28,9 +28,7 @@ import { join } from 'node:path';
|
|
|
28
28
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
29
29
|
import addFormats from 'ajv-formats';
|
|
30
30
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
31
|
-
|
|
32
|
-
/** Server-free assertion-message helper (mirrors driver.describe's "spec — requirement" shape without requiring OPENWOP_BASE_URL). */
|
|
33
|
-
const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
|
|
31
|
+
import { req } from '../lib/requirement-ids.js';
|
|
34
32
|
|
|
35
33
|
function loadSchema(name: string): Record<string, unknown> {
|
|
36
34
|
return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
|
|
@@ -43,12 +41,12 @@ describe('agent-live-runtime-shape: capability advertisement (RFC 0077, server-f
|
|
|
43
41
|
const live = agents?.properties?.liveRuntime;
|
|
44
42
|
expect(
|
|
45
43
|
live,
|
|
46
|
-
|
|
44
|
+
req('openwop.it.agent-live-runtime-shape.the-capabilities-schema-declares-agents-liveruntime-with-its-sub-flags', 'capabilities.md §agents', 'agents.liveRuntime MUST be declared'),
|
|
47
45
|
).toBeDefined();
|
|
48
46
|
for (const flag of ['supported', 'structuredOutput', 'confidenceEscalation', 'sources']) {
|
|
49
47
|
expect(
|
|
50
48
|
live?.properties?.[flag],
|
|
51
|
-
|
|
49
|
+
req('openwop.it.agent-live-runtime-shape.the-capabilities-schema-declares-agents-liveruntime-with-its-sub-flags', 'multi-agent-execution.md §Live manifest dispatch', `agents.liveRuntime.${flag} MUST be declared`),
|
|
52
50
|
).toBeDefined();
|
|
53
51
|
}
|
|
54
52
|
});
|
|
@@ -64,35 +62,35 @@ describe('agent-live-runtime-shape: invocation event payloads (RFC 0077, server-
|
|
|
64
62
|
const completed = ajv.getSchema('payloads#/$defs/agentInvocationCompleted');
|
|
65
63
|
|
|
66
64
|
it('agent.invocation.started validates a content-free start record and requires source', () => {
|
|
67
|
-
expect(started, 'the agentInvocationStarted $def MUST exist').toBeTruthy();
|
|
65
|
+
expect(started, req('openwop.it.agent-live-runtime-shape.agent-invocation-started-validates-a-content-free-start-record-and-requires-sour', 'RFC 0077', 'the agentInvocationStarted $def MUST exist')).toBeTruthy();
|
|
68
66
|
expect(
|
|
69
67
|
started!({ invocationId: 'inv-1', agentId: 'vendor.acme.review.code-reviewer', source: 'run-api', modelClass: 'coding', toolSurfaceCount: 3, memoryBound: false }),
|
|
70
|
-
|
|
68
|
+
req('openwop.it.agent-live-runtime-shape.agent-invocation-started-validates-a-content-free-start-record-and-requires-sour', 'RFC 0077 §C', 'a conforming agent.invocation.started payload MUST validate'),
|
|
71
69
|
).toBe(true);
|
|
72
70
|
// Negative: missing source — every invocation must record its entry point.
|
|
73
71
|
expect(
|
|
74
72
|
started!({ invocationId: 'inv-1', agentId: 'vendor.acme.review.code-reviewer' }),
|
|
75
|
-
|
|
73
|
+
req('openwop.it.agent-live-runtime-shape.agent-invocation-started-validates-a-content-free-start-record-and-requires-sour', 'RFC 0077 §C', 'agent.invocation.started without source MUST be rejected'),
|
|
76
74
|
).toBe(false);
|
|
77
75
|
});
|
|
78
76
|
|
|
79
77
|
it('agent.invocation.completed validates a content-free outcome record and pins the outcome enum', () => {
|
|
80
|
-
expect(completed, 'the agentInvocationCompleted $def MUST exist').toBeTruthy();
|
|
78
|
+
expect(completed, req('openwop.it.agent-live-runtime-shape.agent-invocation-completed-validates-a-content-free-outcome-record-and-pins-the', 'RFC 0077', 'the agentInvocationCompleted $def MUST exist')).toBeTruthy();
|
|
81
79
|
expect(
|
|
82
80
|
completed!({ invocationId: 'inv-1', agentId: 'vendor.acme.review.code-reviewer', outcome: 'completed', schemaValidated: true, confidence: 0.91 }),
|
|
83
|
-
|
|
81
|
+
req('openwop.it.agent-live-runtime-shape.agent-invocation-completed-validates-a-content-free-outcome-record-and-pins-the', 'RFC 0077 §C', 'a conforming agent.invocation.completed payload MUST validate'),
|
|
84
82
|
).toBe(true);
|
|
85
83
|
// Negative: out-of-enum outcome — the canonical value is `completed`, not `done`.
|
|
86
84
|
expect(
|
|
87
85
|
completed!({ invocationId: 'inv-1', agentId: 'a', outcome: 'done' }),
|
|
88
|
-
|
|
86
|
+
req('openwop.it.agent-live-runtime-shape.agent-invocation-completed-validates-a-content-free-outcome-record-and-pins-the', 'RFC 0077 §C', 'agent.invocation.completed with an out-of-enum outcome MUST be rejected'),
|
|
89
87
|
).toBe(false);
|
|
90
88
|
});
|
|
91
89
|
|
|
92
90
|
it('both invocation event names appear in the RunEventType enum', () => {
|
|
93
91
|
const runEvent = loadSchema('run-event.schema.json');
|
|
94
92
|
const enumVals = (runEvent.$defs as Record<string, { enum?: string[] }>).RunEventType?.enum ?? [];
|
|
95
|
-
expect(enumVals).toContain('agent.invocation.started');
|
|
93
|
+
expect(enumVals, req('openwop.it.agent-live-runtime-shape.both-invocation-event-names-appear-in-the-runeventtype-enum', 'RFC 0077', 'both invocation event names appear in the RunEventType enum')).toContain('agent.invocation.started');
|
|
96
94
|
expect(enumVals).toContain('agent.invocation.completed');
|
|
97
95
|
});
|
|
98
96
|
});
|
|
@@ -20,10 +20,11 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import { describe, it, expect } from 'vitest';
|
|
23
|
-
import { driver } from '../lib/driver.js';
|
|
24
23
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
25
24
|
import { readLiveRuntimeCap, invokeLive } from '../lib/liveRuntime.js';
|
|
26
25
|
import { queryTestEvents, isEventLogSeamAvailable, resetTestSeam } from '../lib/event-log-query.js';
|
|
26
|
+
import { req } from '../lib/requirement-ids.js';
|
|
27
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
27
28
|
|
|
28
29
|
describe('agent-live-structured-output (RFC 0077 §B step 6)', () => {
|
|
29
30
|
it('fails the invocation on a result that violates handoff.returnSchemaRef', async () => {
|
|
@@ -32,25 +33,25 @@ describe('agent-live-structured-output (RFC 0077 §B step 6)', () => {
|
|
|
32
33
|
const advertised = cap?.supported === true && cap?.structuredOutput === true;
|
|
33
34
|
if (!behaviorGate('openwop-live-structured-output', advertised)) return;
|
|
34
35
|
|
|
35
|
-
if (!(await isEventLogSeamAvailable())) return; // soft-skip
|
|
36
|
+
if (!(await isEventLogSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isEventLogSeamAvailable())` returned early (soft-skip) (seam, prior step, or fixture unavailable)'); // soft-skip
|
|
36
37
|
const res = await invokeLive({
|
|
37
38
|
source: 'run-api',
|
|
38
39
|
returnSchemaRef: 'conformance-strict-handoff',
|
|
39
40
|
forceInvalidResult: true,
|
|
40
41
|
});
|
|
41
|
-
if (res === null || !res.runId) return; // seam/hook absent — soft-skip
|
|
42
|
+
if (res === null || !res.runId) return softSkip('blocked', 'precondition not met — `res === null || !res.runId` returned early (seam/hook absent — soft-skip) (seam, prior step, or fixture unavailable)'); // seam/hook absent — soft-skip
|
|
42
43
|
|
|
43
44
|
const q = await queryTestEvents(res.runId, { type: 'agent.invocation.completed' });
|
|
44
|
-
if (!q.ok || !q.events[0]) return;
|
|
45
|
+
if (!q.ok || !q.events[0]) return softSkip('blocked', 'precondition not met — `!q.ok || !q.events[0]` returned early (seam, prior step, or fixture unavailable)');
|
|
45
46
|
const payload = q.events[q.events.length - 1]!.payload;
|
|
46
47
|
|
|
47
48
|
expect(
|
|
48
49
|
payload.outcome === 'failed',
|
|
49
|
-
|
|
50
|
+
req('openwop.it.agent-live-structured-output.fails-the-invocation-on-a-result-that-violates-handoff-returnschemaref', 'RFC 0077 §B step 6', 'a result violating handoff.returnSchemaRef MUST fail the invocation (outcome "failed"), not ship as completed'),
|
|
50
51
|
).toBe(true);
|
|
51
52
|
expect(
|
|
52
53
|
payload.schemaValidated !== true,
|
|
53
|
-
|
|
54
|
+
req('openwop.it.agent-live-structured-output.fails-the-invocation-on-a-result-that-violates-handoff-returnschemaref', 'RFC 0077 §B step 6', 'schemaValidated MUST NOT be true for a schema-violating result'),
|
|
54
55
|
).toBe(true);
|
|
55
56
|
|
|
56
57
|
await resetTestSeam();
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
import { describe, it, expect } from 'vitest';
|
|
13
13
|
import { softSkip } from '../lib/soft-skip.js';
|
|
14
|
-
import { driver } from '../lib/driver.js';
|
|
15
14
|
import { readExecutionModelCap, isVersion5, invokeAgentLoop } from '../lib/agentLoop.js';
|
|
15
|
+
import { req } from '../lib/requirement-ids.js';
|
|
16
16
|
|
|
17
17
|
describe('agent-loop-iteration-monotonic (RFC 0061 §B)', () => {
|
|
18
18
|
it('iteration increments by exactly 1 per orchestrator turn, 1-based', async () => {
|
|
@@ -22,13 +22,13 @@ describe('agent-loop-iteration-monotonic (RFC 0061 §B)', () => {
|
|
|
22
22
|
const decisions = res.decisions ?? [];
|
|
23
23
|
expect(
|
|
24
24
|
decisions.length >= 1,
|
|
25
|
-
|
|
25
|
+
req('openwop.it.agent-loop-iteration-monotonic.iteration-increments-by-exactly-1-per-orchestrator-turn-1-based', 'RFC 0061 §B', 'a multi-turn loop MUST emit one runOrchestrator.decided per turn'),
|
|
26
26
|
).toBe(true);
|
|
27
27
|
const iterations = decisions.map((d) => d.iteration);
|
|
28
28
|
const expected = decisions.map((_, k) => k + 1);
|
|
29
29
|
expect(
|
|
30
30
|
JSON.stringify(iterations),
|
|
31
|
-
|
|
31
|
+
req('openwop.it.agent-loop-iteration-monotonic.iteration-increments-by-exactly-1-per-orchestrator-turn-1-based', 'RFC 0061 §B', 'iteration MUST be 1-based + monotonic, incrementing by exactly 1 per turn'),
|
|
32
32
|
).toBe(JSON.stringify(expected));
|
|
33
33
|
});
|
|
34
34
|
});
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
import { describe, it, expect } from 'vitest';
|
|
13
13
|
import { softSkip } from '../lib/soft-skip.js';
|
|
14
|
-
import { driver } from '../lib/driver.js';
|
|
15
14
|
import { readExecutionModelCap, invokeAgentLoop } from '../lib/agentLoop.js';
|
|
15
|
+
import { req } from '../lib/requirement-ids.js';
|
|
16
16
|
|
|
17
17
|
describe('agent-loop-stateful-resume (RFC 0061 §D)', () => {
|
|
18
18
|
it('a mid-loop suspend resumes at the same iteration, counter intact', async () => {
|
|
@@ -23,7 +23,7 @@ describe('agent-loop-stateful-resume (RFC 0061 §D)', () => {
|
|
|
23
23
|
if (res === null) return softSkip('blocked', 'seam absent — soft-skip');
|
|
24
24
|
expect(
|
|
25
25
|
res.resumedIteration,
|
|
26
|
-
|
|
26
|
+
req('openwop.it.agent-loop-stateful-resume.a-mid-loop-suspend-resumes-at-the-same-iteration-counter-intact', 'RFC 0061 §D', 'a stateful resume MUST continue at the suspend iteration — the counter does not reset or skip'),
|
|
27
27
|
).toBe(2);
|
|
28
28
|
});
|
|
29
29
|
});
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
|
|
14
14
|
import { describe, it, expect } from 'vitest';
|
|
15
15
|
import { softSkip } from '../lib/soft-skip.js';
|
|
16
|
-
import { driver } from '../lib/driver.js';
|
|
17
16
|
import { executionModelVersionMax } from '../lib/execution-model-version.js';
|
|
18
17
|
import { readExecutionModelCap } from '../lib/agentLoop.js';
|
|
18
|
+
import { req } from '../lib/requirement-ids.js';
|
|
19
19
|
|
|
20
20
|
describe('agent-loop-version5-shape: advertisement (RFC 0061 §A)', () => {
|
|
21
21
|
it('executionModel.statefulResume/transcriptWindow are well-formed when present', async () => {
|
|
@@ -24,13 +24,13 @@ describe('agent-loop-version5-shape: advertisement (RFC 0061 §A)', () => {
|
|
|
24
24
|
if (em.statefulResume !== undefined) {
|
|
25
25
|
expect(
|
|
26
26
|
typeof em.statefulResume,
|
|
27
|
-
|
|
27
|
+
req('openwop.it.agent-loop-version5-shape.executionmodel-statefulresume-transcriptwindow-are-well-formed-when-present', 'capabilities.schema.json §multiAgent.executionModel', 'statefulResume MUST be a boolean when present'),
|
|
28
28
|
).toBe('boolean');
|
|
29
29
|
}
|
|
30
30
|
if (em.transcriptWindow !== undefined) {
|
|
31
31
|
expect(
|
|
32
32
|
typeof em.transcriptWindow === 'number' && (em.transcriptWindow as number) >= 1,
|
|
33
|
-
|
|
33
|
+
req('openwop.it.agent-loop-version5-shape.executionmodel-statefulresume-transcriptwindow-are-well-formed-when-present', 'capabilities.schema.json §multiAgent.executionModel', 'transcriptWindow MUST be a positive integer when present'),
|
|
34
34
|
).toBe(true);
|
|
35
35
|
}
|
|
36
36
|
if (typeof em.version === 'number') {
|
|
@@ -40,7 +40,7 @@ describe('agent-loop-version5-shape: advertisement (RFC 0061 §A)', () => {
|
|
|
40
40
|
const max = executionModelVersionMax();
|
|
41
41
|
expect(
|
|
42
42
|
(em.version as number) >= 1 && (em.version as number) <= max,
|
|
43
|
-
|
|
43
|
+
req('openwop.it.agent-loop-version5-shape.executionmodel-statefulresume-transcriptwindow-are-well-formed-when-present', 'capabilities.schema.json §multiAgent.executionModel', `version MUST be within the 1–${max} ladder (schema maximum)`),
|
|
44
44
|
).toBe(true);
|
|
45
45
|
}
|
|
46
46
|
});
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
import { describe, it, expect } from 'vitest';
|
|
14
14
|
import { softSkip } from '../lib/soft-skip.js';
|
|
15
|
-
import { driver } from '../lib/driver.js';
|
|
16
15
|
import { readExecutionModelCap, isVersion5, hasWorkspace, invokeAgentLoop } from '../lib/agentLoop.js';
|
|
16
|
+
import { req } from '../lib/requirement-ids.js';
|
|
17
17
|
|
|
18
18
|
describe('agent-loop-workspace-snapshot (RFC 0061 §C)', () => {
|
|
19
19
|
it('a turn-i workspace write is invisible to turn i, visible to turn i+1', async () => {
|
|
@@ -24,11 +24,11 @@ describe('agent-loop-workspace-snapshot (RFC 0061 §C)', () => {
|
|
|
24
24
|
const vis = res.workspaceVisible ?? {};
|
|
25
25
|
expect(
|
|
26
26
|
vis.atWriteTurn,
|
|
27
|
-
|
|
27
|
+
req('openwop.it.agent-loop-workspace-snapshot.a-turn-i-workspace-write-is-invisible-to-turn-i-visible-to-turn-i-1', 'RFC 0061 §C', 'a workspace write during turn i MUST be invisible to turn i\'s snapshot'),
|
|
28
28
|
).toBe(false);
|
|
29
29
|
expect(
|
|
30
30
|
vis.atNextTurn,
|
|
31
|
-
|
|
31
|
+
req('openwop.it.agent-loop-workspace-snapshot.a-turn-i-workspace-write-is-invisible-to-turn-i-visible-to-turn-i-1', 'RFC 0061 §C', 'a workspace write during turn i MUST be visible to turn i+1'),
|
|
32
32
|
).toBe(true);
|
|
33
33
|
});
|
|
34
34
|
});
|
|
@@ -34,9 +34,9 @@ import { join } from 'node:path';
|
|
|
34
34
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
35
35
|
import addFormats from 'ajv-formats';
|
|
36
36
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
37
|
+
import { req } from '../lib/requirement-ids.js';
|
|
37
38
|
|
|
38
39
|
const BASE = 'https://openwop.dev/spec/v1/';
|
|
39
|
-
const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
|
|
40
40
|
function loadSchema(name: string): Record<string, unknown> {
|
|
41
41
|
return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
|
|
42
42
|
}
|
|
@@ -61,56 +61,56 @@ describe('agent-manifest-role-profile: AgentManifest.role + Skill profile (RFC 0
|
|
|
61
61
|
it('NO role + any memoryShape (conversation+longTerm) validates — explicit, never inferred', () => {
|
|
62
62
|
expect(
|
|
63
63
|
manifest({ ...base, memoryShape: { scratchpad: true, conversation: true, longTerm: true } }),
|
|
64
|
-
|
|
64
|
+
req('openwop.it.agent-manifest-role-profile.no-role-any-memoryshape-conversation-longterm-validates-explicit-never-inferred', 'RFC 0131 §A', 'absent role ⇒ unconstrained; nothing reclassifies (today’s meaning, unchanged)'),
|
|
65
65
|
).toBe(true);
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
it('NO role + handoff + rich memory validates — handoff presence does NOT imply skill', () => {
|
|
69
69
|
expect(
|
|
70
70
|
manifest({ ...base, handoff, memoryShape: { conversation: true, longTerm: true } }),
|
|
71
|
-
|
|
71
|
+
req('openwop.it.agent-manifest-role-profile.no-role-handoff-rich-memory-validates-handoff-presence-does-not-imply-skill', 'RFC 0131 §A / Motivation 2', 'handoff is an interop contract, orthogonal to role — no inference'),
|
|
72
72
|
).toBe(true);
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
it('role:"skill" WITH handoff + scratchpad-only memory validates', () => {
|
|
76
76
|
expect(
|
|
77
77
|
manifest({ ...base, role: 'skill', handoff, memoryShape: { scratchpad: true, conversation: false, longTerm: false } }),
|
|
78
|
-
|
|
78
|
+
req('openwop.it.agent-manifest-role-profile.role-skill-with-handoff-scratchpad-only-memory-validates', 'RFC 0131 §B', 'a well-formed skill (handoff + scratchpad-only) MUST validate'),
|
|
79
79
|
).toBe(true);
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
it('role:"skill" with memoryShape.longTerm:true FAILS validation (malformed, not degraded)', () => {
|
|
83
83
|
expect(
|
|
84
84
|
manifest({ ...base, role: 'skill', handoff, memoryShape: { scratchpad: true, longTerm: true } }),
|
|
85
|
-
|
|
85
|
+
req('openwop.it.agent-manifest-role-profile.role-skill-with-memoryshape-longterm-true-fails-validation-malformed-not-degrade', 'RFC 0131 §B', 'a skill declaring longTerm memory is malformed — reject at publish/install'),
|
|
86
86
|
).toBe(false);
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
it('role:"skill" with memoryShape.conversation:true FAILS validation', () => {
|
|
90
90
|
expect(
|
|
91
91
|
manifest({ ...base, role: 'skill', handoff, memoryShape: { conversation: true } }),
|
|
92
|
-
|
|
92
|
+
req('openwop.it.agent-manifest-role-profile.role-skill-with-memoryshape-conversation-true-fails-validation', 'RFC 0131 §B', 'a skill declaring conversation memory is malformed — reject'),
|
|
93
93
|
).toBe(false);
|
|
94
94
|
});
|
|
95
95
|
|
|
96
96
|
it('role:"skill" MISSING handoff FAILS validation', () => {
|
|
97
97
|
expect(
|
|
98
98
|
manifest({ ...base, role: 'skill', memoryShape: { scratchpad: true } }),
|
|
99
|
-
|
|
99
|
+
req('openwop.it.agent-manifest-role-profile.role-skill-missing-handoff-fails-validation', 'RFC 0131 §B', 'a skill MUST declare handoff (task→return capability)'),
|
|
100
100
|
).toBe(false);
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
it('role:"assistant" with conversation+longTerm (and handoff) validates — no profile binds it', () => {
|
|
104
104
|
expect(
|
|
105
105
|
manifest({ ...base, role: 'assistant', handoff, memoryShape: { scratchpad: true, conversation: true, longTerm: true } }),
|
|
106
|
-
|
|
106
|
+
req('openwop.it.agent-manifest-role-profile.role-assistant-with-conversation-longterm-and-handoff-validates-no-profile-binds', 'RFC 0131 §A', 'an assistant’s conversation + long-term memory are legitimate; it MAY ship handoff'),
|
|
107
107
|
).toBe(true);
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
it('role outside the ["skill","assistant"] enum FAILS', () => {
|
|
111
111
|
expect(
|
|
112
112
|
manifest({ ...base, role: 'agent' }),
|
|
113
|
-
|
|
113
|
+
req('openwop.it.agent-manifest-role-profile.role-outside-the-skill-assistant-enum-fails', 'RFC 0131 §A', '"agent" is not an enum value (it is the overloaded word the RFC removes)'),
|
|
114
114
|
).toBe(false);
|
|
115
115
|
});
|
|
116
116
|
});
|