@hyperscale0/hsx 1.0.125 → 1.0.130

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 (43) hide show
  1. package/README.md +2 -2
  2. package/dist/src/cli.js +1 -1
  3. package/dist/src/cli.js.map +1 -1
  4. package/dist/src/compile.d.ts.map +1 -1
  5. package/dist/src/compile.js +155 -21
  6. package/dist/src/compile.js.map +1 -1
  7. package/dist/src/examples-bundle.js +9 -9
  8. package/dist/src/examples-bundle.js.map +1 -1
  9. package/dist/src/headers.d.ts +1 -1
  10. package/dist/src/headers.d.ts.map +1 -1
  11. package/dist/src/headers.js +1 -0
  12. package/dist/src/headers.js.map +1 -1
  13. package/dist/src/parse.js +4 -1
  14. package/dist/src/parse.js.map +1 -1
  15. package/dist/src/std-bundle.d.ts.map +1 -1
  16. package/dist/src/std-bundle.js +8 -7
  17. package/dist/src/std-bundle.js.map +1 -1
  18. package/docs/README.md +102 -50
  19. package/examples/cards.hsx +4 -0
  20. package/examples/collections.hsx +5 -1
  21. package/examples/cost-table.json +80 -56
  22. package/examples/financing.hsx +1 -1
  23. package/examples/insurance.hsx +5 -4
  24. package/examples/lending.hsx +1 -1
  25. package/examples/library.hsx +1 -1
  26. package/examples/rental-deposit.hsx +1 -1
  27. package/examples/reporting.hsx +1 -1
  28. package/examples/serviced.hsx +1 -1
  29. package/package.json +4 -4
  30. package/src/cli.ts +1 -1
  31. package/src/compile.ts +223 -27
  32. package/src/examples-bundle.ts +9 -9
  33. package/src/headers.ts +1 -0
  34. package/src/parse.ts +4 -1
  35. package/src/std-bundle.ts +8 -7
  36. package/std/booking.hsx +75 -0
  37. package/std/cards.hsx +5 -3
  38. package/std/escrow.hsx +35 -9
  39. package/std/financing.hsx +158 -36
  40. package/std/insurance.hsx +9 -5
  41. package/std/marketplace.hsx +3 -3
  42. package/std/money.hsx +3 -3
  43. package/std/wallet.hsx +20 -9
package/README.md CHANGED
@@ -21,8 +21,8 @@ Start with the [first program and rental guide](docs/README.md). Save the
21
21
  It holds 1,000 SAR, charges a one-time 50 SAR late fee, and returns the remainder.
22
22
  The guide explains the fixed business binding and the host needed to execute it.
23
23
 
24
- `npx hsx headers` prints every std instrument and its tunables from the bundled
25
- headers. The [samples](examples/) include both complete action paths and
24
+ `npx hsx headers --json` prints every std instrument and its tunables from the
25
+ bundled headers as JSON. The [samples](examples/) include both complete action paths and
26
26
  compositions that still need child-record actions or adapter bindings. A compile
27
27
  pass does not prove that a flow is publicly executable or funded.
28
28
 
package/dist/src/cli.js CHANGED
@@ -75,7 +75,7 @@ export async function runCli(argv, io) {
75
75
  else {
76
76
  const result = compile(source, { standardLibrary });
77
77
  for (const d of result.diagnostics)
78
- io.err(`${d.source && d.source !== "program" ? d.source : file}:${d.line}:${d.column}: ${d.code} ${d.message}. ${d.fix}`);
78
+ io.err(`${d.source && d.source !== "program" ? d.source : file}:${d.line}:${d.column}: ${d.code} ${d.message.replace(/[^.?!]$/, "$&.")} ${d.fix}`);
79
79
  if (!result.artifacts || result.verdict !== "valid")
80
80
  return 1;
81
81
  if (command === "check")
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/compile.ts"],"names":[],"mappings":"AAOA,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAgBL,KAAK,WAAW,EAQjB,MAAM,kBAAkB,CAAC;AAU1B,OAAO,EAIL,KAAK,UAAU,EAKf,KAAK,IAAI,EACV,MAAM,UAAU,CAAC;AAClB,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CACpC;AACD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,aAAa,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3E;AACD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AACD,MAAM,WAAW,cAAc;IAC7B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;CAClE;AACD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,SAAS,CAAC,EAAE;QACV,QAAQ,EAAE,WAAW,CAAC;QACtB,YAAY,EAAE,eAAe,CAAC;QAC9B,SAAS,EAAE,qBAAqB,EAAE,CAAC;KACpC,CAAC;CACH;AAqTD,wBAAgB,OAAO,CACrB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,GAC3B,aAAa,CAynHf"}
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/compile.ts"],"names":[],"mappings":"AAOA,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAgBL,KAAK,WAAW,EAQjB,MAAM,kBAAkB,CAAC;AAU1B,OAAO,EAIL,KAAK,UAAU,EAKf,KAAK,IAAI,EACV,MAAM,UAAU,CAAC;AAClB,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CACpC;AACD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,aAAa,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3E;AACD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AACD,MAAM,WAAW,cAAc;IAC7B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;CAClE;AACD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,SAAS,CAAC,EAAE;QACV,QAAQ,EAAE,WAAW,CAAC;QACtB,YAAY,EAAE,eAAe,CAAC;QAC9B,SAAS,EAAE,qBAAqB,EAAE,CAAC;KACpC,CAAC;CACH;AAqTD,wBAAgB,OAAO,CACrB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,GAC3B,aAAa,CA6zHf"}
@@ -349,10 +349,6 @@ export function compile(source, options = {}) {
349
349
  for (const decl of program.decls)
350
350
  if (decl.kind === "instrument")
351
351
  templates.set(decl.name, decl);
352
- for (const decl of program.decls) {
353
- if (decl.kind === "instrument" && decl.parameters.length)
354
- fail(decl, "This compiler cannot instantiate a parameterized instrument declared inside a program.", "For this version, specialize the instrument with fixed bindings and remove its parameters. Custom reusable headers require a host-supplied library.");
355
- }
356
352
  const document = {
357
353
  udl: UDL_FORMAT_VERSION,
358
354
  version: 1,
@@ -600,7 +596,11 @@ export function compile(source, options = {}) {
600
596
  const fallback = param.value.kind === "default" ? param.value.value : undefined;
601
597
  const typeName = type.kind === "type" || type.kind === "call" ? type.name : text(type);
602
598
  const partyParameter = attachmentInfo && typeName === "party";
599
+ const optional = type.kind === "type" && type.optional;
600
+ // An optional party stays unset unless the attachment binds it, so a
601
+ // program party that shares its name does not switch it on.
603
602
  const byName = partyParameter &&
603
+ !optional &&
604
604
  (subjectPartyRoles.includes(param.key) ||
605
605
  document.parties[param.key])
606
606
  ? { kind: "name", value: param.key, span: origin }
@@ -612,7 +612,7 @@ export function compile(source, options = {}) {
612
612
  source: declarationSources.get(decl) ?? "program",
613
613
  });
614
614
  if (!actual) {
615
- if (type.kind === "type" && type.optional)
615
+ if (optional)
616
616
  continue;
617
617
  parameterErrors.push({
618
618
  span: origin,
@@ -678,7 +678,9 @@ export function compile(source, options = {}) {
678
678
  const suppliedValue = supplied.get(key);
679
679
  const requirements = decl.body.entries
680
680
  .filter((entry) => entry.key.startsWith("action "))
681
- .flatMap((entry) => asBlock(entries(asBlock(entry.value)).get("subject")).entries);
681
+ .flatMap((entry) =>
682
+ // Read subject rows directly: entries() refuses repeated when branches.
683
+ asBlock(asBlock(entry.value).entries.find((row) => row.key === "subject")?.value).entries);
682
684
  const moneyFields = [
683
685
  ...new Set(requirements
684
686
  .filter((entry) => {
@@ -708,6 +710,21 @@ export function compile(source, options = {}) {
708
710
  (!!attachmentInfo &&
709
711
  subjectPartyRoles.includes(name));
710
712
  const resolvedParties = new Set();
713
+ // A party of a sibling attachment this one references, such as the
714
+ // borrower of `self.plan`, binds here the way it binds there.
715
+ const reachedParty = (name) => {
716
+ if (!attachmentInfo)
717
+ return;
718
+ const targets = fields.flatMap((field) => field.type === "ref" && field.targetKind === "instrument"
719
+ ? [field.target].flat()
720
+ : []);
721
+ const bindings = attachmentInfo.attachments.flatMap((attachment) => targets.some((target) => target === attachment.instrument ||
722
+ target.startsWith(`${attachment.instrument}_`)) && attachment.parties[name]
723
+ ? [attachment.parties[name]]
724
+ : []);
725
+ const distinct = new Set(bindings.map((item) => JSON.stringify(item)));
726
+ return distinct.size === 1 ? bindings[0] : undefined;
727
+ };
711
728
  const resolve = (expr, seen = new Set(), partyBinding = false) => {
712
729
  if (expr.kind === "call" &&
713
730
  ["object", "all", "party"].includes(expr.name)) {
@@ -737,6 +754,15 @@ export function compile(source, options = {}) {
737
754
  const local = (name) => attachmentSubjects.has(name)
738
755
  ? name.slice(attachmentInfo.subjectKindId.length + 1)
739
756
  : `${name} (program)`;
757
+ const elsewhere = [...assignments.values()]
758
+ .filter((assignment) => assignment.target === type &&
759
+ attachmentSubjects.has(assignment.name) &&
760
+ attachmentSubjects.get(assignment.name) !==
761
+ attachmentInfo.subjectKindId)
762
+ .map((assignment) => {
763
+ const subject = attachmentSubjects.get(assignment.name);
764
+ return `\`${subject}.${assignment.name.slice(subject.length + 1)}\``;
765
+ });
740
766
  const target = templates.get(type);
741
767
  const required = target?.parameters
742
768
  .filter((p) => p.value.kind !== "default" &&
@@ -746,7 +772,7 @@ export function compile(source, options = {}) {
746
772
  ? `No \`${type}\` attachment exists on \`${attachmentInfo.subjectKindId}\`.`
747
773
  : `Several \`${type}\` attachments match on \`${attachmentInfo.subjectKindId}\`: ${matches.map(local).join(", ")}.`}`, matches.length
748
774
  ? `Bind \`${parameter}\` explicitly to one of: ${matches.map(local).join(", ")}.`
749
- : `Declare a ${parameter} attachment and bind \`${parameter}: allowance\`. Choose ${required.map((name) => (name.startsWith("per_") ? `its ${name.slice(4).replaceAll("_", " ")} limit` : `\`${name}\``)).join(", ") || "its required bindings"} explicitly.`);
775
+ : `Attach \`${type}\` to \`${attachmentInfo.subjectKindId}\` and bind \`${parameter}\` to that attachment's name. Choose ${required.map((name) => (name.startsWith("per_") ? `its ${name.slice(4).replaceAll("_", " ")} limit` : `\`${name}\``)).join(", ") || "its required bindings"} explicitly.${elsewhere.length ? ` ${elsewhere.join(", ")} ${elsewhere.length === 1 ? "is" : "are"} on another object, which this binding cannot reach.` : ""}`);
750
776
  }
751
777
  if (expr.name !== "all" && matches.length !== 1)
752
778
  failWithCode(expr, partyBinding ? "subject_party_unbound" : "HSX1001", `${id} needs ${expr.name === "all" ? "at least one" : "exactly one"} ${type}`, "declare the required object or supply this tunable explicitly");
@@ -1057,6 +1083,19 @@ export function compile(source, options = {}) {
1057
1083
  value: `${id}_${key}`,
1058
1084
  span: origin,
1059
1085
  });
1086
+ // A subject role only has money here when this attachment binds it.
1087
+ const moneyPath = (expr) => {
1088
+ const lowered = path(expr);
1089
+ const role = lowered.slice("party.".length);
1090
+ if (attachmentInfo &&
1091
+ lowered.startsWith("party.") &&
1092
+ subjectPartyRoles.includes(role) &&
1093
+ !Object.values(attachmentInfo.parties).some((binding) => "role" in binding && binding.role === role))
1094
+ failWithCode(expr, "subject_party_unbound", `\`${role}\` has no money account in \`${decl.name}\``, role === "operator"
1095
+ ? "Use `programOperator` for the company's own account."
1096
+ : `Add a party parameter to \`${decl.name}\` and bind it to \`${role}\` where you attach it.`);
1097
+ return lowered;
1098
+ };
1060
1099
  const fields = [];
1061
1100
  const calculations = [];
1062
1101
  let currentAction;
@@ -1653,10 +1692,10 @@ export function compile(source, options = {}) {
1653
1692
  };
1654
1693
  }
1655
1694
  }
1656
- const fromBinding = slots.get("from");
1657
- if (fromBinding?.kind === "name" &&
1658
- fromBinding.value.includes(".") &&
1659
- slots.has("moves")) {
1695
+ const from = slots.get("from");
1696
+ // A policy member may sit in a state list such as `[funded, dispute.refund_after]`.
1697
+ const fromBinding = (from?.kind === "list" ? from.items : [from]).find((item) => item?.kind === "name" && item.value.includes("."));
1698
+ if (fromBinding?.kind === "name" && slots.has("moves")) {
1660
1699
  const [parameter, member] = fromBinding.value.split(".");
1661
1700
  const suppliedPolicy = supplied.get(parameter);
1662
1701
  if (suppliedPolicy?.kind === "block") {
@@ -1693,6 +1732,7 @@ export function compile(source, options = {}) {
1693
1732
  ...(actionSubject ? { subject: actionSubject } : {}),
1694
1733
  };
1695
1734
  authored.set(a, row.value);
1735
+ const actionFeeCalculations = [];
1696
1736
  for (const binding of boundaryBindings)
1697
1737
  if (!a.subject?.adapters.find((entry) => entry.binding === binding)
1698
1738
  ?.snapshot)
@@ -1777,9 +1817,17 @@ export function compile(source, options = {}) {
1777
1817
  "pass_through",
1778
1818
  ].includes(purposeName))
1779
1819
  fail(purpose, `unknown economic purpose ${purposeName}`, "choose a declared economic purpose");
1780
- const sourcePartyName = sourceParty
1820
+ let sourcePartyName = sourceParty
1781
1821
  ? String(data(sourceParty))
1782
1822
  : undefined;
1823
+ const reached = sourcePartyName && !isParty(sourcePartyName)
1824
+ ? reachedParty(sourcePartyName)
1825
+ : undefined;
1826
+ if (reached) {
1827
+ attachmentInfo.parties[sourcePartyName] = reached;
1828
+ sourcePartyName =
1829
+ "role" in reached ? reached.role : reached.party;
1830
+ }
1783
1831
  if (sourcePartyName && !isParty(sourcePartyName))
1784
1832
  fail(sourceParty, `unknown source party ${sourcePartyName}`, "bind an authored party");
1785
1833
  return economicsParts
@@ -1866,7 +1914,7 @@ export function compile(source, options = {}) {
1866
1914
  operation: "internal_transfer.create",
1867
1915
  ...(economics ? { economics } : {}),
1868
1916
  amount: piece,
1869
- from: path(from),
1917
+ from: moneyPath(from),
1870
1918
  to: `party.${recipient.value}`,
1871
1919
  });
1872
1920
  }
@@ -1886,8 +1934,8 @@ export function compile(source, options = {}) {
1886
1934
  ? { capture: String(data(parts.get("capture"))) }
1887
1935
  : {}),
1888
1936
  amount: val(amount),
1889
- from: path(from),
1890
- to: path(to),
1937
+ from: moneyPath(from),
1938
+ to: moneyPath(to),
1891
1939
  };
1892
1940
  const fee = parts.get("fee");
1893
1941
  if (!fee)
@@ -1920,12 +1968,21 @@ export function compile(source, options = {}) {
1920
1968
  if (rate.kind !== "percent")
1921
1969
  fail(rate, "fee rate needs a percentage", "write a percentage such as 1%");
1922
1970
  const prefix = `${name}_${key}`;
1971
+ // Instrument calculations run at create, before any action
1972
+ // input exists, so a fee on an input amount runs with its action.
1973
+ const perAction = "field" in transfer.amount &&
1974
+ transfer.amount.field.startsWith("input.");
1923
1975
  const derived = (suffix, label, calculation) => {
1924
1976
  const target = prefix + "_" + suffix;
1925
1977
  if (fields.some((f) => f.name === target))
1926
1978
  fail(move, `generated fee field ${target} conflicts with a field`, "rename the authored field or move key");
1927
- fields.push({ name: target, type: "money", label });
1928
- calculations.push({
1979
+ fields.push({
1980
+ name: target,
1981
+ type: "money",
1982
+ label,
1983
+ ...(perAction ? { optional: true } : {}),
1984
+ });
1985
+ (perAction ? actionFeeCalculations : calculations).push({
1929
1986
  ...calculation,
1930
1987
  target,
1931
1988
  });
@@ -2026,6 +2083,8 @@ export function compile(source, options = {}) {
2026
2083
  else
2027
2084
  a[key] = data(expr);
2028
2085
  }
2086
+ if (actionFeeCalculations.length)
2087
+ a.calculate = [...(a.calculate ?? []), ...actionFeeCalculations];
2029
2088
  if (attachmentInfo && !attachmentInfo.child) {
2030
2089
  if (attachmentInfo.exposed.has(name)) {
2031
2090
  if (automatic(a.actor))
@@ -2080,6 +2139,20 @@ export function compile(source, options = {}) {
2080
2139
  message: `${id}.${name}.subject.${requirement.field.name}`,
2081
2140
  });
2082
2141
  }
2142
+ // A parent actor over an empty all() names no instrument that could
2143
+ // invoke the action. A std action then does not exist in this program;
2144
+ // in user code the all() is a mistake.
2145
+ if (typeof a.actor === "object" &&
2146
+ "parent" in a.actor &&
2147
+ Array.isArray(a.actor.parent) &&
2148
+ !a.actor.parent.length) {
2149
+ if ((declarationSources.get(decl) ?? "program") === "program") {
2150
+ const parent = entries(asBlock(slots.get("actor"))).get("parent");
2151
+ fail(parent ?? row, `${parent?.kind === "call" ? `${parent.name}(${text(parent.args[0])})` : `the parent actor of ${name}`} matches no instrument`, "name an instrument this program declares or attaches");
2152
+ }
2153
+ delete lifecycle.transitions[name];
2154
+ continue;
2155
+ }
2083
2156
  inst.actions[name] = a;
2084
2157
  inst.actionOrder.push(name);
2085
2158
  }
@@ -2377,7 +2450,9 @@ export function compile(source, options = {}) {
2377
2450
  });
2378
2451
  };
2379
2452
  for (const decl of program.decls) {
2380
- if (decl.kind === "instrument") {
2453
+ // A parameterized program instrument is a template, like a header
2454
+ // instrument: each attachment instantiates it with its own bindings.
2455
+ if (decl.kind === "instrument" && !decl.parameters.length) {
2381
2456
  addInstrument(decl, decl.name, emptyBlock, decl.span);
2382
2457
  }
2383
2458
  if (decl.kind === "assignment") {
@@ -2632,7 +2707,9 @@ export function compile(source, options = {}) {
2632
2707
  const checkParty = (name, at, inst) => {
2633
2708
  const names = parties(inst);
2634
2709
  if (!names.includes(name))
2635
- fail(at, `\`${name}\` is not a declared party.${didYouMean(name, names)}`, `Declare it with \`party ${name}: business\`, or name a declared party (${names.join(", ")}).`);
2710
+ fail(at, `\`${name}\` is not a declared party.${didYouMean(name, names)}`, subjectPartyRoles.includes(name)
2711
+ ? `Declare a party parameter such as \`holder: party\` on the instrument, use it here, and bind \`holder: ${name}\` where you attach it.`
2712
+ : `Declare it with \`party ${name}: business\`, or name a declared party (${names.join(", ")}).`);
2636
2713
  };
2637
2714
  const checkInput = (name, at, label, input) => {
2638
2715
  const names = input.map((field) => field.name);
@@ -2685,9 +2762,61 @@ export function compile(source, options = {}) {
2685
2762
  inst,
2686
2763
  label: declarations.get(inst).name,
2687
2764
  });
2765
+ // A family member drops an optional reference field its binding left
2766
+ // unset (a borrower-funded plan has no `funds`), so it cannot match and
2767
+ // leaves the selection. The header must still declare the field.
2768
+ const declaredMembers = (selection) => {
2769
+ const members = [selection.instrument].flat();
2770
+ const header = selection.family
2771
+ ? templates.get(`${selection.family.module}.${selection.family.exportPath}`)
2772
+ : undefined;
2773
+ if (!header ||
2774
+ !entries(asBlock(entries(header.body).get("fields"))).has(selection.reference))
2775
+ return members;
2776
+ return members.filter((id) => resolveField(document, byId.get(id), `self.${selection.reference}`));
2777
+ };
2778
+ // A member whose reference points at another attachment of the anchor's
2779
+ // own template (the plan funding another object's escrow) cannot match
2780
+ // either, so each object only selects what can reference it.
2781
+ const kin = (a, b) => {
2782
+ const left = byId.get(a);
2783
+ const right = byId.get(b);
2784
+ return (!!left && !!right && declarations.get(left) === declarations.get(right));
2785
+ };
2786
+ const matchable = (selection, inst, action) => declaredMembers(selection).filter((id) => {
2787
+ const member = byId.get(id);
2788
+ if (!member)
2789
+ return true;
2790
+ const anchor = resolveField(document, inst, selection.anchor, action?.input, action);
2791
+ const reference = resolveField(document, member, `self.${selection.reference}`);
2792
+ if (anchor?.type !== "ref" || reference?.type !== "ref")
2793
+ return true;
2794
+ const targets = [anchor.target].flat();
2795
+ const candidates = [reference.target].flat();
2796
+ return !candidates.every((candidate) => !targets.includes(candidate) &&
2797
+ targets.some((target) => kin(target, candidate)));
2798
+ });
2799
+ // A count over no matchable member is zero.
2800
+ for (const inst of document.instruments)
2801
+ for (const action of Object.values(inst.actions))
2802
+ action.requires = action.requires.map((requirement) => requirement.kind === "aggregate" &&
2803
+ requirement.measure === "count" &&
2804
+ !matchable(requirement.selection, inst, action).length
2805
+ ? {
2806
+ kind: "compare",
2807
+ left: { literal: 0 },
2808
+ operator: requirement.operator,
2809
+ right: requirement.value,
2810
+ }
2811
+ : requirement);
2688
2812
  const checkSelection = (selection, at, scope) => {
2813
+ walk(selection.overlaps, "overlaps", site(selection, "overlaps", at), scope);
2689
2814
  walk(selection.anchor, "anchor", site(selection, "anchor", at), scope);
2690
2815
  walk(selection.where, "where", site(selection, "where", at), scope);
2816
+ const members = matchable(selection, scope.inst, scope.action);
2817
+ if (members.length &&
2818
+ members.length < [selection.instrument].flat().length)
2819
+ selection.instrument = members;
2691
2820
  for (const id of [selection.instrument].flat()) {
2692
2821
  checkTarget(id, site(selection, "instrument", at));
2693
2822
  const target = scopeOf(byId.get(id));
@@ -2696,6 +2825,9 @@ export function compile(source, options = {}) {
2696
2825
  member(key, keySite(selection.where, key, at));
2697
2826
  member(selection.reference, site(selection, "reference", at));
2698
2827
  selection.order?.forEach((key, index) => member(key, site(selection.order, index, at)));
2828
+ if (selection.overlaps)
2829
+ for (const key of ["start", "end"])
2830
+ member(selection.overlaps[key], site(selection.overlaps, key, at));
2699
2831
  if (selection.window)
2700
2832
  member(selection.window.field, site(selection.window, "field", at));
2701
2833
  }
@@ -2921,12 +3053,14 @@ export function compile(source, options = {}) {
2921
3053
  ?.find((binding) => binding.defaultState === stranded.state &&
2922
3054
  instrument.actions[binding.action]?.moves.some((move) => "amount" in move &&
2923
3055
  stranded.accounts.some((account) => move.from === `self.${account}`)));
3056
+ const reaching = stranded.actions.at(-1);
3057
+ const drain = `move ${stranded.accounts.map((account) => `\`self.${account}.balance\``).join(" and ")} out in ${reaching ? `\`${reaching}\`` : "the action that reaches it"}, or add an action from \`${stranded.state}\` that does`;
2924
3058
  return diagnostic({
2925
3059
  code: i.code,
2926
3060
  message: `\`${attachment?.name ?? instrument.id}\` can reach \`${stranded.state}\` with money in ${stranded.accounts.map((account) => `\`${account}\``).join(", ")}, but no action leaves that state and disposes of the balance.`,
2927
3061
  fix: binding
2928
- ? `Restore \`${binding.parameter}: ${stranded.state}\`, or author a complete refund path for every reachable funded state.`
2929
- : "Author a complete refund path for every reachable funded state.",
3062
+ ? `Restore \`${binding.parameter}: ${stranded.state}\`, or ${drain}.`
3063
+ : `${drain[0].toUpperCase()}${drain.slice(1)}.`,
2930
3064
  span: binding?.span ?? origin?.span ?? program.span,
2931
3065
  related: stranded.accounts.map((account) => ({
2932
3066
  source: "program",