@idleware/ringi 0.5.0 → 0.6.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.
- package/package.json +1 -1
- package/target/dts/adapters/fs/index.d.ts +2 -0
- package/target/dts/adapters/fs/lock.d.ts +1 -0
- package/target/dts/adapters/fs/write.d.ts +5 -0
- package/target/dts/adapters/host-posix/group-state.d.ts +7 -0
- package/target/dts/adapters/host-posix/groups.d.ts +1 -0
- package/target/dts/adapters/host-posix/index.d.ts +2 -0
- package/target/dts/adapters/host-posix/launch.d.ts +7 -0
- package/target/dts/adapters/host-posix/probes.d.ts +5 -0
- package/target/dts/adapters/host-posix/stats.d.ts +9 -0
- package/target/dts/adapters/keys-file/index.d.ts +2 -0
- package/target/dts/adapters/state-fs/index.d.ts +5 -0
- package/target/dts/adapters/tool-claude/index.d.ts +2 -0
- package/target/dts/adapters/tool-codex/index.d.ts +2 -0
- package/target/dts/adapters/tool-cursor/index.d.ts +2 -0
- package/target/dts/adapters/tool-traces/index.d.ts +3 -0
- package/target/dts/adapters/transport-git/branches.d.ts +43 -0
- package/target/dts/adapters/transport-git/files.d.ts +2 -0
- package/target/dts/adapters/transport-git/index.d.ts +32 -0
- package/target/dts/adapters/transport-git/marks.d.ts +20 -0
- package/target/dts/adapters/transport-git/remote/admit.d.ts +7 -0
- package/target/dts/adapters/transport-git/remote/alarms.d.ts +3 -0
- package/target/dts/adapters/transport-git/remote/bootstrap.d.ts +7 -0
- package/target/dts/adapters/transport-git/remote/branch-commit.d.ts +3 -0
- package/target/dts/adapters/transport-git/remote/branch-control.d.ts +15 -0
- package/target/dts/adapters/transport-git/remote/branch-scan.d.ts +2 -0
- package/target/dts/adapters/transport-git/remote/branch.d.ts +5 -0
- package/target/dts/adapters/transport-git/remote/cache.d.ts +3 -0
- package/target/dts/adapters/transport-git/remote/commits.d.ts +2 -0
- package/target/dts/adapters/transport-git/remote/forget.d.ts +2 -0
- package/target/dts/adapters/transport-git/remote/git.d.ts +26 -0
- package/target/dts/adapters/transport-git/remote/heartbeat-facts.d.ts +1 -0
- package/target/dts/adapters/transport-git/remote/heartbeat-name.d.ts +6 -0
- package/target/dts/adapters/transport-git/remote/heartbeat-object.d.ts +10 -0
- package/target/dts/adapters/transport-git/remote/heartbeat-push.d.ts +2 -0
- package/target/dts/adapters/transport-git/remote/heartbeat.d.ts +7 -0
- package/target/dts/adapters/transport-git/remote/keys.d.ts +13 -0
- package/target/dts/adapters/transport-git/remote/main.d.ts +11 -0
- package/target/dts/adapters/transport-git/remote/process.d.ts +20 -0
- package/target/dts/adapters/transport-git/remote/push-retry.d.ts +2 -0
- package/target/dts/adapters/transport-git/remote/push-validate.d.ts +2 -0
- package/target/dts/adapters/transport-git/remote/push.d.ts +16 -0
- package/target/dts/adapters/transport-git/remote/roster.d.ts +7 -0
- package/target/dts/adapters/transport-git/remote/signals.d.ts +15 -0
- package/target/dts/adapters/transport-git/remote/signature.d.ts +5 -0
- package/target/dts/adapters/transport-git/remote/sync-heartbeat.d.ts +2 -0
- package/target/dts/adapters/transport-git/remote/sync-rooms.d.ts +6 -0
- package/target/dts/adapters/transport-git/remote/sync-tags.d.ts +8 -0
- package/target/dts/adapters/transport-git/remote/sync.d.ts +2 -0
- package/target/dts/adapters/transport-git/remote/types.d.ts +64 -0
- package/target/dts/adapters/transport-git/remote.d.ts +17 -0
- package/target/dts/adapters/transport-git/repo.d.ts +31 -0
- package/target/dts/adapters/transport-git/run.d.ts +21 -0
- package/target/dts/adapters/transport-git/signing.d.ts +4 -0
- package/target/dts/adapters/transport-git/tags.d.ts +15 -0
- package/target/dts/adapters/transport-git/transport.d.ts +7 -0
- package/target/dts/adapters/transport-kafka/index.d.ts +2 -0
- package/target/dts/adapters/transport-temporal/index.d.ts +2 -0
- package/target/dts/cli.d.ts +2 -1
- package/target/dts/{cli/agent.d.ts → clients/cli/agent/index.d.ts} +3 -3
- package/target/dts/{cli → clients/cli/agent}/session.d.ts +2 -2
- package/target/dts/clients/cli/arg-parse.d.ts +2 -0
- package/target/dts/{cli → clients/cli}/args.d.ts +2 -2
- package/target/dts/clients/cli/commands.d.ts +2 -0
- package/target/dts/clients/cli/context.d.ts +4 -0
- package/target/dts/{cli/index.d.ts → clients/cli/help.d.ts} +1 -3
- package/target/dts/clients/cli/index.d.ts +4 -0
- package/target/dts/clients/cli/operator/heartbeat-format.d.ts +5 -0
- package/target/dts/clients/cli/operator/heartbeat.d.ts +3 -0
- package/target/dts/clients/cli/operator/hub-commands.d.ts +6 -0
- package/target/dts/clients/cli/operator/hub.d.ts +2 -0
- package/target/dts/clients/cli/operator/index.d.ts +5 -0
- package/target/dts/clients/cli/operator/room-lifecycle.d.ts +5 -0
- package/target/dts/clients/cli/operator/room-list.d.ts +5 -0
- package/target/dts/clients/cli/operator/room-members.d.ts +4 -0
- package/target/dts/clients/cli/operator/room.d.ts +2 -0
- package/target/dts/clients/cli/operator/sessions.d.ts +5 -0
- package/target/dts/clients/cli/operator/watch.d.ts +2 -0
- package/target/dts/clients/cli/operator/where-format.d.ts +7 -0
- package/target/dts/clients/cli/operator/where.d.ts +2 -0
- package/target/dts/clients/cli/shared/budget.d.ts +7 -0
- package/target/dts/clients/cli/shared/files.d.ts +4 -0
- package/target/dts/clients/cli/shared/index.d.ts +7 -0
- package/target/dts/clients/cli/shared/messages.d.ts +7 -0
- package/target/dts/clients/cli/shared/profile.d.ts +4 -0
- package/target/dts/clients/cli/shared/session.d.ts +6 -0
- package/target/dts/clients/cli/shared/signals.d.ts +3 -0
- package/target/dts/clients/cli/shared/work.d.ts +6 -0
- package/target/dts/clients/cli/skill/index.d.ts +3 -0
- package/target/dts/{cli/skill.d.ts → clients/cli/skill/targets.d.ts} +1 -2
- package/target/dts/composition/index.d.ts +2 -0
- package/target/dts/{heartbeat → core/agents/heartbeat}/index.d.ts +2 -4
- package/target/dts/{app/heartbeat.d.ts → core/agents/heartbeat/pulse.d.ts} +5 -6
- package/target/dts/core/agents/heartbeat/singleton.d.ts +3 -0
- package/target/dts/core/agents/heartbeat/tools.d.ts +6 -0
- package/target/dts/{app → core/agents}/overview.d.ts +12 -6
- package/target/dts/core/agents/ports/host.d.ts +47 -0
- package/target/dts/core/agents/ports/index.d.ts +9 -0
- package/target/dts/core/agents/ports/tools.d.ts +18 -0
- package/target/dts/core/agents/sessions/agent.d.ts +70 -0
- package/target/dts/core/agents/sessions/binding.d.ts +9 -0
- package/target/dts/core/agents/sessions/context.d.ts +8 -0
- package/target/dts/{runtime/session.d.ts → core/agents/sessions/index.d.ts} +2 -9
- package/target/dts/core/agents/sessions/join.d.ts +20 -0
- package/target/dts/core/agents/sessions/resume.d.ts +2 -0
- package/target/dts/core/agents/sessions/session.d.ts +46 -0
- package/target/dts/core/agents/sessions/wait.d.ts +38 -0
- package/target/dts/core/agents/turns/budgets.d.ts +5 -0
- package/target/dts/core/agents/turns/dispatch.d.ts +9 -0
- package/target/dts/core/agents/turns/exhaustion.d.ts +11 -0
- package/target/dts/core/agents/turns/grants.d.ts +4 -0
- package/target/dts/core/agents/turns/index.d.ts +4 -0
- package/target/dts/core/agents/turns/limits.d.ts +2 -0
- package/target/dts/core/agents/turns/messages.d.ts +10 -0
- package/target/dts/core/agents/turns/pings.d.ts +5 -0
- package/target/dts/core/agents/turns/plan.d.ts +3 -0
- package/target/dts/core/agents/turns/poll.d.ts +8 -0
- package/target/dts/core/agents/turns/results.d.ts +3 -0
- package/target/dts/core/agents/turns/seat.d.ts +2 -0
- package/target/dts/core/agents/turns/types.d.ts +59 -0
- package/target/dts/core/hub/decisions/budget.d.ts +15 -0
- package/target/dts/core/hub/decisions/check.d.ts +6 -0
- package/target/dts/core/hub/decisions/index.d.ts +5 -0
- package/target/dts/core/hub/decisions/proposal.d.ts +38 -0
- package/target/dts/core/hub/decisions/usage.d.ts +12 -0
- package/target/dts/{runtime/reader.d.ts → core/hub/history/index.d.ts} +12 -6
- package/target/dts/core/hub/ports/index.d.ts +16 -0
- package/target/dts/core/hub/ports/state.d.ts +12 -0
- package/target/dts/{store/index.d.ts → core/hub/ports/store.d.ts} +48 -18
- package/target/dts/core/hub/protocol/index.d.ts +5 -0
- package/target/dts/{protocol/index.d.ts → core/hub/protocol/model.d.ts} +0 -25
- package/target/dts/core/hub/protocol/order.d.ts +2 -0
- package/target/dts/core/hub/protocol/reading.d.ts +8 -0
- package/target/dts/core/hub/protocol/text.d.ts +11 -0
- package/target/dts/core/hub/protocol/threads.d.ts +5 -0
- package/target/dts/core/hub/rooms/compat.d.ts +5 -0
- package/target/dts/core/hub/rooms/hubs.d.ts +14 -0
- package/target/dts/core/hub/rooms/index.d.ts +53 -0
- package/target/dts/core/hub/rooms/messages.d.ts +8 -0
- package/target/dts/core/hub/rooms/rooms.d.ts +10 -0
- package/target/dts/core/hub/signals/check.d.ts +3 -0
- package/target/dts/core/hub/signals/effective.d.ts +3 -0
- package/target/dts/core/hub/signals/index.d.ts +5 -0
- package/target/dts/core/hub/signals/marks.d.ts +4 -0
- package/target/dts/core/hub/signals/model.d.ts +28 -0
- package/target/dts/core/hub/signals/pins.d.ts +5 -0
- package/target/dts/{hub/signals.d.ts → core/hub/signals/write.d.ts} +1 -1
- package/target/dts/core/hub/usecases/actor.d.ts +6 -0
- package/target/dts/{app → core/hub/usecases}/budget.d.ts +5 -18
- package/target/dts/core/hub/usecases/config.d.ts +6 -0
- package/target/dts/{app → core/hub/usecases}/context.d.ts +3 -8
- package/target/dts/{app → core/hub/usecases}/hubs.d.ts +1 -1
- package/target/dts/core/hub/usecases/propose.d.ts +17 -0
- package/target/dts/{app → core/hub/usecases}/room.d.ts +8 -34
- package/target/dts/{app → core/hub/usecases}/rooms.d.ts +2 -6
- package/target/dts/core/hub/usecases/roster.d.ts +5 -0
- package/target/dts/core/hub/usecases/send.d.ts +21 -0
- package/target/dts/core/hub/usecases/staging.d.ts +8 -0
- package/target/dts/{app → core/hub/usecases}/view.d.ts +4 -4
- package/target/dts/{domain/profiles.d.ts → core/hub/work/index.d.ts} +3 -7
- package/target/dts/core/hub/work/parse.d.ts +2 -0
- package/target/dts/core/hub/work/task.d.ts +6 -0
- package/target/dts/core/signing/index.d.ts +35 -0
- package/target/dts/index.d.ts +8 -8
- package/target/dts/lib/fail.d.ts +8 -0
- package/target/dts/lib/index.d.ts +3 -11
- package/target/dts/lib/json.d.ts +1 -0
- package/target/esm/adapters/fs/index.js +5 -0
- package/target/esm/adapters/fs/lock.js +83 -0
- package/target/esm/adapters/fs/write.js +25 -0
- package/target/esm/adapters/host-posix/group-state.js +24 -0
- package/target/esm/adapters/host-posix/groups.js +43 -0
- package/target/esm/adapters/host-posix/index.js +35 -0
- package/target/esm/adapters/host-posix/launch.js +80 -0
- package/target/esm/adapters/host-posix/probes.js +66 -0
- package/target/esm/adapters/host-posix/stats.js +27 -0
- package/target/esm/adapters/keys-file/index.js +68 -0
- package/target/esm/adapters/state-fs/index.js +79 -0
- package/target/esm/adapters/tool-claude/index.js +32 -0
- package/target/esm/adapters/tool-codex/index.js +38 -0
- package/target/esm/adapters/tool-cursor/index.js +8 -0
- package/target/esm/adapters/tool-traces/index.js +18 -0
- package/target/esm/adapters/transport-git/branches.js +155 -0
- package/target/esm/adapters/transport-git/files.js +48 -0
- package/target/esm/adapters/transport-git/index.js +128 -0
- package/target/esm/adapters/transport-git/marks.js +88 -0
- package/target/esm/adapters/transport-git/remote/admit.js +71 -0
- package/target/esm/adapters/transport-git/remote/alarms.js +30 -0
- package/target/esm/adapters/transport-git/remote/bootstrap.js +47 -0
- package/target/esm/adapters/transport-git/remote/branch-commit.js +36 -0
- package/target/esm/adapters/transport-git/remote/branch-control.js +37 -0
- package/target/esm/adapters/transport-git/remote/branch-scan.js +28 -0
- package/target/esm/adapters/transport-git/remote/branch.js +37 -0
- package/target/esm/adapters/transport-git/remote/cache.js +23 -0
- package/target/esm/adapters/transport-git/remote/commits.js +25 -0
- package/target/esm/adapters/transport-git/remote/forget.js +35 -0
- package/target/esm/adapters/transport-git/remote/git.js +58 -0
- package/target/esm/adapters/transport-git/remote/heartbeat-facts.js +35 -0
- package/target/esm/adapters/transport-git/remote/heartbeat-name.js +19 -0
- package/target/esm/adapters/transport-git/remote/heartbeat-object.js +40 -0
- package/target/esm/adapters/transport-git/remote/heartbeat-push.js +44 -0
- package/target/esm/adapters/transport-git/remote/heartbeat.js +44 -0
- package/target/esm/adapters/transport-git/remote/keys.js +75 -0
- package/target/esm/adapters/transport-git/remote/main.js +41 -0
- package/target/esm/adapters/transport-git/remote/process.js +37 -0
- package/target/esm/adapters/transport-git/remote/push-retry.js +46 -0
- package/target/esm/adapters/transport-git/remote/push-validate.js +39 -0
- package/target/esm/adapters/transport-git/remote/push.js +62 -0
- package/target/esm/adapters/transport-git/remote/roster.js +48 -0
- package/target/esm/adapters/transport-git/remote/signals.js +63 -0
- package/target/esm/adapters/transport-git/remote/signature.js +56 -0
- package/target/esm/adapters/transport-git/remote/sync-heartbeat.js +26 -0
- package/target/esm/adapters/transport-git/remote/sync-rooms.js +38 -0
- package/target/esm/adapters/transport-git/remote/sync-tags.js +48 -0
- package/target/esm/adapters/transport-git/remote/sync.js +38 -0
- package/target/esm/adapters/transport-git/remote/types.js +10 -0
- package/target/esm/adapters/transport-git/remote.js +17 -0
- package/target/esm/adapters/transport-git/repo.js +115 -0
- package/target/esm/adapters/transport-git/run.js +57 -0
- package/target/esm/adapters/transport-git/signing.js +44 -0
- package/target/esm/adapters/transport-git/tags.js +21 -0
- package/target/esm/adapters/transport-git/transport.js +29 -0
- package/target/esm/adapters/transport-kafka/index.js +4 -0
- package/target/esm/adapters/transport-temporal/index.js +4 -0
- package/target/esm/cli.js +5 -4
- package/target/esm/{cli/agent.js → clients/cli/agent/index.js} +8 -7
- package/target/esm/{cli → clients/cli/agent}/session.js +7 -7
- package/target/esm/clients/cli/arg-parse.js +41 -0
- package/target/esm/{cli → clients/cli}/args.js +3 -36
- package/target/esm/clients/cli/commands.js +45 -0
- package/target/esm/clients/cli/context.js +6 -0
- package/target/esm/{cli/index.js → clients/cli/help.js} +4 -77
- package/target/esm/clients/cli/index.js +27 -0
- package/target/esm/clients/cli/operator/heartbeat-format.js +8 -0
- package/target/esm/clients/cli/operator/heartbeat.js +35 -0
- package/target/esm/clients/cli/operator/hub-commands.js +37 -0
- package/target/esm/clients/cli/operator/hub.js +10 -0
- package/target/esm/clients/cli/operator/index.js +8 -0
- package/target/esm/clients/cli/operator/room-lifecycle.js +23 -0
- package/target/esm/clients/cli/operator/room-list.js +27 -0
- package/target/esm/clients/cli/operator/room-members.js +15 -0
- package/target/esm/clients/cli/operator/room.js +15 -0
- package/target/esm/clients/cli/operator/sessions.js +32 -0
- package/target/esm/clients/cli/operator/watch.js +15 -0
- package/target/esm/clients/cli/operator/where-format.js +24 -0
- package/target/esm/clients/cli/operator/where.js +32 -0
- package/target/esm/clients/cli/shared/budget.js +50 -0
- package/target/esm/clients/cli/shared/files.js +26 -0
- package/target/esm/clients/cli/shared/index.js +10 -0
- package/target/esm/clients/cli/shared/messages.js +41 -0
- package/target/esm/clients/cli/shared/profile.js +17 -0
- package/target/esm/clients/cli/shared/session.js +8 -0
- package/target/esm/clients/cli/shared/signals.js +21 -0
- package/target/esm/clients/cli/shared/work.js +26 -0
- package/target/esm/clients/cli/skill/index.js +40 -0
- package/target/esm/clients/cli/skill/targets.js +20 -0
- package/target/esm/composition/index.js +34 -0
- package/target/esm/{heartbeat → core/agents/heartbeat}/index.js +14 -12
- package/target/esm/{app/heartbeat.js → core/agents/heartbeat/pulse.js} +31 -55
- package/target/esm/core/agents/heartbeat/singleton.js +38 -0
- package/target/esm/core/agents/heartbeat/tools.js +24 -0
- package/target/esm/{app → core/agents}/overview.js +15 -9
- package/target/esm/core/agents/ports/host.js +4 -0
- package/target/esm/core/agents/ports/index.js +7 -0
- package/target/esm/core/agents/ports/tools.js +5 -0
- package/target/esm/{app → core/agents/sessions}/agent.js +11 -43
- package/target/esm/core/agents/sessions/binding.js +43 -0
- package/target/esm/core/agents/sessions/context.js +11 -0
- package/target/esm/core/agents/sessions/index.js +59 -0
- package/target/esm/core/agents/sessions/join.js +55 -0
- package/target/esm/core/agents/sessions/resume.js +54 -0
- package/target/esm/core/agents/sessions/session.js +28 -0
- package/target/esm/core/agents/sessions/wait.js +47 -0
- package/target/esm/core/agents/turns/budgets.js +48 -0
- package/target/esm/core/agents/turns/dispatch.js +40 -0
- package/target/esm/core/agents/turns/exhaustion.js +16 -0
- package/target/esm/core/agents/turns/grants.js +36 -0
- package/target/esm/core/agents/turns/index.js +33 -0
- package/target/esm/core/agents/turns/limits.js +11 -0
- package/target/esm/core/agents/turns/messages.js +32 -0
- package/target/esm/core/agents/turns/pings.js +30 -0
- package/target/esm/core/agents/turns/plan.js +29 -0
- package/target/esm/core/agents/turns/poll.js +48 -0
- package/target/esm/core/agents/turns/results.js +40 -0
- package/target/esm/core/agents/turns/seat.js +44 -0
- package/target/esm/core/agents/turns/types.js +3 -0
- package/target/esm/{domain/index.js → core/hub/capabilities.js} +3 -3
- package/target/esm/core/hub/decisions/budget.js +40 -0
- package/target/esm/core/hub/decisions/check.js +43 -0
- package/target/esm/core/hub/decisions/index.js +10 -0
- package/target/esm/core/hub/decisions/proposal.js +73 -0
- package/target/esm/core/hub/decisions/usage.js +39 -0
- package/target/esm/core/hub/history/index.js +90 -0
- package/target/esm/core/hub/ports/index.js +10 -0
- package/target/esm/core/hub/ports/state.js +5 -0
- package/target/esm/core/hub/ports/store.js +10 -0
- package/target/esm/{protocol → core/hub/protocol}/files.js +4 -2
- package/target/esm/core/hub/protocol/index.js +9 -0
- package/target/esm/core/hub/protocol/model.js +15 -0
- package/target/esm/core/hub/protocol/order.js +39 -0
- package/target/esm/core/hub/protocol/reading.js +29 -0
- package/target/esm/core/hub/protocol/text.js +95 -0
- package/target/esm/core/hub/protocol/threads.js +52 -0
- package/target/esm/core/hub/rooms/compat.js +51 -0
- package/target/esm/core/hub/rooms/hubs.js +92 -0
- package/target/esm/core/hub/rooms/index.js +23 -0
- package/target/esm/core/hub/rooms/messages.js +47 -0
- package/target/esm/core/hub/rooms/rooms.js +84 -0
- package/target/esm/core/hub/signals/check.js +33 -0
- package/target/esm/core/hub/signals/effective.js +31 -0
- package/target/esm/core/hub/signals/index.js +23 -0
- package/target/esm/core/hub/signals/marks.js +30 -0
- package/target/esm/core/hub/signals/model.js +5 -0
- package/target/esm/core/hub/signals/pins.js +21 -0
- package/target/esm/{hub/signals.js → core/hub/signals/write.js} +4 -4
- package/target/esm/core/hub/usecases/actor.js +3 -0
- package/target/esm/core/hub/usecases/budget.js +78 -0
- package/target/esm/core/hub/usecases/config.js +5 -0
- package/target/esm/core/hub/usecases/context.js +13 -0
- package/target/esm/core/hub/usecases/hubs.js +95 -0
- package/target/esm/core/hub/usecases/propose.js +39 -0
- package/target/esm/core/hub/usecases/room.js +82 -0
- package/target/esm/{app → core/hub/usecases}/rooms.js +11 -63
- package/target/esm/core/hub/usecases/roster.js +47 -0
- package/target/esm/core/hub/usecases/send.js +78 -0
- package/target/esm/core/hub/usecases/staging.js +60 -0
- package/target/esm/{app → core/hub/usecases}/view.js +33 -33
- package/target/esm/core/hub/work/index.js +13 -0
- package/target/esm/core/hub/work/parse.js +37 -0
- package/target/esm/core/hub/work/task.js +68 -0
- package/target/esm/core/signing/index.js +4 -0
- package/target/esm/index.js +7 -6
- package/target/esm/lib/fail.js +18 -0
- package/target/esm/lib/index.js +20 -195
- package/target/esm/lib/json.js +81 -0
- package/target/dts/app/agent.d.ts +0 -109
- package/target/dts/app/session.d.ts +0 -65
- package/target/dts/cli/context.d.ts +0 -6
- package/target/dts/cli/operator.d.ts +0 -10
- package/target/dts/cli/shared.d.ts +0 -27
- package/target/dts/domain/decisions.d.ts +0 -65
- package/target/dts/domain/signals.d.ts +0 -37
- package/target/dts/heartbeat/platform.d.ts +0 -15
- package/target/dts/heartbeat/tools.d.ts +0 -11
- package/target/dts/home/index.d.ts +0 -21
- package/target/dts/hub/index.d.ts +0 -72
- package/target/dts/runtime/watch.d.ts +0 -17
- package/target/dts/store/git/index.d.ts +0 -92
- package/target/dts/store/git/remote.d.ts +0 -95
- package/target/dts/store/kafka/index.d.ts +0 -2
- package/target/dts/store/temporal/index.d.ts +0 -2
- package/target/esm/app/budget.js +0 -95
- package/target/esm/app/context.js +0 -16
- package/target/esm/app/hubs.js +0 -76
- package/target/esm/app/room.js +0 -181
- package/target/esm/app/session.js +0 -99
- package/target/esm/cli/context.js +0 -8
- package/target/esm/cli/operator.js +0 -185
- package/target/esm/cli/shared.js +0 -159
- package/target/esm/cli/skill.js +0 -54
- package/target/esm/domain/decisions.js +0 -178
- package/target/esm/domain/profiles.js +0 -96
- package/target/esm/domain/signals.js +0 -134
- package/target/esm/heartbeat/platform.js +0 -83
- package/target/esm/heartbeat/tools.js +0 -68
- package/target/esm/home/index.js +0 -88
- package/target/esm/hub/index.js +0 -224
- package/target/esm/protocol/index.js +0 -219
- package/target/esm/runtime/reader.js +0 -65
- package/target/esm/runtime/session.js +0 -116
- package/target/esm/runtime/watch.js +0 -321
- package/target/esm/store/git/index.js +0 -719
- package/target/esm/store/git/remote.js +0 -928
- package/target/esm/store/index.js +0 -15
- package/target/esm/store/kafka/index.js +0 -3
- package/target/esm/store/temporal/index.js +0 -3
- /package/target/dts/{domain/index.d.ts → core/hub/capabilities.d.ts} +0 -0
- /package/target/dts/{protocol → core/hub/protocol}/files.d.ts +0 -0
package/target/esm/cli/shared.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
// shared: commands the operator and agents both run: messages, threads, work, signals, proposals and grants. Each
|
|
2
|
-
// parses its arguments, calls one app operation and prints the result.
|
|
3
|
-
import fs from 'node:fs';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import * as Budget from '../app/budget.js';
|
|
6
|
-
import * as Room from '../app/room.js';
|
|
7
|
-
import { checkPath, withSizes } from '../app/room.js';
|
|
8
|
-
import { asJson, oneLine, render } from '../app/view.js';
|
|
9
|
-
import { bytes, fail, note, short, when, words } from '../lib/index.js';
|
|
10
|
-
import { attachments, dump, flag, list, opt, out, textOf } from './args.js';
|
|
11
|
-
const sendInput = (o) => ({ text: textOf(o), to: words(opt(o, 'to')), all: flag(o, 'all'), task: flag(o, 'task'),
|
|
12
|
-
state: opt(o, 'state'), assign: opt(o, 'assign') ? words(opt(o, 'assign')) : undefined, roles: opt(o, 'roles'), grant: opt(o, 'grant'),
|
|
13
|
-
files: list(o, 'attach').flatMap(attachments) });
|
|
14
|
-
const sent = (r) => out(`sent ${short(r.id)} to ${r.to.join(', ')}${r.files ? ` with ${r.files} file(s)` : ''}`);
|
|
15
|
-
// Stages files for the actor's next message, like git add: their content is taken into the hub now. Without files it
|
|
16
|
-
// lists what is staged; --drop <path> and --clear take files back out.
|
|
17
|
-
export const add = (a, o) => {
|
|
18
|
-
if (flag(o, 'clear'))
|
|
19
|
-
Room.unstage(a, null);
|
|
20
|
-
else if (list(o, 'drop').length)
|
|
21
|
-
Room.unstage(a, list(o, 'drop'));
|
|
22
|
-
const staged = o._.length ? Room.stage(a, o._.flatMap(attachments)) : Room.staged(a);
|
|
23
|
-
out(staged.length ? `staged for your next message:\n${staged.map(s => ` ${s.path} (${bytes(s.size)})`).join('\n')}` : 'nothing staged');
|
|
24
|
-
};
|
|
25
|
-
export const send = (a, o) => sent(Room.send(a, { ...sendInput(o), re: opt(o, 're') }));
|
|
26
|
-
export const reply = (a, o) => sent(Room.send(a, { ...sendInput(o), re: o._[0] ?? fail('usage: reply <msg> -m <text> …'), reply: true }));
|
|
27
|
-
export const read = (a, o) => {
|
|
28
|
-
const { all, m, replies, marks } = Room.message(a, o._[0] ?? fail('usage: read <msg>'));
|
|
29
|
-
if (flag(o, 'json'))
|
|
30
|
-
return dump(asJson(m));
|
|
31
|
-
out(render(all, m, { files: () => withSizes(a.R, m) }));
|
|
32
|
-
if (replies.length)
|
|
33
|
-
out(`replies: ${replies.map(x => `${short(x.id)} (${x.from})`).join(', ')}`);
|
|
34
|
-
if (marks)
|
|
35
|
-
out(Object.entries(marks).map(([mark, who]) => `${mark} by: ${who.join(', ')}`).join('; '));
|
|
36
|
-
};
|
|
37
|
-
export const thread = (a, o) => {
|
|
38
|
-
const { all, msgs } = Room.thread(a, o._[0] ?? fail('usage: thread <msg>'));
|
|
39
|
-
if (flag(o, 'json'))
|
|
40
|
-
return dump(msgs.map(asJson));
|
|
41
|
-
out(msgs.map(m => render(all, m, { files: () => withSizes(a.R, m) })).join('\n\n'));
|
|
42
|
-
};
|
|
43
|
-
export const taskLine = (t) => {
|
|
44
|
-
const roles = Object.keys(t.roles).length ? ` [${Object.entries(t.roles).map(([id, label]) => `${id}=${label}`).join(' ')}]` : '';
|
|
45
|
-
return `${short(t.id)} ${t.state.padEnd(14)} ${t.requester} → ${t.assignees.join(',') || '(open)'}${roles}${t.taken.length ? ` taken by ${t.taken.join(',')}` : ''}${t.grant ? ` grant ${short(t.grant)}` : ''} ${when(Date.parse(t.at) / 1000).slice(5)} by ${t.by} ${t.subject}`;
|
|
46
|
-
};
|
|
47
|
-
export const tasks = (a, o) => {
|
|
48
|
-
const { views } = Room.tasks(a, { all: flag(o, 'all') });
|
|
49
|
-
if (flag(o, 'json'))
|
|
50
|
-
return dump(views);
|
|
51
|
-
if (!views.length)
|
|
52
|
-
return out(flag(o, 'all') ? 'no work' : `no open work (profile ${a.R.profile.name}; tasks --all for everything)`);
|
|
53
|
-
for (const t of views)
|
|
54
|
-
out(taskLine(t));
|
|
55
|
-
};
|
|
56
|
-
export const log = (a, o) => {
|
|
57
|
-
const msgs = Room.log(a, { agent: opt(o, 'agent'), all: flag(o, 'all'), n: Number(opt(o, 'n') ?? 20) });
|
|
58
|
-
if (flag(o, 'json'))
|
|
59
|
-
return dump(msgs.map(asJson));
|
|
60
|
-
for (const m of msgs)
|
|
61
|
-
out(oneLine(m));
|
|
62
|
-
};
|
|
63
|
-
export const cat = (a, o) => {
|
|
64
|
-
const ref = o._[0] ?? fail('usage: cat <msg> [<path>]');
|
|
65
|
-
const p = o._[1] ?? (() => {
|
|
66
|
-
const { m } = Room.files(a, ref);
|
|
67
|
-
return m.files.length === 1 ? m.files[0].path : fail(`${short(m.id)} has ${m.files.length} files; name one: ${m.files.map(f => f.path).join(', ')}`);
|
|
68
|
-
})();
|
|
69
|
-
process.stdout.write(Room.files(a, ref, p).files[0].content);
|
|
70
|
-
};
|
|
71
|
-
export const get = (a, o) => {
|
|
72
|
-
const { m, files } = Room.files(a, o._[0] ?? fail('usage: get <msg> [-o <dir>]'));
|
|
73
|
-
const dir = path.resolve(opt(o, 'out') ?? short(m.id));
|
|
74
|
-
for (const f of files) {
|
|
75
|
-
const dest = path.join(dir, checkPath(f.path));
|
|
76
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
77
|
-
fs.writeFileSync(dest, f.content);
|
|
78
|
-
out(dest);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
export const who = (a) => {
|
|
82
|
-
for (const x of Room.members(a))
|
|
83
|
-
out(`${x.id.padEnd(12)} ${x.role.padEnd(7)} ${String(x.messages).padStart(4)} msg${x.card ? ` ${x.card}` : ''}`);
|
|
84
|
-
};
|
|
85
|
-
export const signals = (a, o) => {
|
|
86
|
-
const res = Room.signals(a, { repair: flag(o, 'repair') });
|
|
87
|
-
if (res.repaired !== null)
|
|
88
|
-
out(`restored ${res.repaired} signal(s) of ${a.me}`);
|
|
89
|
-
for (const x of res.alarms)
|
|
90
|
-
note(`ALARM ${x}`);
|
|
91
|
-
if (flag(o, 'json'))
|
|
92
|
-
return dump(res.checked);
|
|
93
|
-
const at = (c) => res.all.get(c.target)?.time ?? 0;
|
|
94
|
-
const sorted = [...res.checked].sort((x, y) => at(x) - at(y));
|
|
95
|
-
const shown = flag(o, 'all') ? sorted : sorted.slice(-Number(opt(o, 'n') ?? 20));
|
|
96
|
-
if (!shown.length)
|
|
97
|
-
return out('no signals');
|
|
98
|
-
for (const c of shown)
|
|
99
|
-
out(`${short(c.target)} ${when(at(c)).slice(5)} ${c.actor.padEnd(10)} ${c.signal.padEnd(20)} ${c.ok ? res.all.get(c.target)?.subject ?? '' : `MISMATCH: ${c.why}`}`);
|
|
100
|
-
};
|
|
101
|
-
export const profileCmd = ({ R }, o) => {
|
|
102
|
-
if (flag(o, 'json'))
|
|
103
|
-
return dump(R.profile);
|
|
104
|
-
const P = R.profile;
|
|
105
|
-
out(`room ${R.name} follows profile ${P.name}${P.description ? `: ${P.description}` : ''}`);
|
|
106
|
-
out(`opens with Kind: ${P.opens}; states: ${P.states.join(', ')}; initial ${P.initial}; terminal ${P.terminal.join(', ')}${P.waiting ? `; waiting ${P.waiting}` : ''}`);
|
|
107
|
-
for (const [k, v] of Object.entries(P.rules))
|
|
108
|
-
out(` ${k.padEnd(18)} ${(v ?? []).join(', ')}`);
|
|
109
|
-
};
|
|
110
|
-
// --- decisions and budgets ---
|
|
111
|
-
export const propose = (a, o) => {
|
|
112
|
-
const decider = opt(o, 'decider') ?? fail('--decider <id> is required: who decides (operator, or someone with authority in the hub contract)');
|
|
113
|
-
const r = Budget.propose(a, { text: textOf(o), decider, reviewers: words(opt(o, 'reviewers')), budget: opt(o, 'budget'), due: opt(o, 'due'),
|
|
114
|
-
supersedes: opt(o, 'supersedes'), files: list(o, 'attach').flatMap(attachments) });
|
|
115
|
-
out(`proposed ${short(r.id)} to ${r.to.join(', ') || 'the room'}; decider ${decider}${r.budget ? `, budget ${Budget.budgetText(r.budget)}` : ''}`);
|
|
116
|
-
};
|
|
117
|
-
export const stamp_ = (a, o) => {
|
|
118
|
-
const s = o._[1] ?? '';
|
|
119
|
-
if (!Budget.STAMPS.includes(s))
|
|
120
|
-
fail(`usage: stamp <proposal> ${Budget.STAMPS.join('|')} -m <reason>`);
|
|
121
|
-
const r = Budget.stamp(a, o._[0] ?? fail('name the proposal'), s, textOf(o));
|
|
122
|
-
out(`stamped ${short(r.proposal.id)} ${s}: ${short(r.id)}`);
|
|
123
|
-
};
|
|
124
|
-
export const decide = (a, o) => {
|
|
125
|
-
const d = o._[1] ?? '';
|
|
126
|
-
if (!Budget.DECISIONS.includes(d))
|
|
127
|
-
fail(`usage: decide <proposal> ${Budget.DECISIONS.join('|')} -m <reason>`);
|
|
128
|
-
const r = Budget.decide(a, o._[0] ?? fail('name the proposal'), d, textOf(o));
|
|
129
|
-
out(`${d} ${short(r.proposal.id)}: ${short(r.id)}${r.budget ? `; grant ${short(r.id)} with ${Budget.budgetText(r.budget)}. Work spends it with --grant ${short(r.id)}` : ''}`);
|
|
130
|
-
};
|
|
131
|
-
export const proposals = (a, o) => {
|
|
132
|
-
const { proposals: ps, views } = Budget.proposals(a, { all: flag(o, 'all') });
|
|
133
|
-
if (flag(o, 'json'))
|
|
134
|
-
return dump(views);
|
|
135
|
-
if (!ps.length)
|
|
136
|
-
return out(flag(o, 'all') ? 'no proposals' : 'no open proposals (proposals --all for everything)');
|
|
137
|
-
for (const x of ps) {
|
|
138
|
-
const st = x.reviewers.map(r => `${r}:${x.stamps[r]?.stamp ?? '-'}`).join(' ');
|
|
139
|
-
out(`${short(x.proposal.id)} ${x.state.padEnd(10)} ${x.proposal.from} → ${x.decider}${x.budget ? ` [${Budget.budgetText(x.budget)}]` : ''}${st ? ` ${st}` : ''} ${x.proposal.subject}`);
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
export const grants = (a, o) => {
|
|
143
|
-
const gs = Budget.grants(a);
|
|
144
|
-
if (flag(o, 'json'))
|
|
145
|
-
return dump(gs);
|
|
146
|
-
if (!gs.length)
|
|
147
|
-
return out('no grants');
|
|
148
|
-
for (const g of gs) {
|
|
149
|
-
const u = g.usage;
|
|
150
|
-
out(`${short(g.grant)} ${g.revoked ? 'revoked ' : u.left ? 'active ' : 'spent '} runs ${u.runs}/${g.budget.runs}, open ${u.open}${u.uncertain ? `, uncertain ${u.uncertain}` : ''}, ${u.seconds}s used, ≤${g.budget['run-seconds']}s a run, concurrency ${g.budget.concurrency} ${g.subject}`);
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
// What the session may do on its own: the recorded scope; without one, in a room with a quorum the room's work for it,
|
|
154
|
-
// in any other what the operator accepts when asked.
|
|
155
|
-
export const scopeLine = (s, quorum = false) => s.scope
|
|
156
|
-
?? (quorum ? 'none recorded; the room\'s work for you, split with the other members' : 'none recorded; ask the operator what to accept');
|
|
157
|
-
// The line that keeps an agent of a room waiting for its quorum from doing anything yet.
|
|
158
|
-
export const waiting = (room, st) => `waiting: room ${room} waits for a quorum of ${st.quorum} agents and has ${st.agents}; nothing to do yet, end the turn. Its work starts by itself at the quorum`;
|
|
159
|
-
//# sourceMappingURL=shared.js.map
|
package/target/esm/cli/skill.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
// skill: installs the agent skill for Claude Code, Codex and Cursor.
|
|
2
|
-
import fs from 'node:fs';
|
|
3
|
-
import os from 'node:os';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import { about } from '../app/context.js';
|
|
6
|
-
import { fail } from '../lib/index.js';
|
|
7
|
-
import { flag, out } from './args.js';
|
|
8
|
-
// --- skill ---
|
|
9
|
-
export const SKILL = path.join(about().resources, 'skill', 'ringi');
|
|
10
|
-
export const skillTargets = (project) => {
|
|
11
|
-
const base = project ? process.cwd() : os.homedir();
|
|
12
|
-
return [path.join(base, '.claude', 'skills', 'ringi'), path.join(base, '.agents', 'skills', 'ringi')];
|
|
13
|
-
};
|
|
14
|
-
export const skill = (o) => {
|
|
15
|
-
const sub = o._[0];
|
|
16
|
-
const same = (dir) => {
|
|
17
|
-
try {
|
|
18
|
-
return fs.readFileSync(path.join(dir, 'SKILL.md'), 'utf8') === fs.readFileSync(path.join(SKILL, 'SKILL.md'), 'utf8');
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
if (sub === 'install') {
|
|
25
|
-
for (const dir of skillTargets(flag(o, 'project'))) {
|
|
26
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
27
|
-
fs.cpSync(SKILL, dir, { recursive: true });
|
|
28
|
-
out(`installed ${dir}`);
|
|
29
|
-
}
|
|
30
|
-
return out(`ringi's home is ${about().home}. A sandboxed agent must be allowed to write it; for Codex, the narrowest grant is:
|
|
31
|
-
[sandbox_workspace_write]
|
|
32
|
-
writable_roots = ["${about().home}"]
|
|
33
|
-
in ~/.codex/config.toml. Otherwise agents re-run ringi commands with sandbox escalation, which you approve.`);
|
|
34
|
-
}
|
|
35
|
-
if (sub === 'status') {
|
|
36
|
-
for (const p of [false, true])
|
|
37
|
-
for (const dir of skillTargets(p))
|
|
38
|
-
out(`${same(dir) ? 'ok ' : fs.existsSync(dir) ? 'outdated' : 'missing '} ${dir}`);
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
if (sub === 'uninstall') {
|
|
42
|
-
for (const dir of skillTargets(flag(o, 'project'))) {
|
|
43
|
-
if (!fs.existsSync(dir))
|
|
44
|
-
continue;
|
|
45
|
-
fs.rmSync(dir, { recursive: true });
|
|
46
|
-
out(`removed ${dir}`);
|
|
47
|
-
}
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (sub === 'show')
|
|
51
|
-
return void process.stdout.write(fs.readFileSync(path.join(SKILL, 'SKILL.md'), 'utf8'));
|
|
52
|
-
fail('usage: ringi skill install [--project] | uninstall [--project] | status | show');
|
|
53
|
-
};
|
|
54
|
-
//# sourceMappingURL=skill.js.map
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
// decide: the extension for decisions and budgets (capability `decisions/1`, docs/spec/decisions-1.md). A proposal circulates
|
|
2
|
-
// to named reviewers, who stamp it; only the named decider, holding authority from the hub's contract, decides. An
|
|
3
|
-
// approval that carries a budget is a grant; work spends against it, and the runner that starts model runs writes
|
|
4
|
-
// the usage receipts. Everything here is a pure fold over messages; nothing trusts a model's own report.
|
|
5
|
-
import { ID_RE, one, ordered } from '../protocol/index.js';
|
|
6
|
-
import { fail } from '../lib/index.js';
|
|
7
|
-
export const CAPABILITY = 'decisions/1';
|
|
8
|
-
export const ROOT = 'operator';
|
|
9
|
-
export const BUDGET_KEYS = ['runs', 'run-seconds', 'concurrency'];
|
|
10
|
-
export const STAMPS = ['approve', 'object', 'abstain'];
|
|
11
|
-
export const DECISIONS = ['approved', 'rejected', 'revoked'];
|
|
12
|
-
const ids = (v) => v === null ? [] : [...new Set(v.split(',').map(x => x.trim()).filter(Boolean))];
|
|
13
|
-
// `runs=5, run-seconds=600, concurrency=1`; undefined if malformed. `runs` is required: a budget without a run count
|
|
14
|
-
// bounds nothing; a zero run time or concurrency would disable the bound it names.
|
|
15
|
-
export const parseBudget = (s) => {
|
|
16
|
-
if (s === null || s === undefined)
|
|
17
|
-
return null;
|
|
18
|
-
const b = {};
|
|
19
|
-
for (const part of String(s).split(',').map(x => x.trim()).filter(Boolean)) {
|
|
20
|
-
const m = /^([a-z][a-z-]*)=(\d{1,9})$/.exec(part);
|
|
21
|
-
if (!m || !BUDGET_KEYS.includes(m[1]) || m[1] in b)
|
|
22
|
-
return undefined;
|
|
23
|
-
b[m[1]] = Number(m[2]);
|
|
24
|
-
}
|
|
25
|
-
if (!('runs' in b) || b['run-seconds'] === 0 || b.concurrency === 0)
|
|
26
|
-
return undefined;
|
|
27
|
-
return { 'run-seconds': 1800, concurrency: 1, ...b };
|
|
28
|
-
};
|
|
29
|
-
export const budgetText = (b) => BUDGET_KEYS.map(k => `${k}=${b[k]}`).join(', ');
|
|
30
|
-
// Relative (`90m`, `2h`, `3d`) or an ISO 8601 time → ISO UTC to the second.
|
|
31
|
-
export const parseDue = (s) => {
|
|
32
|
-
const rel = /^(\d{1,6})([mhd])$/.exec(s);
|
|
33
|
-
const t = rel ? Date.now() + Number(rel[1]) * { m: 60e3, h: 3600e3, d: 86400e3 }[rel[2]] : Date.parse(s);
|
|
34
|
-
if (!Number.isFinite(t))
|
|
35
|
-
fail(`--due takes 90m, 2h, 3d or an ISO time, not ${s}`);
|
|
36
|
-
return new Date(t).toISOString().slice(0, 19) + 'Z';
|
|
37
|
-
};
|
|
38
|
-
// Extension trailers are part of a record's validity: a malformed decision record routes nowhere. Returns the reason.
|
|
39
|
-
export const check = (m, isRef) => {
|
|
40
|
-
if (m.bad)
|
|
41
|
-
return null;
|
|
42
|
-
for (const k of ['decider', 'reviewers', 'due', 'budget', 'supersedes', 'stamp', 'decision', 'control', 'grant', 'usage', 'run', 'seconds', 'exit']) {
|
|
43
|
-
if ((m.trailers[k]?.length ?? 0) > 1)
|
|
44
|
-
return `duplicate ${k}`;
|
|
45
|
-
}
|
|
46
|
-
const ref = (k) => one(m, k) === null || isRef(one(m, k));
|
|
47
|
-
if (!ref('grant'))
|
|
48
|
-
return 'malformed Grant';
|
|
49
|
-
if (!ref('control'))
|
|
50
|
-
return 'malformed Control';
|
|
51
|
-
if (one(m, 'budget') !== null && !parseBudget(one(m, 'budget')))
|
|
52
|
-
return 'malformed Budget';
|
|
53
|
-
if (m.kind === 'proposal') {
|
|
54
|
-
if (!ID_RE.test(one(m, 'decider') ?? ''))
|
|
55
|
-
return 'proposal without a valid Decider';
|
|
56
|
-
if (!ids(one(m, 'reviewers')).every(x => ID_RE.test(x)))
|
|
57
|
-
return 'malformed Reviewers';
|
|
58
|
-
if (one(m, 'due') !== null && !Number.isFinite(Date.parse(one(m, 'due'))))
|
|
59
|
-
return 'malformed Due';
|
|
60
|
-
if (!ref('supersedes'))
|
|
61
|
-
return 'malformed Supersedes';
|
|
62
|
-
}
|
|
63
|
-
if (m.kind === 'stamp' && (!m.re || !STAMPS.includes(one(m, 'stamp') ?? '')))
|
|
64
|
-
return 'stamp without Re or a valid Stamp';
|
|
65
|
-
if (m.kind === 'decision' && (!m.re || !DECISIONS.includes(one(m, 'decision') ?? '')))
|
|
66
|
-
return 'decision without Re or a valid Decision';
|
|
67
|
-
if (m.kind === 'usage') {
|
|
68
|
-
if (!isRef(one(m, 'grant') ?? '') || !['reserve', 'settle'].includes(one(m, 'usage') ?? '') || !/^[A-Za-z0-9._:-]{1,128}$/.test(one(m, 'run') ?? ''))
|
|
69
|
-
return 'malformed usage receipt';
|
|
70
|
-
if (one(m, 'usage') === 'settle' && !/^\d{1,9}$/.test(one(m, 'seconds') ?? ''))
|
|
71
|
-
return 'usage settle without Seconds';
|
|
72
|
-
}
|
|
73
|
-
return null;
|
|
74
|
-
};
|
|
75
|
-
// The root always may; anyone else only within the authority table, and never on their own proposal.
|
|
76
|
-
export const mayDecide = (authority, decider, proposer, budget) => {
|
|
77
|
-
if (decider === ROOT)
|
|
78
|
-
return true;
|
|
79
|
-
if (decider === proposer)
|
|
80
|
-
return false;
|
|
81
|
-
const cap = authority?.decide?.[decider];
|
|
82
|
-
if (!cap)
|
|
83
|
-
return false;
|
|
84
|
-
if (!budget)
|
|
85
|
-
return true;
|
|
86
|
-
return BUDGET_KEYS.every(k => Number.isFinite(cap[k]) && budget[k] <= cap[k]);
|
|
87
|
-
};
|
|
88
|
-
// A decision names the room's control commit it was made under (`Control`); its authority is the table in effect
|
|
89
|
-
// there. A commit that does not exist yet cannot be named, so a later contract never promotes or demotes a decision.
|
|
90
|
-
const authorized = (m, p, decider, budget, authorityAt) => {
|
|
91
|
-
if (m.from === ROOT)
|
|
92
|
-
return true;
|
|
93
|
-
const table = authorityAt(one(m, 'control'));
|
|
94
|
-
return m.from === decider && !!table && mayDecide(table, decider, p.from, budget);
|
|
95
|
-
};
|
|
96
|
-
// Everything about one proposal, folded over the messages that answer it, in thread order.
|
|
97
|
-
export const proposalOf = (all, p, authorityAt, now = Date.now() / 1000) => {
|
|
98
|
-
const decider = one(p, 'decider');
|
|
99
|
-
const reviewers = ids(one(p, 'reviewers'));
|
|
100
|
-
const budget = parseBudget(one(p, 'budget')) ?? null;
|
|
101
|
-
const due = one(p, 'due') ? Date.parse(one(p, 'due')) / 1000 : null;
|
|
102
|
-
// A revision supersedes only when its author is the proposer or the root.
|
|
103
|
-
const revisions = ordered([...all.values()].filter(m => !m.bad && m.kind === 'proposal' && one(m, 'supersedes') === p.id && (m.from === p.from || m.from === ROOT)));
|
|
104
|
-
const answers = ordered([...all.values()].filter(m => !m.bad && m.reId === p.id && (m.kind === 'stamp' || m.kind === 'decision')));
|
|
105
|
-
const stamps = {};
|
|
106
|
-
let decision = null;
|
|
107
|
-
let revoked = null;
|
|
108
|
-
const superseded = revisions[0] ?? null;
|
|
109
|
-
const revocation = (m) => !revoked && one(m, 'decision') === 'revoked' && (m.from === decider || m.from === ROOT);
|
|
110
|
-
// A record after the superseding revision in thread order no longer applies to this revision.
|
|
111
|
-
for (const m of ordered([...answers, ...(superseded ? [superseded] : [])])) {
|
|
112
|
-
if (m === superseded)
|
|
113
|
-
break;
|
|
114
|
-
// A reviewer's latest stamp counts; its position relative to the decision is only a same-second tie.
|
|
115
|
-
if (m.kind === 'stamp' && reviewers.includes(m.from))
|
|
116
|
-
stamps[m.from] = { stamp: one(m, 'stamp'), id: m.id, reason: m.subject };
|
|
117
|
-
if (m.kind !== 'decision')
|
|
118
|
-
continue;
|
|
119
|
-
const d = one(m, 'decision');
|
|
120
|
-
if (!decision && d !== 'revoked' && m.from === decider && authorized(m, p, decider, budget, authorityAt))
|
|
121
|
-
decision = { decision: d, id: m.id, by: m.from, time: m.time };
|
|
122
|
-
else if (decision?.decision === 'approved' && revocation(m))
|
|
123
|
-
revoked = { id: m.id, by: m.from, time: m.time };
|
|
124
|
-
}
|
|
125
|
-
// After a superseding revision, only a revocation of an earlier approval still applies to this one.
|
|
126
|
-
if (superseded && decision?.decision === 'approved')
|
|
127
|
-
for (const m of answers)
|
|
128
|
-
if (revocation(m))
|
|
129
|
-
revoked = { id: m.id, by: m.from, time: m.time };
|
|
130
|
-
const missing = reviewers.filter(r => !stamps[r]);
|
|
131
|
-
const state = revoked ? 'revoked' : decision ? decision.decision : superseded ? 'superseded' : due && now > due ? 'overdue' : 'open';
|
|
132
|
-
const grant = decision?.decision === 'approved' && budget ? { id: decision.id, budget, proposal: p, revoked: !!revoked } : null;
|
|
133
|
-
return { proposal: p, decider, reviewers, budget, due, stamps, missing, decision, revoked, superseded, state, grant };
|
|
134
|
-
};
|
|
135
|
-
export const proposals = (all, authorityAt) => [...all.values()].filter(m => !m.bad && m.kind === 'proposal').map(p => proposalOf(all, p, authorityAt));
|
|
136
|
-
export const grantOf = (all, authorityAt, id) => {
|
|
137
|
-
const d = all.get(id);
|
|
138
|
-
if (!d || d.bad || d.kind !== 'decision' || !d.reId || !all.get(d.reId))
|
|
139
|
-
return null;
|
|
140
|
-
const g = proposalOf(all, all.get(d.reId), authorityAt).grant;
|
|
141
|
-
return g?.id === id ? g : null;
|
|
142
|
-
};
|
|
143
|
-
// The receipts a grant's ledger counts, in thread order: every reservation, and for each run (its runner and Run id)
|
|
144
|
-
// the first settlement after its reservation, as the first decision counts. A settlement of no reserved run counts
|
|
145
|
-
// nothing.
|
|
146
|
-
const ledger = (all, grant) => {
|
|
147
|
-
const reserves = [], settled = new Map(), reserved = new Set();
|
|
148
|
-
for (const m of ordered([...all.values()].filter(m => !m.bad && m.kind === 'usage' && one(m, 'grant') === grant.id))) {
|
|
149
|
-
const run = `${m.from}/${one(m, 'run')}`;
|
|
150
|
-
if (one(m, 'usage') === 'reserve') {
|
|
151
|
-
reserves.push(m);
|
|
152
|
-
reserved.add(run);
|
|
153
|
-
}
|
|
154
|
-
else if (reserved.has(run) && !settled.has(run))
|
|
155
|
-
settled.set(run, m);
|
|
156
|
-
}
|
|
157
|
-
return { reserves, settled };
|
|
158
|
-
};
|
|
159
|
-
// Whether a receipt counts: its Grant names a grant, and that grant's ledger holds it.
|
|
160
|
-
export const counted = (all, authorityAt, m) => {
|
|
161
|
-
const g = !m.bad && m.kind === 'usage' ? grantOf(all, authorityAt, one(m, 'grant') ?? '') : null;
|
|
162
|
-
if (!g)
|
|
163
|
-
return false;
|
|
164
|
-
const { reserves, settled } = ledger(all, g);
|
|
165
|
-
return reserves.includes(m) || [...settled.values()].includes(m);
|
|
166
|
-
};
|
|
167
|
-
// Usage from the runners' receipts: every reservation is a run, settled or not; an unsettled one is open while its
|
|
168
|
-
// run could still be going, and uncertain after that.
|
|
169
|
-
export const usageOf = (all, grant, now = Date.now() / 1000) => {
|
|
170
|
-
const { reserves, settled } = ledger(all, grant);
|
|
171
|
-
let seconds = 0;
|
|
172
|
-
for (const m of settled.values())
|
|
173
|
-
seconds += Number(one(m, 'seconds'));
|
|
174
|
-
const unsettled = reserves.filter(m => !settled.has(`${m.from}/${one(m, 'run')}`));
|
|
175
|
-
const open = unsettled.filter(m => now - m.time <= grant.budget['run-seconds'] + 60);
|
|
176
|
-
return { runs: reserves.length, open: open.length, uncertain: unsettled.length - open.length, seconds, left: Math.max(0, grant.budget.runs - reserves.length) };
|
|
177
|
-
};
|
|
178
|
-
//# sourceMappingURL=decisions.js.map
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
// profile: what a task is, as data. ringi is a point of coordination, not a methodology: the states of a piece of
|
|
2
|
-
// work, which of them end it, and who may move it, assign it or label people in it are declared by a profile
|
|
3
|
-
// that lives in the hub (`profiles/<name>.json` on main) and is chosen per room. The A2A task model is one such
|
|
4
|
-
// profile (resources/profiles/a2a-1.json); a team or a framework brings its own (architect, reviewer, tester, …).
|
|
5
|
-
// This file interprets any profile; it knows no state, role or rule by name.
|
|
6
|
-
import { HEARTBEATS, ID_RE, TOKEN_RE, one, ordered } from '../protocol/index.js';
|
|
7
|
-
import { fail, strictJson } from '../lib/index.js';
|
|
8
|
-
export const PROFILE_SCHEMA = 'ringi-profile/1';
|
|
9
|
-
export const DEFAULT_PROFILE = 'a2a-1';
|
|
10
|
-
// A hub whose rooms may follow profiles other than the built-in A2A rules declares this capability, so that an older
|
|
11
|
-
// client, which knows only those rules, refuses it instead of misreading it.
|
|
12
|
-
export const PROFILES_CAPABILITY = 'profiles/1';
|
|
13
|
-
const PRINCIPAL_RE = /^(?:requester|assignee|member|role:[a-z][a-z0-9-]*|agent:[a-z0-9]+(?:[._-][a-z0-9]+)*)$/;
|
|
14
|
-
// A profile is refused, not guessed at, when it is not exactly what this schema describes.
|
|
15
|
-
export const parseProfile = (text, label) => {
|
|
16
|
-
const p = strictJson(text, label);
|
|
17
|
-
const bad = (why) => fail(`${label}: ${why}`);
|
|
18
|
-
if (p.schema !== PROFILE_SCHEMA)
|
|
19
|
-
bad(`schema ${String(p.schema)} is not ${PROFILE_SCHEMA}; upgrade ringi or fix the profile`);
|
|
20
|
-
if (!ID_RE.test(p.name ?? ''))
|
|
21
|
-
bad('a profile needs a name like team-flow-1');
|
|
22
|
-
if (!TOKEN_RE.test(p.opens ?? ''))
|
|
23
|
-
bad('`opens` names the Kind that opens a piece of work');
|
|
24
|
-
if (!Array.isArray(p.states) || !p.states.length || !p.states.every(s => TOKEN_RE.test(s)) || new Set(p.states).size !== p.states.length)
|
|
25
|
-
bad('`states` must be distinct tokens');
|
|
26
|
-
if (!p.states.includes(p.initial))
|
|
27
|
-
bad('`initial` must be one of the states');
|
|
28
|
-
if (!Array.isArray(p.terminal) || !p.terminal.every(s => p.states.includes(s)))
|
|
29
|
-
bad('`terminal` must list states');
|
|
30
|
-
if (p.waiting !== undefined && (!p.states.includes(p.waiting) || p.terminal.includes(p.waiting)))
|
|
31
|
-
bad('`waiting` must be a state that does not end the work');
|
|
32
|
-
if (!p.rules || typeof p.rules !== 'object')
|
|
33
|
-
bad('`rules` is required');
|
|
34
|
-
for (const [k, v] of Object.entries(p.rules)) {
|
|
35
|
-
if (!/^(?:assign|roles|grant|state:(?:\*|[a-z][a-z0-9-]*))$/.test(k))
|
|
36
|
-
bad(`unknown rule ${k}`);
|
|
37
|
-
if (k.startsWith('state:') && k !== 'state:*' && !p.states.includes(k.slice(6)))
|
|
38
|
-
bad(`rule ${k} names an unknown state`);
|
|
39
|
-
if (!Array.isArray(v) || v.length > 64 || !v.every(x => PRINCIPAL_RE.test(x)))
|
|
40
|
-
bad(`rule ${k} must list principals: requester, assignee, member, role:<label>, agent:<id>`);
|
|
41
|
-
}
|
|
42
|
-
return p;
|
|
43
|
-
};
|
|
44
|
-
const allows = (rule, who, t) => !!rule?.some(p => p === 'requester' ? who === t.requester
|
|
45
|
-
: p === 'assignee' ? t.assignees.includes(who)
|
|
46
|
-
: p === 'member' ? true
|
|
47
|
-
: p.startsWith('role:') ? t.roles[who] === p.slice(5)
|
|
48
|
-
: p === `agent:${who}`);
|
|
49
|
-
export const ruleFor = (profile, state) => profile.rules[`state:${state}`] ?? profile.rules['state:*'];
|
|
50
|
-
// A message belongs to the nearest work item on its Re chain, itself included.
|
|
51
|
-
export const taskFor = (all, m, profile) => {
|
|
52
|
-
for (let x = m, i = 0; x && i < 100000; x = x.reId ? all.get(x.reId) : undefined, i++)
|
|
53
|
-
if (x.kind === profile.opens && !x.bad)
|
|
54
|
-
return x;
|
|
55
|
-
return null;
|
|
56
|
-
};
|
|
57
|
-
// A work item folds over its messages in thread order. Every right is judged on the work as it was before the
|
|
58
|
-
// message, so a label given in a message authorizes nothing in that same message, while its holder may still hand it
|
|
59
|
-
// over and reassign in one reply. Opening sets the initial state and assignees (Assign, else To minus the opener; none
|
|
60
|
-
// for To: *). The first terminal state is final; assignment and labels may still change after it.
|
|
61
|
-
export const taskOf = (all, root, profile) => {
|
|
62
|
-
// Heartbeats never take part in work (§6), whatever trailers they carry.
|
|
63
|
-
const msgs = ordered([...all.values()].filter(m => !m.bad && !(m.kind && HEARTBEATS.has(m.kind)) && taskFor(all, m, profile) === root));
|
|
64
|
-
const t = { root, msgs, state: profile.initial, by: root.from, at: root.time, requester: root.from, roles: { ...root.roles },
|
|
65
|
-
assignees: root.assign ?? (root.to.includes('*') ? [] : root.to.filter(x => x !== root.from)), grant: one(root, 'grant'), effects: new Map() };
|
|
66
|
-
t.effects.set(root.id, ['opened', ...(root.assign ? ['assigned'] : [])]);
|
|
67
|
-
for (const m of msgs) {
|
|
68
|
-
if (m === root)
|
|
69
|
-
continue;
|
|
70
|
-
const before = { ...t, roles: { ...t.roles }, assignees: [...t.assignees] };
|
|
71
|
-
const fx = [];
|
|
72
|
-
if (one(m, 'grant') && allows(profile.rules.grant, m.from, before)) {
|
|
73
|
-
t.grant = one(m, 'grant');
|
|
74
|
-
fx.push('grant');
|
|
75
|
-
}
|
|
76
|
-
if (m.roles && allows(profile.rules.roles, m.from, before)) {
|
|
77
|
-
for (const [id, label] of Object.entries(m.roles))
|
|
78
|
-
label === 'none' ? delete t.roles[id] : t.roles[id] = label;
|
|
79
|
-
fx.push('roles');
|
|
80
|
-
}
|
|
81
|
-
if (m.assign && allows(profile.rules.assign, m.from, before)) {
|
|
82
|
-
t.assignees = m.assign;
|
|
83
|
-
fx.push('assigned');
|
|
84
|
-
}
|
|
85
|
-
if (m.state && !profile.terminal.includes(t.state) && profile.states.includes(m.state) && allows(ruleFor(profile, m.state), m.from, before)) {
|
|
86
|
-
Object.assign(t, { state: m.state, by: m.from, at: m.time });
|
|
87
|
-
fx.push(`state.${m.state}`);
|
|
88
|
-
}
|
|
89
|
-
if (fx.length)
|
|
90
|
-
t.effects.set(m.id, fx);
|
|
91
|
-
}
|
|
92
|
-
return t;
|
|
93
|
-
};
|
|
94
|
-
export const tasksIn = (all, profile) => [...all.values()].filter(m => m.kind === profile.opens && !m.bad).map(r => taskOf(all, r, profile));
|
|
95
|
-
export const isOpen = (t, profile) => !profile.terminal.includes(t.state);
|
|
96
|
-
//# sourceMappingURL=profiles.js.map
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
// signals: explicit markers of what happens in a room, beside the messages that carry it. Every effective transition
|
|
2
|
-
// (work opened, assigned, a state reached, a proposal, a counted stamp, the decision, a counted usage receipt) is also
|
|
3
|
-
// a signal of its author on the message that made it: in a git store an annotated tag `<author>.<signal>.<message12>`
|
|
4
|
-
// on that message's commit, with no text of its own, signed on a signed hub. The message's id keeps the name unique;
|
|
5
|
-
// the name, target, author and time are the tag itself. Signals are visible and checkable with the store's own tools
|
|
6
|
-
// (`git tag -v`, a forge's tag list and tag-push webhooks) and cheap to poll.
|
|
7
|
-
//
|
|
8
|
-
// The messages stay the truth. A signal is made only for a transition the fold actually counted (a State the author
|
|
9
|
-
// had no right to makes none). A reader checks every signal against its message and pins the stored object it
|
|
10
|
-
// accepted; a signal that disagrees, or an accepted one that changes or disappears, is an alarm. A signal missing
|
|
11
|
-
// after a crash between message and tag changes nothing and is restored with `signals --repair`.
|
|
12
|
-
//
|
|
13
|
-
// Marks are the second layer, in the same namespace: where attention is, not what was decided. `read` says a message
|
|
14
|
-
// reached its reader (made on delivery); `taken` says a member took a piece of work. A mark changes no state,
|
|
15
|
-
// assignment or budget. It is checked only for being possible: its target is an accepted message of the room, its
|
|
16
|
-
// actor a member; `read` only for a message addressed to the actor or to all, `taken` only for a message that opens
|
|
17
|
-
// work.
|
|
18
|
-
import * as D from './decisions.js';
|
|
19
|
-
import { taskFor, taskOf } from './profiles.js';
|
|
20
|
-
import { HIDDEN, one, visible } from '../protocol/index.js';
|
|
21
|
-
export const MARKS = ['read', 'taken'];
|
|
22
|
-
// A signal's name after its actor: the signal and the message's short id.
|
|
23
|
-
export const signalName = (id, signal) => `${signal}.${id.slice(0, 12)}`;
|
|
24
|
-
// Why the actor cannot put this mark on this message, or nothing when it can.
|
|
25
|
-
export const markWhy = (R, actor, m, mark) => !R.members[actor] ? `${actor} is not a member of ${R.name}`
|
|
26
|
-
: mark === 'read' ? (m.from === actor ? 'one does not read one\'s own message' : !visible(m, actor, HIDDEN) ? `the message is not delivered to ${actor}` : undefined)
|
|
27
|
-
: mark === 'taken' ? (m.kind !== R.profile.opens || m.bad ? `the message does not open work (${R.profile.opens})` : undefined)
|
|
28
|
-
: `unknown mark ${mark}`;
|
|
29
|
-
// The marks on each message that passed the check: target → mark → actors.
|
|
30
|
-
export const marksOn = (checked) => {
|
|
31
|
-
const by = new Map();
|
|
32
|
-
for (const c of checked) {
|
|
33
|
-
if (!c.ok || !MARKS.includes(c.signal))
|
|
34
|
-
continue;
|
|
35
|
-
const e = by.get(c.target) ?? {};
|
|
36
|
-
(e[c.signal] ??= []).push(c.actor);
|
|
37
|
-
by.set(c.target, e);
|
|
38
|
-
}
|
|
39
|
-
return by;
|
|
40
|
-
};
|
|
41
|
-
// The signals a message made, judged on the room as it is now (thread order is fixed, so this does not change).
|
|
42
|
-
export const effective = (R, all, m) => {
|
|
43
|
-
if (m.bad || m.invalid)
|
|
44
|
-
return [];
|
|
45
|
-
const s = [];
|
|
46
|
-
const work = taskFor(all, m, R.profile);
|
|
47
|
-
if (work)
|
|
48
|
-
for (const fx of taskOf(all, work, R.profile).effects.get(m.id) ?? [])
|
|
49
|
-
if (fx === 'opened' || fx === 'assigned' || fx.startsWith('state.'))
|
|
50
|
-
s.push(fx);
|
|
51
|
-
if (m.kind === 'proposal')
|
|
52
|
-
s.push('proposed');
|
|
53
|
-
if (m.kind === 'usage' && D.counted(all, R.authorityAt, m))
|
|
54
|
-
s.push(`usage.${one(m, 'usage')}`);
|
|
55
|
-
const p = m.reId ? all.get(m.reId) : undefined;
|
|
56
|
-
if (p?.kind === 'proposal' && !p.bad) {
|
|
57
|
-
const info = D.proposalOf(all, p, R.authorityAt);
|
|
58
|
-
if (m.kind === 'stamp' && info.reviewers.includes(m.from))
|
|
59
|
-
s.push(`stamp.${one(m, 'stamp')}`);
|
|
60
|
-
if (m.kind === 'decision' && info.decision?.id === m.id)
|
|
61
|
-
s.push(`decision.${info.decision.decision}`);
|
|
62
|
-
if (m.kind === 'decision' && info.revoked?.id === m.id)
|
|
63
|
-
s.push('decision.revoked');
|
|
64
|
-
}
|
|
65
|
-
return s;
|
|
66
|
-
};
|
|
67
|
-
// A signal holds when its author made it, it is named after and points at a message of its author in this room, and
|
|
68
|
-
// that message made exactly this signal.
|
|
69
|
-
export const check = (R, all, records) => records.map(x => {
|
|
70
|
-
const dot = x.name.lastIndexOf('.');
|
|
71
|
-
const id = x.name.slice(dot + 1);
|
|
72
|
-
const signal = x.name.slice(0, dot);
|
|
73
|
-
const m = all.get(x.target);
|
|
74
|
-
const what = () => {
|
|
75
|
-
if (!x.target)
|
|
76
|
-
return 'is not an annotated tag on a message';
|
|
77
|
-
if (x.tagger !== x.actor)
|
|
78
|
-
return `was made by ${x.tagger}, not ${x.actor}`;
|
|
79
|
-
if (id.length !== 12 || !x.target.startsWith(id))
|
|
80
|
-
return 'is named after another message';
|
|
81
|
-
if (!m)
|
|
82
|
-
return 'points at no accepted message of this room';
|
|
83
|
-
if (MARKS.includes(signal)) {
|
|
84
|
-
const why = markWhy(R, x.actor, m, signal);
|
|
85
|
-
if (why)
|
|
86
|
-
return why;
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
if (m.from !== x.actor)
|
|
90
|
-
return `points at a message of ${m.from}`;
|
|
91
|
-
if (!effective(R, all, m).includes(signal))
|
|
92
|
-
return `its message did not make ${signal}`;
|
|
93
|
-
}
|
|
94
|
-
// A signal is its name and its target; any text besides a signature is not one.
|
|
95
|
-
if (x.text !== '')
|
|
96
|
-
return 'carries text; a signal has none';
|
|
97
|
-
return undefined;
|
|
98
|
-
};
|
|
99
|
-
const why = what();
|
|
100
|
-
return { ref: x.ref, actor: x.actor, signal, target: x.target, ok: !why, why };
|
|
101
|
-
});
|
|
102
|
-
// A signal's identity in any store and after an archive: its tag's name `<actor>.<signal>.<message12>`. Pins an older
|
|
103
|
-
// reader kept as `<actor>/<message>.<signal>`, or under a full ref ending so, read the same way.
|
|
104
|
-
const keyOf = (ref) => {
|
|
105
|
-
const parts = ref.split('/'), last = parts.at(-1);
|
|
106
|
-
const old = /^([0-9a-f]{40,64})\.(.+)$/.exec(last);
|
|
107
|
-
return old && parts.length >= 2 ? `${parts.at(-2)}.${old[2]}.${old[1].slice(0, 12)}` : last;
|
|
108
|
-
};
|
|
109
|
-
// A reader's pins: the stored object of each signal it accepted. A changed or vanished one is an alarm.
|
|
110
|
-
export const pins = (records, checked, accepted = {}) => {
|
|
111
|
-
const now = new Map(records.map(x => [`${x.actor}.${x.name}`, x]));
|
|
112
|
-
const alarms = [];
|
|
113
|
-
const next = {};
|
|
114
|
-
for (const [k, object] of Object.entries(accepted)) {
|
|
115
|
-
const key = keyOf(k), x = now.get(key);
|
|
116
|
-
// Two old pins of one signal (its live and its archived ref) that disagree: keep the first as accepted and the
|
|
117
|
-
// other under its own ref as evidence, so the conflict is reported on every read until it is resolved.
|
|
118
|
-
if (key in next && next[key] !== object) {
|
|
119
|
-
alarms.push(`signal ${key} has two different accepted objects (${next[key]} and ${object})`);
|
|
120
|
-
next[k] = object;
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
next[key] = object;
|
|
124
|
-
if (!x)
|
|
125
|
-
alarms.push(`signal ${key} was removed after it was accepted`);
|
|
126
|
-
else if (x.object !== object)
|
|
127
|
-
alarms.push(`signal ${x.ref} was replaced after it was accepted`);
|
|
128
|
-
}
|
|
129
|
-
for (const c of checked)
|
|
130
|
-
if (c.ok && !next[keyOf(c.ref)])
|
|
131
|
-
next[keyOf(c.ref)] = now.get(keyOf(c.ref)).object;
|
|
132
|
-
return { accepted: next, alarms };
|
|
133
|
-
};
|
|
134
|
-
//# sourceMappingURL=signals.js.map
|