@idleware/ringi 0.6.1 → 0.7.1

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 (162) hide show
  1. package/README.md +7 -18
  2. package/package.json +1 -1
  3. package/src/main/resources/profiles/a2a-1.json +0 -4
  4. package/src/main/resources/skill/ringi/SKILL.md +2 -18
  5. package/target/dts/adapters/host-posix/index.d.ts +2 -2
  6. package/target/dts/adapters/transport-git/branches.d.ts +2 -3
  7. package/target/dts/adapters/transport-git/index.d.ts +1 -2
  8. package/target/dts/adapters/transport-git/remote/admit.d.ts +2 -2
  9. package/target/dts/adapters/transport-git/remote/heartbeat.d.ts +2 -2
  10. package/target/dts/adapters/transport-git/remote/keys.d.ts +3 -3
  11. package/target/dts/adapters/transport-git/remote/types.d.ts +0 -1
  12. package/target/dts/adapters/transport-git/remote.d.ts +1 -1
  13. package/target/dts/adapters/transport-git/repo.d.ts +0 -1
  14. package/target/dts/adapters/transport-git/signing.d.ts +3 -3
  15. package/target/dts/clients/cli/agent/index.d.ts +0 -2
  16. package/target/dts/clients/cli/shared/index.d.ts +0 -1
  17. package/target/dts/core/agents/heartbeat/index.d.ts +2 -5
  18. package/target/dts/core/agents/heartbeat/pulse.d.ts +1 -3
  19. package/target/dts/core/agents/overview.d.ts +1 -5
  20. package/target/dts/core/agents/ports/host.d.ts +5 -37
  21. package/target/dts/core/agents/sessions/agent.d.ts +0 -17
  22. package/target/dts/core/agents/sessions/index.d.ts +0 -1
  23. package/target/dts/core/hub/history/index.d.ts +1 -11
  24. package/target/dts/core/hub/ports/store.d.ts +1 -5
  25. package/target/dts/core/hub/protocol/model.d.ts +0 -1
  26. package/target/dts/core/hub/protocol/reading.d.ts +0 -1
  27. package/target/dts/core/hub/rooms/index.d.ts +0 -4
  28. package/target/dts/core/hub/rooms/messages.d.ts +0 -1
  29. package/target/dts/core/hub/rooms/rooms.d.ts +1 -1
  30. package/target/dts/core/hub/signals/model.d.ts +0 -2
  31. package/target/dts/core/hub/usecases/hubs.d.ts +0 -1
  32. package/target/dts/core/hub/usecases/room.d.ts +0 -1
  33. package/target/dts/core/hub/usecases/rooms.d.ts +1 -5
  34. package/target/dts/core/hub/usecases/send.d.ts +0 -1
  35. package/target/dts/core/hub/usecases/view.d.ts +0 -22
  36. package/target/dts/core/hub/work/index.d.ts +0 -1
  37. package/target/dts/index.d.ts +0 -1
  38. package/target/esm/adapters/host-posix/index.js +30 -32
  39. package/target/esm/adapters/transport-git/branches.js +13 -20
  40. package/target/esm/adapters/transport-git/index.js +8 -9
  41. package/target/esm/adapters/transport-git/marks.js +4 -10
  42. package/target/esm/adapters/transport-git/remote/admit.js +8 -10
  43. package/target/esm/adapters/transport-git/remote/heartbeat-push.js +1 -1
  44. package/target/esm/adapters/transport-git/remote/heartbeat.js +4 -4
  45. package/target/esm/adapters/transport-git/remote/keys.js +7 -32
  46. package/target/esm/adapters/transport-git/remote/main.js +1 -4
  47. package/target/esm/adapters/transport-git/remote.js +1 -1
  48. package/target/esm/adapters/transport-git/repo.js +5 -3
  49. package/target/esm/adapters/transport-git/signing.js +12 -17
  50. package/target/esm/adapters/transport-git/transport.js +6 -6
  51. package/target/esm/clients/cli/agent/index.js +4 -10
  52. package/target/esm/clients/cli/arg-parse.js +1 -1
  53. package/target/esm/clients/cli/commands.js +6 -7
  54. package/target/esm/clients/cli/help.js +6 -13
  55. package/target/esm/clients/cli/operator/heartbeat-format.js +1 -1
  56. package/target/esm/clients/cli/operator/hub-commands.js +1 -1
  57. package/target/esm/clients/cli/operator/index.js +1 -1
  58. package/target/esm/clients/cli/operator/room.js +46 -7
  59. package/target/esm/clients/cli/operator/where-format.js +1 -3
  60. package/target/esm/clients/cli/shared/index.js +1 -2
  61. package/target/esm/clients/cli/shared/messages.js +1 -1
  62. package/target/esm/clients/cli/shared/profile.js +2 -2
  63. package/target/esm/clients/cli/shared/work.js +1 -1
  64. package/target/esm/composition/index.js +1 -3
  65. package/target/esm/core/agents/heartbeat/index.js +16 -23
  66. package/target/esm/core/agents/heartbeat/pulse.js +18 -33
  67. package/target/esm/core/agents/heartbeat/tools.js +1 -2
  68. package/target/esm/core/agents/overview.js +5 -6
  69. package/target/esm/core/agents/ports/host.js +2 -2
  70. package/target/esm/core/agents/sessions/agent.js +3 -23
  71. package/target/esm/core/agents/sessions/binding.js +5 -7
  72. package/target/esm/core/agents/sessions/index.js +3 -7
  73. package/target/esm/core/agents/sessions/join.js +1 -5
  74. package/target/esm/core/agents/sessions/resume.js +3 -4
  75. package/target/esm/core/agents/sessions/wait.js +10 -31
  76. package/target/esm/core/hub/capabilities.js +4 -2
  77. package/target/esm/core/hub/history/index.js +3 -1
  78. package/target/esm/core/hub/ports/store.js +3 -3
  79. package/target/esm/core/hub/protocol/index.js +3 -3
  80. package/target/esm/core/hub/protocol/model.js +2 -3
  81. package/target/esm/core/hub/protocol/reading.js +1 -3
  82. package/target/esm/core/hub/rooms/compat.js +1 -2
  83. package/target/esm/core/hub/rooms/hubs.js +2 -5
  84. package/target/esm/core/hub/rooms/index.js +3 -3
  85. package/target/esm/core/hub/rooms/messages.js +5 -10
  86. package/target/esm/core/hub/rooms/rooms.js +9 -38
  87. package/target/esm/core/hub/signals/effective.js +1 -21
  88. package/target/esm/core/hub/signals/index.js +2 -2
  89. package/target/esm/core/hub/signals/pins.js +1 -1
  90. package/target/esm/core/hub/usecases/hubs.js +0 -3
  91. package/target/esm/core/hub/usecases/room.js +2 -3
  92. package/target/esm/core/hub/usecases/rooms.js +4 -17
  93. package/target/esm/core/hub/usecases/roster.js +1 -1
  94. package/target/esm/core/hub/usecases/send.js +2 -12
  95. package/target/esm/core/hub/usecases/view.js +2 -6
  96. package/target/esm/core/hub/work/task.js +4 -11
  97. package/target/esm/index.js +1 -2
  98. package/target/esm/lib/json.js +1 -1
  99. package/target/dts/adapters/host-posix/group-state.d.ts +0 -7
  100. package/target/dts/adapters/host-posix/groups.d.ts +0 -1
  101. package/target/dts/adapters/host-posix/launch.d.ts +0 -7
  102. package/target/dts/adapters/host-posix/probes.d.ts +0 -5
  103. package/target/dts/adapters/host-posix/stats.d.ts +0 -9
  104. package/target/dts/adapters/transport-kafka/index.d.ts +0 -2
  105. package/target/dts/adapters/transport-temporal/index.d.ts +0 -2
  106. package/target/dts/clients/cli/operator/room-lifecycle.d.ts +0 -5
  107. package/target/dts/clients/cli/operator/room-list.d.ts +0 -5
  108. package/target/dts/clients/cli/operator/room-members.d.ts +0 -4
  109. package/target/dts/clients/cli/operator/watch.d.ts +0 -2
  110. package/target/dts/clients/cli/shared/budget.d.ts +0 -7
  111. package/target/dts/core/agents/turns/budgets.d.ts +0 -5
  112. package/target/dts/core/agents/turns/dispatch.d.ts +0 -9
  113. package/target/dts/core/agents/turns/exhaustion.d.ts +0 -11
  114. package/target/dts/core/agents/turns/grants.d.ts +0 -4
  115. package/target/dts/core/agents/turns/index.d.ts +0 -4
  116. package/target/dts/core/agents/turns/limits.d.ts +0 -2
  117. package/target/dts/core/agents/turns/messages.d.ts +0 -10
  118. package/target/dts/core/agents/turns/pings.d.ts +0 -5
  119. package/target/dts/core/agents/turns/plan.d.ts +0 -3
  120. package/target/dts/core/agents/turns/poll.d.ts +0 -8
  121. package/target/dts/core/agents/turns/results.d.ts +0 -3
  122. package/target/dts/core/agents/turns/seat.d.ts +0 -2
  123. package/target/dts/core/agents/turns/types.d.ts +0 -59
  124. package/target/dts/core/hub/decisions/budget.d.ts +0 -15
  125. package/target/dts/core/hub/decisions/check.d.ts +0 -6
  126. package/target/dts/core/hub/decisions/index.d.ts +0 -5
  127. package/target/dts/core/hub/decisions/proposal.d.ts +0 -38
  128. package/target/dts/core/hub/decisions/usage.d.ts +0 -12
  129. package/target/dts/core/hub/usecases/budget.d.ts +0 -23
  130. package/target/dts/core/hub/usecases/propose.d.ts +0 -17
  131. package/target/esm/adapters/host-posix/group-state.js +0 -24
  132. package/target/esm/adapters/host-posix/groups.js +0 -43
  133. package/target/esm/adapters/host-posix/launch.js +0 -80
  134. package/target/esm/adapters/host-posix/probes.js +0 -66
  135. package/target/esm/adapters/host-posix/stats.js +0 -27
  136. package/target/esm/adapters/transport-kafka/index.js +0 -4
  137. package/target/esm/adapters/transport-temporal/index.js +0 -4
  138. package/target/esm/clients/cli/operator/room-lifecycle.js +0 -23
  139. package/target/esm/clients/cli/operator/room-list.js +0 -27
  140. package/target/esm/clients/cli/operator/room-members.js +0 -15
  141. package/target/esm/clients/cli/operator/watch.js +0 -15
  142. package/target/esm/clients/cli/shared/budget.js +0 -50
  143. package/target/esm/core/agents/turns/budgets.js +0 -48
  144. package/target/esm/core/agents/turns/dispatch.js +0 -40
  145. package/target/esm/core/agents/turns/exhaustion.js +0 -16
  146. package/target/esm/core/agents/turns/grants.js +0 -36
  147. package/target/esm/core/agents/turns/index.js +0 -33
  148. package/target/esm/core/agents/turns/limits.js +0 -11
  149. package/target/esm/core/agents/turns/messages.js +0 -32
  150. package/target/esm/core/agents/turns/pings.js +0 -30
  151. package/target/esm/core/agents/turns/plan.js +0 -29
  152. package/target/esm/core/agents/turns/poll.js +0 -48
  153. package/target/esm/core/agents/turns/results.js +0 -40
  154. package/target/esm/core/agents/turns/seat.js +0 -44
  155. package/target/esm/core/agents/turns/types.js +0 -3
  156. package/target/esm/core/hub/decisions/budget.js +0 -40
  157. package/target/esm/core/hub/decisions/check.js +0 -43
  158. package/target/esm/core/hub/decisions/index.js +0 -10
  159. package/target/esm/core/hub/decisions/proposal.js +0 -73
  160. package/target/esm/core/hub/decisions/usage.js +0 -39
  161. package/target/esm/core/hub/usecases/budget.js +0 -78
  162. package/target/esm/core/hub/usecases/propose.js +0 -39
@@ -1,73 +0,0 @@
1
- // proposal: one proposal folded over the messages that answer it, in thread order: its stamps, its decision, a
2
- // revocation, a superseding revision; and the grant an approval with a budget makes.
3
- import { one, ordered } from '../protocol/index.js';
4
- import { ROOT, ids, mayDecide, parseBudget } from './budget.js';
5
- const byOwner = (m, p) => m.from === p.from || m.from === ROOT;
6
- // A revision supersedes only when its author is the proposer or the root.
7
- const revises = (m, p) => m.kind === 'proposal' && one(m, 'supersedes') === p.id && byOwner(m, p);
8
- const answers = (m, p) => m.reId === p.id && (m.kind === 'stamp' || m.kind === 'decision');
9
- const among = (all, keep) => ordered([...all.values()].filter(m => !m.bad && keep(m)));
10
- // A decision names the room's control commit it was made under (`Control`); its authority is the table in effect
11
- // there. A commit that does not exist yet cannot be named, so a later contract never promotes or demotes a decision.
12
- const authorized = (c, m) => {
13
- if (m.from === ROOT)
14
- return true;
15
- const table = c.authorityAt(one(m, 'control'));
16
- return !!table && mayDecide(table, c.decider, c.p.from, c.budget);
17
- };
18
- const decides = (c, m) => one(m, 'decision') !== 'revoked' && m.from === c.decider && authorized(c, m);
19
- const revokes = (c, m) => one(m, 'decision') === 'revoked' && (m.from === c.decider || m.from === ROOT);
20
- const approved = (f) => f.decision?.decision === 'approved';
21
- // One answer applied: a reviewer's latest stamp counts (its position relative to the decision is only a same-second
22
- // tie); the first decision of the decider with authority; then the first revocation of an approval.
23
- const take = (c, f, m) => {
24
- if (m.kind === 'stamp' && c.reviewers.includes(m.from))
25
- f.stamps[m.from] = { stamp: one(m, 'stamp'), id: m.id, reason: m.subject };
26
- if (m.kind !== 'decision')
27
- return;
28
- if (!f.decision && decides(c, m))
29
- f.decision = { decision: one(m, 'decision'), id: m.id, by: m.from, time: m.time };
30
- else if (approved(f) && !f.revoked && revokes(c, m))
31
- f.revoked = { id: m.id, by: m.from, time: m.time };
32
- };
33
- // The answers in thread order; one after the superseding revision no longer applies to this revision, except a
34
- // revocation of an earlier approval.
35
- const fold = (c, list, superseded) => {
36
- const f = { stamps: {}, decision: null, revoked: null };
37
- for (const m of ordered([...list, ...(superseded ? [superseded] : [])])) {
38
- if (m === superseded)
39
- break;
40
- take(c, f, m);
41
- }
42
- const late = superseded && approved(f) && !f.revoked ? list.find(m => revokes(c, m)) : undefined;
43
- if (late)
44
- f.revoked = { id: late.id, by: late.from, time: late.time };
45
- return f;
46
- };
47
- const stateOf = (f, superseded, due, now) => {
48
- if (f.revoked)
49
- return 'revoked';
50
- if (f.decision)
51
- return f.decision.decision;
52
- if (superseded)
53
- return 'superseded';
54
- return due && now > due ? 'overdue' : 'open';
55
- };
56
- export const proposalOf = (all, p, authorityAt, now = Date.now() / 1000) => {
57
- const c = { p, decider: one(p, 'decider'), reviewers: ids(one(p, 'reviewers')), budget: parseBudget(one(p, 'budget')) ?? null, authorityAt };
58
- const due = one(p, 'due') ? Date.parse(one(p, 'due')) / 1000 : null;
59
- const superseded = among(all, m => revises(m, p))[0] ?? null;
60
- const f = fold(c, among(all, m => answers(m, p)), superseded);
61
- const grant = approved(f) && c.budget ? { id: f.decision.id, budget: c.budget, proposal: p, revoked: !!f.revoked } : null;
62
- return { proposal: p, decider: c.decider, reviewers: c.reviewers, budget: c.budget, due, ...f,
63
- missing: c.reviewers.filter(r => !f.stamps[r]), superseded, state: stateOf(f, superseded, due, now), grant };
64
- };
65
- export const proposals = (all, authorityAt) => [...all.values()].filter(m => !m.bad && m.kind === 'proposal').map(p => proposalOf(all, p, authorityAt));
66
- const decision = (d) => !!d && !d.bad && d.kind === 'decision';
67
- export const grantOf = (all, authorityAt, id) => {
68
- const d = all.get(id);
69
- const p = decision(d) && d.reId ? all.get(d.reId) : undefined;
70
- const g = p ? proposalOf(all, p, authorityAt).grant : null;
71
- return g?.id === id ? g : null;
72
- };
73
- //# sourceMappingURL=proposal.js.map
@@ -1,39 +0,0 @@
1
- // usage: what a grant's runs spent, from the usage receipts the runners write.
2
- import { one, ordered } from '../protocol/index.js';
3
- import { grantOf } from './proposal.js';
4
- // The receipts a grant's ledger counts, in thread order: every reservation, and for each run (its runner and Run id)
5
- // the first settlement after its reservation, as the first decision counts. A settlement of no reserved run counts
6
- // nothing.
7
- const ledger = (all, grant) => {
8
- const reserves = [], settled = new Map(), reserved = new Set();
9
- for (const m of ordered([...all.values()].filter(m => !m.bad && m.kind === 'usage' && one(m, 'grant') === grant.id))) {
10
- const run = `${m.from}/${one(m, 'run')}`;
11
- if (one(m, 'usage') === 'reserve') {
12
- reserves.push(m);
13
- reserved.add(run);
14
- }
15
- else if (reserved.has(run) && !settled.has(run))
16
- settled.set(run, m);
17
- }
18
- return { reserves, settled };
19
- };
20
- // Whether a receipt counts: its Grant names a grant, and that grant's ledger holds it.
21
- export const counted = (all, authorityAt, m) => {
22
- const g = !m.bad && m.kind === 'usage' ? grantOf(all, authorityAt, one(m, 'grant') ?? '') : null;
23
- if (!g)
24
- return false;
25
- const { reserves, settled } = ledger(all, g);
26
- return reserves.includes(m) || [...settled.values()].includes(m);
27
- };
28
- // Usage from the runners' receipts: every reservation is a run, settled or not; an unsettled one is open while its
29
- // run could still be going, and uncertain after that.
30
- export const usageOf = (all, grant, now = Date.now() / 1000) => {
31
- const { reserves, settled } = ledger(all, grant);
32
- let seconds = 0;
33
- for (const m of settled.values())
34
- seconds += Number(one(m, 'seconds'));
35
- const unsettled = reserves.filter(m => !settled.has(`${m.from}/${one(m, 'run')}`));
36
- const open = unsettled.filter(m => now - m.time <= grant.budget['run-seconds'] + 60);
37
- return { runs: reserves.length, open: open.length, uncertain: unsettled.length - open.length, seconds, left: Math.max(0, grant.budget.runs - reserves.length) };
38
- };
39
- //# sourceMappingURL=usage.js.map
@@ -1,78 +0,0 @@
1
- // budget: proposals, reviewers' stamps, the decider's decision, and the grants it makes (decisions/1). Each operation
2
- // takes who acts and typed input, and returns data; interfaces print it.
3
- import * as D from '../decisions/index.js';
4
- import { locked } from '../ports/index.js';
5
- import { OPERATOR, append } from '../rooms/index.js';
6
- import { fail, note, short } from '../../../lib/index.js';
7
- import { checkOutgoing, compose, lookup } from '../protocol/index.js';
8
- import { linked } from '../history/index.js';
9
- import { isRef } from './actor.js';
10
- import { grantView, proposalView } from './view.js';
11
- const proposalAt = (all, ref) => {
12
- const p = lookup(all, ref);
13
- if (p.kind !== 'proposal' || p.bad)
14
- fail(`${short(p.id)} is not a proposal`);
15
- return p;
16
- };
17
- export const stamp = ({ R, me }, ref, s, text) => {
18
- const { all } = linked(R, me);
19
- const p = proposalAt(all, ref);
20
- if (!D.STAMPS.includes(s))
21
- fail(`usage: stamp <proposal> ${D.STAMPS.join('|')} -m <reason>`);
22
- const info = D.proposalOf(all, p, R.authorityAt);
23
- if (!info.reviewers.includes(me))
24
- fail(`you are not a named reviewer of ${short(p.id)} (reviewers: ${info.reviewers.join(', ') || 'none'})`);
25
- if (info.decision)
26
- fail(`${short(p.id)} is already ${info.decision.decision}`);
27
- const out = compose(text, [['To', [...new Set([p.from, info.decider])].filter(x => x !== me).join(', ') || p.from], ['Re', p.id], ['Kind', 'stamp'], ['Stamp', s], ['Hop', String(p.hopEff + 1)]]);
28
- checkOutgoing(out, isRef(R));
29
- return { proposal: p, id: append(R, me, out) };
30
- };
31
- // Why the actor may not revoke the proposal's approval: only its decider or the operator revokes, and only an approval.
32
- const revokeProblem = (info, p, me) => {
33
- if (info.state !== 'approved')
34
- return `${short(p.id)} is ${info.state}; only an approval can be revoked`;
35
- return me !== info.decider && me !== OPERATOR ? `only ${info.decider} or the operator revokes it` : null;
36
- };
37
- // Why the actor may not decide the proposal: only its named decider with authority, once, on its latest revision.
38
- const decideProblem = ({ R, me }, info, p) => {
39
- if (me !== info.decider)
40
- return `only the named decider, ${info.decider}, decides ${short(p.id)}`;
41
- if (!D.mayDecide(R.contract.authority, me, p.from, info.budget))
42
- return `${me} has no authority to decide this${info.budget ? ` budget (${D.budgetText(info.budget)})` : ''} in hub ${R.hub.name}, or it is your own proposal`;
43
- if (info.decision)
44
- return `${short(p.id)} is already ${info.decision.decision}`;
45
- return info.superseded ? `${short(p.id)} was superseded by ${short(info.superseded.id)}; decide that revision` : null;
46
- };
47
- // The decision names the control entry, and so the authority, it was made under (decisions/1).
48
- export const decide = ({ R, me }, ref, d, text) => locked(`grant-${R.hub.name}`, () => {
49
- const { all } = linked(R, me);
50
- const p = proposalAt(all, ref);
51
- if (!D.DECISIONS.includes(d))
52
- fail(`usage: decide <proposal> ${D.DECISIONS.join('|')} -m <reason>`);
53
- const info = D.proposalOf(all, p, R.authorityAt);
54
- const why = d === 'revoked' ? revokeProblem(info, p, me) : decideProblem({ R, me }, info, p);
55
- if (why)
56
- fail(why);
57
- const to = [...new Set([p.from, ...info.reviewers])].filter(x => x !== me);
58
- const out = compose(text, [['To', to.join(', ') || '*'], ['Re', p.id], ['Kind', 'decision'], ['Decision', d], ['Control', R.head], ['Hop', String(p.hopEff + 1)]]);
59
- checkOutgoing(out, isRef(R));
60
- const id = append(R, me, out);
61
- const approved = d === 'approved';
62
- if (approved && info.missing.length)
63
- note(`decided without stamps from ${info.missing.join(', ')}`);
64
- return { proposal: p, id, budget: approved ? info.budget : null };
65
- });
66
- // Open proposals (with `all`, every one).
67
- export const proposals = ({ R, me }, { all: everything = false } = {}) => {
68
- const { all } = linked(R, me);
69
- const ps = D.proposals(all, R.authorityAt).filter(x => everything || ['open', 'overdue'].includes(x.state));
70
- return { proposals: ps, views: ps.map(proposalView) };
71
- };
72
- export const grants = ({ R, me }) => {
73
- const { all } = linked(R, me);
74
- return D.proposals(all, R.authorityAt).filter(x => x.grant).map(x => grantView(x, D.usageOf(all, x.grant)));
75
- };
76
- export { propose } from './propose.js';
77
- export { DECISIONS, STAMPS, budgetText } from '../decisions/index.js';
78
- //# sourceMappingURL=budget.js.map
@@ -1,39 +0,0 @@
1
- // propose: a proposal for the decider and its reviewers, its budget and revision checked before it is written
2
- // (decisions/1).
3
- import * as D from '../decisions/index.js';
4
- import { OPERATOR, append } from '../rooms/index.js';
5
- import { fail, note, short } from '../../../lib/index.js';
6
- import { ID_RE, checkOutgoing, compose, lookup } from '../protocol/index.js';
7
- import { linked } from '../history/index.js';
8
- import { isRef } from './actor.js';
9
- // Named reviewers, the proposer never among them.
10
- const reviewersOf = (me, x) => {
11
- if (!ID_RE.test(x.decider))
12
- fail(`bad decider ${x.decider}`);
13
- const reviewers = [...new Set(x.reviewers ?? [])].filter(r => r !== me);
14
- for (const r of reviewers)
15
- if (!ID_RE.test(r))
16
- fail(`bad reviewer ${r}`);
17
- return reviewers;
18
- };
19
- const budgetOf = (x) => x.budget ? D.parseBudget(x.budget) ?? fail('--budget takes runs=<n>[, run-seconds=<n>][, concurrency=<n>]') : null;
20
- // A revision supersedes the actor's own proposal; the operator may revise anyone's.
21
- const supersededOf = (all, me, ref) => {
22
- const sup = ref ? lookup(all, ref) : null;
23
- const mine = sup?.kind === 'proposal' && (sup.from === me || me === OPERATOR);
24
- return !sup || mine ? sup : fail(`${short(sup.id)} is not your proposal`);
25
- };
26
- export const propose = ({ R, me }, x) => {
27
- const { all } = linked(R, me);
28
- const reviewers = reviewersOf(me, x), budget = budgetOf(x), sup = supersededOf(all, me, x.supersedes);
29
- if (budget && !D.mayDecide(R.contract.authority, x.decider, me, budget))
30
- note(`${x.decider} has no authority for this budget in hub ${R.hub.name}; only operator could approve it`);
31
- const to = [...new Set([...reviewers, x.decider])].filter(t => t !== me);
32
- const text = compose(x.text, [['To', to.join(', ') || '*'], ['Kind', 'proposal'], ['Decider', x.decider], ['Reviewers', reviewers.join(', ')],
33
- ['Due', x.due && D.parseDue(x.due)], ['Budget', budget && D.budgetText(budget)], ['Supersedes', sup?.id]]);
34
- const bad = D.check(checkOutgoing(text, isRef(R)), isRef(R));
35
- if (bad)
36
- fail(`refusing to send: ${bad}`);
37
- return { id: append(R, me, text, x.files ?? []), to, budget };
38
- };
39
- //# sourceMappingURL=propose.js.map