@openwop/openwop-conformance 1.163.0 → 2.0.0-rc.1
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 +262 -14
- package/dist/lib/certification-bundle-v3.js +142 -0
- package/dist/lib/paths.js +25 -3
- package/dist/lib/requirement-ids.js +57 -4
- package/dist/lib/requirement-ledger.js +1 -0
- package/dist/lib/scenario-disposition.js +6 -1
- package/dist/lib/spec-coherence.js +13 -32
- package/dist/spec-artifacts.lock.json +5 -0
- package/package.json +11 -33
- package/requirements.json +22892 -11701
- package/scenario-majors.json +1493 -0
- package/schemas/CORPUS-STAMP.json +137 -5
- package/src/cli.ts +236 -19
- package/src/global-setup.ts +3 -2
- package/src/lib/certification-bundle-v3.ts +175 -0
- package/src/lib/corpus-stamp.ts +29 -1
- package/src/lib/driver.ts +9 -1
- package/src/lib/era2-seed.ts +197 -0
- package/src/lib/paths.ts +25 -3
- package/src/lib/requirement-ids.ts +54 -4
- package/src/lib/requirement-ledger.ts +7 -1
- package/src/lib/scenario-disposition.ts +6 -1
- package/src/lib/seams.ts +45 -0
- package/src/lib/spec-coherence.ts +15 -32
- package/src/lib/v2.ts +62 -0
- 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/v2-approver-enforced.test.ts +97 -0
- package/src/scenarios/v2-assurance-downgrade-audited.test.ts +75 -0
- package/src/scenarios/v2-bundle-v3-signed.test.ts +96 -0
- package/src/scenarios/v2-capabilities-root-closed.test.ts +63 -0
- package/src/scenarios/v2-capability-record-shape.test.ts +104 -0
- package/src/scenarios/v2-chain-pin-exact.test.ts +118 -0
- package/src/scenarios/v2-coherence-not-in-bundle.test.ts +98 -0
- package/src/scenarios/v2-compensation-read-projection.test.ts +85 -0
- package/src/scenarios/v2-configurable-closed.test.ts +67 -0
- package/src/scenarios/v2-dual-stack-negotiation.test.ts +118 -0
- package/src/scenarios/v2-effect-identity-business-key.test.ts +132 -0
- package/src/scenarios/v2-effect-seam-manifest.test.ts +163 -0
- package/src/scenarios/v2-enum-growth-rule.test.ts +69 -0
- package/src/scenarios/v2-era-key.test.ts +86 -0
- package/src/scenarios/v2-error-registry.test.ts +89 -0
- package/src/scenarios/v2-event-type-closed.test.ts +97 -0
- package/src/scenarios/v2-fork-a-v1-run.test.ts +109 -0
- package/src/scenarios/v2-form-when-reuses-edge-conditions.test.ts +70 -0
- package/src/scenarios/v2-header-scheme.test.ts +67 -0
- package/src/scenarios/v2-id-grammar.test.ts +77 -0
- package/src/scenarios/v2-idempotency-key-grammar.test.ts +65 -0
- package/src/scenarios/v2-interrupt-token-scheme.test.ts +55 -0
- package/src/scenarios/v2-lane-issuer-advertised.test.ts +62 -0
- package/src/scenarios/v2-legacy-profiles-absent.test.ts +78 -0
- package/src/scenarios/v2-manifest-ceiling-refused.test.ts +130 -0
- package/src/scenarios/v2-manifest-hatch-carried.test.ts +120 -0
- package/src/scenarios/v2-min-client-version.test.ts +48 -0
- package/src/scenarios/v2-minimum-version-refused.test.ts +141 -0
- package/src/scenarios/v2-mrtr-rounds-ceiling.test.ts +95 -0
- package/src/scenarios/v2-negotiation-authenticated.test.ts +125 -0
- package/src/scenarios/v2-negotiation-decided-emitted.test.ts +149 -0
- package/src/scenarios/v2-no-transport-advertisement.test.ts +57 -0
- package/src/scenarios/v2-owner-subject-required.test.ts +72 -0
- package/src/scenarios/v2-pack-isolation.test.ts +147 -0
- package/src/scenarios/v2-payload-registry-closed.test.ts +110 -0
- package/src/scenarios/v2-peer-dependency-declared.test.ts +132 -0
- package/src/scenarios/v2-pinned-run-disposition.test.ts +124 -0
- package/src/scenarios/v2-poll-cursor-v2.test.ts +114 -0
- package/src/scenarios/v2-preferred-version-default.test.ts +83 -0
- package/src/scenarios/v2-profiles-derived-only.test.ts +70 -0
- package/src/scenarios/v2-provider-conflict.test.ts +115 -0
- package/src/scenarios/v2-refresh-sla.test.ts +78 -0
- package/src/scenarios/v2-relaxation-recorded.test.ts +134 -0
- package/src/scenarios/v2-revocation-honored.test.ts +66 -0
- package/src/scenarios/v2-subject-link-record.test.ts +102 -0
- package/src/scenarios/v2-unmapped-type-refused.test.ts +95 -0
- package/src/scenarios/v2-v1-events-translated.test.ts +105 -0
- package/src/scenarios/v2-v1-signed-webhook-accepted.test.ts +109 -0
- package/src/scenarios/v2-webhook-durable-delivery.test.ts +238 -0
- package/src/scenarios/v2-well-known-one-resource.test.ts +129 -0
- 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 +44 -6
- 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 -4160
- 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
|
@@ -28,8 +28,7 @@ import addFormats from 'ajv-formats';
|
|
|
28
28
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
29
29
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
30
30
|
import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
|
|
31
|
-
|
|
32
|
-
const cite = (section: string, requirement: string): string => `${section} — ${requirement}`;
|
|
31
|
+
import { req } from '../lib/requirement-ids.js';
|
|
33
32
|
const CAPS = join(SCHEMAS_DIR, 'capabilities.schema.json');
|
|
34
33
|
const MANIFEST = join(SCHEMAS_DIR, 'workflow-chain-pack-manifest.schema.json');
|
|
35
34
|
|
|
@@ -40,20 +39,20 @@ function loadSchema(path: string): Record<string, unknown> {
|
|
|
40
39
|
describe('chain-subchain-fanout §A: capability + manifest shape (RFC 0133, always-on)', () => {
|
|
41
40
|
it('capabilities.schema.json §workflowChainPacks.subChains requires supported:boolean + maxDepth default 8', () => {
|
|
42
41
|
const raw = readFileSync(CAPS, 'utf8');
|
|
43
|
-
expect(raw.includes('"subChains"'),
|
|
42
|
+
expect(raw.includes('"subChains"'), req('openwop.it.chain-subchain-fanout.capabilities-schema-json-workflowchainpacks-subchains-requires-supported-boolean', 'capabilities §workflowChainPacks', 'the subChains block MUST exist')).toBe(
|
|
44
43
|
true,
|
|
45
44
|
);
|
|
46
45
|
const schema = loadSchema(CAPS);
|
|
47
46
|
// The subChains sub-block MUST be present somewhere in the workflowChainPacks family.
|
|
48
47
|
expect(
|
|
49
48
|
JSON.stringify(schema).includes('"subChains"'),
|
|
50
|
-
|
|
49
|
+
req('openwop.it.chain-subchain-fanout.capabilities-schema-json-workflowchainpacks-subchains-requires-supported-boolean', 'capabilities §subChains', 'declared in the capabilities schema'),
|
|
51
50
|
).toBe(true);
|
|
52
51
|
expect(
|
|
53
52
|
raw.includes('sub_chain_unsupported'),
|
|
54
|
-
|
|
53
|
+
req('openwop.it.chain-subchain-fanout.capabilities-schema-json-workflowchainpacks-subchains-requires-supported-boolean', 'capabilities §subChains', 'the description MUST cite the sub_chain_unsupported refusal'),
|
|
55
54
|
).toBe(true);
|
|
56
|
-
expect(raw.includes('"default": 8'),
|
|
55
|
+
expect(raw.includes('"default": 8'), req('openwop.it.chain-subchain-fanout.capabilities-schema-json-workflowchainpacks-subchains-requires-supported-boolean', 'capabilities §subChains.maxDepth', 'RECOMMENDED default 8')).toBe(true);
|
|
57
56
|
});
|
|
58
57
|
|
|
59
58
|
it('manifest schema accepts a core.dispatch fan-out over a subChainRef worker', () => {
|
|
@@ -93,7 +92,7 @@ describe('chain-subchain-fanout §A: capability + manifest shape (RFC 0133, alwa
|
|
|
93
92
|
},
|
|
94
93
|
],
|
|
95
94
|
};
|
|
96
|
-
expect(validate(pack),
|
|
95
|
+
expect(validate(pack), req('openwop.it.chain-subchain-fanout.manifest-schema-accepts-a-core-dispatch-fan-out-over-a-subchainref-worker', 'manifest §subChains', `a subChainRef fan-out validates: ${ajv.errorsText(validate.errors)}`)).toBe(
|
|
97
96
|
true,
|
|
98
97
|
);
|
|
99
98
|
});
|
|
@@ -120,7 +119,7 @@ describe('chain-subchain-fanout §A: capability + manifest shape (RFC 0133, alwa
|
|
|
120
119
|
};
|
|
121
120
|
expect(
|
|
122
121
|
validate(pack),
|
|
123
|
-
|
|
122
|
+
req('openwop.it.chain-subchain-fanout.manifest-schema-rejects-a-concrete-config-workflowid-inside-a-fragment-the-1-2-n', 'manifest §config not-guard', 'a chain MUST NOT pin a concrete config.workflowId'),
|
|
124
123
|
).toBe(false);
|
|
125
124
|
});
|
|
126
125
|
});
|
|
@@ -134,6 +133,6 @@ describe('chain-subchain-fanout §B: host child fan-out (RFC 0133, capability-ga
|
|
|
134
133
|
// invariant `sub-chain-child-tenant-scoped` (child owned by parent's tenant).
|
|
135
134
|
// The from-chain response MUST carry the §1.3 contract: { workflowId,
|
|
136
135
|
// subChainWorkflowIds[] (tenant-scoped, deduped), nodeCount }.
|
|
137
|
-
expect(wcp?.subChains?.supported, 'host advertising subChains.supported implements child fan-out').toBe(true);
|
|
136
|
+
expect(wcp?.subChains?.supported, req('openwop.it.chain-subchain-fanout.fans-out-n-child-runs-over-a-subchainref-worker-returns-the-from-chain-contract', 'RFC 0133 §1.2', 'host advertising subChains.supported implements child fan-out')).toBe(true);
|
|
138
137
|
});
|
|
139
138
|
});
|
|
@@ -30,9 +30,7 @@ import {
|
|
|
30
30
|
mintChildWorkflowId,
|
|
31
31
|
type WorkflowChain,
|
|
32
32
|
} from '../lib/workflow-chain-expansion.js';
|
|
33
|
-
|
|
34
|
-
/** Server-free assertion-message helper (mirrors driver.describe without OPENWOP_BASE_URL). */
|
|
35
|
-
const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
|
|
33
|
+
import { req } from '../lib/requirement-ids.js';
|
|
36
34
|
const SPEC = 'workflow-chain-packs.md §"Sub-chain composition (RFC 0133)"';
|
|
37
35
|
|
|
38
36
|
/** A leaf child chain — one plain node, no further composition. */
|
|
@@ -83,53 +81,53 @@ const ctx = (tenantId = 'tenant-a') => ({
|
|
|
83
81
|
describe('chain-subchain-sibling: co-registration (RFC 0133 §1, server-free)', () => {
|
|
84
82
|
it('co-registers the referenced sibling as its own workflow', () => {
|
|
85
83
|
const { children } = expandChainTree(PARENT, ctx());
|
|
86
|
-
expect(children.length,
|
|
87
|
-
expect(children[0]?.chainId,
|
|
84
|
+
expect(children.length, req('openwop.it.chain-subchain-sibling.co-registers-the-referenced-sibling-as-its-own-workflow', SPEC, '§1.3 step 2 — one distinct sibling ref ⇒ one co-registered child')).toBe(1);
|
|
85
|
+
expect(children[0]?.chainId, req('openwop.it.chain-subchain-sibling.co-registers-the-referenced-sibling-as-its-own-workflow', SPEC, 'child carries the composed chainId')).toBe('lesson-batch');
|
|
88
86
|
expect(
|
|
89
87
|
children[0]?.fragment.nodes.length,
|
|
90
|
-
|
|
88
|
+
req('openwop.it.chain-subchain-sibling.co-registers-the-referenced-sibling-as-its-own-workflow', SPEC, 'child is a fully expanded fragment (its own registered workflow)'),
|
|
91
89
|
).toBe(1);
|
|
92
90
|
});
|
|
93
91
|
|
|
94
92
|
it('mints a DETERMINISTIC, TENANT-SCOPED, version-pinned child id', () => {
|
|
95
93
|
const { children } = expandChainTree(PARENT, ctx());
|
|
96
94
|
const expected = mintChildWorkflowId('tenant-a', 'lesson-batch', '1.0.0');
|
|
97
|
-
expect(children[0]?.childWorkflowId,
|
|
95
|
+
expect(children[0]?.childWorkflowId, req('openwop.it.chain-subchain-sibling.mints-a-deterministic-tenant-scoped-version-pinned-child-id', SPEC, '§1.3 step 2 — deterministic (tenantId, childChainId, version) id')).toBe(
|
|
98
96
|
expected,
|
|
99
97
|
);
|
|
100
98
|
// Re-instantiating in the same tenant converges on the same id.
|
|
101
99
|
const again = expandChainTree(PARENT, ctx());
|
|
102
|
-
expect(again.children[0]?.childWorkflowId,
|
|
100
|
+
expect(again.children[0]?.childWorkflowId, req('openwop.it.chain-subchain-sibling.mints-a-deterministic-tenant-scoped-version-pinned-child-id', SPEC, 'repeat instantiation in-tenant converges')).toBe(expected);
|
|
103
101
|
});
|
|
104
102
|
|
|
105
103
|
it('scopes the child id per TENANT — two tenants NEVER collide on the global registry (isolation)', () => {
|
|
106
104
|
const a = expandChainTree(PARENT, ctx('tenant-a')).children[0]?.childWorkflowId;
|
|
107
105
|
const b = expandChainTree(PARENT, ctx('tenant-b')).children[0]?.childWorkflowId;
|
|
108
|
-
expect(a,
|
|
106
|
+
expect(a, req('openwop.it.chain-subchain-sibling.scopes-the-child-id-per-tenant-two-tenants-never-collide-on-the-global-registry', SPEC, 'tenant-a mints an id')).toBeTruthy();
|
|
109
107
|
expect(
|
|
110
108
|
a !== b,
|
|
111
|
-
|
|
109
|
+
req('openwop.it.chain-subchain-sibling.scopes-the-child-id-per-tenant-two-tenants-never-collide-on-the-global-registry', SPEC, '§1.3 SECURITY sub-chain-child-tenant-scoped — distinct tenants ⇒ distinct child ids, no cross-tenant collision'),
|
|
112
110
|
).toBe(true);
|
|
113
111
|
});
|
|
114
112
|
|
|
115
113
|
it('registers a child referenced twice exactly ONCE (dedup by deterministic id)', () => {
|
|
116
114
|
const { children } = expandChainTree(PARENT, ctx());
|
|
117
115
|
const ids = children.map((c) => c.childWorkflowId);
|
|
118
|
-
expect(new Set(ids).size,
|
|
119
|
-
expect(ids.length,
|
|
116
|
+
expect(new Set(ids).size, req('openwop.it.chain-subchain-sibling.registers-a-child-referenced-twice-exactly-once-dedup-by-deterministic-id', SPEC, '§1.3 step 2 — a shared child registers once')).toBe(ids.length);
|
|
117
|
+
expect(ids.length, req('openwop.it.chain-subchain-sibling.registers-a-child-referenced-twice-exactly-once-dedup-by-deterministic-id', SPEC, 'both build-0 + build-1 collapse to one child')).toBe(1);
|
|
120
118
|
});
|
|
121
119
|
|
|
122
120
|
it('rewrites config.subChainRef → the minted child config.workflowId', () => {
|
|
123
121
|
const { parent } = expandChainTree(PARENT, ctx());
|
|
124
122
|
const expected = mintChildWorkflowId('tenant-a', 'lesson-batch', '1.0.0');
|
|
125
123
|
const dispatchNodes = parent.nodes.filter((n) => n.typeId === 'core.subWorkflow');
|
|
126
|
-
expect(dispatchNodes.length,
|
|
124
|
+
expect(dispatchNodes.length, req('openwop.it.chain-subchain-sibling.rewrites-config-subchainref-the-minted-child-config-workflowid', SPEC, 'both dispatch nodes present')).toBe(2);
|
|
127
125
|
for (const n of dispatchNodes) {
|
|
128
126
|
const config = n.config as Record<string, unknown>;
|
|
129
|
-
expect(config['workflowId'],
|
|
127
|
+
expect(config['workflowId'], req('openwop.it.chain-subchain-sibling.rewrites-config-subchainref-the-minted-child-config-workflowid', SPEC, '§1.3 step 3 — subChainRef rewritten to minted child id')).toBe(expected);
|
|
130
128
|
expect(
|
|
131
129
|
'subChainRef' in config,
|
|
132
|
-
|
|
130
|
+
req('openwop.it.chain-subchain-sibling.rewrites-config-subchainref-the-minted-child-config-workflowid', SPEC, '§1.3 step 3 — transient subChainRef key dropped from the runtime config'),
|
|
133
131
|
).toBe(false);
|
|
134
132
|
}
|
|
135
133
|
});
|
|
@@ -140,7 +138,7 @@ describe('chain-subchain-sibling: co-registration (RFC 0133 §1, server-free)',
|
|
|
140
138
|
const referenced = parent.nodes
|
|
141
139
|
.filter((n) => n.typeId === 'core.subWorkflow')
|
|
142
140
|
.map((n) => (n.config as Record<string, unknown>)['workflowId']);
|
|
143
|
-
expect(referenced.every((id) => id === childId),
|
|
141
|
+
expect(referenced.every((id) => id === childId), req('openwop.it.chain-subchain-sibling.preserves-the-child-reference-at-runtime-concrete-workflowid-unlike-inline-mode', SPEC, 'parent HOLDS the co-registered child at runtime')).toBe(
|
|
144
142
|
true,
|
|
145
143
|
);
|
|
146
144
|
});
|
|
@@ -33,6 +33,8 @@ import { describe, it, expect } from 'vitest';
|
|
|
33
33
|
import { driver } from '../lib/driver.js';
|
|
34
34
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
35
35
|
import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
|
|
36
|
+
import { req } from '../lib/requirement-ids.js';
|
|
37
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
36
38
|
|
|
37
39
|
const PROFILE = 'openwop-channel-presence';
|
|
38
40
|
const SUBJECT_REF = /^(user|agent):.+/;
|
|
@@ -47,37 +49,37 @@ describe('channel-presence-behavioral (RFC 0110 §Conformance)', () => {
|
|
|
47
49
|
|
|
48
50
|
const conversationId = 'conf:channel-presence:c1';
|
|
49
51
|
const res = await driver.post('/v1/host/sample/channel-presence/snapshot', { conversationId, member: 'user:conformance-runner' });
|
|
50
|
-
if (res.status === 404 || res.status === 405) return; // seam unwired — host witnesses via its own route test (dual-staging)
|
|
52
|
+
if (res.status === 404 || res.status === 405) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 405` returned early (seam unwired — host witnesses via its own route test (dual-staging)) (seam, prior step, or fixture unavailable)'); // seam unwired — host witnesses via its own route test (dual-staging)
|
|
51
53
|
|
|
52
54
|
expect(
|
|
53
55
|
res.status === 200,
|
|
54
|
-
|
|
56
|
+
req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal', 'the presence snapshot seam MUST return 200 for a member'),
|
|
55
57
|
).toBe(true);
|
|
56
58
|
const snap = res.json as PresenceSnapshot;
|
|
57
59
|
|
|
58
60
|
// MUST 1 — CLOSED shape: exactly conversationId / present / typing (no PII field rides).
|
|
59
61
|
expect(
|
|
60
62
|
Object.keys(snap).sort().join(','),
|
|
61
|
-
|
|
63
|
+
req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal', 'channel.presence carries ONLY conversationId/present/typing (no PII)'),
|
|
62
64
|
).toBe('conversationId,present,typing');
|
|
63
|
-
expect(snap.conversationId,
|
|
65
|
+
expect(snap.conversationId, req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal', 'the snapshot echoes the conversationId')).toBe(conversationId);
|
|
64
66
|
|
|
65
67
|
// MUST 2 — every ref is an opaque RFC 0041 subject ref (no PII).
|
|
66
68
|
for (const ref of [...snap.present, ...snap.typing]) {
|
|
67
69
|
expect(
|
|
68
70
|
SUBJECT_REF.test(ref),
|
|
69
|
-
|
|
71
|
+
req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal / RFC 0041', `present/typing ref "${ref}" MUST be an opaque user:/agent: subject ref`),
|
|
70
72
|
).toBe(true);
|
|
71
73
|
}
|
|
72
74
|
// typing is a subset of present.
|
|
73
75
|
for (const ref of snap.typing) {
|
|
74
|
-
expect(snap.present.includes(ref),
|
|
76
|
+
expect(snap.present.includes(ref), req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal', 'every typing ref MUST also be present')).toBe(true);
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
// MUST 3 — NON-VACUOUS: the snapshotting member is present.
|
|
78
80
|
expect(
|
|
79
81
|
snap.present.includes('user:conformance-runner'),
|
|
80
|
-
|
|
82
|
+
req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal', 'the snapshotting member MUST appear in present (members-only, real)'),
|
|
81
83
|
).toBe(true);
|
|
82
84
|
});
|
|
83
85
|
});
|
|
@@ -34,8 +34,7 @@ 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
|
-
|
|
38
|
-
const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
|
|
37
|
+
import { req } from '../lib/requirement-ids.js';
|
|
39
38
|
|
|
40
39
|
function loadSchema(name: string): Record<string, unknown> {
|
|
41
40
|
return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
|
|
@@ -49,26 +48,26 @@ describe('channel-presence-shape: the channel.presence payload (RFC 0110 §Propo
|
|
|
49
48
|
it('a conforming presence snapshot (present + typing) validates', () => {
|
|
50
49
|
expect(
|
|
51
50
|
presence({ conversationId: 'chan-eng', present: ['user:alice', 'agent:iris'], typing: ['user:alice'] }),
|
|
52
|
-
|
|
51
|
+
req('openwop.it.channel-presence-shape.a-conforming-presence-snapshot-present-typing-validates', 'RFC 0110 §Proposal', 'a conforming channel.presence payload MUST validate'),
|
|
53
52
|
).toBe(true);
|
|
54
53
|
});
|
|
55
54
|
|
|
56
55
|
it('typing is OPTIONAL — a snapshot with nobody typing validates', () => {
|
|
57
56
|
expect(
|
|
58
57
|
presence({ conversationId: 'chan-eng', present: ['user:alice'] }),
|
|
59
|
-
|
|
58
|
+
req('openwop.it.channel-presence-shape.typing-is-optional-a-snapshot-with-nobody-typing-validates', 'RFC 0110 §Proposal', 'typing is optional'),
|
|
60
59
|
).toBe(true);
|
|
61
60
|
});
|
|
62
61
|
|
|
63
62
|
it('conversationId and present are REQUIRED', () => {
|
|
64
|
-
expect(presence({ present: ['user:a'] }),
|
|
65
|
-
expect(presence({ conversationId: 'c' }),
|
|
63
|
+
expect(presence({ present: ['user:a'] }), req('openwop.it.channel-presence-shape.conversationid-and-present-are-required', 'RFC 0110 §Proposal', 'conversationId is required')).toBe(false);
|
|
64
|
+
expect(presence({ conversationId: 'c' }), req('openwop.it.channel-presence-shape.conversationid-and-present-are-required', 'RFC 0110 §Proposal', 'present is required')).toBe(false);
|
|
66
65
|
});
|
|
67
66
|
|
|
68
67
|
it('the payload is CLOSED — a non-subject-ref field (ip/location) MUST be rejected (the no-PII guard)', () => {
|
|
69
68
|
expect(
|
|
70
69
|
presence({ conversationId: 'c', present: ['user:a'], ip: '10.0.0.1' }),
|
|
71
|
-
|
|
70
|
+
req('openwop.it.channel-presence-shape.the-payload-is-closed-a-non-subject-ref-field-ip-location-must-be-rejected-the-n', 'RFC 0110 §Proposal', 'channel.presence MUST forbid extra keys — no PII rides the payload'),
|
|
72
71
|
).toBe(false);
|
|
73
72
|
});
|
|
74
73
|
});
|
|
@@ -77,7 +76,7 @@ describe('channel-presence-shape: event type + capability advertisement (RFC 011
|
|
|
77
76
|
it('run-event.schema.json enumerates `channel.presence` as a RunEvent type', () => {
|
|
78
77
|
const re = loadSchema('run-event.schema.json');
|
|
79
78
|
const enumVals = JSON.stringify(re);
|
|
80
|
-
expect(enumVals.includes('"channel.presence"'),
|
|
79
|
+
expect(enumVals.includes('"channel.presence"'), req('openwop.it.channel-presence-shape.run-event-schema-json-enumerates-channel-presence-as-a-runevent-type', 'RFC 0110 §Proposal', 'channel.presence MUST be a declared RunEvent type')).toBe(true);
|
|
81
80
|
});
|
|
82
81
|
|
|
83
82
|
it('capabilities.schema.json declares channelPresence with supported, closed', () => {
|
|
@@ -85,9 +84,9 @@ describe('channel-presence-shape: event type + capability advertisement (RFC 011
|
|
|
85
84
|
const block = (caps.properties as Record<string, Record<string, unknown>>).channelPresence as
|
|
86
85
|
| { properties?: Record<string, unknown>; required?: string[]; additionalProperties?: boolean }
|
|
87
86
|
| undefined;
|
|
88
|
-
expect(block,
|
|
89
|
-
expect(block?.properties?.supported,
|
|
90
|
-
expect(block?.required,
|
|
91
|
-
expect(block?.additionalProperties,
|
|
87
|
+
expect(block, req('openwop.it.channel-presence-shape.capabilities-schema-json-declares-channelpresence-with-supported-closed', 'RFC 0110 §Conformance', 'capabilities.channelPresence MUST be declared')).toBeDefined();
|
|
88
|
+
expect(block?.properties?.supported, req('openwop.it.channel-presence-shape.capabilities-schema-json-declares-channelpresence-with-supported-closed', 'RFC 0110 §Conformance', 'channelPresence.supported MUST be declared')).toBeDefined();
|
|
89
|
+
expect(block?.required, req('openwop.it.channel-presence-shape.capabilities-schema-json-declares-channelpresence-with-supported-closed', 'RFC 0110 §Conformance', 'supported MUST be required on the block')).toContain('supported');
|
|
90
|
+
expect(block?.additionalProperties, req('openwop.it.channel-presence-shape.capabilities-schema-json-declares-channelpresence-with-supported-closed', 'RFC 0110 §Conformance', 'the block MUST be closed')).toBe(false);
|
|
92
91
|
});
|
|
93
92
|
});
|
|
@@ -22,6 +22,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
22
22
|
import { driver } from '../lib/driver.js';
|
|
23
23
|
import { pollUntilTerminal } from '../lib/polling.js';
|
|
24
24
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
25
|
+
import { req } from '../lib/requirement-ids.js';
|
|
25
26
|
|
|
26
27
|
const WORKFLOW_ID = 'conformance-channel-ttl';
|
|
27
28
|
const SKIP_NO_FIXTURE = !isFixtureAdvertised(WORKFLOW_ID);
|
|
@@ -38,7 +39,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('channel-ttl: conformance-channel-ttl drops ent
|
|
|
38
39
|
const runId = (create.json as { runId: string }).runId;
|
|
39
40
|
|
|
40
41
|
const terminal = await pollUntilTerminal(runId);
|
|
41
|
-
expect(terminal.status,
|
|
42
|
+
expect(terminal.status, req('openwop.it.channel-ttl.after-the-post-ttl-write-the-channel-contains-exactly-one-entry-with-value-d',
|
|
42
43
|
'fixtures.md conformance-channel-ttl §Terminal status',
|
|
43
44
|
'fixture MUST reach terminal `completed`',
|
|
44
45
|
)).toBe('completed');
|
|
@@ -46,22 +47,22 @@ describe.skipIf(SKIP_NO_FIXTURE)('channel-ttl: conformance-channel-ttl drops ent
|
|
|
46
47
|
const variables = terminal.variables ?? {};
|
|
47
48
|
const events = variables.events as ChannelEntry[] | undefined;
|
|
48
49
|
|
|
49
|
-
expect(Array.isArray(events),
|
|
50
|
+
expect(Array.isArray(events), req('openwop.it.channel-ttl.after-the-post-ttl-write-the-channel-contains-exactly-one-entry-with-value-d',
|
|
50
51
|
'channels-and-reducers.md §append',
|
|
51
52
|
'channel state MUST be stored as an array of {value, _ts} entries',
|
|
52
53
|
)).toBe(true);
|
|
53
54
|
|
|
54
|
-
expect(events!.length,
|
|
55
|
+
expect(events!.length, req('openwop.it.channel-ttl.after-the-post-ttl-write-the-channel-contains-exactly-one-entry-with-value-d',
|
|
55
56
|
'channels-and-reducers.md §TTL — write-time filter',
|
|
56
57
|
'after the post-TTL write, exactly 1 entry MUST remain (the 3 priors aged out)',
|
|
57
58
|
)).toBe(1);
|
|
58
59
|
|
|
59
|
-
expect(events![0].value,
|
|
60
|
+
expect(events![0].value, req('openwop.it.channel-ttl.after-the-post-ttl-write-the-channel-contains-exactly-one-entry-with-value-d',
|
|
60
61
|
'fixtures.md conformance-channel-ttl §Topology',
|
|
61
62
|
'the surviving entry MUST be the post-delay write (value "d")',
|
|
62
63
|
)).toBe('d');
|
|
63
64
|
|
|
64
|
-
expect(typeof events![0]._ts,
|
|
65
|
+
expect(typeof events![0]._ts, req('openwop.it.channel-ttl.after-the-post-ttl-write-the-channel-contains-exactly-one-entry-with-value-d',
|
|
65
66
|
'channels-and-reducers.md §append entry shape',
|
|
66
67
|
'each channel entry MUST carry a numeric `_ts` write timestamp',
|
|
67
68
|
)).toBe('number');
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
import { describe, it, expect } from 'vitest';
|
|
30
|
-
import { driver } from '../lib/driver.js';
|
|
31
30
|
import { behaviorGate, behaviorGatePresent } from '../lib/behavior-gate.js';
|
|
32
31
|
import { readCardPacksCap, cardPacksSupported, executeCard } from '../lib/cardPacks.js';
|
|
32
|
+
import { req } from '../lib/requirement-ids.js';
|
|
33
33
|
|
|
34
34
|
const PROFILE = 'openwop-chat-card-packs';
|
|
35
35
|
|
|
@@ -40,13 +40,13 @@ describe('chat-card-pack-execution: prompt -> envelope -> typed artifact (RFC 00
|
|
|
40
40
|
if (!behaviorGatePresent(PROFILE, res)) return; // seam absent: skip default, FAIL strict
|
|
41
41
|
expect(
|
|
42
42
|
res.json['validated'],
|
|
43
|
-
|
|
43
|
+
req('openwop.it.chat-card-pack-execution.a-registered-card-produces-a-schema-validated-artifact', 'chat-card-packs.md "Card execution"', 'the host MUST validate the LLM output against the linked outputArtifactType schema'),
|
|
44
44
|
).toBe(true);
|
|
45
45
|
const evt = res.json['artifactCreated'] as { registered?: unknown } | undefined;
|
|
46
46
|
if (evt && 'registered' in evt) {
|
|
47
47
|
expect(
|
|
48
48
|
evt.registered,
|
|
49
|
-
|
|
49
|
+
req('openwop.it.chat-card-pack-execution.a-registered-card-produces-a-schema-validated-artifact', 'run-event-payloads.schema.json artifactCreated', 'a validated card output MUST emit artifact.created with registered:true'),
|
|
50
50
|
).toBe(true);
|
|
51
51
|
}
|
|
52
52
|
});
|
|
@@ -62,7 +62,7 @@ describe('chat-card-pack-execution: prompt -> envelope -> typed artifact (RFC 00
|
|
|
62
62
|
if (!behaviorGatePresent(PROFILE, res.json['contentTrust'])) return; // FAIL strict
|
|
63
63
|
expect(
|
|
64
64
|
res.json['contentTrust'],
|
|
65
|
-
|
|
65
|
+
req('openwop.it.chat-card-pack-execution.card-input-derived-prompt-content-propagates-contenttrust-untrusted-r2', 'chat-card-packs.md "Trust boundary" (R2)', 'a prompt segment derived from a card input MUST carry contentTrust:"untrusted"'),
|
|
66
66
|
).toBe('untrusted');
|
|
67
67
|
});
|
|
68
68
|
});
|
|
@@ -30,6 +30,7 @@ import Ajv2020 from 'ajv/dist/2020.js';
|
|
|
30
30
|
import addFormats from 'ajv-formats';
|
|
31
31
|
import type { ErrorObject } from 'ajv';
|
|
32
32
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
33
|
+
import { req } from '../lib/requirement-ids.js';
|
|
33
34
|
|
|
34
35
|
const SCHEMA_PATH = join(SCHEMAS_DIR, 'chat-card-pack-manifest.schema.json');
|
|
35
36
|
|
|
@@ -68,7 +69,7 @@ describe('category: chat-card-pack manifest validation', () => {
|
|
|
68
69
|
it('positive: a valid chat card pack manifest validates cleanly', () => {
|
|
69
70
|
expect(
|
|
70
71
|
validate(validManifest()),
|
|
71
|
-
`chat-card-packs.md §"Manifest format": a well-formed kind:"card" manifest MUST validate. Errors: ${JSON.stringify(validate.errors)}
|
|
72
|
+
req('openwop.it.chat-card-pack-manifest-validation.positive-a-valid-chat-card-pack-manifest-validates-cleanly', 'chat-card-packs.md', `chat-card-packs.md §"Manifest format": a well-formed kind:"card" manifest MUST validate. Errors: ${JSON.stringify(validate.errors)}`),
|
|
72
73
|
).toBe(true);
|
|
73
74
|
});
|
|
74
75
|
|
|
@@ -77,24 +78,24 @@ describe('category: chat-card-pack manifest validation', () => {
|
|
|
77
78
|
const errs = failsWith(manifest, 'additionalProperties');
|
|
78
79
|
expect(
|
|
79
80
|
errs.some((e) => (e.params as { additionalProperty?: string }).additionalProperty === 'artifactTypes'),
|
|
80
|
-
'chat-card-packs.md §"Pack kind": one kind per pack (additionalProperties:false)',
|
|
81
|
+
req('openwop.it.chat-card-pack-manifest-validation.negative-a-manifest-mixing-cards-and-artifacttypes-is-rejected', 'chat-card-packs.md', 'chat-card-packs.md §"Pack kind": one kind per pack (additionalProperties:false)'),
|
|
81
82
|
).toBe(true);
|
|
82
83
|
});
|
|
83
84
|
|
|
84
85
|
it('negative: an empty cards[] is rejected', () => {
|
|
85
|
-
expect(failsWith({ ...validManifest(), cards: [] }, 'minItems').length).toBeGreaterThan(0);
|
|
86
|
+
expect(failsWith({ ...validManifest(), cards: [] }, 'minItems').length, req('openwop.it.chat-card-pack-manifest-validation.negative-an-empty-cards-is-rejected', 'chat-card-packs.md', 'negative: an empty cards[] is rejected')).toBeGreaterThan(0);
|
|
86
87
|
});
|
|
87
88
|
|
|
88
89
|
it('negative: an uppercase-scope cardTypeId is rejected', () => {
|
|
89
90
|
const m = validManifest();
|
|
90
91
|
m.cards[0]!.cardTypeId = 'Vendor.Acme.Card';
|
|
91
|
-
expect(failsWith(m, 'pattern').length).toBeGreaterThan(0);
|
|
92
|
+
expect(failsWith(m, 'pattern').length, req('openwop.it.chat-card-pack-manifest-validation.negative-an-uppercase-scope-cardtypeid-is-rejected', 'chat-card-packs.md', 'negative: an uppercase-scope cardTypeId is rejected')).toBeGreaterThan(0);
|
|
92
93
|
});
|
|
93
94
|
|
|
94
95
|
it('negative: a card missing prompt is rejected', () => {
|
|
95
96
|
const m = validManifest();
|
|
96
97
|
delete (m.cards[0] as { prompt?: unknown }).prompt;
|
|
97
|
-
expect(failsWith(m, 'required').length).toBeGreaterThan(0);
|
|
98
|
+
expect(failsWith(m, 'required').length, req('openwop.it.chat-card-pack-manifest-validation.negative-a-card-missing-prompt-is-rejected', 'chat-card-packs.md', 'negative: a card missing prompt is rejected')).toBeGreaterThan(0);
|
|
98
99
|
});
|
|
99
100
|
|
|
100
101
|
it('negative: a non-portable inputs[].type (canvas-reference) is rejected', () => {
|
|
@@ -102,7 +103,7 @@ describe('category: chat-card-pack manifest validation', () => {
|
|
|
102
103
|
m.cards[0]!.inputs[0]!.type = 'canvas-reference';
|
|
103
104
|
expect(
|
|
104
105
|
failsWith(m, 'pattern').length,
|
|
105
|
-
'chat-card-packs.md §"Input fields": type is the closed portable enum OR a vendor.*/x- extension',
|
|
106
|
+
req('openwop.it.chat-card-pack-manifest-validation.negative-a-non-portable-inputs-type-canvas-reference-is-rejected', 'chat-card-packs.md', 'chat-card-packs.md §"Input fields": type is the closed portable enum OR a vendor.*/x- extension'),
|
|
106
107
|
).toBeGreaterThan(0);
|
|
107
108
|
});
|
|
108
109
|
|
|
@@ -111,7 +112,7 @@ describe('category: chat-card-pack manifest validation', () => {
|
|
|
111
112
|
m.cards[0]!.inputs[0]!.type = 'vendor.myndhyve.canvas-ref';
|
|
112
113
|
expect(
|
|
113
114
|
validate(m),
|
|
114
|
-
'chat-card-packs.md §"Input fields": a vendor.<org>.<kind> input type extension MUST validate (other hosts ignore it)',
|
|
115
|
+
req('openwop.it.chat-card-pack-manifest-validation.positive-a-vendor-prefixed-inputs-type-extension-is-tolerated', 'chat-card-packs.md', 'chat-card-packs.md §"Input fields": a vendor.<org>.<kind> input type extension MUST validate (other hosts ignore it)'),
|
|
115
116
|
).toBe(true);
|
|
116
117
|
});
|
|
117
118
|
|
|
@@ -121,7 +122,7 @@ describe('category: chat-card-pack manifest validation', () => {
|
|
|
121
122
|
m.cards[0]!.inputs[0]!.type = t;
|
|
122
123
|
expect(
|
|
123
124
|
validate(m),
|
|
124
|
-
`chat-card-packs.md §"Input fields": portable inputs[].type "${t}" MUST validate (G9 resolved 2026-05-27)
|
|
125
|
+
req('openwop.it.chat-card-pack-manifest-validation.positive-the-full-portable-inputs-type-subset-validates-g9-incl-multiselect-file', 'chat-card-packs.md', `chat-card-packs.md §"Input fields": portable inputs[].type "${t}" MUST validate (G9 resolved 2026-05-27)`),
|
|
125
126
|
).toBe(true);
|
|
126
127
|
}
|
|
127
128
|
});
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
import { describe, it, expect } from 'vitest';
|
|
21
21
|
import { softSkip } from '../lib/soft-skip.js';
|
|
22
22
|
import { driver } from '../lib/driver.js';
|
|
23
|
+
import { req } from '../lib/requirement-ids.js';
|
|
23
24
|
|
|
24
25
|
interface CommitmentCaps {
|
|
25
26
|
agents?: { commitments?: { supported?: boolean } };
|
|
@@ -54,14 +55,14 @@ describe('commitment-fired: fire contract (RFC 0068 §C, capability-gated)', ()
|
|
|
54
55
|
});
|
|
55
56
|
if (res.status === 404 || res.status === 501) return softSkip('blocked', 'seam not wired — soft-skip');
|
|
56
57
|
|
|
57
|
-
expect(res.status,
|
|
58
|
+
expect(res.status, req('openwop.it.commitment-fired.a-fired-commitment-emits-a-content-free-event-with-memory-provenance-exactly-onc', 'RFC 0068 §C', 'an advertised commitment seam MUST succeed')).toBe(200);
|
|
58
59
|
const r = res.json as FireResult;
|
|
59
60
|
|
|
60
61
|
// §C — required identifiers.
|
|
61
|
-
expect(r.event?.commitmentId,
|
|
62
|
+
expect(r.event?.commitmentId, req('openwop.it.commitment-fired.a-fired-commitment-emits-a-content-free-event-with-memory-provenance-exactly-onc', 'RFC 0068 §C', 'commitment.fired MUST carry commitmentId')).toBeTruthy();
|
|
62
63
|
expect(
|
|
63
64
|
r.event?.memoryRef,
|
|
64
|
-
|
|
65
|
+
req('openwop.it.commitment-fired.a-fired-commitment-emits-a-content-free-event-with-memory-provenance-exactly-onc', 'RFC 0068 §C.1', 'commitment.fired MUST carry the source memoryRef (CTI-1 provenance)'),
|
|
65
66
|
).toBeTruthy();
|
|
66
67
|
|
|
67
68
|
// §C.3 — content-free: the inferred intention text MUST NOT appear on the event.
|
|
@@ -69,7 +70,7 @@ describe('commitment-fired: fire contract (RFC 0068 §C, capability-gated)', ()
|
|
|
69
70
|
const serialized = JSON.stringify(r.event ?? {});
|
|
70
71
|
expect(
|
|
71
72
|
serialized.includes(r.intentionCanary),
|
|
72
|
-
|
|
73
|
+
req('openwop.it.commitment-fired.a-fired-commitment-emits-a-content-free-event-with-memory-provenance-exactly-onc', 'RFC 0068 §C.3', 'the inferred intention text MUST NOT appear on the commitment.fired payload'),
|
|
73
74
|
).toBe(false);
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -77,7 +78,7 @@ describe('commitment-fired: fire contract (RFC 0068 §C, capability-gated)', ()
|
|
|
77
78
|
if (typeof r.fireCount === 'number') {
|
|
78
79
|
expect(
|
|
79
80
|
r.fireCount,
|
|
80
|
-
|
|
81
|
+
req('openwop.it.commitment-fired.a-fired-commitment-emits-a-content-free-event-with-memory-provenance-exactly-onc', 'RFC 0068 §C.2', 'a commitment MUST fire at most once per satisfied condition'),
|
|
81
82
|
).toBeLessThanOrEqual(1);
|
|
82
83
|
}
|
|
83
84
|
});
|