capdag 0.158.370 → 0.162.386

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 CHANGED
@@ -23,7 +23,7 @@ npm install capdag
23
23
  const { CapUrn, CapUrnBuilder, CapMatcher } = require('capdag');
24
24
 
25
25
  // Create from string (with required direction specifiers)
26
- const cap = CapUrn.fromString('cap:in="media:binary";op=extract;out="media:object"');
26
+ const cap = CapUrn.fromString('cap:in="media:binary";extract;out="media:object"');
27
27
  console.log(cap.toString());
28
28
 
29
29
  // Use builder pattern
@@ -35,14 +35,14 @@ const built = new CapUrnBuilder()
35
35
  .build();
36
36
 
37
37
  // Matching
38
- const request = CapUrn.fromString('cap:in="media:binary";op=extract;out="media:object"');
38
+ const request = CapUrn.fromString('cap:in="media:binary";extract;out="media:object"');
39
39
  console.log(cap.accepts(request)); // true
40
40
 
41
41
  // Find best match by specificity
42
42
  const caps = [
43
- CapUrn.fromString('cap:in=*;op=extract;out=*'),
44
- CapUrn.fromString('cap:in="media:binary";op=extract;out="media:object"'),
45
- CapUrn.fromString('cap:ext=pdf;in="media:binary";op=extract;out="media:object"')
43
+ CapUrn.fromString('cap:in=*;extract;out=*'),
44
+ CapUrn.fromString('cap:in="media:binary";extract;out="media:object"'),
45
+ CapUrn.fromString('cap:ext=pdf;in="media:binary";extract;out="media:object"')
46
46
  ];
47
47
  const best = CapMatcher.findBestMatch(caps, request);
48
48
  console.log(best.toString()); // Most specific match
package/RULES.md CHANGED
@@ -14,7 +14,7 @@ Cap URNs **must** include `in` and `out` tags that specify input/output media ty
14
14
 
15
15
  ```javascript
16
16
  // Valid cap URN with direction specifiers
17
- const cap = CapUrn.fromString('cap:in="media:binary";op=extract;out="media:object"');
17
+ const cap = CapUrn.fromString('cap:in="media:binary";extract;out="media:object"');
18
18
 
19
19
  // Invalid - missing direction specifiers
20
20
  CapUrn.fromString('cap:op=extract'); // throws ErrorCodes.MISSING_IN_SPEC
@@ -26,13 +26,13 @@ Direction specifier values must be valid Media URNs or special pattern values:
26
26
 
27
27
  ```javascript
28
28
  // Valid: Media URN value
29
- 'cap:in="media:binary";op=extract;out="media:object"'
29
+ 'cap:in="media:binary";extract;out="media:object"'
30
30
 
31
31
  // Valid: Must-have-any (any media type)
32
- 'cap:in=*;op=extract;out=*'
32
+ 'cap:in=*;extract;out=*'
33
33
 
34
34
  // Invalid: Not a Media URN or special value
35
- 'cap:in=binary;op=extract;out=object' // throws ErrorCodes.INVALID_MEDIA_URN
35
+ 'cap:in=binary;extract;out=object' // throws ErrorCodes.INVALID_MEDIA_URN
36
36
  ```
37
37
 
38
38
  ### 3. Matching Semantics
@@ -59,8 +59,8 @@ Specificity uses graded scoring:
59
59
  | Unspecified (K=?) or missing | 0 |
60
60
 
61
61
  Examples:
62
- - `cap:in="media:binary";op=extract;out="media:object"` → 3+3+3 = 9
63
- - `cap:in=*;op=extract;out=*` → 2+3+2 = 7
62
+ - `cap:in="media:binary";extract;out="media:object"` → 3+3+3 = 9
63
+ - `cap:in=*;extract;out=*` → 2+3+2 = 7
64
64
 
65
65
  ## Cap-Specific Error Codes
66
66
 
package/capdag.js CHANGED
@@ -922,7 +922,7 @@ const MEDIA_YAML_RECORD = 'media:record;textable;yaml';
922
922
  const MEDIA_YAML_LIST = 'media:list;textable;yaml';
923
923
  const MEDIA_YAML_LIST_RECORD = 'media:list;record;textable;yaml';
924
924
  const MEDIA_CSV = 'media:csv;list;record;textable';
925
- const MEDIA_CSV_LIST = 'media:csv;list;textable';
925
+ const MEDIA_CSV_LIST = 'media:csv;list;record;textable';
926
926
 
927
927
  // File path type — for arguments that represent filesystem paths.
928
928
  // There is a single media URN; cardinality (single file vs many files)
@@ -4528,6 +4528,24 @@ class CartridgeRepoServer {
4528
4528
  * Reasons why a cartridge attachment attempt failed.
4529
4529
  * Mirrors Rust CartridgeAttachmentErrorKind.
4530
4530
  */
4531
+ const CartridgeLifecycle = Object.freeze({
4532
+ // Discovery scan has found the version directory and is about
4533
+ // to inspect it. Transient.
4534
+ DISCOVERED: 'discovered',
4535
+ // Reading cartridge.json, computing directory hash, validating
4536
+ // on-disk install context. Hashing can take seconds for large
4537
+ // model cartridges; runs on a background queue so other
4538
+ // cartridges' inspections proceed in parallel.
4539
+ INSPECTING: 'inspecting',
4540
+ // Inspection succeeded; awaiting a verdict from the registry
4541
+ // verifier service. Skipped for dev cartridges
4542
+ // (registry_url == null) and bundle cartridges.
4543
+ VERIFYING: 'verifying',
4544
+ // Cleared every gate. Caps are registered with the engine and
4545
+ // dispatch can route requests to this cartridge.
4546
+ OPERATIONAL: 'operational',
4547
+ });
4548
+
4531
4549
  const CartridgeAttachmentErrorKind = Object.freeze({
4532
4550
  INCOMPATIBLE: 'incompatible',
4533
4551
  MANIFEST_INVALID: 'manifest_invalid',
@@ -4636,9 +4654,9 @@ class CartridgeRuntimeStats {
4636
4654
  /**
4637
4655
  * Full identity of an installed cartridge, including optional attachment error
4638
4656
  * and runtime statistics.
4639
- * Mirrors Rust InstalledCartridgeIdentity.
4657
+ * Mirrors Rust InstalledCartridgeRecord.
4640
4658
  */
4641
- class InstalledCartridgeIdentity {
4659
+ class InstalledCartridgeRecord {
4642
4660
  /**
4643
4661
  * @param {Object} opts
4644
4662
  * @param {string|null} [opts.registryUrl=null]
@@ -4646,17 +4664,21 @@ class InstalledCartridgeIdentity {
4646
4664
  * @param {string} opts.id
4647
4665
  * @param {string} opts.version
4648
4666
  * @param {string} opts.sha256
4667
+ * @param {Array<Object>} [opts.capGroups=[]] - Cartridge's manifest cap_groups; each element is `{name, caps, adapter_urns}`.
4649
4668
  * @param {CartridgeAttachmentError|null} [opts.attachmentError=null]
4650
4669
  * @param {CartridgeRuntimeStats|null} [opts.runtimeStats=null]
4670
+ * @param {string} [opts.lifecycle='discovered'] - One of `discovered` | `inspecting` | `verifying` | `operational`. Mutually exclusive with attachmentError; see `machfab-mac/docs/cartridge state machine.md`.
4651
4671
  */
4652
- constructor({ registryUrl = null, channel, id, version, sha256, attachmentError = null, runtimeStats = null }) {
4672
+ constructor({ registryUrl = null, channel, id, version, sha256, capGroups = [], attachmentError = null, runtimeStats = null, lifecycle = 'discovered' }) {
4653
4673
  this.registry_url = registryUrl;
4654
4674
  this.channel = channel;
4655
4675
  this.id = id;
4656
4676
  this.version = version;
4657
4677
  this.sha256 = sha256;
4678
+ this.cap_groups = capGroups;
4658
4679
  this.attachment_error = attachmentError;
4659
4680
  this.runtime_stats = runtimeStats;
4681
+ this.lifecycle = lifecycle;
4660
4682
  }
4661
4683
 
4662
4684
  toJSON() {
@@ -4665,24 +4687,50 @@ class InstalledCartridgeIdentity {
4665
4687
  id: this.id,
4666
4688
  version: this.version,
4667
4689
  sha256: this.sha256,
4690
+ lifecycle: this.lifecycle,
4668
4691
  };
4669
4692
  if (this.registry_url !== null) obj.registry_url = this.registry_url;
4693
+ if (this.cap_groups && this.cap_groups.length > 0) obj.cap_groups = this.cap_groups;
4670
4694
  if (this.attachment_error !== null) obj.attachment_error = this.attachment_error.toJSON();
4671
4695
  if (this.runtime_stats !== null) obj.runtime_stats = this.runtime_stats.toJSON();
4672
4696
  return obj;
4673
4697
  }
4674
4698
 
4675
4699
  static fromJSON(d) {
4676
- return new InstalledCartridgeIdentity({
4700
+ return new InstalledCartridgeRecord({
4677
4701
  registryUrl: d.registry_url !== undefined ? d.registry_url : null,
4678
4702
  channel: d.channel,
4679
4703
  id: d.id,
4680
4704
  version: d.version,
4681
4705
  sha256: d.sha256,
4706
+ capGroups: Array.isArray(d.cap_groups) ? d.cap_groups : [],
4682
4707
  attachmentError: d.attachment_error ? CartridgeAttachmentError.fromJSON(d.attachment_error) : null,
4683
4708
  runtimeStats: d.runtime_stats ? CartridgeRuntimeStats.fromJSON(d.runtime_stats) : null,
4709
+ // Default to 'discovered' (the safe sentinel) — never
4710
+ // 'operational' — when the field is missing from the wire.
4711
+ lifecycle: typeof d.lifecycle === 'string' ? d.lifecycle : 'discovered',
4684
4712
  });
4685
4713
  }
4714
+
4715
+ /**
4716
+ * Flat de-duplicated cap-URN view across this cartridge's groups,
4717
+ * preserving first-seen order.
4718
+ * @returns {Array<string>}
4719
+ */
4720
+ capUrns() {
4721
+ const seen = new Set();
4722
+ const out = [];
4723
+ for (const group of this.cap_groups) {
4724
+ const caps = (group && Array.isArray(group.caps)) ? group.caps : [];
4725
+ for (const cap of caps) {
4726
+ const urn = (cap && typeof cap.urn === 'string') ? cap.urn : '';
4727
+ if (!urn || seen.has(urn)) continue;
4728
+ seen.add(urn);
4729
+ out.push(urn);
4730
+ }
4731
+ }
4732
+ return out;
4733
+ }
4686
4734
  }
4687
4735
 
4688
4736
  // ============================================================================
@@ -5942,10 +5990,11 @@ module.exports = {
5942
5990
  CartridgeRepoServer,
5943
5991
  CartridgeChannel,
5944
5992
  // Bifaci — cartridge attachment & runtime identity
5993
+ CartridgeLifecycle,
5945
5994
  CartridgeAttachmentErrorKind,
5946
5995
  CartridgeAttachmentError,
5947
5996
  CartridgeRuntimeStats,
5948
- InstalledCartridgeIdentity,
5997
+ InstalledCartridgeRecord,
5949
5998
  // Registry slug
5950
5999
  DEV_SLUG,
5951
6000
  SLUG_HEX_LEN,