@prestack/thread 0.1.3 → 0.1.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 (270) hide show
  1. package/CHANGELOG.md +563 -0
  2. package/dist/core/actor.d.ts +1 -1
  3. package/dist/core/actor.js +5 -4
  4. package/dist/core/actor.ts +5 -4
  5. package/dist/core/attach.d.ts +0 -7
  6. package/dist/core/attach.js +38 -67
  7. package/dist/core/attach.ts +34 -80
  8. package/dist/core/chain.js +13 -17
  9. package/dist/core/chain.ts +11 -15
  10. package/dist/core/condition.d.ts +4 -4
  11. package/dist/core/condition.js +2 -2
  12. package/dist/core/descend.d.ts +4 -2
  13. package/dist/core/descend.js +91 -23
  14. package/dist/core/descend.ts +90 -21
  15. package/dist/core/errors/catalogue.d.ts +52 -0
  16. package/dist/{operations/errors/errors.js → core/errors/catalogue.js} +1 -1
  17. package/dist/{operations/errors/errors.ts → core/errors/catalogue.ts} +1 -1
  18. package/dist/{operations/errors/catalog.d.ts → core/errors/error.d.ts} +2 -3
  19. package/dist/{operations/errors/catalog.js → core/errors/error.js} +1 -16
  20. package/dist/{operations/errors/catalog.ts → core/errors/error.ts} +3 -19
  21. package/dist/core/errors/namespaces.d.ts +3 -0
  22. package/dist/core/errors/namespaces.js +15 -0
  23. package/dist/core/errors/namespaces.ts +19 -0
  24. package/dist/core/finding.js +2 -2
  25. package/dist/core/finding.ts +1 -2
  26. package/dist/core/init.d.ts +1 -1
  27. package/dist/core/init.js +51 -5
  28. package/dist/core/init.ts +58 -5
  29. package/dist/core/invoked.d.ts +1 -1
  30. package/dist/core/invoked.js +3 -1
  31. package/dist/core/invoked.ts +5 -2
  32. package/dist/core/round.js +36 -22
  33. package/dist/core/round.ts +26 -9
  34. package/dist/core/rows.d.ts +4 -0
  35. package/dist/core/rows.js +31 -2
  36. package/dist/core/rows.ts +33 -1
  37. package/dist/core/scope.d.ts +1 -0
  38. package/dist/core/scope.js +1 -0
  39. package/dist/core/scope.ts +2 -0
  40. package/dist/core/thread.d.ts +3 -3
  41. package/dist/core/tree.d.ts +4 -1
  42. package/dist/core/tree.js +26 -6
  43. package/dist/core/tree.ts +29 -6
  44. package/dist/core/types.d.ts +3 -3
  45. package/dist/core/types.js +3 -1
  46. package/dist/core/types.ts +2 -1
  47. package/dist/derivation/attach.js +3 -2
  48. package/dist/derivation/attach.ts +2 -1
  49. package/dist/derivation/generators/build.js +6 -6
  50. package/dist/derivation/generators/build.ts +1 -1
  51. package/dist/derivation/generators/check.js +1 -1
  52. package/dist/derivation/generators/determinism.js +1 -1
  53. package/dist/derivation/generators/release.js +60 -47
  54. package/dist/derivation/generators/release.ts +66 -43
  55. package/dist/derivation/release.d.ts +7 -3
  56. package/dist/derivation/release.js +14 -1
  57. package/dist/derivation/release.ts +22 -2
  58. package/dist/integrations/attach.d.ts +4 -0
  59. package/dist/integrations/attach.js +37 -56
  60. package/dist/integrations/attach.ts +54 -60
  61. package/dist/integrations/cli.d.ts +37 -0
  62. package/dist/integrations/cli.js +440 -0
  63. package/dist/integrations/cli.ts +543 -0
  64. package/dist/{core/files.d.ts → integrations/disk.d.ts} +16 -24
  65. package/dist/integrations/disk.js +435 -0
  66. package/dist/integrations/disk.ts +465 -0
  67. package/dist/integrations/generators/read.js +6 -6
  68. package/dist/integrations/generators/read.ts +4 -4
  69. package/dist/integrations/generators/vault.js +10 -11
  70. package/dist/integrations/generators/vault.ts +4 -5
  71. package/dist/{operations/http.d.ts → integrations/https.d.ts} +10 -6
  72. package/dist/integrations/https.js +170 -0
  73. package/dist/integrations/https.ts +216 -0
  74. package/dist/integrations/pglite.d.ts +26 -0
  75. package/dist/integrations/pglite.js +143 -0
  76. package/dist/integrations/pglite.ts +206 -0
  77. package/dist/integrations/secret.d.ts +8 -2
  78. package/dist/integrations/secret.js +3 -5
  79. package/dist/integrations/secret.ts +10 -6
  80. package/dist/integrations/target.d.ts +155 -14
  81. package/dist/integrations/target.js +171 -50
  82. package/dist/integrations/target.ts +377 -61
  83. package/dist/integrations/vault.d.ts +1 -0
  84. package/dist/integrations/vault.js +20 -5
  85. package/dist/integrations/vault.ts +17 -5
  86. package/dist/integrity/attach.js +8 -77
  87. package/dist/integrity/attach.ts +7 -76
  88. package/dist/integrity/check-threads.js +5 -5
  89. package/dist/integrity/check-threads.ts +2 -2
  90. package/dist/integrity/constraint.d.ts +0 -1
  91. package/dist/integrity/constraint.js +267 -366
  92. package/dist/integrity/constraint.ts +267 -375
  93. package/dist/integrity/generators/compiler.js +14 -17
  94. package/dist/integrity/generators/compiler.ts +10 -15
  95. package/dist/integrity/generators/gate.js +15 -15
  96. package/dist/integrity/generators/gate.ts +10 -10
  97. package/dist/integrity/generators/issues.js +7 -7
  98. package/dist/integrity/generators/publish.js +39 -57
  99. package/dist/integrity/generators/publish.ts +44 -55
  100. package/dist/integrity/generators/trial.d.ts +3 -3
  101. package/dist/integrity/generators/trial.js +133 -165
  102. package/dist/integrity/generators/trial.ts +145 -169
  103. package/dist/integrity/lint.js +9 -13
  104. package/dist/integrity/lint.ts +7 -10
  105. package/dist/integrity/lsp/bin.js +5 -4
  106. package/dist/integrity/lsp/bin.ts +3 -1
  107. package/dist/integrity/lsp/diagnostics.js +3 -3
  108. package/dist/integrity/lsp/diagnostics.ts +1 -1
  109. package/dist/integrity/lsp/lint.js +19 -30
  110. package/dist/integrity/lsp/lint.ts +16 -32
  111. package/dist/integrity/lsp/server.js +3 -3
  112. package/dist/integrity/slopnator.d.ts +3 -13
  113. package/dist/integrity/slopnator.js +59 -38
  114. package/dist/integrity/slopnator.ts +54 -38
  115. package/dist/integrity/slopnators/sl_broken_lineage.js +2 -2
  116. package/dist/integrity/slopnators/sl_declared_elsewhere.js +1 -1
  117. package/dist/integrity/slopnators/sl_derived_drift.js +4 -4
  118. package/dist/integrity/slopnators/sl_derived_drift.ts +1 -1
  119. package/dist/integrity/slopnators/sl_door_in_a_node.js +220 -0
  120. package/dist/integrity/slopnators/sl_door_in_a_node.ts +250 -0
  121. package/dist/integrity/slopnators/sl_inert_island.js +10 -8
  122. package/dist/integrity/slopnators/sl_inert_island.ts +8 -6
  123. package/dist/integrity/slopnators/sl_missing_row.js +6 -51
  124. package/dist/integrity/slopnators/sl_missing_row.ts +4 -50
  125. package/dist/integrity/slopnators/sl_no_barrel.js +1 -1
  126. package/dist/integrity/slopnators/sl_no_child_process.js +36 -18
  127. package/dist/integrity/slopnators/sl_no_child_process.ts +44 -18
  128. package/dist/integrity/slopnators/sl_no_dispatch_bypass.js +80 -149
  129. package/dist/integrity/slopnators/sl_no_dispatch_bypass.ts +95 -147
  130. package/dist/integrity/slopnators/sl_no_import_cycle.js +15 -4
  131. package/dist/integrity/slopnators/sl_no_import_cycle.ts +20 -4
  132. package/dist/integrity/slopnators/sl_no_such_command.js +2 -2
  133. package/dist/integrity/slopnators/sl_no_such_command.ts +1 -1
  134. package/dist/integrity/slopnators/sl_outside_an_operation.js +20 -0
  135. package/dist/integrity/slopnators/sl_outside_an_operation.ts +25 -0
  136. package/dist/integrity/slopnators/sl_screen_holds_only_declared.d.ts +2 -0
  137. package/dist/integrity/slopnators/sl_screen_holds_only_declared.js +61 -0
  138. package/dist/integrity/slopnators/sl_screen_holds_only_declared.ts +70 -0
  139. package/dist/integrity/slopnators/sl_secret_literal.js +1 -33
  140. package/dist/integrity/slopnators/sl_secret_literal.ts +1 -33
  141. package/dist/integrity/slopnators/sl_stale_path.js +5 -22
  142. package/dist/integrity/slopnators/sl_stale_path.ts +4 -20
  143. package/dist/integrity/slopnators/sl_twice_meant.js +1 -1
  144. package/dist/integrity/slopnators/sl_twice_parented.js +29 -5
  145. package/dist/integrity/slopnators/sl_twice_parented.ts +28 -4
  146. package/dist/integrity/slopnators/sl_undeclared_crossing.d.ts +4 -1
  147. package/dist/integrity/slopnators/sl_undeclared_crossing.js +426 -62
  148. package/dist/integrity/slopnators/sl_undeclared_crossing.ts +454 -70
  149. package/dist/integrity/slopnators/sl_undeclared_destination.js +59 -25
  150. package/dist/integrity/slopnators/sl_undeclared_destination.ts +69 -21
  151. package/dist/integrity/slopnators/sl_undeclared_list.d.ts +2 -0
  152. package/dist/integrity/slopnators/sl_undeclared_list.js +363 -0
  153. package/dist/integrity/slopnators/sl_undeclared_list.ts +358 -0
  154. package/dist/integrity/slopnators/sl_undeclared_node.js +1 -11
  155. package/dist/integrity/slopnators/sl_undeclared_node.ts +0 -10
  156. package/dist/integrity/slopnators/sl_undeclared_operation.js +111 -29
  157. package/dist/integrity/slopnators/sl_undeclared_operation.ts +134 -26
  158. package/dist/integrity/slopnators/sl_undeclared_variant.js +2 -2
  159. package/dist/integrity/slopnators/sl_undeclared_webhook.d.ts +2 -0
  160. package/dist/integrity/slopnators/sl_undeclared_webhook.js +90 -0
  161. package/dist/integrity/slopnators/sl_undeclared_webhook.ts +108 -0
  162. package/dist/integrity/slopnators/sl_underived_route.d.ts +2 -0
  163. package/dist/integrity/slopnators/sl_underived_route.js +61 -0
  164. package/dist/integrity/slopnators/sl_underived_route.ts +72 -0
  165. package/dist/integrity/slopnators/sl_ungoverned_island.js +3 -3
  166. package/dist/integrity/slopnators/sl_ungoverned_island.ts +1 -1
  167. package/dist/integrity/slopnators/sl_unlisted_program.d.ts +2 -0
  168. package/dist/integrity/slopnators/sl_unlisted_program.js +39 -0
  169. package/dist/integrity/slopnators/sl_unlisted_program.ts +40 -0
  170. package/dist/integrity/slopnators/sl_unnamed_island.js +1 -1
  171. package/dist/integrity/slopnators/sl_unpaired_member.js +3 -3
  172. package/dist/integrity/slopnators/sl_unpaired_member.ts +1 -1
  173. package/dist/integrity/slopnators/sl_unpaired_slopnator.js +4 -4
  174. package/dist/integrity/slopnators/sl_unpaired_slopnator.ts +1 -1
  175. package/dist/integrity/slopnators/sl_unprefixed_member.js +5 -31
  176. package/dist/integrity/slopnators/sl_unprefixed_member.ts +2 -28
  177. package/dist/integrity/slopnators/sl_unthreaded.js +11 -7
  178. package/dist/integrity/slopnators/sl_unthreaded.ts +6 -7
  179. package/dist/integrity/slopnators/sl_untranslated_key.js +2 -25
  180. package/dist/integrity/slopnators/sl_untranslated_key.ts +1 -25
  181. package/dist/integrity/slopnators/sl_unvaulted_secret.d.ts +2 -0
  182. package/dist/integrity/slopnators/sl_unvaulted_secret.js +107 -0
  183. package/dist/integrity/slopnators/sl_unvaulted_secret.ts +132 -0
  184. package/dist/integrity/slopnators/sl_unversioned.js +6 -4
  185. package/dist/integrity/slopnators/sl_unversioned.ts +5 -3
  186. package/dist/integrity/sweep.d.ts +1 -0
  187. package/dist/integrity/sweep.js +105 -42
  188. package/dist/integrity/sweep.ts +115 -42
  189. package/dist/knowledge/attach.js +4 -3
  190. package/dist/knowledge/attach.ts +3 -2
  191. package/dist/knowledge/generators/docsgen.js +8 -6
  192. package/dist/knowledge/generators/docsgen.ts +4 -2
  193. package/dist/knowledge/generators/glossary.js +4 -4
  194. package/dist/knowledge/generators/glossary.ts +1 -1
  195. package/dist/operations/access.d.ts +23 -0
  196. package/dist/operations/access.js +28 -1
  197. package/dist/operations/access.ts +43 -0
  198. package/dist/operations/attach.js +33 -113
  199. package/dist/operations/attach.ts +51 -117
  200. package/dist/operations/capabilities.d.ts +14 -5
  201. package/dist/operations/capabilities.js +13 -4
  202. package/dist/operations/capabilities.ts +27 -8
  203. package/dist/operations/dispatch.d.ts +8 -2
  204. package/dist/operations/dispatch.js +128 -185
  205. package/dist/operations/dispatch.ts +138 -191
  206. package/dist/operations/error-results.d.ts +1 -1
  207. package/dist/operations/error-results.js +2 -2
  208. package/dist/operations/error-results.ts +2 -2
  209. package/dist/operations/generators/capability.d.ts +11 -1
  210. package/dist/operations/generators/capability.js +481 -224
  211. package/dist/operations/generators/capability.ts +562 -233
  212. package/dist/operations/generators/compile.js +66 -39
  213. package/dist/operations/generators/compile.ts +78 -39
  214. package/dist/operations/generators/permits.js +11 -12
  215. package/dist/operations/generators/permits.ts +3 -4
  216. package/dist/operations/generators/seed.d.ts +1 -0
  217. package/dist/operations/generators/seed.js +19 -17
  218. package/dist/operations/generators/seed.ts +22 -14
  219. package/dist/operations/generators/trial.d.ts +6 -8
  220. package/dist/operations/generators/trial.js +200 -70
  221. package/dist/operations/generators/trial.ts +230 -93
  222. package/dist/operations/nodes.d.ts +15 -16
  223. package/dist/operations/nodes.ts +16 -17
  224. package/dist/operations/operations.d.ts +40 -4
  225. package/dist/operations/operations.js +1 -0
  226. package/dist/operations/operations.ts +61 -4
  227. package/dist/operations/result.d.ts +2 -2
  228. package/dist/operations/result.ts +2 -2
  229. package/package.json +1 -4
  230. package/dist/core/answers.d.ts +0 -171
  231. package/dist/core/answers.js +0 -789
  232. package/dist/core/answers.ts +0 -999
  233. package/dist/core/client.d.ts +0 -63
  234. package/dist/core/client.js +0 -249
  235. package/dist/core/client.ts +0 -289
  236. package/dist/core/files.js +0 -171
  237. package/dist/core/files.ts +0 -222
  238. package/dist/integrations/module.d.ts +0 -6
  239. package/dist/integrations/module.js +0 -153
  240. package/dist/integrations/module.ts +0 -191
  241. package/dist/integrity/slopnators/sl_unkept_rows.js +0 -104
  242. package/dist/integrity/slopnators/sl_unkept_rows.ts +0 -111
  243. package/dist/integrity/slopnators/sl_unseamed_reach.js +0 -73
  244. package/dist/integrity/slopnators/sl_unseamed_reach.ts +0 -79
  245. package/dist/operations/cost.d.ts +0 -14
  246. package/dist/operations/cost.js +0 -37
  247. package/dist/operations/cost.ts +0 -58
  248. package/dist/operations/errors/errors.d.ts +0 -52
  249. package/dist/operations/http.js +0 -124
  250. package/dist/operations/http.ts +0 -169
  251. package/dist/operations/memory.d.ts +0 -104
  252. package/dist/operations/memory.js +0 -365
  253. package/dist/operations/memory.ts +0 -470
  254. package/dist/operations/metering.d.ts +0 -55
  255. package/dist/operations/metering.js +0 -247
  256. package/dist/operations/metering.ts +0 -328
  257. package/dist/operations/queue-policy.d.ts +0 -3
  258. package/dist/operations/queue-policy.js +0 -8
  259. package/dist/operations/queue-policy.ts +0 -10
  260. package/dist/operations/seams.d.ts +0 -239
  261. package/dist/operations/seams.js +0 -45
  262. package/dist/operations/seams.ts +0 -364
  263. package/dist/operations/store.d.ts +0 -14
  264. package/dist/operations/store.js +0 -1
  265. package/dist/operations/store.ts +0 -29
  266. /package/dist/{operations → core}/errors/classes.d.ts +0 -0
  267. /package/dist/{operations → core}/errors/classes.js +0 -0
  268. /package/dist/{operations → core}/errors/classes.ts +0 -0
  269. /package/dist/integrity/slopnators/{sl_unkept_rows.d.ts → sl_door_in_a_node.d.ts} +0 -0
  270. /package/dist/integrity/slopnators/{sl_unseamed_reach.d.ts → sl_outside_an_operation.d.ts} +0 -0
@@ -1,14 +1,13 @@
1
- import { execFileSync } from 'node:child_process';
2
- import { attached, existsSync, readFileSync, readdirSync } from "../core/files.js";
1
+ import { starts } from '../integrations/cli.js';
2
+ import { attached, existsSync, readFileSync, readdirSync } from '../integrations/disk.js';
3
3
  import { join } from 'node:path';
4
- import { stdout } from 'node:process';
5
- import { descend } from "../core/descend.js";
6
- import { runChecker } from "../core/finding.js";
7
- import { exit, invoked } from "../core/invoked.js";
4
+ import { argv, stdout } from 'node:process';
5
+ import { runChecker } from '../core/finding.js';
6
+ import { exit, invoked } from '../core/invoked.js';
8
7
  import { parser } from 'typescript-eslint';
9
- import { CONSTRAINTS } from "./constraint.js";
10
- import { NOT_WRITTEN, ROOT, governs, load, reads, rules, slopnatorName, sweeps, visits } from "./slopnator.js";
11
- import { deriveTrials, runTrials } from "./generators/trial.js";
8
+ import { CONSTRAINTS } from './constraint.js';
9
+ import { NOT_WRITTEN, ROOT, derivedHere, governs, load, proofsOf, reads, rules, slopnatorName, subject, sweeps, visits } from './slopnator.js';
10
+ import { crossed, deriveTrials, runTrials } from './generators/trial.js';
12
11
  const PARSEABLE = /\.(ts|tsx|mts|cts|mjs|cjs|js|jsx)$/;
13
12
  function tree(text) {
14
13
  const read = (jsx) => parser.parseForESLint(text, {
@@ -57,6 +56,23 @@ export function visit(root, on, each) {
57
56
  };
58
57
  step(root);
59
58
  }
59
+ const blank = (said) => said.replace(/[^\n]/g, ' ');
60
+ const sourcesIn = (one) => typeof one === 'string'
61
+ ? [one]
62
+ : one.files.flatMap((each) => (typeof each.source === 'string' ? [each.source] : []));
63
+ function without(text, rule, slopnators) {
64
+ let said = text;
65
+ for (const proof of proofsOf(rule, slopnators).wrong) {
66
+ for (const source of sourcesIn(proof)) {
67
+ for (const one of [source, source.trim()]) {
68
+ if (one === '')
69
+ continue;
70
+ said = said.replaceAll(one, blank(one));
71
+ }
72
+ }
73
+ }
74
+ return said;
75
+ }
60
76
  const ELSEWHERE = new Set(['node_modules', '.git']);
61
77
  function ignoredIn(root) {
62
78
  const at = join(root, '.gitignore');
@@ -67,28 +83,12 @@ function ignoredIn(root) {
67
83
  .map((line) => line.trim().replace(/^\//, '').replace(/\/$/, ''))
68
84
  .filter((line) => line !== '' && !line.startsWith('#') && !line.includes('*') && !line.startsWith('!')));
69
85
  }
70
- function authored() {
71
- const found = new Set();
72
- try {
73
- for (const [at, threadings] of descend().threaded) {
74
- if (threadings.some((one) => one.list === 'derives' && (one.row.by ?? one.row.runs) !== undefined))
75
- found.add(at);
76
- }
77
- }
78
- catch {
79
- }
80
- return found;
81
- }
82
86
  export function tracked(root) {
83
- const derived = authored();
84
- const mine = (one) => !derived.has(one);
87
+ const derived = derivedHere();
88
+ const mine = (one) => derived?.has(one) !== true;
85
89
  try {
86
- const listed = execFileSync('git', ['ls-files', '--cached', '--others', '--exclude-standard'], {
87
- cwd: root,
88
- encoding: 'utf8',
89
- stdio: ['ignore', 'pipe', 'ignore'],
90
- })
91
- .split('\n')
90
+ const listed = starts('git', ['ls-files', '--cached', '--others', '--exclude-standard'], { at: root })
91
+ .out.split('\n')
92
92
  .filter(Boolean);
93
93
  if (!attached() && listed.length > 0) {
94
94
  return [...new Set(listed)].filter((one) => existsSync(join(root, one)) && mine(one)).sort();
@@ -123,10 +123,20 @@ export function sweep(root, all, slopnators, files) {
123
123
  .filter((one) => one.slopnator !== undefined && visits(one.slopnator));
124
124
  const findings = [];
125
125
  let swept = 0;
126
+ const spent = new Map();
127
+ const timed = (rule, work) => {
128
+ const began = Date.now();
129
+ try {
130
+ return work();
131
+ }
132
+ finally {
133
+ spent.set(rule, (spent.get(rule) ?? 0) + Date.now() - began);
134
+ }
135
+ };
126
136
  const met = new Set();
127
137
  for (const file of files) {
128
- const reading = readers.filter((one) => governs(one.rule, file));
129
- const walking = walkers.filter((one) => governs(one.rule, file));
138
+ const reading = readers.filter((one) => subject(one.rule) && governs(one.rule, file));
139
+ const walking = walkers.filter((one) => subject(one.rule) && governs(one.rule, file));
130
140
  for (const one of reading)
131
141
  met.add(one.rule.id);
132
142
  for (const one of walking)
@@ -142,12 +152,12 @@ export function sweep(root, all, slopnators, files) {
142
152
  }
143
153
  swept += 1;
144
154
  for (const { rule, slopnator } of reading) {
145
- const held = slopnator.holds(undefined, {
155
+ const held = timed(rule.id, () => slopnator.holds(undefined, {
146
156
  filename: file,
147
- text,
157
+ text: without(text, rule, slopnators),
148
158
  ancestors: () => [],
149
159
  comments: () => [],
150
- });
160
+ }));
151
161
  if (held === false || held === NOT_WRITTEN)
152
162
  continue;
153
163
  findings.push({ rule: rule.id, file, found: typeof held === 'string' ? held : slopnatorName(rule.id) });
@@ -177,7 +187,7 @@ export function sweep(root, all, slopnators, files) {
177
187
  });
178
188
  continue;
179
189
  }
180
- visit(ast, on, (node, ancestors) => {
190
+ timed(rule.id, () => visit(ast, on, (node, ancestors) => {
181
191
  const held = slopnator.holds(node, {
182
192
  filename: file,
183
193
  text,
@@ -187,14 +197,14 @@ export function sweep(root, all, slopnators, files) {
187
197
  if (held === false || held === NOT_WRITTEN)
188
198
  return;
189
199
  findings.push({ rule: rule.id, file, found: typeof held === 'string' ? held : slopnatorName(rule.id) });
190
- });
200
+ }));
191
201
  }
192
202
  }
193
203
  for (const rule of all) {
194
204
  const slopnator = slopnators.get(slopnatorName(rule.id));
195
205
  if (slopnator === undefined || reads(slopnator))
196
206
  continue;
197
- for (const found of slopnator.checks(root))
207
+ for (const found of timed(rule.id, () => slopnator.checks(root)))
198
208
  findings.push({ rule: rule.id, file: '', found });
199
209
  }
200
210
  const unrun = all.filter((rule) => slopnators.get(slopnatorName(rule.id)) === undefined).map((rule) => rule.id);
@@ -207,6 +217,7 @@ export function sweep(root, all, slopnators, files) {
207
217
  unrun,
208
218
  unmet,
209
219
  linted,
220
+ spent,
210
221
  rules: readers.length +
211
222
  walkers.length +
212
223
  all.filter((rule) => {
@@ -216,17 +227,54 @@ export function sweep(root, all, slopnators, files) {
216
227
  };
217
228
  }
218
229
  if (invoked(import.meta.url)) {
219
- const governing = [...CONSTRAINTS, ...((await rules()) ?? [])];
230
+ const began = Date.now();
231
+ const declared = [...CONSTRAINTS, ...((await rules()) ?? [])];
232
+ let only;
233
+ let flagged = false;
234
+ for (const one of argv) {
235
+ if (flagged) {
236
+ only = one;
237
+ break;
238
+ }
239
+ if (one === '--only')
240
+ flagged = true;
241
+ }
242
+ let governing = [];
243
+ for (const one of declared) {
244
+ const id = one['id'];
245
+ if (only === undefined || id === only || slopnatorName(id) === only)
246
+ governing = [...governing, one];
247
+ }
248
+ if (governing[0] === undefined) {
249
+ runChecker('sweep', [
250
+ {
251
+ file: '',
252
+ detail: 'this tree declares no rule called ' + String(only),
253
+ instead: 'name a rule by its id, or by the slopnator beside it — `thread rules` lists both. Running all of them while ' +
254
+ 'saying one was asked for is a green tick over a sweep nobody asked for, so nothing was swept',
255
+ },
256
+ ], '');
257
+ exit(1);
258
+ }
220
259
  const slopnators = await load(ROOT, governing);
221
260
  const named = new Map(governing.map((rule) => [rule.id, rule]));
261
+ const loaded = Date.now();
222
262
  const run = sweep(ROOT, governing, slopnators, tracked(ROOT));
223
- const { default: plugin } = await import("./lint.js");
224
- const proving = runTrials(deriveTrials(governing, slopnators).trials, governing, plugin.rules, parser, slopnators);
225
- const unproven = proving.outcomes.filter((one) => !one.passed);
263
+ const walked = Date.now();
264
+ const { default: plugin } = await import('./lint.js');
265
+ const derived = deriveTrials(governing, slopnators).trials;
266
+ const proving = runTrials(derived, governing, plugin.rules, parser, slopnators);
267
+ const proved = Date.now();
268
+ const crossing = new Map();
269
+ const unproven = [
270
+ ...proving.outcomes.filter((one) => !one.passed),
271
+ ...crossed(derived, declared, plugin.rules, parser, await load(ROOT, declared), crossing),
272
+ ];
273
+ const done = Date.now();
226
274
  const failing = new Map();
227
275
  for (const one of unproven) {
228
276
  const held = failing.get(one.rule) ?? [];
229
- held.push(` ${one.failures.join('; ')}`);
277
+ held.push(` ${one.id} — ${one.failures.join('; ')}`);
230
278
  failing.set(one.rule, held);
231
279
  }
232
280
  const warned = new Set();
@@ -268,6 +316,21 @@ if (invoked(import.meta.url)) {
268
316
  `${String(run.linted.length)} of them reading a syntax tree, and ${String(proving.passed)} of ${String(proving.outcomes.length)} rule trial(s) passed, ${String(proving.measured)} measured` +
269
317
  `${run.unrun.length === 0 ? '' : `, ${String(run.unrun.length)} that DID NOT RUN AT ALL`}` +
270
318
  `${run.unmet.length === 0 ? '' : `, and ${String(run.unmet.length)} that governed no file here and so measured nothing: ${run.unmet.join(', ')}`}`);
319
+ const seconds = (ms) => String(Math.round(ms / 1000)) + ' s';
320
+ const slowest = (spent) => [...spent.entries()]
321
+ .sort((one, two) => two[1] - one[1])
322
+ .slice(0, 3)
323
+ .map(([rule, ms]) => rule + ' ' + seconds(ms))
324
+ .join(', ');
325
+ const own = new Map(run.spent);
326
+ for (const [rule, ms] of proving.spent)
327
+ own.set(rule, (own.get(rule) ?? 0) + ms);
328
+ stdout.write('sweep: it took ' + seconds(done - began) + '. Loading the rules took ' + seconds(loaded - began) +
329
+ ', reading the files in this tree ' + seconds(walked - loaded) +
330
+ ', running each rule on its own examples ' + seconds(proved - walked) +
331
+ ', and holding what each rule recommends against every other rule ' + seconds(done - proved) +
332
+ '. Slowest on their own files and examples: ' + slowest(own) +
333
+ '. Slowest to hold against the rest: ' + slowest(crossing) + '.\n');
271
334
  const forbidding = findings.length - run.findings.filter((one) => named.get(one.rule)?.severity === 'warning').length;
272
335
  if (forbidding > 0)
273
336
  exit(1);
@@ -1,19 +1,18 @@
1
- import { execFileSync } from 'node:child_process'
2
- import { attached, existsSync, readFileSync, readdirSync } from '../core/files.ts'
1
+ import { starts } from '../integrations/cli.ts'
2
+ import { attached, existsSync, readFileSync, readdirSync } from '../integrations/disk.ts'
3
3
  import { join } from 'node:path'
4
- import { stdout } from 'node:process'
4
+ import { argv, stdout } from 'node:process'
5
5
  import { pathToFileURL } from 'node:url'
6
6
 
7
- import { descend } from '../core/descend.ts'
8
7
  import { runChecker, type Finding } from '../core/finding.ts'
9
8
  import { exit, invoked } from '../core/invoked.ts'
10
9
 
11
10
  import { parser } from 'typescript-eslint'
12
11
 
13
- import { CONSTRAINTS, type Constraint } from './constraint.ts'
14
- import { NOT_WRITTEN, ROOT, governs, load, reads, rules, slopnatorName, sweeps, visits, type Reading, type Slopnator, type Spoken, type Visiting } from './slopnator.ts'
12
+ import { CONSTRAINTS, type Constraint, type Proof } from './constraint.ts'
13
+ import { NOT_WRITTEN, ROOT, derivedHere, governs, load, proofsOf, reads, rules, slopnatorName, subject, sweeps, visits, type Reading, type Slopnator, type Spoken, type Visiting } from './slopnator.ts'
15
14
  import { ruleMessage } from './lint.ts'
16
- import { deriveTrials, runTrials } from './generators/trial.ts'
15
+ import { crossed, deriveTrials, runTrials } from './generators/trial.ts'
17
16
 
18
17
  const PARSEABLE = /\.(ts|tsx|mts|cts|mjs|cjs|js|jsx)$/
19
18
 
@@ -65,6 +64,26 @@ export function visit(root: Node, on: ReadonlySet<string>, each: (node: Node, an
65
64
  step(root)
66
65
  }
67
66
 
67
+ const blank = (said: string): string => said.replace(/[^\n]/g, ' ')
68
+
69
+ const sourcesIn = (one: Proof): readonly string[] =>
70
+ typeof one === 'string'
71
+ ? [one]
72
+ : one.files.flatMap((each) => (typeof each.source === 'string' ? [each.source] : []))
73
+
74
+ function without(text: string, rule: Constraint, slopnators: ReadonlyMap<string, Slopnator>): string {
75
+ let said = text
76
+ for (const proof of proofsOf(rule, slopnators).wrong) {
77
+ for (const source of sourcesIn(proof)) {
78
+ for (const one of [source, source.trim()]) {
79
+ if (one === '') continue
80
+ said = said.replaceAll(one, blank(one))
81
+ }
82
+ }
83
+ }
84
+ return said
85
+ }
86
+
68
87
  export interface Caught {
69
88
  readonly rule: string
70
89
  readonly file: string
@@ -84,30 +103,14 @@ function ignoredIn(root: string): ReadonlySet<string> {
84
103
  )
85
104
  }
86
105
 
87
- function authored(): ReadonlySet<string> {
88
- const found = new Set<string>()
89
- try {
90
- for (const [at, threadings] of descend().threaded) {
91
- if (threadings.some((one) => one.list === 'derives' && (one.row.by ?? one.row.runs) !== undefined)) found.add(at)
92
- }
93
- } catch {
94
-
95
- }
96
- return found
97
- }
98
-
99
106
  export function tracked(root: string): readonly string[] {
100
- const derived = authored()
101
- const mine = (one: string): boolean => !derived.has(one)
107
+ const derived = derivedHere()
108
+ const mine = (one: string): boolean => derived?.has(one) !== true
102
109
 
103
110
  try {
104
111
 
105
- const listed = execFileSync('git', ['ls-files', '--cached', '--others', '--exclude-standard'], {
106
- cwd: root,
107
- encoding: 'utf8',
108
- stdio: ['ignore', 'pipe', 'ignore'],
109
- })
110
- .split('\n')
112
+ const listed = starts('git', ['ls-files', '--cached', '--others', '--exclude-standard'], { at: root })
113
+ .out.split('\n')
111
114
  .filter(Boolean)
112
115
  if (!attached() && listed.length > 0) {
113
116
  return [...new Set(listed)].filter((one) => existsSync(join(root, one)) && mine(one)).sort()
@@ -146,6 +149,7 @@ export function sweep(
146
149
  readonly unrun: readonly string[]
147
150
  readonly unmet: readonly string[]
148
151
  readonly linted: readonly string[]
152
+ readonly spent: ReadonlyMap<string, number>
149
153
  } {
150
154
  const readers = all
151
155
  .map((rule) => ({ rule, slopnator: slopnators.get(slopnatorName(rule.id)) }))
@@ -157,12 +161,21 @@ export function sweep(
157
161
 
158
162
  const findings: Caught[] = []
159
163
  let swept = 0
164
+ const spent = new Map<string, number>()
165
+ const timed = <T>(rule: string, work: () => T): T => {
166
+ const began = Date.now()
167
+ try {
168
+ return work()
169
+ } finally {
170
+ spent.set(rule, (spent.get(rule) ?? 0) + Date.now() - began)
171
+ }
172
+ }
160
173
 
161
174
  const met = new Set<string>()
162
175
 
163
176
  for (const file of files) {
164
- const reading = readers.filter((one) => governs(one.rule, file))
165
- const walking = walkers.filter((one) => governs(one.rule, file))
177
+ const reading = readers.filter((one) => subject(one.rule) && governs(one.rule, file))
178
+ const walking = walkers.filter((one) => subject(one.rule) && governs(one.rule, file))
166
179
  for (const one of reading) met.add(one.rule.id)
167
180
  for (const one of walking) met.add(one.rule.id)
168
181
  if (reading.length === 0 && walking.length === 0) continue
@@ -176,12 +189,14 @@ export function sweep(
176
189
  swept += 1
177
190
 
178
191
  for (const { rule, slopnator } of reading) {
179
- const held = slopnator.holds(undefined, {
180
- filename: file,
181
- text,
182
- ancestors: () => [],
183
- comments: () => [],
184
- })
192
+ const held = timed(rule.id, () =>
193
+ slopnator.holds(undefined, {
194
+ filename: file,
195
+ text: without(text, rule, slopnators),
196
+ ancestors: () => [],
197
+ comments: () => [],
198
+ }),
199
+ )
185
200
  if (held === false || held === NOT_WRITTEN) continue
186
201
  findings.push({ rule: rule.id, file, found: typeof held === 'string' ? held : slopnatorName(rule.id) })
187
202
  }
@@ -213,7 +228,7 @@ export function sweep(
213
228
  })
214
229
  continue
215
230
  }
216
- visit(ast, on, (node, ancestors) => {
231
+ timed(rule.id, () => visit(ast, on, (node, ancestors) => {
217
232
  const held = slopnator.holds(node, {
218
233
  filename: file,
219
234
  text,
@@ -222,14 +237,14 @@ export function sweep(
222
237
  })
223
238
  if (held === false || held === NOT_WRITTEN) return
224
239
  findings.push({ rule: rule.id, file, found: typeof held === 'string' ? held : slopnatorName(rule.id) })
225
- })
240
+ }))
226
241
  }
227
242
  }
228
243
 
229
244
  for (const rule of all) {
230
245
  const slopnator = slopnators.get(slopnatorName(rule.id))
231
246
  if (slopnator === undefined || reads(slopnator)) continue
232
- for (const found of slopnator.checks(root)) findings.push({ rule: rule.id, file: '', found })
247
+ for (const found of timed(rule.id, () => slopnator.checks(root))) findings.push({ rule: rule.id, file: '', found })
233
248
  }
234
249
 
235
250
  const unrun = all.filter((rule) => slopnators.get(slopnatorName(rule.id)) === undefined).map((rule) => rule.id)
@@ -243,6 +258,7 @@ export function sweep(
243
258
  unrun,
244
259
  unmet,
245
260
  linted,
261
+ spent,
246
262
  rules:
247
263
  readers.length +
248
264
  walkers.length +
@@ -254,19 +270,59 @@ export function sweep(
254
270
  }
255
271
 
256
272
  if (invoked(import.meta.url)) {
257
- const governing = [...CONSTRAINTS, ...((await rules()) ?? [])]
273
+ const began = Date.now()
274
+ const declared = [...CONSTRAINTS, ...((await rules()) ?? [])]
275
+ let only: string | undefined
276
+ let flagged = false
277
+ for (const one of argv) {
278
+ if (flagged) {
279
+ only = one
280
+ break
281
+ }
282
+ if (one === '--only') flagged = true
283
+ }
284
+ let governing: readonly Constraint[] = []
285
+ for (const one of declared) {
286
+ const id = one['id']
287
+ if (only === undefined || id === only || slopnatorName(id) === only) governing = [...governing, one]
288
+ }
289
+ if (governing[0] === undefined) {
290
+ runChecker(
291
+ 'sweep',
292
+ [
293
+ {
294
+ file: '',
295
+ detail: 'this tree declares no rule called ' + String(only),
296
+ instead:
297
+ 'name a rule by its id, or by the slopnator beside it — `thread rules` lists both. Running all of them while ' +
298
+ 'saying one was asked for is a green tick over a sweep nobody asked for, so nothing was swept',
299
+ },
300
+ ],
301
+ '',
302
+ )
303
+ exit(1)
304
+ }
258
305
  const slopnators = await load(ROOT, governing)
259
306
  const named = new Map(governing.map((rule) => [rule.id, rule]))
307
+ const loaded = Date.now()
260
308
  const run = sweep(ROOT, governing, slopnators, tracked(ROOT))
309
+ const walked = Date.now()
261
310
 
262
311
  const { default: plugin } = await import('./lint.ts')
263
- const proving = runTrials(deriveTrials(governing, slopnators).trials, governing, plugin.rules, parser, slopnators)
264
- const unproven = proving.outcomes.filter((one) => !one.passed)
312
+ const derived = deriveTrials(governing, slopnators).trials
313
+ const proving = runTrials(derived, governing, plugin.rules, parser, slopnators)
314
+ const proved = Date.now()
315
+ const crossing = new Map<string, number>()
316
+ const unproven = [
317
+ ...proving.outcomes.filter((one) => !one.passed),
318
+ ...crossed(derived, declared, plugin.rules, parser, await load(ROOT, declared), crossing),
319
+ ]
320
+ const done = Date.now()
265
321
 
266
322
  const failing = new Map<string, string[]>()
267
323
  for (const one of unproven) {
268
324
  const held = failing.get(one.rule) ?? []
269
- held.push(` ${one.failures.join('; ')}`)
325
+ held.push(` ${one.id} — ${one.failures.join('; ')}`)
270
326
  failing.set(one.rule, held)
271
327
  }
272
328
 
@@ -315,6 +371,23 @@ if (invoked(import.meta.url)) {
315
371
  `${run.unrun.length === 0 ? '' : `, ${String(run.unrun.length)} that DID NOT RUN AT ALL`}` +
316
372
  `${run.unmet.length === 0 ? '' : `, and ${String(run.unmet.length)} that governed no file here and so measured nothing: ${run.unmet.join(', ')}`}`,
317
373
  )
374
+ const seconds = (ms: number): string => String(Math.round(ms / 1000)) + ' s'
375
+ const slowest = (spent: ReadonlyMap<string, number>): string =>
376
+ [...spent.entries()]
377
+ .sort((one, two) => two[1] - one[1])
378
+ .slice(0, 3)
379
+ .map(([rule, ms]) => rule + ' ' + seconds(ms))
380
+ .join(', ')
381
+ const own = new Map(run.spent)
382
+ for (const [rule, ms] of proving.spent) own.set(rule, (own.get(rule) ?? 0) + ms)
383
+ stdout.write(
384
+ 'sweep: it took ' + seconds(done - began) + '. Loading the rules took ' + seconds(loaded - began) +
385
+ ', reading the files in this tree ' + seconds(walked - loaded) +
386
+ ', running each rule on its own examples ' + seconds(proved - walked) +
387
+ ', and holding what each rule recommends against every other rule ' + seconds(done - proved) +
388
+ '. Slowest on their own files and examples: ' + slowest(own) +
389
+ '. Slowest to hold against the rest: ' + slowest(crossing) + '.\n',
390
+ )
318
391
  const forbidding = findings.length - run.findings.filter((one) => named.get(one.rule)?.severity === 'warning').length
319
392
  if (forbidding > 0) exit(1)
320
393
  if (warned.size > 0) {
@@ -1,7 +1,8 @@
1
- import { quoted } from "../core/rows.js";
1
+ import { SHAPED } from '../core/init.js';
2
+ import { quoted } from '../core/rows.js';
2
3
  const DESCRIBES = 'The system that compiles what this repository holds into forms a reader can understand — the glossary first, and every later view of the tree computed rather than written.';
3
4
  const CONCEPTS = 'Every word this framework means something specific by that no declaration coins — its own verbs and the fields they sit in, written by a person because nothing in the tree can state them, and read into the glossary with everything else.';
4
- const CONCEPTS_SOURCE = `import type { Member } from '../core/thread.ts'
5
+ const CONCEPTS_SOURCE = `import type { Member } from '${SHAPED}'
5
6
 
6
7
  export interface Concept extends Member {
7
8
  readonly avoid?: readonly string[]
@@ -288,7 +289,7 @@ export const ATTACH = {
288
289
  {
289
290
  file: 'knowledge.ts',
290
291
  source: [
291
- "import type { Threaded } from '../core/thread.ts'",
292
+ `import type { Threaded } from '${SHAPED}'`,
292
293
  '',
293
294
  'export const KNOWLEDGE: Threaded = {',
294
295
  " id: 'knowledge',",
@@ -1,5 +1,6 @@
1
1
  import type { Attaching } from '../core/attach.ts'
2
2
 
3
+ import { SHAPED } from '../core/init.ts'
3
4
  import { quoted } from '../core/rows.ts'
4
5
 
5
6
  const DESCRIBES =
@@ -8,7 +9,7 @@ const DESCRIBES =
8
9
  const CONCEPTS =
9
10
  'Every word this framework means something specific by that no declaration coins — its own verbs and the fields they sit in, written by a person because nothing in the tree can state them, and read into the glossary with everything else.'
10
11
 
11
- const CONCEPTS_SOURCE = `import type { Member } from '../core/thread.ts'
12
+ const CONCEPTS_SOURCE = `import type { Member } from '${SHAPED}'
12
13
 
13
14
  export interface Concept extends Member {
14
15
  readonly avoid?: readonly string[]
@@ -298,7 +299,7 @@ export const ATTACH: Attaching = {
298
299
  {
299
300
  file: 'knowledge.ts',
300
301
  source: [
301
- "import type { Threaded } from '../core/thread.ts'",
302
+ `import type { Threaded } from '${SHAPED}'`,
302
303
  '',
303
304
  'export const KNOWLEDGE: Threaded = {',
304
305
  " id: 'knowledge',",
@@ -1,10 +1,10 @@
1
- import { existsSync, readFileSync, writeFileSync } from "../../core/files.js";
1
+ import { existsSync, readFileSync, writeFileSync } from '../../integrations/disk.js';
2
2
  import { resolve } from 'node:path';
3
3
  import { argv, stderr, stdout } from 'node:process';
4
- import { exit } from "../../core/invoked.js";
5
- import { ROOT, descend } from "../../core/descend.js";
6
- import { forbids, runChecker } from "../../core/finding.js";
7
- import { agentInstructions } from "../../integrity/lint.js";
4
+ import { exit } from '../../core/invoked.js';
5
+ import { ROOT, descend } from '../../core/descend.js';
6
+ import { forbids, runChecker } from '../../core/finding.js';
7
+ import { agentInstructions } from '../../integrity/lint.js';
8
8
  const AT = 'docs.md';
9
9
  const CHECKING = argv.includes('--check');
10
10
  const SHOWING = argv.includes('--show');
@@ -71,7 +71,9 @@ const line = (one) => {
71
71
  ].join('\n');
72
72
  };
73
73
  const words = [...pass.coined].sort(([one], [two]) => (one < two ? -1 : 1));
74
- const commands = [...pass.derived.values(), ...[...under.values()].flat().map((one) => one.row)]
74
+ const threadedRows = new Set([...pass.threaded.values()].flat().map((one) => one.row));
75
+ const loose = [...pass.stated.values()].filter((one) => !threadedRows.has(one));
76
+ const commands = [...pass.derived.values(), ...[...under.values()].flat().map((one) => one.row), ...loose]
75
77
  .filter((one) => text(one.by)?.startsWith('thread ') === true)
76
78
  .reduce((found, one) => found.set(text(one.by), one), new Map());
77
79
  const sections = [...under.keys()].sort();
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync, writeFileSync } from '../../core/files.ts'
1
+ import { existsSync, readFileSync, writeFileSync } from '../../integrations/disk.ts'
2
2
  import { dirname, resolve } from 'node:path'
3
3
  import { argv, stderr, stdout } from 'node:process'
4
4
 
@@ -96,7 +96,9 @@ const line = (one: { readonly list: string; readonly row: Row }): string => {
96
96
 
97
97
  const words = [...pass.coined].sort(([one], [two]) => (one < two ? -1 : 1))
98
98
 
99
- const commands = [...pass.derived.values(), ...[...under.values()].flat().map((one) => one.row)]
99
+ const threadedRows = new Set([...pass.threaded.values()].flat().map((one) => one.row))
100
+ const loose = [...pass.stated.values()].filter((one) => !threadedRows.has(one))
101
+ const commands = [...pass.derived.values(), ...[...under.values()].flat().map((one) => one.row), ...loose]
100
102
  .filter((one) => text(one.by)?.startsWith('thread ') === true)
101
103
  .reduce((found, one) => found.set(text(one.by) as string, one), new Map<string, Row>())
102
104
 
@@ -1,10 +1,10 @@
1
- import { existsSync, readFileSync, writeFileSync } from "../../core/files.js";
1
+ import { existsSync, readFileSync, writeFileSync } from '../../integrations/disk.js';
2
2
  import { dirname, relative, resolve } from 'node:path';
3
3
  import { argv, stderr, stdout } from 'node:process';
4
4
  import { fileURLToPath } from 'node:url';
5
- import { exit } from "../../core/invoked.js";
6
- import { ROOT, descend } from "../../core/descend.js";
7
- import { forbids, runChecker } from "../../core/finding.js";
5
+ import { exit } from '../../core/invoked.js';
6
+ import { ROOT, descend } from '../../core/descend.js';
7
+ import { forbids, runChecker } from '../../core/finding.js';
8
8
  function refuse(why) {
9
9
  stderr.write(`glossary: ${why}\n`);
10
10
  exit(1);
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync, writeFileSync } from '../../core/files.ts'
1
+ import { existsSync, readFileSync, writeFileSync } from '../../integrations/disk.ts'
2
2
  import { dirname, relative, resolve } from 'node:path'
3
3
  import { argv, stderr, stdout } from 'node:process'
4
4
  import { fileURLToPath } from 'node:url'
@@ -13,6 +13,29 @@ export declare function declaredWords(entities: readonly {
13
13
  };
14
14
  }[], which: 'roles' | 'entitlements', everybody: string): readonly string[];
15
15
  export declare function undeclared(answered: string, offers: readonly string[], which: 'roles' | 'entitlements'): string | undefined;
16
+ export interface Declaring {
17
+ readonly id: string;
18
+ readonly holds: readonly {
19
+ readonly id: string;
20
+ readonly options?: readonly string[];
21
+ }[];
22
+ readonly rows?: readonly Record<string, unknown>[];
23
+ readonly must?: readonly {
24
+ readonly unique?: readonly string[];
25
+ }[];
26
+ readonly actor?: {
27
+ readonly roles: string;
28
+ readonly entitlements?: string;
29
+ };
30
+ }
31
+ export interface Caller {
32
+ readonly id: string;
33
+ readonly entity: string;
34
+ readonly roles: readonly string[];
35
+ readonly entitlements: readonly string[];
36
+ }
37
+ export declare const keyIn: (one: Declaring) => string | undefined;
38
+ export declare const declaredCallers: (entities: readonly Declaring[]) => readonly Caller[];
16
39
  export interface Grant extends Member {
17
40
  readonly may: readonly string[];
18
41
  readonly on?: string;