@idleware/ringi 0.7.2 → 0.8.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 (201) hide show
  1. package/README.md +18 -11
  2. package/package.json +1 -1
  3. package/src/main/resources/skill/ringi/SKILL.md +3 -4
  4. package/target/dts/adapters/{transport-git → store-git}/branches.d.ts +1 -3
  5. package/target/dts/adapters/{transport-git → store-git}/index.d.ts +0 -1
  6. package/target/dts/adapters/store-git/marks.d.ts +21 -0
  7. package/target/dts/adapters/{transport-git → store-git}/remote/push.d.ts +0 -1
  8. package/target/dts/adapters/store-git/remote/stream-check.d.ts +12 -0
  9. package/target/dts/adapters/store-git/remote/stream-control.d.ts +8 -0
  10. package/target/dts/adapters/store-git/remote/stream-facts.d.ts +4 -0
  11. package/target/dts/adapters/store-git/remote/streams.d.ts +31 -0
  12. package/target/dts/adapters/store-git/remote/sync-streams.d.ts +2 -0
  13. package/target/dts/adapters/{transport-git → store-git}/remote/types.d.ts +5 -4
  14. package/target/dts/adapters/{transport-git → store-git}/remote.d.ts +1 -4
  15. package/target/dts/adapters/{transport-git → store-git}/repo.d.ts +3 -2
  16. package/target/dts/adapters/{transport-git → store-git}/signing.d.ts +0 -1
  17. package/target/dts/clients/cli/operator/hub-commands.d.ts +0 -2
  18. package/target/dts/clients/cli/operator/index.d.ts +1 -1
  19. package/target/dts/clients/cli/operator/sessions.d.ts +0 -1
  20. package/target/dts/clients/cli/operator/where-format.d.ts +1 -1
  21. package/target/dts/clients/cli/shared/index.d.ts +2 -2
  22. package/target/dts/clients/cli/shared/messages.d.ts +0 -1
  23. package/target/dts/clients/cli/shared/profile.d.ts +0 -1
  24. package/target/dts/clients/cli/skill/index.d.ts +2 -1
  25. package/target/dts/core/agents/overview.d.ts +4 -7
  26. package/target/dts/core/agents/sessions/index.d.ts +0 -1
  27. package/target/dts/core/agents/sessions/join.d.ts +1 -2
  28. package/target/dts/core/hub/history/index.d.ts +1 -10
  29. package/target/dts/core/hub/ports/store.d.ts +35 -23
  30. package/target/dts/core/hub/rooms/address.d.ts +6 -0
  31. package/target/dts/core/hub/rooms/adoption.d.ts +7 -0
  32. package/target/dts/core/hub/rooms/compat.d.ts +3 -1
  33. package/target/dts/core/hub/rooms/contracts.d.ts +16 -0
  34. package/target/dts/core/hub/rooms/hubs.d.ts +3 -3
  35. package/target/dts/core/hub/rooms/index.d.ts +5 -6
  36. package/target/dts/core/hub/rooms/room-catalogue.d.ts +9 -0
  37. package/target/dts/core/hub/rooms/room-life.d.ts +10 -0
  38. package/target/dts/core/hub/rooms/room-view.d.ts +3 -0
  39. package/target/dts/core/hub/rooms/rooms.d.ts +4 -2
  40. package/target/dts/core/hub/signals/check.d.ts +2 -2
  41. package/target/dts/core/hub/signals/model.d.ts +2 -10
  42. package/target/dts/core/hub/signals/pins.d.ts +2 -2
  43. package/target/dts/core/hub/usecases/config.d.ts +0 -1
  44. package/target/dts/core/hub/usecases/context.d.ts +1 -2
  45. package/target/dts/core/hub/usecases/hubs.d.ts +1 -8
  46. package/target/dts/core/hub/usecases/invite.d.ts +12 -0
  47. package/target/dts/core/hub/usecases/room.d.ts +0 -1
  48. package/target/dts/core/hub/usecases/rooms.d.ts +9 -7
  49. package/target/dts/core/hub/usecases/roster.d.ts +1 -2
  50. package/target/dts/core/hub/work/index.d.ts +0 -1
  51. package/target/dts/index.d.ts +1 -1
  52. package/target/esm/adapters/{tool-claude → agent-claude}/index.js +2 -2
  53. package/target/esm/adapters/{tool-codex → agent-codex}/index.js +2 -2
  54. package/target/esm/adapters/{tool-cursor → agent-cursor}/index.js +1 -1
  55. package/target/esm/adapters/{tool-traces → agent-traces}/index.js +1 -1
  56. package/target/esm/adapters/state-fs/index.js +2 -2
  57. package/target/esm/adapters/{transport-git → store-git}/branches.js +21 -27
  58. package/target/esm/adapters/{transport-git → store-git}/index.js +10 -28
  59. package/target/esm/adapters/store-git/marks.js +86 -0
  60. package/target/esm/adapters/{transport-git → store-git}/remote/commits.js +3 -1
  61. package/target/esm/adapters/{transport-git → store-git}/remote/git.js +8 -1
  62. package/target/esm/adapters/{transport-git → store-git}/remote/keys.js +8 -3
  63. package/target/esm/adapters/{transport-git → store-git}/remote/push-retry.js +24 -6
  64. package/target/esm/adapters/store-git/remote/push-validate.js +19 -0
  65. package/target/esm/adapters/{transport-git → store-git}/remote/push.js +13 -14
  66. package/target/esm/adapters/store-git/remote/stream-check.js +44 -0
  67. package/target/esm/adapters/store-git/remote/stream-control.js +33 -0
  68. package/target/esm/adapters/store-git/remote/stream-facts.js +40 -0
  69. package/target/esm/adapters/store-git/remote/streams.js +76 -0
  70. package/target/esm/adapters/store-git/remote/sync-streams.js +28 -0
  71. package/target/esm/adapters/store-git/remote/sync.js +59 -0
  72. package/target/esm/adapters/{transport-git → store-git}/remote/types.js +0 -3
  73. package/target/esm/adapters/{transport-git → store-git}/remote.js +1 -4
  74. package/target/esm/adapters/{transport-git → store-git}/repo.js +42 -4
  75. package/target/esm/adapters/{transport-git → store-git}/signing.js +1 -9
  76. package/target/esm/adapters/store-git/transport.js +60 -0
  77. package/target/esm/clients/cli/agent/index.js +1 -1
  78. package/target/esm/clients/cli/agent/session.js +10 -10
  79. package/target/esm/clients/cli/commands.js +5 -5
  80. package/target/esm/clients/cli/context.js +1 -1
  81. package/target/esm/clients/cli/help.js +15 -21
  82. package/target/esm/clients/cli/operator/heartbeat-format.js +1 -1
  83. package/target/esm/clients/cli/operator/heartbeat.js +1 -2
  84. package/target/esm/clients/cli/operator/hub-commands.js +6 -19
  85. package/target/esm/clients/cli/operator/hub.js +2 -2
  86. package/target/esm/clients/cli/operator/index.js +2 -2
  87. package/target/esm/clients/cli/operator/room.js +25 -32
  88. package/target/esm/clients/cli/operator/sessions.js +4 -22
  89. package/target/esm/clients/cli/operator/where-format.js +2 -1
  90. package/target/esm/clients/cli/operator/where.js +5 -7
  91. package/target/esm/clients/cli/shared/index.js +2 -2
  92. package/target/esm/clients/cli/shared/messages.js +2 -12
  93. package/target/esm/clients/cli/shared/profile.js +1 -6
  94. package/target/esm/clients/cli/skill/index.js +14 -19
  95. package/target/esm/composition/index.js +4 -4
  96. package/target/esm/core/agents/heartbeat/pulse.js +4 -4
  97. package/target/esm/core/agents/overview.js +13 -25
  98. package/target/esm/core/agents/sessions/binding.js +1 -1
  99. package/target/esm/core/agents/sessions/index.js +3 -2
  100. package/target/esm/core/agents/sessions/join.js +17 -9
  101. package/target/esm/core/agents/sessions/resume.js +3 -6
  102. package/target/esm/core/hub/capabilities.js +1 -4
  103. package/target/esm/core/hub/history/index.js +23 -13
  104. package/target/esm/core/hub/ports/store.js +2 -2
  105. package/target/esm/core/hub/rooms/address.js +18 -0
  106. package/target/esm/core/hub/rooms/adoption.js +32 -0
  107. package/target/esm/core/hub/rooms/compat.js +39 -14
  108. package/target/esm/core/hub/rooms/contracts.js +62 -0
  109. package/target/esm/core/hub/rooms/hubs.js +33 -56
  110. package/target/esm/core/hub/rooms/index.js +2 -2
  111. package/target/esm/core/hub/rooms/messages.js +6 -6
  112. package/target/esm/core/hub/rooms/room-catalogue.js +31 -0
  113. package/target/esm/core/hub/rooms/room-life.js +59 -0
  114. package/target/esm/core/hub/rooms/room-view.js +39 -0
  115. package/target/esm/core/hub/rooms/rooms.js +26 -37
  116. package/target/esm/core/hub/signals/check.js +21 -26
  117. package/target/esm/core/hub/signals/index.js +10 -10
  118. package/target/esm/core/hub/signals/model.js +0 -2
  119. package/target/esm/core/hub/signals/pins.js +44 -16
  120. package/target/esm/core/hub/signals/write.js +8 -10
  121. package/target/esm/core/hub/usecases/actor.js +1 -1
  122. package/target/esm/core/hub/usecases/config.js +2 -2
  123. package/target/esm/core/hub/usecases/context.js +5 -8
  124. package/target/esm/core/hub/usecases/hubs.js +16 -33
  125. package/target/esm/core/hub/usecases/invite.js +26 -0
  126. package/target/esm/core/hub/usecases/room.js +4 -5
  127. package/target/esm/core/hub/usecases/rooms.js +40 -35
  128. package/target/esm/core/hub/usecases/roster.js +12 -21
  129. package/target/esm/core/hub/usecases/send.js +10 -6
  130. package/target/esm/core/hub/work/parse.js +1 -1
  131. package/target/esm/lib/fail.js +2 -2
  132. package/target/dts/adapters/transport-git/marks.d.ts +0 -20
  133. package/target/dts/adapters/transport-git/remote/bootstrap.d.ts +0 -7
  134. package/target/dts/adapters/transport-git/remote/heartbeat-name.d.ts +0 -6
  135. package/target/dts/adapters/transport-git/remote/heartbeat-object.d.ts +0 -10
  136. package/target/dts/adapters/transport-git/remote/heartbeat-push.d.ts +0 -2
  137. package/target/dts/adapters/transport-git/remote/heartbeat.d.ts +0 -7
  138. package/target/dts/adapters/transport-git/remote/signals.d.ts +0 -15
  139. package/target/dts/adapters/transport-git/remote/sync-heartbeat.d.ts +0 -2
  140. package/target/dts/adapters/transport-git/remote/sync-rooms.d.ts +0 -6
  141. package/target/dts/adapters/transport-git/remote/sync-tags.d.ts +0 -8
  142. package/target/dts/adapters/transport-git/tags.d.ts +0 -15
  143. package/target/dts/clients/cli/skill/targets.d.ts +0 -3
  144. package/target/dts/core/hub/usecases/staging.d.ts +0 -8
  145. package/target/esm/adapters/transport-git/marks.js +0 -82
  146. package/target/esm/adapters/transport-git/remote/bootstrap.js +0 -47
  147. package/target/esm/adapters/transport-git/remote/heartbeat-name.js +0 -19
  148. package/target/esm/adapters/transport-git/remote/heartbeat-object.js +0 -40
  149. package/target/esm/adapters/transport-git/remote/heartbeat-push.js +0 -44
  150. package/target/esm/adapters/transport-git/remote/heartbeat.js +0 -44
  151. package/target/esm/adapters/transport-git/remote/push-validate.js +0 -39
  152. package/target/esm/adapters/transport-git/remote/signals.js +0 -63
  153. package/target/esm/adapters/transport-git/remote/sync-heartbeat.js +0 -26
  154. package/target/esm/adapters/transport-git/remote/sync-rooms.js +0 -38
  155. package/target/esm/adapters/transport-git/remote/sync-tags.js +0 -48
  156. package/target/esm/adapters/transport-git/remote/sync.js +0 -38
  157. package/target/esm/adapters/transport-git/tags.js +0 -21
  158. package/target/esm/adapters/transport-git/transport.js +0 -29
  159. package/target/esm/clients/cli/skill/targets.js +0 -20
  160. package/target/esm/core/hub/usecases/staging.js +0 -60
  161. /package/target/dts/adapters/{tool-claude → agent-claude}/index.d.ts +0 -0
  162. /package/target/dts/adapters/{tool-codex → agent-codex}/index.d.ts +0 -0
  163. /package/target/dts/adapters/{tool-cursor → agent-cursor}/index.d.ts +0 -0
  164. /package/target/dts/adapters/{tool-traces → agent-traces}/index.d.ts +0 -0
  165. /package/target/dts/adapters/{transport-git → store-git}/files.d.ts +0 -0
  166. /package/target/dts/adapters/{transport-git → store-git}/remote/admit.d.ts +0 -0
  167. /package/target/dts/adapters/{transport-git → store-git}/remote/alarms.d.ts +0 -0
  168. /package/target/dts/adapters/{transport-git → store-git}/remote/branch-commit.d.ts +0 -0
  169. /package/target/dts/adapters/{transport-git → store-git}/remote/branch-control.d.ts +0 -0
  170. /package/target/dts/adapters/{transport-git → store-git}/remote/branch-scan.d.ts +0 -0
  171. /package/target/dts/adapters/{transport-git → store-git}/remote/branch.d.ts +0 -0
  172. /package/target/dts/adapters/{transport-git → store-git}/remote/cache.d.ts +0 -0
  173. /package/target/dts/adapters/{transport-git → store-git}/remote/commits.d.ts +0 -0
  174. /package/target/dts/adapters/{transport-git → store-git}/remote/forget.d.ts +0 -0
  175. /package/target/dts/adapters/{transport-git → store-git}/remote/git.d.ts +0 -0
  176. /package/target/dts/adapters/{transport-git → store-git}/remote/heartbeat-facts.d.ts +0 -0
  177. /package/target/dts/adapters/{transport-git → store-git}/remote/keys.d.ts +0 -0
  178. /package/target/dts/adapters/{transport-git → store-git}/remote/main.d.ts +0 -0
  179. /package/target/dts/adapters/{transport-git → store-git}/remote/process.d.ts +0 -0
  180. /package/target/dts/adapters/{transport-git → store-git}/remote/push-retry.d.ts +0 -0
  181. /package/target/dts/adapters/{transport-git → store-git}/remote/push-validate.d.ts +0 -0
  182. /package/target/dts/adapters/{transport-git → store-git}/remote/roster.d.ts +0 -0
  183. /package/target/dts/adapters/{transport-git → store-git}/remote/signature.d.ts +0 -0
  184. /package/target/dts/adapters/{transport-git → store-git}/remote/sync.d.ts +0 -0
  185. /package/target/dts/adapters/{transport-git → store-git}/run.d.ts +0 -0
  186. /package/target/dts/adapters/{transport-git → store-git}/transport.d.ts +0 -0
  187. /package/target/esm/adapters/{transport-git → store-git}/files.js +0 -0
  188. /package/target/esm/adapters/{transport-git → store-git}/remote/admit.js +0 -0
  189. /package/target/esm/adapters/{transport-git → store-git}/remote/alarms.js +0 -0
  190. /package/target/esm/adapters/{transport-git → store-git}/remote/branch-commit.js +0 -0
  191. /package/target/esm/adapters/{transport-git → store-git}/remote/branch-control.js +0 -0
  192. /package/target/esm/adapters/{transport-git → store-git}/remote/branch-scan.js +0 -0
  193. /package/target/esm/adapters/{transport-git → store-git}/remote/branch.js +0 -0
  194. /package/target/esm/adapters/{transport-git → store-git}/remote/cache.js +0 -0
  195. /package/target/esm/adapters/{transport-git → store-git}/remote/forget.js +0 -0
  196. /package/target/esm/adapters/{transport-git → store-git}/remote/heartbeat-facts.js +0 -0
  197. /package/target/esm/adapters/{transport-git → store-git}/remote/main.js +0 -0
  198. /package/target/esm/adapters/{transport-git → store-git}/remote/process.js +0 -0
  199. /package/target/esm/adapters/{transport-git → store-git}/remote/roster.js +0 -0
  200. /package/target/esm/adapters/{transport-git → store-git}/remote/signature.js +0 -0
  201. /package/target/esm/adapters/{transport-git → store-git}/run.js +0 -0
@@ -1,44 +0,0 @@
1
- // heartbeat-push: a beat published with a lease on the object it replaces; a stale update loses.
2
- import * as C from '../../../lib/index.js';
3
- import { git, isRemote, locked, object, origin } from './git.js';
4
- import { checkHeartbeat, heartbeatRef } from './heartbeat.js';
5
- import { checkUrl } from './keys.js';
6
- import { SHA, TAG_ACCEPT, TAG_TRACK, TAGS } from './types.js';
7
- // Publish only the actor's exact heartbeat with an explicit old OID. A racing beat is ordinary contention, never a
8
- // signal rewrite alarm. Neither success nor failure changes immutable acceptance pins or history state.
9
- export const pushHeartbeat = (H, R, who, sha, expected) => {
10
- const ref = heartbeatRef(who, R.genesis);
11
- if (!SHA.test(sha) || (expected !== null && !SHA.test(expected)))
12
- C.fail('heartbeat publication requires full object ids');
13
- if (!isRemote(H))
14
- return true;
15
- return locked(H, () => publishHeartbeat({ H, R, ref, sha, expected }));
16
- };
17
- const publishHeartbeat = ({ H, R, ref, sha, expected }) => {
18
- if (object(H, ref) !== sha)
19
- return false;
20
- if (object(H, TAG_ACCEPT + ref.slice(TAGS.length)))
21
- C.fail('heartbeat namespace overlaps previously accepted signal history');
22
- checkHeartbeat(H, R, ref, sha);
23
- const url = origin(H);
24
- if (!url)
25
- return true;
26
- checkUrl(url);
27
- const r = git(H, ['push', '-q', '--porcelain', `--force-with-lease=${ref}:${expected ?? ''}`, url, `${sha}:${ref}`], { ok: true });
28
- if (r.status !== 0 && !reconcileHeartbeat(H, { url, ref, sha, stdout: r.stdout, stderr: r.stderr }))
29
- return false;
30
- git(H, ['update-ref', TAG_TRACK + ref.slice(TAGS.length), sha]);
31
- if (H.heartbeatErrors)
32
- delete H.heartbeatErrors[ref];
33
- return true;
34
- };
35
- const reconcileHeartbeat = (H, { url, ref, sha, stdout, stderr }) => {
36
- const observed = git(H, ['ls-remote', '--refs', url, ref], { ok: true });
37
- const got = observed.status === 0 ? observed.stdout.trim().split(/\s+/) : [];
38
- if (got[0] === sha && got[1] === ref)
39
- return true;
40
- if (/\[rejected\].*\(stale info\)/.test(stdout))
41
- return false;
42
- return C.fail(`heartbeat push failed for ${ref.slice(TAGS.length)}: ${String(stderr || stdout || 'transport error').trim().split('\n').at(-1)}`);
43
- };
44
- //# sourceMappingURL=heartbeat-push.js.map
@@ -1,44 +0,0 @@
1
- // heartbeat: a signed heartbeat made and verified; it is published by heartbeat-push.ts.
2
- import * as C from '../../../lib/index.js';
3
- import { git, isRemote, reason } from './git.js';
4
- import { heartbeatBody } from './heartbeat-facts.js';
5
- import { heartbeatRef } from './heartbeat-name.js';
6
- import { checkHeartbeat } from './heartbeat-object.js';
7
- import { signBytes } from '../signing.js';
8
- import { SHA, TAGS } from './types.js';
9
- export { checkHeartbeat, heartbeatObject } from './heartbeat-object.js';
10
- export { heartbeatBody } from './heartbeat-facts.js';
11
- export { HEARTBEAT_NAME, heartbeatName, heartbeatRef } from './heartbeat-name.js';
12
- export const verifyHeartbeat = (H, R, ref, sha) => {
13
- if (!isRemote(H))
14
- return null;
15
- if (H.remoteAlarms?.[ref])
16
- return H.remoteAlarms[ref];
17
- if (H.heartbeatErrors?.[ref])
18
- return H.heartbeatErrors[ref];
19
- try {
20
- checkHeartbeat(H, R, ref, sha);
21
- return null;
22
- }
23
- catch (e) {
24
- return reason(e);
25
- }
26
- };
27
- // Object construction has one named input; signing needs no custody path.
28
- export const makeHeartbeat = (...[H, R, who, target, text]) => createHeartbeat({ H, R, who, target, text });
29
- const createHeartbeat = ({ H, R, who, target, text }) => {
30
- const ref = heartbeatRef(who, R.genesis);
31
- if (!SHA.test(target))
32
- C.fail('heartbeat target must be a full commit id');
33
- if (/^Room:/m.test(text))
34
- C.fail('heartbeat Room is transport metadata');
35
- const body = `Room: ${R.genesis}\n${text.trimEnd()}\n`;
36
- heartbeatBody(body);
37
- const raw = `object ${target}\ntype commit\ntag ${ref.slice(TAGS.length)}\ntagger ${who} <${who}@ringi> ${Math.floor(Date.now() / 1000)} +0000\n\n${body}`;
38
- const signature = signBytes(H, who, raw);
39
- const sha = git(H, ['mktag'], { input: raw + signature }).trim();
40
- if (isRemote(H))
41
- checkHeartbeat(H, R, ref, sha);
42
- return sha;
43
- };
44
- //# sourceMappingURL=heartbeat.js.map
@@ -1,39 +0,0 @@
1
- // push-validate: a ref checked before it is published: main, a room's branch, or an actor's signal on a message of a
2
- // verified room.
3
- import * as C from '../../../lib/index.js';
4
- import * as P from '../../../core/hub/protocol/index.js';
5
- import { branchData } from './branch.js';
6
- import { ancestor, refs } from './git.js';
7
- import { verifyMain } from './main.js';
8
- import { checkSignal, signalObject } from './signals.js';
9
- import { TAGS } from './types.js';
10
- export const validateRef = (H, ref, sha) => {
11
- if (ref.startsWith(TAGS)) {
12
- return validateSignalRef(H, ref, sha);
13
- }
14
- if (ref === 'refs/heads/main') {
15
- verifyMain(H, sha);
16
- return;
17
- }
18
- const room = /^refs\/heads\/([^/]+)$/.exec(ref) ?? C.fail('only explicit main, room or signal refs may be pushed');
19
- if (!P.ID_RE.test(room[1]))
20
- C.fail('only explicit main, room or signal refs may be pushed');
21
- const why = branchData(H, room[1], sha).skipped.get(sha);
22
- if (why)
23
- C.fail(`${sha.slice(0, 12)} is no valid commit of room ${room[1]}: ${why}`);
24
- };
25
- const validateSignalRef = (H, ref, sha) => {
26
- const s = signalObject(H, ref, sha);
27
- for (const [branchRef, head] of refs(H, 'refs/heads/')) {
28
- const name = branchRef.slice('refs/heads/'.length);
29
- if (name === 'main' || name.includes('/') || !ancestor(H, s.message, head))
30
- continue;
31
- const b = branchData(H, name, head);
32
- if (b.control.includes(s.message) || b.authors.has(s.message) || b.skipped.has(s.message)) {
33
- checkSignal(H, { name, ref: branchRef, head: b.control.at(-1), genesis: b.genesis }, ref, sha);
34
- return;
35
- }
36
- }
37
- return C.fail('signal points at no verified room');
38
- };
39
- //# sourceMappingURL=push-validate.js.map
@@ -1,63 +0,0 @@
1
- // signals: a signal tag's name, object and target checked: its actor's own, on a message of the room's branch.
2
- import * as C from '../../../lib/index.js';
3
- import * as P from '../../../core/hub/protocol/index.js';
4
- import { branch } from './branch.js';
5
- import { git, isRemote, reason, rev } from './git.js';
6
- import { heartbeatName } from './heartbeat.js';
7
- import { checkSignature } from './signature.js';
8
- import { SHA, TAGS } from './types.js';
9
- export const SIGNAL_NAME = /^([a-z0-9]+(?:[_-][a-z0-9]+)*)\.([a-z][a-z0-9.-]*)\.([0-9a-f]{12})$/;
10
- export const signalName = (ref) => {
11
- if (heartbeatName(ref))
12
- C.fail('heartbeat is not an immutable signal');
13
- const m = ref.startsWith(TAGS) && SIGNAL_NAME.exec(ref.slice(TAGS.length));
14
- if (!m)
15
- return C.fail('malformed signal tag namespace');
16
- return { actor: m[1], id: m[3], signal: m[2] };
17
- };
18
- // The signed header carries the full target, tag name and actor; there is no message body.
19
- export const signalObject = (H, ref, sha) => {
20
- const s = signalName(ref);
21
- if (git(H, ['cat-file', '-t', sha]).trim() !== 'tag')
22
- C.fail('signal must be an annotated tag');
23
- const text = P.decodeText(git(H, ['cat-file', 'tag', sha], { raw: true }));
24
- if (text.invalid)
25
- C.fail(`signal tag is ${text.invalid}`);
26
- const [header, ...rest] = text.text.split('\n\n');
27
- const target = /^object ([0-9a-f]+)\ntype commit\ntag ([^\n]+)\ntagger ([^<\n]+) <[^\n]*> \d+ [+-]\d{4}\n?$/.exec(header) ?? C.fail('malformed signal tag headers');
28
- if (!SHA.test(target[1]) || !target[1].startsWith(s.id) || target[2] !== ref.slice('refs/tags/'.length) || target[3].trim() !== s.actor)
29
- C.fail('signal tag name, actor or target disagrees');
30
- const body = rest.join('\n\n').split('-----BEGIN SSH SIGNATURE-----')[0];
31
- if (body !== '')
32
- C.fail('signal tag message must be empty');
33
- return { ...s, message: target[1] };
34
- };
35
- // Derived signals belong to their message's author; read/taken marks may name another member's message.
36
- // The room is determined by the full target commit on its verified branch, never by a short name or a tag body.
37
- export const checkSignal = (H, R, ref, sha) => {
38
- const s = signalObject(H, ref, sha);
39
- const b = branch(H, R, rev(H, R.ref) ?? C.fail('signal room has no branch here'));
40
- const signer = b.entries.find(e => e.principal === s.actor) ?? C.fail(`unadmitted signal principal ${s.actor}`);
41
- checkSignature(H, sha, s.actor, signer.key, 'tag');
42
- const mark = s.signal === 'read' || s.signal === 'taken';
43
- if (s.message === R.genesis)
44
- C.fail('signal points at no message of this room');
45
- const author = b.authors.get(s.message);
46
- if (!(mark ? author : author === s.actor))
47
- C.fail(`signal points at no accepted message ${mark ? 'of this room' : 'of its actor'}`);
48
- };
49
- export const verifySignal = (H, R, ref, sha) => {
50
- if (!isRemote(H))
51
- return null;
52
- const alarm = H.remoteAlarms?.[ref];
53
- if (alarm)
54
- return alarm;
55
- try {
56
- checkSignal(H, R, ref, sha);
57
- return null;
58
- }
59
- catch (e) {
60
- return reason(e);
61
- }
62
- };
63
- //# sourceMappingURL=signals.js.map
@@ -1,26 +0,0 @@
1
- // sync-heartbeat: a fetched heartbeat verified and installed as the remote's current object; its errors stay apart
2
- // from signal alarms.
3
- import * as C from '../../../lib/index.js';
4
- import { git, reason } from './git.js';
5
- import { checkHeartbeat, heartbeatObject } from './heartbeat.js';
6
- import { TAGS, TAG_ACCEPT, TAG_TRACK } from './types.js';
7
- export const syncHeartbeat = ({ H, tags, pinned, byGenesis }, name) => {
8
- const beatRef = TAGS + name;
9
- if (pinned.has(TAG_ACCEPT + name)) {
10
- H.remoteAlarms[beatRef] = 'heartbeat namespace overlaps a previously accepted signal; operator review required';
11
- return;
12
- }
13
- try {
14
- const sha = tags.get(TAG_TRACK + name) ?? C.fail('heartbeat is absent from the remote');
15
- const b = heartbeatObject(H, beatRef, sha);
16
- const R = byGenesis.get(b.genesis) ?? C.fail('heartbeat room is missing or quarantined');
17
- checkHeartbeat(H, R, beatRef, sha);
18
- git(H, ['update-ref', beatRef, sha]);
19
- }
20
- catch (e) {
21
- H.heartbeatErrors[beatRef] = reason(e);
22
- git(H, ['update-ref', '-d', beatRef]);
23
- C.note(`heartbeat ${name}: ${reason(e)}; withheld`);
24
- }
25
- };
26
- //# sourceMappingURL=sync-heartbeat.js.map
@@ -1,38 +0,0 @@
1
- // sync-rooms: the rooms' branches as fetched, verified, and indexed by genesis and by commit.
2
- import * as C from '../../../lib/index.js';
3
- import * as P from '../../../core/hub/protocol/index.js';
4
- import { branchData } from './branch.js';
5
- import { promote, reason, refs, rev } from './git.js';
6
- import { ACCEPT, TRACK } from './types.js';
7
- export const syncRooms = (H, fetched) => {
8
- // Every other branch is a room.
9
- const names = roomNames(H, fetched);
10
- const byGenesis = new Map(), byTarget = new Map();
11
- for (const name of names) {
12
- const ref = 'refs/heads/' + name;
13
- try {
14
- if (!P.ID_RE.test(name))
15
- C.fail('invalid room name');
16
- const sha = fetched.get(TRACK + name) ?? C.fail(`${name} was deleted on the remote`);
17
- const data = branchData(H, name, sha);
18
- if (byGenesis.has(data.genesis))
19
- C.fail('room genesis is already bound to another room');
20
- promote(H, ref, sha);
21
- // Local commits not yet published stay on top.
22
- const local = branchData(H, name, rev(H, ref), data.genesis);
23
- const R = { name, ref, head: local.control.at(-1), genesis: data.genesis };
24
- byGenesis.set(data.genesis, R);
25
- for (const target of [...local.control, ...local.authors.keys(), ...local.skipped.keys()])
26
- byTarget.set(target, R);
27
- }
28
- catch (e) {
29
- H.remoteAlarms[ref] = reason(e);
30
- }
31
- }
32
- return { byGenesis, byTarget };
33
- };
34
- const roomNames = (H, fetched) => {
35
- const names = new Set([...fetched.keys(), ...refs(H, ACCEPT).keys()].map(r => r.slice(r.startsWith(TRACK) ? TRACK.length : ACCEPT.length)).filter(r => r !== 'main' && !r.includes('/')));
36
- return names;
37
- };
38
- //# sourceMappingURL=sync-rooms.js.map
@@ -1,48 +0,0 @@
1
- // sync-tags: fetched tags sorted into signals (immutable, pinned) and heartbeats (replaced).
2
- import * as C from '../../../lib/index.js';
3
- import { git, object, reason, refs, zero } from './git.js';
4
- import { heartbeatName } from './heartbeat.js';
5
- import { SIGNAL_NAME, checkSignal, signalObject } from './signals.js';
6
- import { TAGS, TAG_ACCEPT, TAG_TRACK } from './types.js';
7
- import { syncHeartbeat } from './sync-heartbeat.js';
8
- const missingHeartbeats = (H, tags, pinned) => {
9
- // Include local beats to remove disappeared remote telemetry; unlike signals, nothing is pinned.
10
- for (const ref of refs(H, TAGS).keys())
11
- if (heartbeatName(ref) && !tags.has(TAG_TRACK + ref.slice(TAGS.length))) {
12
- if (pinned.has(TAG_ACCEPT + ref.slice(TAGS.length)))
13
- continue; // never waive previously accepted history
14
- git(H, ['update-ref', '-d', ref]);
15
- }
16
- };
17
- const syncSignal = ({ H, tags, pinned, byTarget }, name) => {
18
- const ref = TAGS + name;
19
- try {
20
- const sha = tags.get(TAG_TRACK + name) ?? C.fail('signal was deleted on the remote after acceptance');
21
- const s = signalObject(H, ref, sha);
22
- const R = byTarget.get(s.message) ?? C.fail('signal room is missing or quarantined');
23
- checkSignal(H, R, ref, sha);
24
- const acc = pinned.get(TAG_ACCEPT + name), cur = object(H, ref);
25
- if (acc && acc !== sha)
26
- C.fail('signal was replaced after transport acceptance');
27
- if (cur && cur !== sha)
28
- C.fail('signal diverges from the local tag object');
29
- git(H, ['update-ref', ref, sha, cur ?? zero(H)]);
30
- git(H, ['update-ref', TAG_ACCEPT + name, sha, acc ?? zero(H)]);
31
- }
32
- catch (e) {
33
- H.remoteAlarms[ref] = reason(e);
34
- }
35
- };
36
- export const syncTags = (H, rooms) => {
37
- const tags = refs(H, TAG_TRACK), pinned = refs(H, TAG_ACCEPT);
38
- missingHeartbeats(H, tags, pinned);
39
- const state = { H, tags, pinned, ...rooms };
40
- const names = new Set([...tags.keys()].map(r => r.slice(TAG_TRACK.length)).concat([...pinned.keys()].map(r => r.slice(TAG_ACCEPT.length))));
41
- for (const name of names) {
42
- if (heartbeatName(TAGS + name))
43
- syncHeartbeat(state, name);
44
- else if (SIGNAL_NAME.test(name))
45
- syncSignal(state, name);
46
- }
47
- };
48
- //# sourceMappingURL=sync-tags.js.map
@@ -1,38 +0,0 @@
1
- // sync: one fetch of a signed hub under its transport lock: contract, rooms, signals and heartbeats verified.
2
- import * as C from '../../../lib/index.js';
3
- import { pushAlarms } from './alarms.js';
4
- import { git, isRemote, locked, origin, promote, reason, refs, rev, suffix } from './git.js';
5
- import { checkUrl } from './keys.js';
6
- import { verifyHub, verifyMain } from './main.js';
7
- import { syncRooms } from './sync-rooms.js';
8
- import { syncTags } from './sync-tags.js';
9
- import { TAGS, TAG_TRACK, TRACK } from './types.js';
10
- const syncUnlocked = (H) => {
11
- H.remoteAlarms = { ...pushAlarms(H) };
12
- H.heartbeatErrors = {};
13
- const url = origin(H);
14
- if (!url) {
15
- if (rev(H, 'refs/heads/main'))
16
- verifyHub(H);
17
- return H;
18
- }
19
- checkUrl(url);
20
- git(H, ['-c', 'fetch.fsckObjects=true', 'fetch', '-q', '--no-tags', '--prune', url,
21
- `+refs/heads/*:${TRACK}*`, `+${TAGS}*:${TAG_TRACK}*`]);
22
- const fetched = refs(H, TRACK);
23
- const main = fetched.get(TRACK + 'main') || C.fail('ALARM remote main was deleted or is missing; refusing authority from the hub');
24
- try {
25
- verifyMain(H, main);
26
- promote(H, 'refs/heads/main', main);
27
- }
28
- catch (e) {
29
- C.fail(`ALARM hub ${H.name}: ${reason(e)}; nothing is delivered`);
30
- }
31
- H.main = rev(H, 'refs/heads/main');
32
- syncTags(H, syncRooms(H, fetched));
33
- for (const [ref, why] of Object.entries(H.remoteAlarms))
34
- C.note(`ALARM ${suffix(ref)}: ${why}; quarantined and withheld`);
35
- return H;
36
- };
37
- export const sync = (H) => !isRemote(H) ? H : locked(H, () => syncUnlocked(H));
38
- //# sourceMappingURL=sync.js.map
@@ -1,21 +0,0 @@
1
- // tags: signal tags as git lists them, and an annotated tag object read whole.
2
- const SIGNAL_REF = /^refs\/tags\/([a-z0-9]+(?:[_-][a-z0-9]+)*)\.([a-z][a-z0-9.-]*\.[0-9a-f]{12})$/;
3
- // `for-each-ref` lines `<ref> <object> <type>` of tags named `<actor>.<signal>.<message12>`, but for heartbeats.
4
- export const signalTags = (listing, heartbeat) => listing.split('\n').flatMap(line => {
5
- const [ref, object, type] = line.split(' ');
6
- const m = SIGNAL_REF.exec(ref ?? '');
7
- return m && !heartbeat(ref) ? [{ ref, actor: m[1], name: m[2], object, type }] : [];
8
- });
9
- // A tag object's target commit, tagger and time, and its text without a signature.
10
- export const tagObject = (body) => {
11
- const split = body.indexOf('\n\n');
12
- const hdr = body.subarray(0, split < 0 ? body.length : split).toString('utf8');
13
- const tagger = /^tagger (.*?) <[^>\n]*> (\d+) [+-]\d{4}$/m.exec(hdr);
14
- return {
15
- target: /^object ([0-9a-f]+)\ntype commit$/m.exec(hdr)?.[1] ?? '',
16
- tagger: tagger?.[1] ?? '',
17
- time: Number(tagger?.[2] ?? NaN),
18
- text: split < 0 ? '' : body.subarray(split + 2).toString('utf8').split('-----BEGIN SSH SIGNATURE-----')[0],
19
- };
20
- };
21
- //# sourceMappingURL=tags.js.map
@@ -1,29 +0,0 @@
1
- // transport: the git store as a store type: a hub's repository is `store/.git` in the hub's directory; a signed hub's
2
- // root identity comes from Signer and a published hub is replicated by bootstrap (remote/bootstrap.ts).
3
- import { fail } from '../../lib/index.js';
4
- import { GitStore } from './index.js';
5
- import * as Remote from './remote.js';
6
- const context = (d, opt) => d.trust === 'signed'
7
- ? (typeof opt.signer === 'function' ? opt.signer() : opt.signer) ?? fail('signed hubs require an injected Signer')
8
- : undefined;
9
- // `home`: where this machine keeps its state and scratch indexes; Signer owns key custody.
10
- export const gitTransport = (home, opt = {}) => ({
11
- // One branch per room with its messages and control records, signals as tags on them (hub-1, Layout).
12
- layout: 'git/2',
13
- // Before contracts named it: ringi 0.1 kept a room as branches under `<room>/` (git/1).
14
- layoutOf: store => store.roomBranches().some(b => b.includes('/')) ? 'git/1' : 'git/2',
15
- open: (at, d) => new GitStore(at, d, home, context(d, opt)),
16
- create: (at, d, genesis) => {
17
- const signing = context(d, opt);
18
- if (signing)
19
- d.root = GitStore.rootFor(at, d, home, signing);
20
- const g = genesis(d);
21
- const store = GitStore.create(at, d, { home, signing }, g.files, g.text);
22
- if (d.trust === 'signed')
23
- d.genesis = store.contractHead();
24
- const custody = signing?.custody?.(d.name, 'operator') ?? null;
25
- return { store, custody };
26
- },
27
- attach: (name, url, pins) => { Remote.hubAdd({ home, name, url, ...pins }); },
28
- });
29
- //# sourceMappingURL=transport.js.map
@@ -1,20 +0,0 @@
1
- // targets: where the skill goes: each agent tool's skill directory under the user's home or the project.
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
- import { about } from '../../../core/hub/usecases/context.js';
6
- import { skillDirs } from '../../../core/agents/sessions/context.js';
7
- export const SKILL = path.join(about().resources, 'skill', 'ringi');
8
- export const skillTargets = (project) => {
9
- const base = project ? process.cwd() : os.homedir();
10
- return skillDirs(base);
11
- };
12
- export const sameSkill = (dir) => {
13
- try {
14
- return fs.readFileSync(path.join(dir, 'SKILL.md'), 'utf8') === fs.readFileSync(path.join(SKILL, 'SKILL.md'), 'utf8');
15
- }
16
- catch {
17
- return false;
18
- }
19
- };
20
- //# sourceMappingURL=targets.js.map
@@ -1,60 +0,0 @@
1
- // staging, like git's index: add takes a file's content into the store now, and the actor's next message carries it,
2
- // whatever happens to the file meanwhile. Results and state travel only so, never through a shared directory. The store
3
- // keeps staged contents reachable (`retain`); it grows before the list does and shrinks after, so a crash in between
4
- // leaks an object rather than loses one.
5
- import fs from 'node:fs';
6
- import { fail } from '../../../lib/index.js';
7
- import { checkCollisions } from '../protocol/files.js';
8
- import { loadState, readerLock, saveState } from '../history/index.js';
9
- const FILE_MAX = 64 << 20;
10
- const tooBig = (path, size) => size > FILE_MAX && fail(`${path} is ${Math.ceil(size / (1 << 20))} MiB; an attachment is at most ${FILE_MAX >> 20} MiB`);
11
- // What retain keeps: each staged content once, named by its id, so two snapshots of one path both stay.
12
- const kept = (all) => [...new Set(all.map(s => s.blob))].map(blob => ({ path: blob, blob, mode: '100644' }));
13
- export const staged = ({ R, me }) => loadState(R, me).staged ?? [];
14
- export const stage = ({ R, me }, files) => {
15
- const taken = files.map(e => {
16
- if (!e.file)
17
- fail(`${e.path}: add takes files`);
18
- tooBig(e.path, fs.statSync(e.file).size);
19
- const b = R.hub.store.blob(e.file);
20
- tooBig(e.path, b.size);
21
- return { path: e.path, blob: b.id, mode: e.mode, size: b.size };
22
- });
23
- return readerLock(R, me, () => {
24
- const st = loadState(R, me);
25
- const next = new Map((st.staged ?? []).map(s => [s.path, s]));
26
- for (const s of taken)
27
- next.set(s.path, s);
28
- const all = [...next.values()];
29
- checkCollisions(all.map(s => s.path));
30
- R.hub.store.retain(R.s, me, kept([...all, ...st.staged ?? []]));
31
- saveState(R, me, { ...st, staged: all });
32
- R.hub.store.retain(R.s, me, kept(all));
33
- return all;
34
- });
35
- };
36
- export const shrink = ({ R, me }, keep) => {
37
- const st = loadState(R, me);
38
- const left = (st.staged ?? []).filter(keep);
39
- saveState(R, me, { ...st, staged: left });
40
- R.hub.store.retain(R.s, me, kept(left));
41
- return left;
42
- };
43
- // Unstages the given paths, or everything.
44
- export const unstage = (a, paths) => readerLock(a.R, a.me, () => {
45
- const missing = (paths ?? []).filter(p => !staged(a).some(s => s.path === p));
46
- if (missing.length)
47
- fail(`not staged: ${missing.join(', ')}`);
48
- return shrink(a, s => paths !== null && !paths.includes(s.path));
49
- });
50
- // What the actor staged goes along, an explicit attachment of the same path in its place.
51
- export const outgoing = (stagedNow, explicit) => {
52
- for (const e of explicit)
53
- if (e.file)
54
- tooBig(e.path, fs.statSync(e.file).size);
55
- const named = new Set(explicit.map(e => e.path));
56
- const entries = [...stagedNow.filter(s => !named.has(s.path)).map(s => ({ path: s.path, blob: s.blob, mode: s.mode })), ...explicit];
57
- checkCollisions(entries.map(e => e.path));
58
- return entries;
59
- };
60
- //# sourceMappingURL=staging.js.map