@openwop/openwop-conformance 2.42.3 → 2.42.5

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.
Files changed (54) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +1 -1
  3. package/dist/spec-artifacts.lock.json +2 -2
  4. package/package.json +2 -2
  5. package/requirements.json +292 -103
  6. package/schemas/CORPUS-STAMP.json +9 -9
  7. package/src/lib/agentOrgChart.ts +21 -4
  8. package/src/lib/effect-receiver.ts +23 -2
  9. package/src/lib/toolCatalog.ts +29 -5
  10. package/src/scenarios/agent-manifest-runtime.test.ts +17 -4
  11. package/src/scenarios/agent-org-chart-scoping.test.ts +27 -4
  12. package/src/scenarios/agent-roster-attribution.test.ts +28 -4
  13. package/src/scenarios/agentPackExport.test.ts +33 -0
  14. package/src/scenarios/agentPackInstall.test.ts +32 -0
  15. package/src/scenarios/agentReasoningEvents.test.ts +22 -13
  16. package/src/scenarios/agents-run-tool-allowlist.test.ts +6 -2
  17. package/src/scenarios/ai-envelope-shape.test.ts +9 -8
  18. package/src/scenarios/anonymous-actor-write-gated.test.ts +12 -6
  19. package/src/scenarios/audit-log-integrity.test.ts +37 -0
  20. package/src/scenarios/context-budget-transcript-bound.test.ts +14 -4
  21. package/src/scenarios/context-summarization-replay.test.ts +17 -8
  22. package/src/scenarios/conversationLifecycle.test.ts +12 -1
  23. package/src/scenarios/conversationReplayDeterminism.test.ts +19 -3
  24. package/src/scenarios/cost-attribution.test.ts +12 -0
  25. package/src/scenarios/debug-bundle-truncation.test.ts +16 -3
  26. package/src/scenarios/distillation-shape.test.ts +30 -0
  27. package/src/scenarios/envelope-truncated.test.ts +6 -2
  28. package/src/scenarios/feedback-fork-not-copied.test.ts +28 -7
  29. package/src/scenarios/idempotency-concurrent-claim.test.ts +27 -9
  30. package/src/scenarios/idempotency-key-determinism.test.ts +6 -2
  31. package/src/scenarios/mcp-server-untrusted-args.test.ts +20 -5
  32. package/src/scenarios/mcp-tool-roundtrip.test.ts +7 -21
  33. package/src/scenarios/memory-compaction-provenance-tag.test.ts +11 -3
  34. package/src/scenarios/orchestratorDispatch.test.ts +18 -2
  35. package/src/scenarios/pack-registry.test.ts +8 -1
  36. package/src/scenarios/production-backpressure.test.ts +17 -11
  37. package/src/scenarios/redaction.test.ts +8 -2
  38. package/src/scenarios/replay-fanout-suppression.test.ts +18 -2
  39. package/src/scenarios/runner-ledger.test.ts +7 -2
  40. package/src/scenarios/stream-modes.test.ts +27 -0
  41. package/src/scenarios/tool-catalog-projection.test.ts +35 -12
  42. package/src/scenarios/v2-effect-identity-business-key.test.ts +40 -6
  43. package/src/scenarios/v2-era-2-append-vocabulary.test.ts +12 -3
  44. package/src/scenarios/v2-idempotency-in-flight.test.ts +16 -0
  45. package/src/scenarios/v2-mcp-tasks.test.ts +17 -3
  46. package/src/scenarios/v2-min-client-version.test.ts +11 -1
  47. package/src/scenarios/v2-run-diff-identical.test.ts +13 -5
  48. package/src/scenarios/v2-run-pause-resume.test.ts +4 -1
  49. package/src/scenarios/v2-sse-last-event-id.test.ts +7 -0
  50. package/src/scenarios/v2-version-header-honored.test.ts +22 -3
  51. package/src/scenarios/v2-webhook-durable-delivery.test.ts +8 -0
  52. package/src/scenarios/v2-webhook-unregister-stops-delivery.test.ts +6 -1
  53. package/src/scenarios/version-negotiation.test.ts +12 -1
  54. package/src/scenarios/webhook-signed-delivery.test.ts +18 -3
package/requirements.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "tests": 2439,
7
7
  "withStableId": 2439,
8
8
  "interpolatedTitles": 0,
9
- "explicitIds": 2333
9
+ "explicitIds": 2331
10
10
  },
11
11
  "records": [
12
12
  {
@@ -1901,6 +1901,10 @@
1901
1901
  "section": "RFC 0074 §B",
1902
1902
  "requirement": "agents.manifestRuntime.installScope (when present) MUST be 'host' or 'tenant'"
1903
1903
  },
1904
+ {
1905
+ "section": "RFC 0072 §A / node-packs.md §Agent inventory",
1906
+ "requirement": "a host advertising agents.manifestRuntime.supported MUST serve GET /v1/agents (it answered 404/405/501)"
1907
+ },
1904
1908
  {
1905
1909
  "section": "RFC 0072 §A",
1906
1910
  "requirement": "GET /v1/agents MUST return an agents[] array"
@@ -1926,7 +1930,7 @@
1926
1930
  {
1927
1931
  "id": "openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco",
1928
1932
  "file": "agent-org-chart-scoping.test.ts",
1929
- "line": 40,
1933
+ "line": 39,
1930
1934
  "title": "serves the normative org-chart + responsibility roll-up, tree-shaped and tenant-scoped",
1931
1935
  "explicitId": "openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco",
1932
1936
  "citations": [
@@ -1934,6 +1938,14 @@
1934
1938
  "section": "RFC 0087 §E / RFC 0074",
1935
1939
  "requirement": "agents.orgChart.installScope (when present) MUST be 'host' or 'tenant'"
1936
1940
  },
1941
+ {
1942
+ "section": "agent-org-chart.md §A / §E",
1943
+ "requirement": "a host advertising agents.orgChart.supported MUST serve GET /v1/agents/org-chart with 200"
1944
+ },
1945
+ {
1946
+ "section": "agent-org-chart.schema.json",
1947
+ "requirement": "GET /v1/agents/org-chart MUST return a JSON org-chart object"
1948
+ },
1937
1949
  {
1938
1950
  "section": "agent-org-chart.schema.json",
1939
1951
  "requirement": "GET /v1/agents/org-chart MUST return departments[] + members[]"
@@ -1954,6 +1966,10 @@
1954
1966
  "section": "agent-org-chart.md §A",
1955
1967
  "requirement": "a member's departmentId MUST be a department in the chart"
1956
1968
  },
1969
+ {
1970
+ "section": "agent-org-chart.md §D / §E",
1971
+ "requirement": "a host advertising agents.orgChart.responsibilityView MUST serve GET /v1/agents/org-chart/{departmentId} with 200 for a department in the caller's chart"
1972
+ },
1957
1973
  {
1958
1974
  "section": "agent-org-chart.md §D",
1959
1975
  "requirement": "the responsibility view MUST carry a responsibilities[] roll-up"
@@ -2305,6 +2321,10 @@
2305
2321
  "section": "RFC 0086 §F / RFC 0074 §B",
2306
2322
  "requirement": "agents.roster.installScope (when present) MUST be 'host' or 'tenant'"
2307
2323
  },
2324
+ {
2325
+ "section": "agent-roster.md §B",
2326
+ "requirement": "a host advertising agents.roster.supported MUST serve GET /v1/agents/roster (got 404/405/501)"
2327
+ },
2308
2328
  {
2309
2329
  "section": "agent-roster.md §B",
2310
2330
  "requirement": "GET /v1/agents/roster MUST return a roster[] array"
@@ -2802,13 +2822,18 @@
2802
2822
  {
2803
2823
  "id": "openwop.it.agentPackExport.exported-manifests-contain-required-agentmanifest-fields",
2804
2824
  "file": "agentPackExport.test.ts",
2805
- "line": 28,
2825
+ "line": 53,
2806
2826
  "title": "exported manifests contain required AgentManifest fields",
2807
2827
  "explicitId": "openwop.it.agentPackExport.exported-manifests-contain-required-agentmanifest-fields",
2808
2828
  "citations": [
2809
2829
  {
2810
2830
  "section": "RFCS/0003-agent-packs.md",
2811
2831
  "requirement": "exported manifests contain required AgentManifest fields"
2832
+ },
2833
+ {
2834
+ "section": "schemas/agent-manifest.schema.json",
2835
+ "requirement": null,
2836
+ "interpolated": true
2812
2837
  }
2813
2838
  ]
2814
2839
  },
@@ -2858,13 +2883,18 @@
2858
2883
  {
2859
2884
  "id": "openwop.it.agentPackInstall.host-exposes-installed-agent-manifests-with-required-agentmanifest-fields",
2860
2885
  "file": "agentPackInstall.test.ts",
2861
- "line": 29,
2886
+ "line": 54,
2862
2887
  "title": "host exposes installed agent manifests with required AgentManifest fields",
2863
2888
  "explicitId": "openwop.it.agentPackInstall.host-exposes-installed-agent-manifests-with-required-agentmanifest-fields",
2864
2889
  "citations": [
2865
2890
  {
2866
2891
  "section": "RFCS/0003-agent-packs.md",
2867
2892
  "requirement": "host exposes installed agent manifests with required AgentManifest fields"
2893
+ },
2894
+ {
2895
+ "section": "schemas/agent-manifest.schema.json",
2896
+ "requirement": null,
2897
+ "interpolated": true
2868
2898
  }
2869
2899
  ]
2870
2900
  },
@@ -2888,11 +2918,20 @@
2888
2918
  "title": "host emits at least one canonical agent.* event during a reasoning-fixture run",
2889
2919
  "explicitId": "openwop.it.agentReasoningEvents.host-emits-at-least-one-canonical-agent-event-during-a-reasoning-fixture-run",
2890
2920
  "citations": [
2921
+ {
2922
+ "section": "schemas/run-event-payloads.schema.json#/$defs/agentToolReturned",
2923
+ "requirement": "agent.toolReturned MUST carry a callId (schema-required)"
2924
+ },
2891
2925
  {
2892
2926
  "section": "schemas/run-event-payloads.schema.json",
2893
2927
  "requirement": null,
2894
2928
  "interpolated": true
2895
2929
  },
2930
+ {
2931
+ "section": "schemas/run-event.schema.json",
2932
+ "requirement": null,
2933
+ "interpolated": true
2934
+ },
2896
2935
  {
2897
2936
  "section": "schemas/run-event-payloads.schema.json",
2898
2937
  "requirement": null,
@@ -2990,18 +3029,13 @@
2990
3029
  "file": "agents-run-tool-allowlist.test.ts",
2991
3030
  "line": 85,
2992
3031
  "title": "skips cleanly when pack source is not bundled",
2993
- "explicitId": "openwop.it.agents-run-tool-allowlist.skips-cleanly-when-pack-source-is-not-bundled",
2994
- "citations": [
2995
- {
2996
- "section": "threat-model-prompt-injection.md",
2997
- "requirement": "skips cleanly when pack source is not bundled"
2998
- }
2999
- ]
3032
+ "explicitId": null,
3033
+ "citations": []
3000
3034
  },
3001
3035
  {
3002
3036
  "id": "openwop.it.agents-run-tool-allowlist.rejects-function-typed-tool-handler-the-defect-path",
3003
3037
  "file": "agents-run-tool-allowlist.test.ts",
3004
- "line": 94,
3038
+ "line": 98,
3005
3039
  "title": "rejects function-typed tool.handler (the defect path)",
3006
3040
  "explicitId": null,
3007
3041
  "citations": []
@@ -3009,7 +3043,7 @@
3009
3043
  {
3010
3044
  "id": "openwop.it.agents-run-tool-allowlist.rejects-tool-declaration-missing-a-name",
3011
3045
  "file": "agents-run-tool-allowlist.test.ts",
3012
- "line": 113,
3046
+ "line": 117,
3013
3047
  "title": "rejects tool declaration missing a name",
3014
3048
  "explicitId": null,
3015
3049
  "citations": []
@@ -3017,7 +3051,7 @@
3017
3051
  {
3018
3052
  "id": "openwop.it.agents-run-tool-allowlist.rejects-tool-declaration-missing-a-kind-discriminator",
3019
3053
  "file": "agents-run-tool-allowlist.test.ts",
3020
- "line": 122,
3054
+ "line": 126,
3021
3055
  "title": "rejects tool declaration missing a kind discriminator",
3022
3056
  "explicitId": null,
3023
3057
  "citations": []
@@ -3025,7 +3059,7 @@
3025
3059
  {
3026
3060
  "id": "openwop.it.agents-run-tool-allowlist.rejects-tool-driven-runs-when-host-does-not-provide-agentruntime",
3027
3061
  "file": "agents-run-tool-allowlist.test.ts",
3028
- "line": 131,
3062
+ "line": 135,
3029
3063
  "title": "rejects tool-driven runs when host does not provide agentRuntime",
3030
3064
  "explicitId": null,
3031
3065
  "citations": []
@@ -3033,7 +3067,7 @@
3033
3067
  {
3034
3068
  "id": "openwop.it.agents-run-tool-allowlist.tool-less-run-succeeds-via-callaiwithtools-safe-fallback-preserved",
3035
3069
  "file": "agents-run-tool-allowlist.test.ts",
3036
- "line": 145,
3070
+ "line": 149,
3037
3071
  "title": "tool-less run succeeds via callAIWithTools (safe fallback preserved)",
3038
3072
  "explicitId": "openwop.it.agents-run-tool-allowlist.tool-less-run-succeeds-via-callaiwithtools-safe-fallback-preserved",
3039
3073
  "citations": [
@@ -3046,7 +3080,7 @@
3046
3080
  {
3047
3081
  "id": "openwop.it.agents-run-tool-allowlist.agentruntime-run-path-threads-through-unchanged-when-host-provides-it",
3048
3082
  "file": "agents-run-tool-allowlist.test.ts",
3049
- "line": 162,
3083
+ "line": 166,
3050
3084
  "title": "agentRuntime.run path threads through unchanged when host provides it",
3051
3085
  "explicitId": "openwop.it.agents-run-tool-allowlist.agentruntime-run-path-threads-through-unchanged-when-host-provides-it",
3052
3086
  "citations": [
@@ -3065,18 +3099,18 @@
3065
3099
  "citations": [
3066
3100
  {
3067
3101
  "section": "capabilities.md §supportedEnvelopes",
3068
- "requirement": "each entry MUST be a string"
3102
+ "requirement": "supportedEnvelopes MUST be an array"
3069
3103
  },
3070
3104
  {
3071
3105
  "section": "capabilities.md §supportedEnvelopes",
3072
- "requirement": "supportedEnvelopes MUST be an array"
3106
+ "requirement": "each entry MUST be a string"
3073
3107
  }
3074
3108
  ]
3075
3109
  },
3076
3110
  {
3077
3111
  "id": "openwop.it.ai-envelope-shape.top-level-ai-envelope-schema-json-compiles-under-ajv2020",
3078
3112
  "file": "ai-envelope-shape.test.ts",
3079
- "line": 90,
3113
+ "line": 91,
3080
3114
  "title": "top-level ai-envelope.schema.json compiles under Ajv2020",
3081
3115
  "explicitId": "openwop.it.ai-envelope-shape.top-level-ai-envelope-schema-json-compiles-under-ajv2020",
3082
3116
  "citations": [
@@ -3089,7 +3123,7 @@
3089
3123
  {
3090
3124
  "id": "openwop.it.ai-envelope-shape.universal-kind-schema-envelopes-schema-json-compiles-under-ajv2020",
3091
3125
  "file": "ai-envelope-shape.test.ts",
3092
- "line": 97,
3126
+ "line": 98,
3093
3127
  "title": null,
3094
3128
  "explicitId": "openwop.it.ai-envelope-shape.universal-kind-schema-envelopes-schema-json-compiles-under-ajv2020",
3095
3129
  "citations": [
@@ -3103,7 +3137,7 @@
3103
3137
  {
3104
3138
  "id": "openwop.it.ai-envelope-shape.accepts-a-positive-aienvelope-fixture",
3105
3139
  "file": "ai-envelope-shape.test.ts",
3106
- "line": 113,
3140
+ "line": 114,
3107
3141
  "title": "accepts a positive AIEnvelope fixture",
3108
3142
  "explicitId": "openwop.it.ai-envelope-shape.accepts-a-positive-aienvelope-fixture",
3109
3143
  "citations": [
@@ -3117,7 +3151,7 @@
3117
3151
  {
3118
3152
  "id": "openwop.it.ai-envelope-shape.rejects-a-negative-aienvelope-fixture-missing-required-meta",
3119
3153
  "file": "ai-envelope-shape.test.ts",
3120
- "line": 132,
3154
+ "line": 133,
3121
3155
  "title": "rejects a negative AIEnvelope fixture missing required `meta`",
3122
3156
  "explicitId": "openwop.it.ai-envelope-shape.rejects-a-negative-aienvelope-fixture-missing-required-meta",
3123
3157
  "citations": [
@@ -3130,7 +3164,7 @@
3130
3164
  {
3131
3165
  "id": "openwop.it.ai-envelope-shape.rejects-an-envelope-with-unknown-top-level-property-additionalproperties-false",
3132
3166
  "file": "ai-envelope-shape.test.ts",
3133
- "line": 145,
3167
+ "line": 146,
3134
3168
  "title": "rejects an envelope with unknown top-level property (additionalProperties:false)",
3135
3169
  "explicitId": "openwop.it.ai-envelope-shape.rejects-an-envelope-with-unknown-top-level-property-additionalproperties-false",
3136
3170
  "citations": [
@@ -3143,7 +3177,7 @@
3143
3177
  {
3144
3178
  "id": "openwop.it.ai-envelope-shape.valid-clarification-request-envelope-status-accepted",
3145
3179
  "file": "ai-envelope-shape.test.ts",
3146
- "line": 161,
3180
+ "line": 162,
3147
3181
  "title": "valid clarification.request envelope → status: accepted",
3148
3182
  "explicitId": "openwop.it.ai-envelope-shape.valid-clarification-request-envelope-status-accepted",
3149
3183
  "citations": [
@@ -3156,7 +3190,7 @@
3156
3190
  {
3157
3191
  "id": "openwop.it.ai-envelope-shape.envelope-missing-required-meta-block-status-invalid",
3158
3192
  "file": "ai-envelope-shape.test.ts",
3159
- "line": 181,
3193
+ "line": 182,
3160
3194
  "title": "envelope missing required meta block → status: invalid",
3161
3195
  "explicitId": "openwop.it.ai-envelope-shape.envelope-missing-required-meta-block-status-invalid",
3162
3196
  "citations": [
@@ -3173,7 +3207,7 @@
3173
3207
  {
3174
3208
  "id": "openwop.it.ai-envelope-shape.vendor-namespaced-kind-not-in-supportedenvelopes-status-gated",
3175
3209
  "file": "ai-envelope-shape.test.ts",
3176
- "line": 202,
3210
+ "line": 203,
3177
3211
  "title": "vendor-namespaced kind not in supportedEnvelopes → status: gated",
3178
3212
  "explicitId": "openwop.it.ai-envelope-shape.vendor-namespaced-kind-not-in-supportedenvelopes-status-gated",
3179
3213
  "citations": [
@@ -3190,7 +3224,7 @@
3190
3224
  {
3191
3225
  "id": "openwop.it.ai-envelope-shape.counter-at-cap-status-breached",
3192
3226
  "file": "ai-envelope-shape.test.ts",
3193
- "line": 224,
3227
+ "line": 225,
3194
3228
  "title": "counter at cap → status: breached",
3195
3229
  "explicitId": "openwop.it.ai-envelope-shape.counter-at-cap-status-breached",
3196
3230
  "citations": [
@@ -3203,7 +3237,7 @@
3203
3237
  {
3204
3238
  "id": "openwop.it.ai-envelope-shape.accepted-outcome-carries-normalizedmeta-contenttrust-per-rfc-0021-a-point-6",
3205
3239
  "file": "ai-envelope-shape.test.ts",
3206
- "line": 246,
3240
+ "line": 247,
3207
3241
  "title": "accepted outcome carries normalizedMeta.contentTrust per RFC 0021 §A point 6",
3208
3242
  "explicitId": "openwop.it.ai-envelope-shape.accepted-outcome-carries-normalizedmeta-contenttrust-per-rfc-0021-a-point-6",
3209
3243
  "citations": [
@@ -3216,7 +3250,7 @@
3216
3250
  {
3217
3251
  "id": "openwop.it.ai-envelope-shape.envelope-supplied-meta-contenttrust-takes-precedence-over-runtrustboundary",
3218
3252
  "file": "ai-envelope-shape.test.ts",
3219
- "line": 273,
3253
+ "line": 274,
3220
3254
  "title": "envelope-supplied meta.contentTrust takes precedence over runTrustBoundary",
3221
3255
  "explicitId": "openwop.it.ai-envelope-shape.envelope-supplied-meta-contenttrust-takes-precedence-over-runtrustboundary",
3222
3256
  "citations": [
@@ -3229,7 +3263,7 @@
3229
3263
  {
3230
3264
  "id": "openwop.it.ai-envelope-shape.non-iso-8601-meta-ts-status-invalid-format-defense-in-depth",
3231
3265
  "file": "ai-envelope-shape.test.ts",
3232
- "line": 297,
3266
+ "line": 298,
3233
3267
  "title": "non-ISO-8601 meta.ts → status: invalid (format defense-in-depth)",
3234
3268
  "explicitId": "openwop.it.ai-envelope-shape.non-iso-8601-meta-ts-status-invalid-format-defense-in-depth",
3235
3269
  "citations": [
@@ -3242,7 +3276,7 @@
3242
3276
  {
3243
3277
  "id": "openwop.it.ai-envelope-shape.universal-kind-allowed-regardless-of-nodeallowedkinds-always-allowed-per-univers",
3244
3278
  "file": "ai-envelope-shape.test.ts",
3245
- "line": 314,
3279
+ "line": 315,
3246
3280
  "title": "universal kind allowed regardless of nodeAllowedKinds (always-allowed per §\"Universal kinds\")",
3247
3281
  "explicitId": "openwop.it.ai-envelope-shape.universal-kind-allowed-regardless-of-nodeallowedkinds-always-allowed-per-univers",
3248
3282
  "citations": [
@@ -3255,7 +3289,7 @@
3255
3289
  {
3256
3290
  "id": "openwop.it.ai-envelope-shape.host-advertising-any-universal-kind-has-a-matching-schema-on-disk",
3257
3291
  "file": "ai-envelope-shape.test.ts",
3258
- "line": 340,
3292
+ "line": 341,
3259
3293
  "title": "host advertising any universal kind has a matching schema on disk",
3260
3294
  "explicitId": "openwop.it.ai-envelope-shape.host-advertising-any-universal-kind-has-a-matching-schema-on-disk",
3261
3295
  "citations": [
@@ -5412,7 +5446,7 @@
5412
5446
  {
5413
5447
  "id": "openwop.it.audit-log-integrity.host-that-claims-the-profile-advertises-required-capability-fields",
5414
5448
  "file": "audit-log-integrity.test.ts",
5415
- "line": 45,
5449
+ "line": 69,
5416
5450
  "title": "host that claims the profile advertises required capability fields",
5417
5451
  "explicitId": "openwop.it.audit-log-integrity.host-that-claims-the-profile-advertises-required-capability-fields",
5418
5452
  "citations": [
@@ -5429,7 +5463,7 @@
5429
5463
  {
5430
5464
  "id": "openwop.it.audit-log-integrity.get-v1-audit-verify-on-a-recent-range-reports-chainvalid-true",
5431
5465
  "file": "audit-log-integrity.test.ts",
5432
- "line": 68,
5466
+ "line": 92,
5433
5467
  "title": "GET /v1/audit/verify on a recent range reports chainValid: true",
5434
5468
  "explicitId": "openwop.it.audit-log-integrity.get-v1-audit-verify-on-a-recent-range-reports-chainvalid-true",
5435
5469
  "citations": [
@@ -5437,6 +5471,11 @@
5437
5471
  "section": "auth-profiles.md §\"Audit-log integrity\" §\"Verification endpoint\"",
5438
5472
  "requirement": "claiming openwop-audit-log-integrity profile REQUIRES exposing GET /v1/audit/verify"
5439
5473
  },
5474
+ {
5475
+ "section": "audit-verify-result.schema.json",
5476
+ "requirement": null,
5477
+ "interpolated": true
5478
+ },
5440
5479
  {
5441
5480
  "section": "auth-profiles.md §\"Audit-log integrity\"",
5442
5481
  "requirement": "unmodified audit range MUST report chainValid: true"
@@ -9489,19 +9528,44 @@
9489
9528
  {
9490
9529
  "section": "RFCS/0005-conversation.md",
9491
9530
  "requirement": "emits all three lifecycle events with matching conversationId; no exchanges after close"
9531
+ },
9532
+ {
9533
+ "section": "RFCS/0005-conversation.md",
9534
+ "requirement": "the open → exchange → close fixture run MUST terminate `completed`"
9535
+ },
9536
+ {
9537
+ "section": "RFCS/0005-conversation.md",
9538
+ "requirement": "`conversation.exchanged` MUST be emitted for the fixture's one exchange turn"
9539
+ },
9540
+ {
9541
+ "section": "RFCS/0005-conversation.md (CO-3)",
9542
+ "requirement": null,
9543
+ "interpolated": true
9492
9544
  }
9493
9545
  ]
9494
9546
  },
9495
9547
  {
9496
9548
  "id": "openwop.it.conversationReplayDeterminism.forked-run-yields-byte-equal-conversation-channel-projection",
9497
9549
  "file": "conversationReplayDeterminism.test.ts",
9498
- "line": 29,
9550
+ "line": 30,
9499
9551
  "title": "forked run yields byte-equal conversation channel projection",
9500
9552
  "explicitId": "openwop.it.conversationReplayDeterminism.forked-run-yields-byte-equal-conversation-channel-projection",
9501
9553
  "citations": [
9502
9554
  {
9503
9555
  "section": "RFCS/0005-conversation.md",
9504
9556
  "requirement": "forked run yields byte-equal conversation channel projection"
9557
+ },
9558
+ {
9559
+ "section": "RFCS/0005-conversation.md",
9560
+ "requirement": "the source run of a conversation fixture MUST project a non-empty channels object"
9561
+ },
9562
+ {
9563
+ "section": "spec/v1/replay.md",
9564
+ "requirement": "a host advertising replay.modes [\"replay\"] MUST accept a mode:\"replay\" fork (404/501 is a failure)"
9565
+ },
9566
+ {
9567
+ "section": "RFCS/0005-conversation.md",
9568
+ "requirement": "a replay-forked run MUST yield a byte-equal conversation channel projection"
9505
9569
  }
9506
9570
  ]
9507
9571
  },
@@ -9644,6 +9708,10 @@
9644
9708
  "section": "run-snapshot.schema.json §metrics.openwopCost",
9645
9709
  "requirement": "metrics.openwopCost MUST be populated after a node calls ctx.recordCost()"
9646
9710
  },
9711
+ {
9712
+ "section": "run-snapshot.schema.json §metrics.openwopCost / observability.md §Cost attribution attributes",
9713
+ "requirement": "metrics.openwopCost MUST carry the recorded cost — at least one of usd or tokens — after ctx.recordCost()"
9714
+ },
9647
9715
  {
9648
9716
  "section": "observability.md §openwop.cost.tokens.input",
9649
9717
  "requirement": "tokens.input MUST be a non-negative integer"
@@ -9665,7 +9733,7 @@
9665
9733
  {
9666
9734
  "id": "openwop.it.cost-attribution.cost-emit-fixture-run-must-emit-a-node-completed-event-for-the-cost-emitting-nod",
9667
9735
  "file": "cost-attribution.test.ts",
9668
- "line": 209,
9736
+ "line": 221,
9669
9737
  "title": "cost-emit fixture run MUST emit a node.completed event for the cost-emitting node",
9670
9738
  "explicitId": "openwop.it.cost-attribution.cost-emit-fixture-run-must-emit-a-node-completed-event-for-the-cost-emitting-nod",
9671
9739
  "citations": [
@@ -9678,7 +9746,7 @@
9678
9746
  {
9679
9747
  "id": "openwop.it.cost-attribution.only-allowlisted-openwop-cost-attributes-reach-the-otel-span-g6-close-criteria-a",
9680
9748
  "file": "cost-attribution.test.ts",
9681
- "line": 248,
9749
+ "line": 260,
9682
9750
  "title": "only allowlisted openwop.cost.* attributes reach the OTel span (G6 close criteria — allowlist enforcement)",
9683
9751
  "explicitId": "openwop.it.cost-attribution.only-allowlisted-openwop-cost-attributes-reach-the-otel-span-g6-close-criteria-a",
9684
9752
  "citations": [
@@ -9695,7 +9763,7 @@
9695
9763
  {
9696
9764
  "id": "openwop.it.cost-attribution.credential-shaped-canaries-do-not-leak-to-any-otel-attribute-g6-close-criteria-r",
9697
9765
  "file": "cost-attribution.test.ts",
9698
- "line": 287,
9766
+ "line": 299,
9699
9767
  "title": "credential-shaped canaries do NOT leak to any OTel attribute (G6 close criteria — redaction)",
9700
9768
  "explicitId": "openwop.it.cost-attribution.credential-shaped-canaries-do-not-leak-to-any-otel-attribute-g6-close-criteria-r",
9701
9769
  "citations": [
@@ -10158,6 +10226,11 @@
10158
10226
  "section": "debug-bundle.md §\"Bundle size limits\"",
10159
10227
  "requirement": "baseline bundle MUST NOT be truncated"
10160
10228
  },
10229
+ {
10230
+ "section": "debug-bundle.md §\"Bundle size limits\"",
10231
+ "requirement": null,
10232
+ "interpolated": true
10233
+ },
10161
10234
  {
10162
10235
  "section": "debug-bundle.md §\"Bundle size limits\"",
10163
10236
  "requirement": "truncated: true MUST be accompanied by a non-empty truncatedReason string"
@@ -11058,7 +11131,7 @@
11058
11131
  {
11059
11132
  "id": "openwop.it.distillation-shape.capabilities-memory-distillation-is-absent-or-a-well-formed-object",
11060
11133
  "file": "distillation-shape.test.ts",
11061
- "line": 20,
11134
+ "line": 40,
11062
11135
  "title": "capabilities.memory.distillation is absent or a well-formed object",
11063
11136
  "explicitId": "openwop.it.distillation-shape.capabilities-memory-distillation-is-absent-or-a-well-formed-object",
11064
11137
  "citations": [
@@ -11070,6 +11143,11 @@
11070
11143
  "section": "capabilities.schema.json §memory.distillation",
11071
11144
  "requirement": "maxTokenBudget MUST be a positive integer when present"
11072
11145
  },
11146
+ {
11147
+ "section": "capabilities.schema.json §memory.distillation",
11148
+ "requirement": null,
11149
+ "interpolated": true
11150
+ },
11073
11151
  {
11074
11152
  "section": "capabilities.schema.json §memory.distillation",
11075
11153
  "requirement": null,
@@ -12270,7 +12348,7 @@
12270
12348
  {
12271
12349
  "id": "openwop.it.envelope-truncated.payload-includes-nodeid-provider-model-partialpayloadavailable-boolean",
12272
12350
  "file": "envelope-truncated.test.ts",
12273
- "line": 82,
12351
+ "line": 86,
12274
12352
  "title": "payload includes nodeId + provider + model + partialPayloadAvailable boolean",
12275
12353
  "explicitId": "openwop.it.envelope-truncated.payload-includes-nodeid-provider-model-partialpayloadavailable-boolean",
12276
12354
  "citations": [
@@ -12283,7 +12361,7 @@
12283
12361
  {
12284
12362
  "id": "openwop.it.envelope-truncated.retry-attempt-receives-a-maxtokens-value-strictly-greater-than-the-previous-atte",
12285
12363
  "file": "envelope-truncated.test.ts",
12286
- "line": 101,
12364
+ "line": 105,
12287
12365
  "title": "retry attempt receives a maxTokens value strictly greater than the previous attempt (RFC 0033 §B truncationBudgetMultiplier)",
12288
12366
  "explicitId": "openwop.it.envelope-truncated.retry-attempt-receives-a-maxtokens-value-strictly-greater-than-the-previous-atte",
12289
12367
  "citations": [
@@ -12296,7 +12374,7 @@
12296
12374
  {
12297
12375
  "id": "openwop.it.envelope-truncated.run-terminates-completed-after-the-second-attempt-succeeds",
12298
12376
  "file": "envelope-truncated.test.ts",
12299
- "line": 126,
12377
+ "line": 130,
12300
12378
  "title": "run terminates `completed` after the second attempt succeeds",
12301
12379
  "explicitId": "openwop.it.envelope-truncated.run-terminates-completed-after-the-second-attempt-succeeds",
12302
12380
  "citations": [
@@ -12887,10 +12965,30 @@
12887
12965
  {
12888
12966
  "id": "openwop.it.feedback-fork-not-copied.a-fork-of-an-annotated-run-starts-with-zero-annotations",
12889
12967
  "file": "feedback-fork-not-copied.test.ts",
12890
- "line": 18,
12968
+ "line": 19,
12891
12969
  "title": "a fork of an annotated run starts with zero annotations",
12892
12970
  "explicitId": "openwop.it.feedback-fork-not-copied.a-fork-of-an-annotated-run-starts-with-zero-annotations",
12893
12971
  "citations": [
12972
+ {
12973
+ "section": "RFC 0056 §B",
12974
+ "requirement": "POST /v1/runs/{runId}/annotations MUST return 201"
12975
+ },
12976
+ {
12977
+ "section": "RFC 0056 §B",
12978
+ "requirement": "GET /v1/runs/{runId}/annotations MUST return 200"
12979
+ },
12980
+ {
12981
+ "section": "RFC 0056 §B",
12982
+ "requirement": "positive control: the source run MUST list the annotation just posted"
12983
+ },
12984
+ {
12985
+ "section": "RFC 0056 §B",
12986
+ "requirement": "GET /v1/runs/{forkId}/annotations MUST return 200 for the fork"
12987
+ },
12988
+ {
12989
+ "section": "RFC 0056 §B",
12990
+ "requirement": "the annotation list MUST carry an annotations[] array"
12991
+ },
12894
12992
  {
12895
12993
  "section": "RFC 0056 §D",
12896
12994
  "requirement": "annotations are a side-store and MUST NOT be copied into a fork"
@@ -14422,10 +14520,22 @@
14422
14520
  "title": "the race is real at higher concurrency too — a claim that only holds at 2 is not a claim",
14423
14521
  "explicitId": "openwop.it.idempotency-concurrent-claim.the-race-is-real-at-higher-concurrency-too-a-claim-that-only-holds-at-2-is-not-a",
14424
14522
  "citations": [
14523
+ {
14524
+ "section": "host-sample-test-seams.md §25",
14525
+ "requirement": "with executors: 5 at least three executors MUST reach the chokepoint — otherwise this leg repeats the two-executor case and witnesses nothing new"
14526
+ },
14527
+ {
14528
+ "section": "host-sample-test-seams.md §25",
14529
+ "requirement": "the seam MUST report mintedIds, one per executor"
14530
+ },
14425
14531
  {
14426
14532
  "section": "idempotency.md §\"Concurrent duplicates (Layer 2)\"",
14427
14533
  "requirement": "exactly one effect regardless of how many executors race — at most one wins the compare-and-set, the rest observe the hit"
14428
14534
  },
14535
+ {
14536
+ "section": "host-sample-test-seams.md §25",
14537
+ "requirement": "mintedIds length MUST equal attempted"
14538
+ },
14429
14539
  {
14430
14540
  "section": "idempotency.md §\"Idempotency key composition\"",
14431
14541
  "requirement": "one identity across all executors at any concurrency"
@@ -14437,18 +14547,13 @@
14437
14547
  "file": "idempotency-key-determinism.test.ts",
14438
14548
  "line": 113,
14439
14549
  "title": "skips cleanly when packs/ is not bundled",
14440
- "explicitId": "openwop.it.idempotency-key-determinism.skips-cleanly-when-packs-is-not-bundled",
14441
- "citations": [
14442
- {
14443
- "section": "idempotency.md §\"Idempotency-Key",
14444
- "requirement": "skips cleanly when packs/ is not bundled"
14445
- }
14446
- ]
14550
+ "explicitId": null,
14551
+ "citations": []
14447
14552
  },
14448
14553
  {
14449
14554
  "id": "openwop.it.idempotency-key-determinism.default-mode-composite-identical-runid-nodeid-payload-produces-identical-keys",
14450
14555
  "file": "idempotency-key-determinism.test.ts",
14451
- "line": 125,
14556
+ "line": 129,
14452
14557
  "title": "default mode (composite) — identical (runId, nodeId, payload) produces identical keys",
14453
14558
  "explicitId": "openwop.it.idempotency-key-determinism.default-mode-composite-identical-runid-nodeid-payload-produces-identical-keys",
14454
14559
  "citations": [
@@ -14461,7 +14566,7 @@
14461
14566
  {
14462
14567
  "id": "openwop.it.idempotency-key-determinism.payload-sensitivity-different-payload-produces-different-key",
14463
14568
  "file": "idempotency-key-determinism.test.ts",
14464
- "line": 138,
14569
+ "line": 142,
14465
14570
  "title": "payload sensitivity — different payload produces different key",
14466
14571
  "explicitId": "openwop.it.idempotency-key-determinism.payload-sensitivity-different-payload-produces-different-key",
14467
14572
  "citations": [
@@ -14474,7 +14579,7 @@
14474
14579
  {
14475
14580
  "id": "openwop.it.idempotency-key-determinism.run-isolation-different-runid-produces-different-key",
14476
14581
  "file": "idempotency-key-determinism.test.ts",
14477
- "line": 146,
14582
+ "line": 150,
14478
14583
  "title": "run isolation — different runId produces different key",
14479
14584
  "explicitId": "openwop.it.idempotency-key-determinism.run-isolation-different-runid-produces-different-key",
14480
14585
  "citations": [
@@ -14487,7 +14592,7 @@
14487
14592
  {
14488
14593
  "id": "openwop.it.idempotency-key-determinism.node-isolation-different-nodeid-produces-different-key",
14489
14594
  "file": "idempotency-key-determinism.test.ts",
14490
- "line": 154,
14595
+ "line": 158,
14491
14596
  "title": "node isolation — different nodeId produces different key",
14492
14597
  "explicitId": "openwop.it.idempotency-key-determinism.node-isolation-different-nodeid-produces-different-key",
14493
14598
  "citations": [
@@ -14500,7 +14605,7 @@
14500
14605
  {
14501
14606
  "id": "openwop.it.idempotency-key-determinism.hash-mode-is-deterministic-in-the-payload-alone-run-node-ignored",
14502
14607
  "file": "idempotency-key-determinism.test.ts",
14503
- "line": 162,
14608
+ "line": 166,
14504
14609
  "title": "hash mode is deterministic in the payload alone (run/node ignored)",
14505
14610
  "explicitId": "openwop.it.idempotency-key-determinism.hash-mode-is-deterministic-in-the-payload-alone-run-node-ignored",
14506
14611
  "citations": [
@@ -14513,7 +14618,7 @@
14513
14618
  {
14514
14619
  "id": "openwop.it.idempotency-key-determinism.output-shape-every-emitted-key-matches-openwop-sha256-prefix-16",
14515
14620
  "file": "idempotency-key-determinism.test.ts",
14516
- "line": 171,
14621
+ "line": 175,
14517
14622
  "title": "output shape — every emitted key matches openwop-<sha256-prefix-16>",
14518
14623
  "explicitId": "openwop.it.idempotency-key-determinism.output-shape-every-emitted-key-matches-openwop-sha256-prefix-16",
14519
14624
  "citations": [
@@ -14527,7 +14632,7 @@
14527
14632
  {
14528
14633
  "id": "openwop.it.idempotency-key-determinism.uuid-mode-rejects-with-config-invalid-safety-fix-per-1-1-2",
14529
14634
  "file": "idempotency-key-determinism.test.ts",
14530
- "line": 186,
14635
+ "line": 190,
14531
14636
  "title": "uuid mode rejects with CONFIG_INVALID (safety-fix per 1.1.2)",
14532
14637
  "explicitId": "openwop.it.idempotency-key-determinism.uuid-mode-rejects-with-config-invalid-safety-fix-per-1-1-2",
14533
14638
  "citations": [
@@ -14540,7 +14645,7 @@
14540
14645
  {
14541
14646
  "id": "openwop.it.idempotency-key-determinism.cross-impl-invariant-pack-output-equals-canonical-sha-256-formula",
14542
14647
  "file": "idempotency-key-determinism.test.ts",
14543
- "line": 201,
14648
+ "line": 205,
14544
14649
  "title": "cross-impl invariant — pack output equals canonical SHA-256 formula",
14545
14650
  "explicitId": "openwop.it.idempotency-key-determinism.cross-impl-invariant-pack-output-equals-canonical-sha-256-formula",
14546
14651
  "citations": [
@@ -16435,7 +16540,7 @@
16435
16540
  {
16436
16541
  "id": "openwop.it.mcp-server-untrusted-args.capabilities-mcp-servermount-is-well-formed-when-present",
16437
16542
  "file": "mcp-server-untrusted-args.test.ts",
16438
- "line": 67,
16543
+ "line": 71,
16439
16544
  "title": "capabilities.mcp.serverMount is well-formed when present",
16440
16545
  "explicitId": "openwop.it.mcp-server-untrusted-args.capabilities-mcp-servermount-is-well-formed-when-present",
16441
16546
  "citations": [
@@ -16448,7 +16553,7 @@
16448
16553
  {
16449
16554
  "id": "openwop.it.mcp-server-untrusted-args.tools-call-with-malformed-arguments-is-rejected-with-json-rpc-32602-before-workf",
16450
16555
  "file": "mcp-server-untrusted-args.test.ts",
16451
- "line": 75,
16556
+ "line": 79,
16452
16557
  "title": "tools/call with malformed arguments is rejected with JSON-RPC -32602 BEFORE workflow start",
16453
16558
  "explicitId": "openwop.it.mcp-server-untrusted-args.tools-call-with-malformed-arguments-is-rejected-with-json-rpc-32602-before-workf",
16454
16559
  "citations": [
@@ -16469,13 +16574,21 @@
16469
16574
  {
16470
16575
  "id": "openwop.it.mcp-server-untrusted-args.tools-call-with-valid-arguments-is-accepted",
16471
16576
  "file": "mcp-server-untrusted-args.test.ts",
16472
- "line": 96,
16577
+ "line": 100,
16473
16578
  "title": "tools/call with valid arguments is accepted",
16474
16579
  "explicitId": "openwop.it.mcp-server-untrusted-args.tools-call-with-valid-arguments-is-accepted",
16475
16580
  "citations": [
16476
16581
  {
16477
16582
  "section": "RFC 0020 §D",
16478
- "requirement": "valid args MUST NOT trigger -32602"
16583
+ "requirement": "the JSON-RPC envelope MUST answer 200"
16584
+ },
16585
+ {
16586
+ "section": "RFC 0020 §D",
16587
+ "requirement": "valid args MUST NOT be rejected with any JSON-RPC error"
16588
+ },
16589
+ {
16590
+ "section": "RFC 0020 §D",
16591
+ "requirement": "an accepted tools/call MUST return a JSON-RPC result"
16479
16592
  }
16480
16593
  ]
16481
16594
  },
@@ -16554,7 +16667,7 @@
16554
16667
  {
16555
16668
  "id": "openwop.it.mcp-tool-roundtrip.host-invokes-the-configured-mcp-server-and-surfaces-the-tool-response-in-the-eve",
16556
16669
  "file": "mcp-tool-roundtrip.test.ts",
16557
- "line": 286,
16670
+ "line": 272,
16558
16671
  "title": "host invokes the configured MCP server and surfaces the tool response in the event log",
16559
16672
  "explicitId": "openwop.it.mcp-tool-roundtrip.host-invokes-the-configured-mcp-server-and-surfaces-the-tool-response-in-the-eve",
16560
16673
  "citations": [
@@ -16571,7 +16684,7 @@
16571
16684
  {
16572
16685
  "id": "openwop.it.mcp-tool-roundtrip.raw-when-present-is-the-server-calltoolresult-unaltered-and-iserror-agrees",
16573
16686
  "file": "mcp-tool-roundtrip.test.ts",
16574
- "line": 344,
16687
+ "line": 330,
16575
16688
  "title": "raw, when present, is the server CallToolResult unaltered and isError agrees",
16576
16689
  "explicitId": "openwop.it.mcp-tool-roundtrip.raw-when-present-is-the-server-calltoolresult-unaltered-and-iserror-agrees",
16577
16690
  "citations": [
@@ -18300,6 +18413,14 @@
18300
18413
  {
18301
18414
  "section": "RFCS/0006-orchestrator.md",
18302
18415
  "requirement": "fixture emits at least one kind:next-worker decision"
18416
+ },
18417
+ {
18418
+ "section": "RFCS/0006-orchestrator.md",
18419
+ "requirement": "the dispatch node MUST emit node.started after the supervisor decides next-worker"
18420
+ },
18421
+ {
18422
+ "section": "RFCS/0006-orchestrator.md",
18423
+ "requirement": "runOrchestrator.decided{next-worker} MUST precede node.started{dispatch} in event-log sequence"
18303
18424
  }
18304
18425
  ]
18305
18426
  },
@@ -19127,13 +19248,17 @@
19127
19248
  {
19128
19249
  "section": "node-packs.md §\"GET /v1/packs/{name}/-/{version}.sig\"",
19129
19250
  "requirement": "404 response MUST carry a string `error` field — `signature_not_available` is the canonical code"
19251
+ },
19252
+ {
19253
+ "section": "node-packs.md §\"GET /v1/packs/{name}/-/{version}.sig\"",
19254
+ "requirement": "nonexistent (name, version) MUST return 404 `signature_not_available`"
19130
19255
  }
19131
19256
  ]
19132
19257
  },
19133
19258
  {
19134
19259
  "id": "openwop.it.pack-registry.get-v1-packs-bad-name-version-json-returns-400-invalid-pack-name",
19135
19260
  "file": "pack-registry.test.ts",
19136
- "line": 214,
19261
+ "line": 221,
19137
19262
  "title": "GET /v1/packs/{bad-name}/-/{version}.json returns 400 invalid_pack_name",
19138
19263
  "explicitId": "openwop.it.pack-registry.get-v1-packs-bad-name-version-json-returns-400-invalid-pack-name",
19139
19264
  "citations": [
@@ -19150,7 +19275,7 @@
19150
19275
  {
19151
19276
  "id": "openwop.it.pack-registry.get-v1-packs-name-bad-version-json-returns-400-invalid-version",
19152
19277
  "file": "pack-registry.test.ts",
19153
- "line": 234,
19278
+ "line": 241,
19154
19279
  "title": "GET /v1/packs/{name}/-/{bad-version}.json returns 400 invalid_version",
19155
19280
  "explicitId": "openwop.it.pack-registry.get-v1-packs-name-bad-version-json-returns-400-invalid-version",
19156
19281
  "citations": [
@@ -19163,7 +19288,7 @@
19163
19288
  {
19164
19289
  "id": "openwop.it.pack-registry.get-v1-packs-name-catalog-records-validate-against-the-documented-shape",
19165
19290
  "file": "pack-registry.test.ts",
19166
- "line": 254,
19291
+ "line": 261,
19167
19292
  "title": "GET /v1/packs/{name} catalog records validate against the documented shape",
19168
19293
  "explicitId": "openwop.it.pack-registry.get-v1-packs-name-catalog-records-validate-against-the-documented-shape",
19169
19294
  "citations": [
@@ -19195,7 +19320,7 @@
19195
19320
  {
19196
19321
  "id": "openwop.it.pack-registry.get-v1-packs-name-keychain-returns-well-formed-key-entries-when-present",
19197
19322
  "file": "pack-registry.test.ts",
19198
- "line": 309,
19323
+ "line": 316,
19199
19324
  "title": "GET /v1/packs/{name}/-/keychain returns well-formed key entries when present",
19200
19325
  "explicitId": "openwop.it.pack-registry.get-v1-packs-name-keychain-returns-well-formed-key-entries-when-present",
19201
19326
  "citations": [
@@ -19493,14 +19618,10 @@
19493
19618
  {
19494
19619
  "id": "openwop.it.production-backpressure.get-well-known-openwop-returns-200-even-when-inflight-is-saturated",
19495
19620
  "file": "production-backpressure.test.ts",
19496
- "line": 312,
19621
+ "line": 318,
19497
19622
  "title": "GET /.well-known/openwop returns 200 even when inflight is saturated",
19498
19623
  "explicitId": "openwop.it.production-backpressure.get-well-known-openwop-returns-200-even-when-inflight-is-saturated",
19499
19624
  "citations": [
19500
- {
19501
- "section": "production-profile.md §Backpressure",
19502
- "requirement": "discovery MUST answer regardless of load"
19503
- },
19504
19625
  {
19505
19626
  "section": "production-profile.md §Backpressure",
19506
19627
  "requirement": "discovery MUST bypass the inflight cap (health probes always answer)"
@@ -21907,7 +22028,7 @@
21907
22028
  "citations": [
21908
22029
  {
21909
22030
  "section": "capabilities.md",
21910
- "requirement": "skips when host does NOT advertise secrets.supported"
22031
+ "requirement": "a credentialRef value MUST NOT appear in any RunEvent payload"
21911
22032
  }
21912
22033
  ]
21913
22034
  },
@@ -24945,6 +25066,14 @@
24945
25066
  "section": "stream-modes.md mode-to-event mapping",
24946
25067
  "requirement": "debug stream event count MUST be >= updates stream event count"
24947
25068
  },
25069
+ {
25070
+ "section": "stream-modes.md §Mode-to-event mapping",
25071
+ "requirement": "every event type emitted in updates mode is also ✅ in debug mode — debug MUST carry each of them"
25072
+ },
25073
+ {
25074
+ "section": "stream-modes.md §Mode-to-event mapping",
25075
+ "requirement": "debug mode MUST emit node.started (✅ debug) for the fixture's node"
25076
+ },
24948
25077
  {
24949
25078
  "section": "stream-modes.md §debug",
24950
25079
  "requirement": "debug stream MUST close on terminal event"
@@ -25551,6 +25680,16 @@
25551
25680
  "title": "lists schema-valid ToolDescriptors, serves by-id + 404s, is auth-gated, and never discloses another principal",
25552
25681
  "explicitId": "openwop.it.tool-catalog-projection.lists-schema-valid-tooldescriptors-serves-by-id-404s-is-auth-gated-and-never-dis",
25553
25682
  "citations": [
25683
+ {
25684
+ "section": "tool-catalog.md §B",
25685
+ "requirement": null,
25686
+ "interpolated": true
25687
+ },
25688
+ {
25689
+ "section": "tool-catalog.md §B",
25690
+ "requirement": null,
25691
+ "interpolated": true
25692
+ },
25554
25693
  {
25555
25694
  "section": "tool-catalog.md §B",
25556
25695
  "requirement": null,
@@ -25569,6 +25708,10 @@
25569
25708
  "section": "tool-catalog.md §C",
25570
25709
  "requirement": "ToolDescriptor.safetyTier MUST be pure|read|write|exec"
25571
25710
  },
25711
+ {
25712
+ "section": "tool-catalog.md §B",
25713
+ "requirement": "GET /v1/tools/{toolId} MUST return 200 for a toolId the caller's own list returned"
25714
+ },
25572
25715
  {
25573
25716
  "section": "tool-catalog.md §B",
25574
25717
  "requirement": "GET /v1/tools/{toolId} MUST return the requested descriptor"
@@ -25586,7 +25729,7 @@
25586
25729
  {
25587
25730
  "id": "openwop.it.tool-catalog-projection.advisory-should-an-unchanged-catalog-reads-identically-sorted-by-toolid",
25588
25731
  "file": "tool-catalog-projection.test.ts",
25589
- "line": 143,
25732
+ "line": 164,
25590
25733
  "title": "advisory (SHOULD): an unchanged catalog reads identically, sorted by toolId",
25591
25734
  "explicitId": "openwop.it.tool-catalog-projection.advisory-should-an-unchanged-catalog-reads-identically-sorted-by-toolid",
25592
25735
  "citations": [
@@ -28765,7 +28908,7 @@
28765
28908
  {
28766
28909
  "id": "openwop.it.v2-effect-identity-business-key.get-runs-runid-effects-validates-and-every-row-is-keyed-on-business-identity-or",
28767
28910
  "file": "v2-effect-identity-business-key.test.ts",
28768
- "line": 49,
28911
+ "line": 50,
28769
28912
  "title": "GET /runs/{runId}/effects validates and every row is keyed on business identity or the activity recipe",
28770
28913
  "explicitId": "openwop.requirement.0173.effect-identity-business-key",
28771
28914
  "citations": [
@@ -28805,7 +28948,7 @@
28805
28948
  {
28806
28949
  "id": "openwop.it.v2-effect-identity-business-key.the-same-provider-key-is-presented-across-two-transport-retries",
28807
28950
  "file": "v2-effect-identity-business-key.test.ts",
28808
- "line": 107,
28951
+ "line": 108,
28809
28952
  "title": "the same provider key is presented across two transport retries",
28810
28953
  "explicitId": "openwop.requirement.0173.effect-identity-business-key.retry",
28811
28954
  "citations": [
@@ -28828,6 +28971,20 @@
28828
28971
  "section": "spec/v2/core/idempotency.md §Layer 2: effect identity",
28829
28972
  "requirement": null,
28830
28973
  "interpolated": true
28974
+ },
28975
+ {
28976
+ "section": "spec/v2/core/idempotency.md §Layer 2: effect identity",
28977
+ "requirement": null,
28978
+ "interpolated": true
28979
+ },
28980
+ {
28981
+ "section": "spec/v2/core/idempotency.md §Layer 2: effect identity",
28982
+ "requirement": null,
28983
+ "interpolated": true
28984
+ },
28985
+ {
28986
+ "section": "spec/v2/core/idempotency.md §Layer 2: effect identity",
28987
+ "requirement": "the key the ledger records MUST be the key the provider received — a ledger that disagrees with the wire is not a witness"
28831
28988
  }
28832
28989
  ]
28833
28990
  },
@@ -28981,7 +29138,7 @@
28981
29138
  {
28982
29139
  "id": "openwop.it.v2-era-2-append-vocabulary.the-run-keeps-the-era-it-was-created-with-an-append-does-not-promote-it-to-era-3",
28983
29140
  "file": "v2-era-2-append-vocabulary.test.ts",
28984
- "line": 165,
29141
+ "line": 174,
28985
29142
  "title": "the run keeps the era it was created with; an append does not promote it to era 3",
28986
29143
  "explicitId": "openwop.requirement.0176.era-2-append-vocabulary",
28987
29144
  "citations": [
@@ -29361,6 +29518,11 @@
29361
29518
  "requirement": null,
29362
29519
  "interpolated": true
29363
29520
  },
29521
+ {
29522
+ "section": "spec/v2/core/idempotency.md Concurrency",
29523
+ "requirement": null,
29524
+ "interpolated": true
29525
+ },
29364
29526
  {
29365
29527
  "section": "spec/v2/core/idempotency.md Concurrency",
29366
29528
  "requirement": null,
@@ -29371,7 +29533,7 @@
29371
29533
  {
29372
29534
  "id": "openwop.it.v2-idempotency-in-flight.each-loser-is-a-marked-replay-of-a-final-outcome-or-409-idempotency-in-flight-wi",
29373
29535
  "file": "v2-idempotency-in-flight.test.ts",
29374
- "line": 113,
29536
+ "line": 119,
29375
29537
  "title": "each loser is a marked replay of a final outcome, or 409 idempotency_in_flight with no retry timing in details",
29376
29538
  "explicitId": "openwop.requirement.0213.in-flight-loser-outcome",
29377
29539
  "citations": [
@@ -29385,6 +29547,11 @@
29385
29547
  "requirement": null,
29386
29548
  "interpolated": true
29387
29549
  },
29550
+ {
29551
+ "section": "spec/v2/core/idempotency.md Concurrency",
29552
+ "requirement": null,
29553
+ "interpolated": true
29554
+ },
29388
29555
  {
29389
29556
  "section": "spec/v2/core/errors.md §Retry timing",
29390
29557
  "requirement": null,
@@ -29400,7 +29567,7 @@
29400
29567
  {
29401
29568
  "id": "openwop.it.v2-idempotency-in-flight.while-the-seam-holds-the-claim-a-same-key-create-is-refused-409-idempotency-in-f",
29402
29569
  "file": "v2-idempotency-in-flight.test.ts",
29403
- "line": 138,
29570
+ "line": 154,
29404
29571
  "title": "while the seam holds the claim, a same-key create is refused 409 idempotency_in_flight by the host and the held create still wins",
29405
29572
  "explicitId": "openwop.requirement.0213.in-flight-refused-under-hold",
29406
29573
  "citations": [
@@ -30607,6 +30774,11 @@
30607
30774
  "section": "interop-map.json mcp.mrtr InputRequiredResult",
30608
30775
  "requirement": "the entry is projected as the MRTR row projects it (elicitation/create)"
30609
30776
  },
30777
+ {
30778
+ "section": "RFC 0198 §B.4; ext-tasks §Task Execution Errors",
30779
+ "requirement": null,
30780
+ "interpolated": true
30781
+ },
30610
30782
  {
30611
30783
  "section": "interop-map.json mcp.tasks.status failed; ext-tasks §Task Execution Errors",
30612
30784
  "requirement": null,
@@ -30617,7 +30789,7 @@
30617
30789
  {
30618
30790
  "id": "openwop.it.v2-mcp-tasks.tasks-update-answered-twice-resolves-the-interrupt-once-and-the-task-completes",
30619
30791
  "file": "v2-mcp-tasks.test.ts",
30620
- "line": 314,
30792
+ "line": 323,
30621
30793
  "title": "tasks/update answered twice resolves the interrupt once and the task completes",
30622
30794
  "explicitId": "openwop.requirement.0198.task-update-resolves-once",
30623
30795
  "citations": [
@@ -30645,7 +30817,7 @@
30645
30817
  {
30646
30818
  "id": "openwop.it.v2-mcp-tasks.a-tasks-update-from-a-caller-not-in-approverslist-resolves-nothing",
30647
30819
  "file": "v2-mcp-tasks.test.ts",
30648
- "line": 334,
30820
+ "line": 343,
30649
30821
  "title": "a tasks/update from a caller not in approversList resolves nothing",
30650
30822
  "explicitId": "openwop.requirement.0198.task-update-approver-checked",
30651
30823
  "citations": [
@@ -30673,7 +30845,7 @@
30673
30845
  {
30674
30846
  "id": "openwop.it.v2-mcp-tasks.tasks-get-appends-nothing-to-the-run-log",
30675
30847
  "file": "v2-mcp-tasks.test.ts",
30676
- "line": 365,
30848
+ "line": 374,
30677
30849
  "title": "tasks/get appends nothing to the run log",
30678
30850
  "explicitId": "openwop.requirement.0198.task-get-read-only",
30679
30851
  "citations": [
@@ -30687,7 +30859,7 @@
30687
30859
  {
30688
30860
  "id": "openwop.it.v2-mcp-tasks.an-unreadable-task-is-answered-32602-exactly-as-a-nonexistent-one",
30689
30861
  "file": "v2-mcp-tasks.test.ts",
30690
- "line": 380,
30862
+ "line": 389,
30691
30863
  "title": "an unreadable task is answered -32602 exactly as a nonexistent one",
30692
30864
  "explicitId": "openwop.requirement.0198.task-unreadable-not-found",
30693
30865
  "citations": [
@@ -30719,7 +30891,7 @@
30719
30891
  {
30720
30892
  "id": "openwop.it.v2-mcp-tasks.a-subscriptions-listen-acknowledgement-leaves-out-a-task-the-caller-cannot-read",
30721
30893
  "file": "v2-mcp-tasks.test.ts",
30722
- "line": 413,
30894
+ "line": 422,
30723
30895
  "title": "a subscriptions/listen acknowledgement leaves out a task the caller cannot read",
30724
30896
  "explicitId": "openwop.requirement.0198.listen-omits-unreadable",
30725
30897
  "citations": [
@@ -30747,7 +30919,7 @@
30747
30919
  {
30748
30920
  "id": "openwop.it.v2-mcp-tasks.tasks-cancel-cancels-the-run-on-a-terminal-task-it-is-acknowledged-and-appends-n",
30749
30921
  "file": "v2-mcp-tasks.test.ts",
30750
- "line": 435,
30922
+ "line": 444,
30751
30923
  "title": "tasks/cancel cancels the run; on a terminal task it is acknowledged and appends nothing",
30752
30924
  "explicitId": "openwop.requirement.0198.task-cancel-cancels-run",
30753
30925
  "citations": [
@@ -30779,7 +30951,7 @@
30779
30951
  {
30780
30952
  "id": "openwop.it.v2-mcp-tasks.a-client-disconnect-before-the-host-answers-a-task-less-tools-call-cancels-the-r",
30781
30953
  "file": "v2-mcp-tasks.test.ts",
30782
- "line": 454,
30954
+ "line": 463,
30783
30955
  "title": "a client disconnect before the host answers a task-less tools/call cancels the run it started",
30784
30956
  "explicitId": "openwop.requirement.0198.disconnect-cancels-run",
30785
30957
  "citations": [
@@ -30802,7 +30974,7 @@
30802
30974
  {
30803
30975
  "id": "openwop.it.v2-mcp-tasks.a-disconnect-after-createtaskresult-never-affects-the-run",
30804
30976
  "file": "v2-mcp-tasks.test.ts",
30805
- "line": 474,
30977
+ "line": 483,
30806
30978
  "title": "a disconnect after CreateTaskResult never affects the run",
30807
30979
  "explicitId": "openwop.requirement.0198.task-survives-disconnect",
30808
30980
  "citations": [
@@ -30821,7 +30993,7 @@
30821
30993
  {
30822
30994
  "id": "openwop.it.v2-mcp-tasks.a-blocking-tools-call-on-an-sse-stream-whose-run-is-cancelled-carries-no-notific",
30823
30995
  "file": "v2-mcp-tasks.test.ts",
30824
- "line": 489,
30996
+ "line": 498,
30825
30997
  "title": "a blocking tools/call on an SSE stream whose run is cancelled carries no notifications/cancelled and ends isError true",
30826
30998
  "explicitId": "openwop.requirement.0198.no-server-cancelled",
30827
30999
  "citations": [
@@ -32345,7 +32517,7 @@
32345
32517
  {
32346
32518
  "id": "openwop.it.v2-run-diff-identical.two-identical-logs-diff-to-divergedatseq-null-and-empty-eventdiffs-in-a-response",
32347
32519
  "file": "v2-run-diff-identical.test.ts",
32348
- "line": 54,
32520
+ "line": 57,
32349
32521
  "title": "two identical logs diff to divergedAtSeq null and empty eventDiffs, in a response that validates and echoes both ids",
32350
32522
  "explicitId": "openwop.requirement.0170.run-diff-identical",
32351
32523
  "citations": [
@@ -32585,7 +32757,7 @@
32585
32757
  {
32586
32758
  "id": "openwop.it.v2-run-pause-resume.a-running-run-pauses-202-paused-refuses-a-second-pause-409-resumes-202-running-a",
32587
32759
  "file": "v2-run-pause-resume.test.ts",
32588
- "line": 77,
32760
+ "line": 80,
32589
32761
  "title": "a running run pauses (202 paused), refuses a second pause (409), resumes (202 running), and the log carries run.paused then run.resumed",
32590
32762
  "explicitId": "openwop.requirement.0170.run-pause-resume",
32591
32763
  "citations": [
@@ -32803,6 +32975,11 @@
32803
32975
  "requirement": null,
32804
32976
  "interpolated": true
32805
32977
  },
32978
+ {
32979
+ "section": "spec/v2/core/events.md §SSE frames",
32980
+ "requirement": null,
32981
+ "interpolated": true
32982
+ },
32806
32983
  {
32807
32984
  "section": "spec/v2/core/events.md §SSE frames",
32808
32985
  "requirement": "the host MUST close the empty resume itself"
@@ -33213,7 +33390,8 @@
33213
33390
  },
33214
33391
  {
33215
33392
  "section": "spec/v2/core/versioning.md §1.3",
33216
- "requirement": "a host that does not serve major 2 MUST refuse with 406 protocol_version_unsupported, which it did"
33393
+ "requirement": null,
33394
+ "interpolated": true
33217
33395
  },
33218
33396
  {
33219
33397
  "section": "spec/v2/core/versioning.md §1.3",
@@ -33224,7 +33402,7 @@
33224
33402
  {
33225
33403
  "id": "openwop.it.v2-version-header-honored.a-host-advertising-two-majors-serves-two-different-representations",
33226
33404
  "file": "v2-version-header-honored.test.ts",
33227
- "line": 166,
33405
+ "line": 185,
33228
33406
  "title": "a host advertising two majors serves two different representations",
33229
33407
  "explicitId": "openwop.requirement.0172.version-header-honored",
33230
33408
  "citations": [
@@ -33427,7 +33605,7 @@
33427
33605
  {
33428
33606
  "id": "openwop.it.v2-webhook-durable-delivery.the-dead-letter-read-is-served-and-its-records-carry-no-payload",
33429
33607
  "file": "v2-webhook-durable-delivery.test.ts",
33430
- "line": 470,
33608
+ "line": 478,
33431
33609
  "title": "the dead-letter read is served and its records carry no payload",
33432
33610
  "explicitId": "openwop.requirement.0188.dead-letter-read",
33433
33611
  "citations": [
@@ -33440,7 +33618,7 @@
33440
33618
  {
33441
33619
  "id": "openwop.it.v2-webhook-durable-delivery.after-unregister-the-dead-letter-read-answers-404-not-found-as-for-a-subscriptio",
33442
33620
  "file": "v2-webhook-durable-delivery.test.ts",
33443
- "line": 491,
33621
+ "line": 499,
33444
33622
  "title": "after unregister, the dead-letter read answers 404 not_found, as for a subscription that never existed",
33445
33623
  "explicitId": "openwop.requirement.0217.dead-letter-read-after-unregister",
33446
33624
  "citations": [
@@ -33467,7 +33645,7 @@
33467
33645
  {
33468
33646
  "id": "openwop.it.v2-webhook-durable-delivery.a-dead-letter-record-carries-no-delivered-payload",
33469
33647
  "file": "v2-webhook-durable-delivery.test.ts",
33470
- "line": 524,
33648
+ "line": 532,
33471
33649
  "title": "a dead-letter record carries no delivered payload",
33472
33650
  "explicitId": "openwop.requirement.0188.dead-letter-content-free",
33473
33651
  "citations": [
@@ -34043,13 +34221,18 @@
34043
34221
  {
34044
34222
  "section": "capabilities.md §3 + version-negotiation.md",
34045
34223
  "requirement": "Capabilities.protocolVersion MUST be a non-empty string"
34224
+ },
34225
+ {
34226
+ "section": "RFC 0149 §C; capabilities.schema.json protocolVersion.pattern",
34227
+ "requirement": null,
34228
+ "interpolated": true
34046
34229
  }
34047
34230
  ]
34048
34231
  },
34049
34232
  {
34050
34233
  "id": "openwop.it.version-negotiation.every-event-has-the-6-required-runeventdoc-fields-per-run-event-schema-json",
34051
34234
  "file": "version-negotiation.test.ts",
34052
- "line": 82,
34235
+ "line": 93,
34053
34236
  "title": "every event has the 6 required RunEventDoc fields per run-event.schema.json",
34054
34237
  "explicitId": "openwop.it.version-negotiation.every-event-has-the-6-required-runeventdoc-fields-per-run-event-schema-json",
34055
34238
  "citations": [
@@ -34090,7 +34273,7 @@
34090
34273
  {
34091
34274
  "id": "openwop.it.version-negotiation.event-sequences-within-a-run-are-strictly-monotonic",
34092
34275
  "file": "version-negotiation.test.ts",
34093
- "line": 126,
34276
+ "line": 137,
34094
34277
  "title": "event sequences within a run are strictly monotonic",
34095
34278
  "explicitId": "openwop.it.version-negotiation.event-sequences-within-a-run-are-strictly-monotonic",
34096
34279
  "citations": [
@@ -34104,7 +34287,7 @@
34104
34287
  {
34105
34288
  "id": "openwop.it.version-negotiation.events-poll-with-lastsequence-past-current-end-returns-empty-events-iscomplete",
34106
34289
  "file": "version-negotiation.test.ts",
34107
- "line": 154,
34290
+ "line": 165,
34108
34291
  "title": "events/poll with lastSequence past current end returns empty events + isComplete",
34109
34292
  "explicitId": "openwop.it.version-negotiation.events-poll-with-lastsequence-past-current-end-returns-empty-events-iscomplete",
34110
34293
  "citations": [
@@ -34630,7 +34813,7 @@
34630
34813
  {
34631
34814
  "id": "openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature",
34632
34815
  "file": "webhook-signed-delivery.test.ts",
34633
- "line": 170,
34816
+ "line": 172,
34634
34817
  "title": "host POSTs run events to subscriber with valid X-openwop-Signature",
34635
34818
  "explicitId": "openwop.it.webhook-signed-delivery.host-posts-run-events-to-subscriber-with-valid-x-openwop-signature",
34636
34819
  "citations": [
@@ -34657,7 +34840,13 @@
34657
34840
  },
34658
34841
  {
34659
34842
  "section": "webhooks.md §\"Delivery headers\"",
34660
- "requirement": "X-openwop-Timestamp MUST be a Unix-seconds integer string"
34843
+ "requirement": null,
34844
+ "interpolated": true
34845
+ },
34846
+ {
34847
+ "section": "webhooks.md §\"Delivery headers\"; §\"Verification recipe\" step 1 (±5 minutes)",
34848
+ "requirement": null,
34849
+ "interpolated": true
34661
34850
  },
34662
34851
  {
34663
34852
  "section": "webhooks.md §\"Delivery headers\"",
@@ -34681,7 +34870,7 @@
34681
34870
  {
34682
34871
  "id": "openwop.it.webhook-signed-delivery.control-with-a-tunnel-wired-the-host-still-refuses-the-loopback-receiver",
34683
34872
  "file": "webhook-signed-delivery.test.ts",
34684
- "line": 425,
34873
+ "line": 440,
34685
34874
  "title": "control: with a tunnel wired, the host still refuses the loopback receiver",
34686
34875
  "explicitId": "openwop.it.webhook-signed-delivery.control-with-a-tunnel-wired-the-host-still-refuses-the-loopback-receiver",
34687
34876
  "citations": [