capdag 1.241.684 → 1.246.701

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/capdag.js CHANGED
@@ -949,6 +949,50 @@ class CapUrn {
949
949
  return runtimeOut;
950
950
  }
951
951
 
952
+ /**
953
+ * THE effect-audit predicate: does an actually-emitted runtime output
954
+ * satisfy this cap's declared effect contract for the given runtime
955
+ * input? Every check of "did the cap emit what its effect promised"
956
+ * must go through this — never a hand-rolled combination of
957
+ * inferRuntimeOutputMedia with equality or conformance checks, so the
958
+ * contract has exactly one definition.
959
+ *
960
+ * The condition is deliberately asymmetric per effect:
961
+ * - effect=none / effect=patch compute an EXACT runtime output type,
962
+ * so the emission must be tag-equivalent to the inference. A more
963
+ * specific emission would still be a lie: the effect promises the
964
+ * type is fully determined by the input.
965
+ * - effect=declared promises only the declared out=, so an emission
966
+ * that is MORE specific than the declaration is legal and desirable;
967
+ * the emission must conform to the declared output. A more generic
968
+ * emission breaks downstream plan refinement and fails.
969
+ *
970
+ * Throws (rather than returning false) when the inference itself is
971
+ * impossible: the runtime input does not conform to the declared
972
+ * input, the effect is the unconstrained request form (?effect), or
973
+ * the URN state is internally inconsistent — those are upstream
974
+ * contract breaks, not emission mismatches.
975
+ *
976
+ * @param {MediaUrn} runtimeInput
977
+ * @param {MediaUrn} runtimeOutput
978
+ * @returns {boolean}
979
+ */
980
+ isConformantRuntimeOutput(runtimeInput, runtimeOutput) {
981
+ const inferred = this.inferRuntimeOutputMedia(runtimeInput);
982
+ switch (this.effectValue) {
983
+ case CapEffect.NONE:
984
+ case CapEffect.PATCH:
985
+ return runtimeOutput.isEquivalent(inferred);
986
+ case CapEffect.DECLARED:
987
+ return runtimeOutput.conformsTo(inferred);
988
+ default:
989
+ throw new CapUrnError(
990
+ ErrorCodes.INVALID_EFFECT_APPLICATION,
991
+ 'Cannot audit an emission against an unconstrained effect request'
992
+ );
993
+ }
994
+ }
995
+
952
996
  _validateAdmissible() {
953
997
  const inMedia = this.inMediaUrn();
954
998
  const outMedia = this.outMediaUrn();
@@ -1561,6 +1605,17 @@ class MediaUrn {
1561
1605
  */
1562
1606
  isFilePath() { return this._hasMarkerTag('file-path'); }
1563
1607
 
1608
+ /**
1609
+ * True if this URN carries the `live` marker tag — a live-feed
1610
+ * REFERENCE (13.2 §Reference Media): the arg value is a selector record
1611
+ * the runtime resolves into an unbounded content stream via a registered
1612
+ * provider, the same transport-resolution family as `media:file-path`.
1613
+ * This is the canonical membership predicate for that family; callers
1614
+ * must not test the `live` tag themselves.
1615
+ * @returns {boolean}
1616
+ */
1617
+ isLiveFeed() { return this._hasMarkerTag('live'); }
1618
+
1564
1619
  /**
1565
1620
  * Check if this represents a collection type.
1566
1621
  * Returns true if the "collection" marker tag is present.
package/capdag.test.js CHANGED
@@ -2797,6 +2797,16 @@ function test551_isFilePath() {
2797
2797
  assert(!MediaUrn.fromString(MEDIA_IDENTITY).isFilePath(), 'MEDIA_IDENTITY should not be file-path');
2798
2798
  }
2799
2799
 
2800
+ // TEST553: is_live_feed returns true for every URN carrying the `live` marker tag (the reference-media family the runtime resolves via providers), false for everything else — including content URNs a feed delivers.
2801
+ function test553_isLiveFeed() {
2802
+ assert(MediaUrn.fromString('media:live').isLiveFeed(), 'media:live should be live-feed');
2803
+ assert(MediaUrn.fromString('media:live;synthetic').isLiveFeed(), 'media:live;synthetic should be live-feed');
2804
+ assert(MediaUrn.fromString('media:audio;live;microphone').isLiveFeed(), 'microphone URN should be live-feed');
2805
+ assert(!MediaUrn.fromString(MEDIA_STRING).isLiveFeed(), 'MEDIA_STRING should not be live-feed');
2806
+ assert(!MediaUrn.fromString(MEDIA_FILE_PATH).isLiveFeed(), 'MEDIA_FILE_PATH should not be live-feed');
2807
+ assert(!MediaUrn.fromString('media:audio;pcm').isLiveFeed(), 'feed CONTENT urns should not be live-feed');
2808
+ }
2809
+
2800
2810
  // Mirror-specific coverage: isCollection returns true when collection marker tag is present
2801
2811
  // Mirror-specific coverage: N/A for JS (MEDIA_COLLECTION constants removed - no longer exists)
2802
2812
  function test6272_isCollection() {
@@ -3206,6 +3216,80 @@ function test127_invalidEffectNoneFailsHard() {
3206
3216
  );
3207
3217
  }
3208
3218
 
3219
+ // TEST8121: isConformantRuntimeOutput — effect=declared accepts a more
3220
+ // specific emission, rejects a more generic one
3221
+ function test8121_effectConformanceDeclaredAsymmetry() {
3222
+ const cap = CapUrn.fromString('cap:extract;in="media:ext=pdf";out="media:record"');
3223
+ const input = MediaUrn.fromString('media:ext=pdf');
3224
+
3225
+ assert(
3226
+ cap.isConformantRuntimeOutput(input, MediaUrn.fromString('media:record')),
3227
+ 'emitting exactly the declared out is conformant'
3228
+ );
3229
+ assert(
3230
+ cap.isConformantRuntimeOutput(input, MediaUrn.fromString('media:fmt=json;record')),
3231
+ 'a more specific emission than the declared out is conformant'
3232
+ );
3233
+ assert(
3234
+ !cap.isConformantRuntimeOutput(input, MediaUrn.fromString('media:')),
3235
+ 'a more generic emission than the declared out is a violation'
3236
+ );
3237
+ assert(
3238
+ !cap.isConformantRuntimeOutput(input, MediaUrn.fromString('media:ext=png;image')),
3239
+ 'an unrelated emission is a violation'
3240
+ );
3241
+ }
3242
+
3243
+ // TEST8122: isConformantRuntimeOutput — effect=none requires the emission
3244
+ // to be tag-equivalent to the runtime input; MORE specific is still a lie
3245
+ function test8122_effectConformanceNoneRequiresEquivalence() {
3246
+ const cap = CapUrn.fromString('cap:decimate-sequence;effect=none');
3247
+ const input = MediaUrn.fromString('media:ext=png;image');
3248
+
3249
+ assert(
3250
+ cap.isConformantRuntimeOutput(input, input),
3251
+ 'emitting exactly the runtime input type is conformant'
3252
+ );
3253
+ assert(
3254
+ !cap.isConformantRuntimeOutput(input, MediaUrn.fromString('media:ext=png;image;width=64')),
3255
+ 'effect=none promises the output type IS the input type; more specific is a lie'
3256
+ );
3257
+ assert(
3258
+ !cap.isConformantRuntimeOutput(input, MediaUrn.fromString('media:image')),
3259
+ 'a more generic emission is a violation'
3260
+ );
3261
+
3262
+ const strict = CapUrn.fromString('cap:effect=none;in="media:image";out="media:image"');
3263
+ const nonImage = MediaUrn.fromString('media:ext=pdf');
3264
+ assertThrows(
3265
+ () => strict.isConformantRuntimeOutput(nonImage, nonImage),
3266
+ ErrorCodes.INVALID_EFFECT_APPLICATION,
3267
+ 'a nonconforming runtime input is an upstream contract break, surfaced as an error'
3268
+ );
3269
+ }
3270
+
3271
+ // TEST8123: isConformantRuntimeOutput — effect=patch requires exactly the
3272
+ // delta-patched input type
3273
+ function test8123_effectConformancePatchRequiresPatchedInput() {
3274
+ const cap = CapUrn.fromString(
3275
+ 'cap:convert;effect=patch;in="media:ext=jpeg;image";out="media:ext=png;image"'
3276
+ );
3277
+ const input = MediaUrn.fromString('media:ext=jpeg;image;width=64');
3278
+
3279
+ assert(
3280
+ cap.isConformantRuntimeOutput(input, MediaUrn.fromString('media:ext=png;image;width=64')),
3281
+ 'the delta-patched input type (preserved tags intact) is conformant'
3282
+ );
3283
+ assert(
3284
+ !cap.isConformantRuntimeOutput(input, MediaUrn.fromString('media:ext=png;image')),
3285
+ 'dropping the preserved width tag violates the patch promise'
3286
+ );
3287
+ assert(
3288
+ !cap.isConformantRuntimeOutput(input, input),
3289
+ 'emitting the unpatched input type is a violation'
3290
+ );
3291
+ }
3292
+
3209
3293
  // TEST128: omitted effect means declared; unconstrained effect must be explicit
3210
3294
  function test128_effectDispatchRequiresExplicitWildcard() {
3211
3295
  const noneCandidate = CapUrn.fromString('cap:effect=none');
@@ -7234,6 +7318,7 @@ async function runTests() {
7234
7318
  runTest('TEST1315: is_numeric', test549_isNumeric);
7235
7319
  runTest('TEST1298: is_bool', test550_isBool);
7236
7320
  runTest('TEST1299: is_file_path', test551_isFilePath);
7321
+ runTest('TEST553: is_live_feed', test553_isLiveFeed);
7237
7322
  runTest('TEST1302: predicate_constant_consistency', test558_predicateConstantConsistency);
7238
7323
 
7239
7324
  // cap_urn.rs: TEST1303-TEST1307 (CapUrn tier tests)
@@ -7270,6 +7355,9 @@ async function runTests() {
7270
7355
  runTest('TEST655: effect_declared_uses_declared_output', test126_effectDeclaredUsesDeclaredOutput);
7271
7356
  runTest('TEST656: invalid_effect_none_fails_hard', test127_invalidEffectNoneFailsHard);
7272
7357
  runTest('TEST657: effect_dispatch_requires_explicit_wildcard', test128_effectDispatchRequiresExplicitWildcard);
7358
+ runTest('TEST8121: effect_conformance_declared_asymmetry', test8121_effectConformanceDeclaredAsymmetry);
7359
+ runTest('TEST8122: effect_conformance_none_requires_equivalence', test8122_effectConformanceNoneRequiresEquivalence);
7360
+ runTest('TEST8123: effect_conformance_patch_requires_patched_input', test8123_effectConformancePatchRequiresPatchedInput);
7273
7361
 
7274
7362
  // machine module: parser tests (mirrors parser.rs)
7275
7363
  console.log('\n--- machine/parser.rs ---');
package/package.json CHANGED
@@ -41,5 +41,5 @@
41
41
  "pretest": "npm run build:parser",
42
42
  "test": "node capdag.test.js"
43
43
  },
44
- "version": "1.241.684"
44
+ "version": "1.246.701"
45
45
  }