@idleware/ringi 0.7.1 → 0.8.0

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 (202) 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 +2 -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/dts/lib/fail.d.ts +1 -0
  53. package/target/esm/adapters/{tool-claude → agent-claude}/index.js +2 -2
  54. package/target/esm/adapters/{tool-codex → agent-codex}/index.js +2 -2
  55. package/target/esm/adapters/{tool-cursor → agent-cursor}/index.js +1 -1
  56. package/target/esm/adapters/{tool-traces → agent-traces}/index.js +1 -1
  57. package/target/esm/adapters/state-fs/index.js +2 -2
  58. package/target/esm/adapters/{transport-git → store-git}/branches.js +21 -27
  59. package/target/esm/adapters/{transport-git → store-git}/index.js +10 -28
  60. package/target/esm/adapters/store-git/marks.js +86 -0
  61. package/target/esm/adapters/{transport-git → store-git}/remote/commits.js +3 -1
  62. package/target/esm/adapters/{transport-git → store-git}/remote/git.js +8 -1
  63. package/target/esm/adapters/{transport-git → store-git}/remote/keys.js +8 -3
  64. package/target/esm/adapters/{transport-git → store-git}/remote/push-retry.js +24 -6
  65. package/target/esm/adapters/store-git/remote/push-validate.js +19 -0
  66. package/target/esm/adapters/{transport-git → store-git}/remote/push.js +13 -14
  67. package/target/esm/adapters/store-git/remote/stream-check.js +44 -0
  68. package/target/esm/adapters/store-git/remote/stream-control.js +33 -0
  69. package/target/esm/adapters/store-git/remote/stream-facts.js +40 -0
  70. package/target/esm/adapters/store-git/remote/streams.js +76 -0
  71. package/target/esm/adapters/store-git/remote/sync-streams.js +28 -0
  72. package/target/esm/adapters/store-git/remote/sync.js +59 -0
  73. package/target/esm/adapters/{transport-git → store-git}/remote/types.js +0 -3
  74. package/target/esm/adapters/{transport-git → store-git}/remote.js +1 -4
  75. package/target/esm/adapters/{transport-git → store-git}/repo.js +42 -4
  76. package/target/esm/adapters/{transport-git → store-git}/signing.js +1 -9
  77. package/target/esm/adapters/store-git/transport.js +60 -0
  78. package/target/esm/clients/cli/agent/index.js +1 -1
  79. package/target/esm/clients/cli/agent/session.js +9 -9
  80. package/target/esm/clients/cli/commands.js +5 -5
  81. package/target/esm/clients/cli/context.js +1 -1
  82. package/target/esm/clients/cli/help.js +14 -20
  83. package/target/esm/clients/cli/operator/heartbeat-format.js +1 -1
  84. package/target/esm/clients/cli/operator/heartbeat.js +1 -2
  85. package/target/esm/clients/cli/operator/hub-commands.js +6 -19
  86. package/target/esm/clients/cli/operator/hub.js +2 -2
  87. package/target/esm/clients/cli/operator/index.js +2 -2
  88. package/target/esm/clients/cli/operator/room.js +25 -32
  89. package/target/esm/clients/cli/operator/sessions.js +4 -22
  90. package/target/esm/clients/cli/operator/where-format.js +2 -1
  91. package/target/esm/clients/cli/operator/where.js +5 -7
  92. package/target/esm/clients/cli/shared/index.js +2 -2
  93. package/target/esm/clients/cli/shared/messages.js +2 -12
  94. package/target/esm/clients/cli/shared/profile.js +1 -6
  95. package/target/esm/clients/cli/skill/index.js +14 -19
  96. package/target/esm/composition/index.js +4 -4
  97. package/target/esm/core/agents/heartbeat/pulse.js +4 -4
  98. package/target/esm/core/agents/overview.js +13 -25
  99. package/target/esm/core/agents/sessions/binding.js +1 -1
  100. package/target/esm/core/agents/sessions/index.js +3 -2
  101. package/target/esm/core/agents/sessions/join.js +17 -9
  102. package/target/esm/core/agents/sessions/resume.js +3 -6
  103. package/target/esm/core/hub/capabilities.js +1 -4
  104. package/target/esm/core/hub/history/index.js +23 -13
  105. package/target/esm/core/hub/ports/store.js +2 -2
  106. package/target/esm/core/hub/rooms/address.js +18 -0
  107. package/target/esm/core/hub/rooms/adoption.js +32 -0
  108. package/target/esm/core/hub/rooms/compat.js +39 -14
  109. package/target/esm/core/hub/rooms/contracts.js +62 -0
  110. package/target/esm/core/hub/rooms/hubs.js +33 -56
  111. package/target/esm/core/hub/rooms/index.js +2 -2
  112. package/target/esm/core/hub/rooms/messages.js +6 -6
  113. package/target/esm/core/hub/rooms/room-catalogue.js +31 -0
  114. package/target/esm/core/hub/rooms/room-life.js +59 -0
  115. package/target/esm/core/hub/rooms/room-view.js +39 -0
  116. package/target/esm/core/hub/rooms/rooms.js +26 -37
  117. package/target/esm/core/hub/signals/check.js +21 -26
  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 +18 -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 +6 -1
  132. package/target/esm/lib/index.js +4 -3
  133. package/target/dts/adapters/transport-git/marks.d.ts +0 -20
  134. package/target/dts/adapters/transport-git/remote/bootstrap.d.ts +0 -7
  135. package/target/dts/adapters/transport-git/remote/heartbeat-name.d.ts +0 -6
  136. package/target/dts/adapters/transport-git/remote/heartbeat-object.d.ts +0 -10
  137. package/target/dts/adapters/transport-git/remote/heartbeat-push.d.ts +0 -2
  138. package/target/dts/adapters/transport-git/remote/heartbeat.d.ts +0 -7
  139. package/target/dts/adapters/transport-git/remote/signals.d.ts +0 -15
  140. package/target/dts/adapters/transport-git/remote/sync-heartbeat.d.ts +0 -2
  141. package/target/dts/adapters/transport-git/remote/sync-rooms.d.ts +0 -6
  142. package/target/dts/adapters/transport-git/remote/sync-tags.d.ts +0 -8
  143. package/target/dts/adapters/transport-git/tags.d.ts +0 -15
  144. package/target/dts/clients/cli/skill/targets.d.ts +0 -3
  145. package/target/dts/core/hub/usecases/staging.d.ts +0 -8
  146. package/target/esm/adapters/transport-git/marks.js +0 -82
  147. package/target/esm/adapters/transport-git/remote/bootstrap.js +0 -47
  148. package/target/esm/adapters/transport-git/remote/heartbeat-name.js +0 -19
  149. package/target/esm/adapters/transport-git/remote/heartbeat-object.js +0 -40
  150. package/target/esm/adapters/transport-git/remote/heartbeat-push.js +0 -44
  151. package/target/esm/adapters/transport-git/remote/heartbeat.js +0 -44
  152. package/target/esm/adapters/transport-git/remote/push-validate.js +0 -39
  153. package/target/esm/adapters/transport-git/remote/signals.js +0 -63
  154. package/target/esm/adapters/transport-git/remote/sync-heartbeat.js +0 -26
  155. package/target/esm/adapters/transport-git/remote/sync-rooms.js +0 -38
  156. package/target/esm/adapters/transport-git/remote/sync-tags.js +0 -48
  157. package/target/esm/adapters/transport-git/remote/sync.js +0 -38
  158. package/target/esm/adapters/transport-git/tags.js +0 -21
  159. package/target/esm/adapters/transport-git/transport.js +0 -29
  160. package/target/esm/clients/cli/skill/targets.js +0 -20
  161. package/target/esm/core/hub/usecases/staging.js +0 -60
  162. /package/target/dts/adapters/{tool-claude → agent-claude}/index.d.ts +0 -0
  163. /package/target/dts/adapters/{tool-codex → agent-codex}/index.d.ts +0 -0
  164. /package/target/dts/adapters/{tool-cursor → agent-cursor}/index.d.ts +0 -0
  165. /package/target/dts/adapters/{tool-traces → agent-traces}/index.d.ts +0 -0
  166. /package/target/dts/adapters/{transport-git → store-git}/files.d.ts +0 -0
  167. /package/target/dts/adapters/{transport-git → store-git}/remote/admit.d.ts +0 -0
  168. /package/target/dts/adapters/{transport-git → store-git}/remote/alarms.d.ts +0 -0
  169. /package/target/dts/adapters/{transport-git → store-git}/remote/branch-commit.d.ts +0 -0
  170. /package/target/dts/adapters/{transport-git → store-git}/remote/branch-control.d.ts +0 -0
  171. /package/target/dts/adapters/{transport-git → store-git}/remote/branch-scan.d.ts +0 -0
  172. /package/target/dts/adapters/{transport-git → store-git}/remote/branch.d.ts +0 -0
  173. /package/target/dts/adapters/{transport-git → store-git}/remote/cache.d.ts +0 -0
  174. /package/target/dts/adapters/{transport-git → store-git}/remote/commits.d.ts +0 -0
  175. /package/target/dts/adapters/{transport-git → store-git}/remote/forget.d.ts +0 -0
  176. /package/target/dts/adapters/{transport-git → store-git}/remote/git.d.ts +0 -0
  177. /package/target/dts/adapters/{transport-git → store-git}/remote/heartbeat-facts.d.ts +0 -0
  178. /package/target/dts/adapters/{transport-git → store-git}/remote/keys.d.ts +0 -0
  179. /package/target/dts/adapters/{transport-git → store-git}/remote/main.d.ts +0 -0
  180. /package/target/dts/adapters/{transport-git → store-git}/remote/process.d.ts +0 -0
  181. /package/target/dts/adapters/{transport-git → store-git}/remote/push-retry.d.ts +0 -0
  182. /package/target/dts/adapters/{transport-git → store-git}/remote/push-validate.d.ts +0 -0
  183. /package/target/dts/adapters/{transport-git → store-git}/remote/roster.d.ts +0 -0
  184. /package/target/dts/adapters/{transport-git → store-git}/remote/signature.d.ts +0 -0
  185. /package/target/dts/adapters/{transport-git → store-git}/remote/sync.d.ts +0 -0
  186. /package/target/dts/adapters/{transport-git → store-git}/run.d.ts +0 -0
  187. /package/target/dts/adapters/{transport-git → store-git}/transport.d.ts +0 -0
  188. /package/target/esm/adapters/{transport-git → store-git}/files.js +0 -0
  189. /package/target/esm/adapters/{transport-git → store-git}/remote/admit.js +0 -0
  190. /package/target/esm/adapters/{transport-git → store-git}/remote/alarms.js +0 -0
  191. /package/target/esm/adapters/{transport-git → store-git}/remote/branch-commit.js +0 -0
  192. /package/target/esm/adapters/{transport-git → store-git}/remote/branch-control.js +0 -0
  193. /package/target/esm/adapters/{transport-git → store-git}/remote/branch-scan.js +0 -0
  194. /package/target/esm/adapters/{transport-git → store-git}/remote/branch.js +0 -0
  195. /package/target/esm/adapters/{transport-git → store-git}/remote/cache.js +0 -0
  196. /package/target/esm/adapters/{transport-git → store-git}/remote/forget.js +0 -0
  197. /package/target/esm/adapters/{transport-git → store-git}/remote/heartbeat-facts.js +0 -0
  198. /package/target/esm/adapters/{transport-git → store-git}/remote/main.js +0 -0
  199. /package/target/esm/adapters/{transport-git → store-git}/remote/process.js +0 -0
  200. /package/target/esm/adapters/{transport-git → store-git}/remote/roster.js +0 -0
  201. /package/target/esm/adapters/{transport-git → store-git}/remote/signature.js +0 -0
  202. /package/target/esm/adapters/{transport-git → store-git}/run.js +0 -0
@@ -1,7 +1,7 @@
1
1
  import type { Profile } from '../work/index.ts';
2
- import type { Descriptor, Member, Rev, Store, StoredRoom } from '../ports/store.ts';
2
+ import type { Descriptor, Member, Rev, RoomEndpoint, Store, StoredRoom } from '../ports/store.ts';
3
3
  export declare const OPERATOR = "operator";
4
- export declare const HUB_MAJOR = 1;
4
+ export declare const HUB_MAJOR = 2;
5
5
  export declare const PROTOCOL_MAJOR = 1;
6
6
  export declare const CAPS: Set<string>;
7
7
  export declare const RESERVED_ROOMS: Set<string>;
@@ -11,7 +11,7 @@ export type Contract = {
11
11
  protocol: number;
12
12
  trust: 'asserted' | 'signed';
13
13
  capabilities?: string[];
14
- store?: string;
14
+ store: string;
15
15
  profile?: string;
16
16
  root?: string;
17
17
  };
@@ -19,13 +19,12 @@ export type Hub = {
19
19
  name: string;
20
20
  dir: string;
21
21
  d: Descriptor;
22
- store: Store;
23
- main: Rev;
24
- contract: Contract;
25
22
  signed: boolean;
26
23
  };
27
24
  export type Room = {
28
25
  hub: Hub;
26
+ endpoint: RoomEndpoint;
27
+ store: Store;
29
28
  s: StoredRoom;
30
29
  name: string;
31
30
  head: Rev;
@@ -0,0 +1,9 @@
1
+ import type { RoomEndpoint, Store } from '../ports/store.ts';
2
+ import type { Hub } from './index.ts';
3
+ export declare const endpointKey: (H: Hub, name: string) => string[];
4
+ export declare const roomDir: (H: Hub, name: string) => string;
5
+ export declare const transportFor: (H: Hub, e: RoomEndpoint) => import("../ports/store.ts").Transport;
6
+ export declare const roomLock: (H: Hub, name: string) => string;
7
+ export declare const uniqueName: (H: Hub, name: string) => void;
8
+ export declare const roomNames: (H: Hub) => string[];
9
+ export declare const selectedStore: (H: Hub, endpoint: RoomEndpoint) => Store;
@@ -0,0 +1,10 @@
1
+ import type { RoomEndpoint } from '../ports/store.ts';
2
+ import type { Hub, Room } from './index.ts';
3
+ export declare const createRoom: (H: Hub, name: string, { who, text, files, remote }: {
4
+ who: string;
5
+ text: string;
6
+ files: Record<string, string>;
7
+ remote?: string;
8
+ }) => Room;
9
+ export declare const attachRoom: (H: Hub, name: string, endpoint: RoomEndpoint) => Room;
10
+ export declare const deleteRoom: (R: Room) => void;
@@ -0,0 +1,3 @@
1
+ import type { RoomEndpoint, Store } from '../ports/store.ts';
2
+ import type { Hub, Room } from './index.ts';
3
+ export declare const openedRoom: (H: Hub, endpoint: RoomEndpoint, store: Store) => Room;
@@ -1,8 +1,10 @@
1
1
  import type { Member } from '../ports/store.ts';
2
2
  import type { Hub, Room } from './index.ts';
3
- export declare const roomNames: (H: Hub) => string[];
4
- export declare const openRoom: (H: Hub, name: string | null | undefined, { quiet }?: {
3
+ export { roomNames } from './room-catalogue.ts';
4
+ export { createRoom, attachRoom, deleteRoom } from './room-life.ts';
5
+ export declare const openRoom: (H: Hub, name: string | null | undefined, { quiet, refresh }?: {
5
6
  quiet?: boolean;
7
+ refresh?: boolean;
6
8
  }) => Room | null;
7
9
  export declare const room: (H: Hub, name: string | null | undefined) => Room;
8
10
  export declare const ROOM_MD: (name: string) => string;
@@ -1,3 +1,3 @@
1
1
  import type { All } from '../protocol/index.ts';
2
- import type { Checked, RoomModel, SignalRecord } from './model.ts';
3
- export declare const check: (R: RoomModel, all: All, records: SignalRecord[]) => Checked[];
2
+ import type { Checked, RoomModel, SignalEvent } from './model.ts';
3
+ export declare const check: (R: RoomModel, all: All, records: SignalEvent[]) => Checked[];
@@ -5,15 +5,7 @@ export type RoomModel = {
5
5
  profile: Profile;
6
6
  members: Record<string, unknown>;
7
7
  };
8
- export type SignalRecord = {
9
- ref: string;
10
- object: string;
11
- name: string;
12
- actor: string;
13
- target: string;
14
- tagger: string;
15
- text: string;
16
- };
8
+ export type { SignalEvent } from '../ports/store.ts';
17
9
  export type Checked = {
18
10
  ref: string;
19
11
  actor: string;
@@ -21,6 +13,6 @@ export type Checked = {
21
13
  target: string;
22
14
  ok: boolean;
23
15
  why?: string;
16
+ pending?: boolean;
24
17
  };
25
18
  export declare const MARKS: string[];
26
- export declare const signalName: (id: string, signal: string) => string;
@@ -1,5 +1,5 @@
1
- import type { Checked, SignalRecord } from './model.ts';
2
- export declare const pins: (records: SignalRecord[], checked: Checked[], accepted?: Record<string, string>) => {
1
+ import type { Checked, SignalEvent } from './model.ts';
2
+ export declare const pins: (records: SignalEvent[], checked: Checked[], accepted?: Record<string, string>) => {
3
3
  accepted: Record<string, string>;
4
4
  alarms: string[];
5
5
  };
@@ -1,5 +1,4 @@
1
1
  export type Config = {
2
- hub: string;
3
2
  room: string | null;
4
3
  };
5
4
  export declare const config: () => Config;
@@ -1,7 +1,6 @@
1
1
  import { config } from '../rooms/index.ts';
2
2
  import type { Actor } from './actor.ts';
3
- export declare const operator: ({ hub, room }?: {
4
- hub?: string;
3
+ export declare const operator: ({ room }?: {
5
4
  room?: string;
6
5
  }) => Actor;
7
6
  export declare const about: () => {
@@ -2,10 +2,9 @@ import type { Hub } from '../rooms/index.ts';
2
2
  export declare const hubOf: (name?: string) => Hub;
3
3
  export type HubView = {
4
4
  name: string;
5
- current: boolean;
6
5
  store: string;
7
6
  trust: string;
8
- contract: string;
7
+ contract: string | null;
9
8
  rooms: number;
10
9
  remote: string | null;
11
10
  dir: string;
@@ -17,13 +16,8 @@ export declare const create: (name: string, { signed, url }?: {
17
16
  }) => {
18
17
  H: Hub;
19
18
  rootKey: string | null;
20
- add: string | null;
19
+ remote: string | null;
21
20
  };
22
- export declare const use: (name: string) => void;
23
- export declare const add: (name: string, url: string, { root, genesis }: {
24
- root?: string;
25
- genesis?: string;
26
- }) => Hub;
27
21
  export type AmendInput = {
28
22
  text: string;
29
23
  set?: string[];
@@ -0,0 +1,12 @@
1
+ import type { Room } from '../rooms/index.ts';
2
+ export type Invite = {
3
+ schema: 'ringi-invite/1';
4
+ room: string;
5
+ address: string;
6
+ genesis: string;
7
+ hubGenesis: string;
8
+ trust: 'signed';
9
+ root: string;
10
+ };
11
+ export declare const invite: (R: Room) => string | null;
12
+ export declare const readInvite: (s: string) => Invite | null;
@@ -5,7 +5,6 @@ import type { All, Message } from '../protocol/index.ts';
5
5
  import type { Actor } from './actor.ts';
6
6
  import type { TaskView } from './view.ts';
7
7
  export * from './actor.ts';
8
- export * from './staging.ts';
9
8
  export * from './send.ts';
10
9
  export declare const marks: (R: Room, all: All) => Map<string, Record<string, string[]>>;
11
10
  export declare const message: ({ R, me }: Actor, ref: string) => {
@@ -1,20 +1,22 @@
1
1
  import type { Hub, Room } from '../rooms/index.ts';
2
- export { admit, forgetLog, remove } from './roster.ts';
3
- export declare const roomIn: (H: Hub, name?: string | null) => Room;
2
+ export { admit, forgetLog } from './roster.ts';
3
+ export declare const roomNamed: (name?: string | null) => Room;
4
4
  export type RoomView = {
5
5
  name: string;
6
+ hub: string;
6
7
  current: boolean;
7
8
  members: number;
8
9
  profile: string;
9
10
  genesis: string;
10
11
  };
11
- export declare const rooms: (H: Hub) => RoomView[];
12
- export declare const create: (H: Hub, name: string, { profile, quorum }?: {
12
+ export declare const rooms: () => RoomView[];
13
+ export declare const create: (H: Hub, name: string, { profile, quorum, url }?: {
13
14
  profile?: string;
14
15
  quorum?: number;
16
+ url?: string;
15
17
  }) => {
16
18
  profile: string;
19
+ join: string | null;
17
20
  };
18
- export declare const use: (H: Hub, name: string) => Room;
19
- export declare const erase: (H: Hub, R: Room) => void;
20
- export declare const rebase: (H: Hub, R: Room) => void;
21
+ export declare const use: (name: string) => Room;
22
+ export declare const erase: (R: Room) => void;
@@ -1,5 +1,4 @@
1
1
  import type { Hub, Room } from '../rooms/index.ts';
2
- export declare const notSigned: (H: Hub, what: string) => void;
2
+ export declare const agentId: (who: string) => string;
3
3
  export declare const admit: (H: Hub, R: Room, who: string, key: string) => void;
4
- export declare const remove: (H: Hub, R: Room, who: string) => void;
5
4
  export declare const forgetLog: (H: Hub, R: Room, id: string) => number;
@@ -5,7 +5,6 @@ export declare const PROFILES_CAPABILITY = "profiles/1";
5
5
  export type Rules = {
6
6
  assign?: string[];
7
7
  roles?: string[];
8
- grant?: string[];
9
8
  [state: `state:${string}`]: string[] | undefined;
10
9
  };
11
10
  export type Profile = {
@@ -2,6 +2,6 @@ import './composition/index.ts';
2
2
  export * from './core/hub/protocol/index.ts';
3
3
  export * from './core/hub/work/index.ts';
4
4
  export * as signals from './core/hub/signals/index.ts';
5
- export type { Store, Transport, Descriptor, StoredRoom, StoredMessage, SignalRecord, Rev } from './core/hub/ports/store.ts';
5
+ export type { Store, Transport, Descriptor, RoomEndpoint, StoredRoom, StoredMessage, SignalEvent, SignalHead, Rev } from './core/hub/ports/store.ts';
6
6
  export { openHub, openRoom, createHub, contractAt } from './core/hub/rooms/index.ts';
7
7
  export type { Hub, Room, Contract } from './core/hub/rooms/index.ts';
@@ -1,3 +1,4 @@
1
+ export declare const withoutCredentials: (text: string) => string;
1
2
  export declare class Fail extends Error {
2
3
  }
3
4
  export declare const fail: (msg: string) => never;
@@ -1,10 +1,10 @@
1
- // tool-claude: Claude Code. A session says so in its environment (CLAUDECODE, CLAUDE_CODE_SESSION_ID) and is known by
1
+ // agent-claude: Claude Code. A session says so in its environment (CLAUDECODE, CLAUDE_CODE_SESSION_ID) and is known by
2
2
  // its session id, `claude:<id>`. While it works it writes its transcript
3
3
  // $CLAUDE_CONFIG_DIR (or ~/.claude)/projects/<dir>/<session id>.jsonl; it reads skills from .claude/skills.
4
4
  import fs from 'node:fs';
5
5
  import os from 'node:os';
6
6
  import path from 'node:path';
7
- import { UUID, mtime, newestFirst } from '../tool-traces/index.js';
7
+ import { UUID, mtime, newestFirst } from '../agent-traces/index.js';
8
8
  const transcript = (id) => {
9
9
  const root = path.join(process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), '.claude'), 'projects');
10
10
  const dir = newestFirst(root).find(d => fs.existsSync(path.join(root, d, `${id}.jsonl`)));
@@ -1,10 +1,10 @@
1
- // tool-codex: Codex. A session says so in its environment (CODEX_*); a chat names itself on every ringi command with
1
+ // agent-codex: Codex. A session says so in its environment (CODEX_*); a chat names itself on every ringi command with
2
2
  // RINGI_SESSION=codex-<thread id>. While it works it writes its rollout
3
3
  // $CODEX_HOME (or ~/.codex)/sessions/<yyyy>/<mm>/<dd>/rollout-<time>-<thread id>.jsonl; it reads skills from
4
4
  // .agents/skills, and its sandbox writes where its writable roots allow.
5
5
  import os from 'node:os';
6
6
  import path from 'node:path';
7
- import { UUID, mtime, newestFirst } from '../tool-traces/index.js';
7
+ import { UUID, mtime, newestFirst } from '../agent-traces/index.js';
8
8
  const rollout = (id) => {
9
9
  const root = path.join(process.env.CODEX_HOME ?? path.join(os.homedir(), '.codex'), 'sessions');
10
10
  for (const y of newestFirst(root))
@@ -1,4 +1,4 @@
1
- // tool-cursor: Cursor, recognised only: a session says so in its environment (CURSOR_*) or by its process. It names no
1
+ // agent-cursor: Cursor, recognised only: a session says so in its environment (CURSOR_*) or by its process. It names no
2
2
  // session, writes no trace ringi reads, and gets no skill.
3
3
  export const cursor = {
4
4
  id: 'cursor',
@@ -1,4 +1,4 @@
1
- // tool-traces: what the tool adapters share to find a session's trace: a session id at the end of a name, directories
1
+ // agent-traces: what the agent adapters share to find a session's trace: a session id at the end of a name, directories
2
2
  // newest first, and when a file was last written.
3
3
  import fs from 'node:fs';
4
4
  export const UUID = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;
@@ -5,7 +5,7 @@ import fs from 'node:fs';
5
5
  import path from 'node:path';
6
6
  import { errno, fail, strictJson } from '../../lib/index.js';
7
7
  import { guardWrite, locked as lockFile, mkdirIn, writeJsonAtomic } from '../fs/index.js';
8
- const HOME_VERSION = 3;
8
+ const HOME_VERSION = 4;
9
9
  // State fails closed: unreadable JSON is an error, never a silent fresh start.
10
10
  const readJson = (f, dflt) => {
11
11
  let raw;
@@ -40,7 +40,7 @@ export const stateFs = ({ root, build }) => {
40
40
  if (fs.existsSync(marker)) {
41
41
  const v = readJson(marker, {}).version;
42
42
  if (v !== HOME_VERSION)
43
- fail(`${root} is a ringi home of version ${v}; this ringi ${build.version} needs version ${HOME_VERSION}: set RINGI_HOME to a new directory for a fresh home; ringi does not migrate`);
43
+ fail(`${root} is a ringi home of version ${v}; this ringi ${build.version} needs version ${HOME_VERSION}. Move it away (the ringi that made it still reads it with RINGI_HOME pointing there) or set RINGI_HOME to a new directory; ringi does not migrate`);
44
44
  return;
45
45
  }
46
46
  if (fs.existsSync(root) && fs.readdirSync(root).length)
@@ -4,23 +4,17 @@ import { fail } from '../../lib/index.js';
4
4
  import * as Remote from './remote.js';
5
5
  import { ZERO } from './run.js';
6
6
  import { Repo } from './repo.js';
7
- import { ID_RE, parse } from '../../core/hub/protocol/index.js';
7
+ import { parse } from '../../core/hub/protocol/index.js';
8
8
  // The root's principal, and the files only its control records may change.
9
9
  const ROOT = 'operator';
10
10
  export const CONTROL_FILES = new Set(['ROOM.md', 'members.json', 'profile.json', 'allowed_signers']);
11
11
  export class Branches extends Repo {
12
- ref(name) { return `refs/heads/${name}`; }
12
+ ref(_name) { return 'refs/heads/chat'; }
13
13
  tip(name) { return this.rev(this.ref(name)); }
14
- // Every branch but the contract's, by name.
15
- roomBranches() {
16
- return this.git(['for-each-ref', '--format=%(refname:lstrip=2)', 'refs/heads/']).split('\n').filter(b => b && b !== 'main');
17
- }
18
- // Every branch but the contract's is a room.
14
+ // One repository holds one chat. Its logical name is pinned by the local endpoint.
19
15
  roomNames() {
20
- const prefix = 'refs/heads/';
21
- const names = this.git(['for-each-ref', '--format=%(refname)', prefix]).split('\n').filter(Boolean).map(r => r.slice(prefix.length))
22
- .filter(n => ID_RE.test(n) && n !== 'main');
23
- return names.sort();
16
+ const endpoint = this.h.endpoint;
17
+ return endpoint && this.rev('refs/heads/chat') ? [endpoint.name] : [];
24
18
  }
25
19
  // A control record: the room's genesis, or a root commit of Kind: room.
26
20
  isControl(room, sha, author, text) {
@@ -51,19 +45,29 @@ export class Branches extends Repo {
51
45
  }
52
46
  scan(room, tip, after) {
53
47
  const shas = this.git(['rev-list', '--topo-order', '--reverse', tip, '--not', after ?? `${room.genesis}^@`]).trim().split('\n').filter(Boolean);
48
+ let parent = after ?? this.rev(`${room.genesis}^`) ?? fail('room has no contract parent');
54
49
  return Remote.readCommits(this.h, shas).map(c => {
50
+ if (c.parents.length !== 1 || c.parents[0] !== parent)
51
+ fail('ALARM room chat is not one linear history');
52
+ parent = c.sha;
55
53
  const text = c.body.toString('utf8');
54
+ if (c.sha === room.genesis && (c.author !== ROOT || parse(text, x => this.isRef(x)).kind !== 'room'))
55
+ fail('ALARM room genesis is not a root control');
56
56
  return { sha: c.sha, parent: c.parents[0], author: c.author, text, control: this.isControl(room, c.sha, c.author, text) };
57
57
  });
58
58
  }
59
59
  room(name) {
60
+ if (!this.h.endpoint || this.h.endpoint.name !== name)
61
+ return null;
60
62
  const ref = this.ref(name);
61
63
  const tip = this.tip(name);
62
64
  if (!tip)
63
65
  return null;
64
66
  const genesis = this.git(['rev-list', '--first-parent', '--reverse', tip, '^refs/heads/main']).split('\n')[0]
65
67
  || this.git(['rev-list', '--first-parent', '--reverse', tip]).split('\n').filter(Boolean).at(-1);
66
- if (this.trust === 'signed' && this.h.remoteAlarms?.[ref])
68
+ if (this.h.endpoint.genesis && genesis !== this.h.endpoint.genesis)
69
+ fail(`ALARM room ${name}: changed genesis`);
70
+ if (this.h.remoteAlarms?.[ref])
67
71
  fail(`ALARM ${this.h.remoteAlarms[ref]}; room ${name} is quarantined`);
68
72
  const control = this.entries({ name, genesis }, tip).filter(e => e.control).map(e => ({ rev: e.sha, text: e.text }));
69
73
  return { name, head: control.at(-1).rev, genesis, tip, base: this.rev(`${genesis}^`) ?? ZERO, control };
@@ -74,10 +78,14 @@ export class Branches extends Repo {
74
78
  return r.status === 0 ? r.stdout : null;
75
79
  }
76
80
  createRoom(name, who, text, files) {
77
- const ref = `refs/heads/${name}`;
81
+ const ref = this.ref(name);
82
+ const endpoint = this.h.endpoint ?? fail('createRoom requires its explicit endpoint');
83
+ if (endpoint.name !== name)
84
+ fail('createRoom requires its named endpoint');
78
85
  if (this.rev(ref))
79
86
  fail(`room ${name} exists in hub ${this.d.name}`);
80
87
  const sha = this.commit(who, text, this.tree(null, Object.entries(files).map(([p, c]) => ({ path: p, content: c, mode: '100644' }))), [this.contractHead()]);
88
+ endpoint.genesis = sha;
81
89
  if (!this.advance(ref, sha, null))
82
90
  fail(`room ${name} was created meanwhile`);
83
91
  return sha;
@@ -92,20 +100,6 @@ export class Branches extends Repo {
92
100
  refsUnder(prefix) {
93
101
  return this.git(['for-each-ref', '--format=%(refname) %(objectname)', prefix]).split('\n').filter(Boolean).map(l => l.split(' '));
94
102
  }
95
- // Every ref of the room in one transaction: its branch, every tag on its commits (signals, heartbeats,
96
- // anyone's), what the store keeps under its genesis (pins, evidence) and its unpublished commits. Objects are left to
97
- // the repository.
98
- deleteRoom(room) {
99
- const commits = this.commitsOf(room);
100
- const tags = this.git(['for-each-ref', '--format=%(refname) %(objectname) %(*objectname)', 'refs/tags/']).split('\n').filter(Boolean)
101
- .map(l => l.split(' ')).filter(([, object, target]) => commits.has(target || object)).map(([ref]) => ref);
102
- const kept = this.refsUnder('refs/ringi/').map(([ref]) => ref).filter(ref => {
103
- const [, , kind, key] = ref.split('/');
104
- return key === room.genesis || (kind === 'unpublished' && commits.has(key));
105
- });
106
- const refs = [this.ref(room.name), ...tags, ...kept];
107
- this.git(['update-ref', '--stdin'], { input: ['start', ...refs.map(r => `delete ${r}`), 'prepare', 'commit', ''].join('\n') });
108
- }
109
103
  remote(room) {
110
104
  return { name: room.name, ref: this.ref(room.name), head: room.head, genesis: room.genesis };
111
105
  }
@@ -1,15 +1,7 @@
1
- // git-store: the Store port on git. The store directory holds one repository (`store/.git`):
2
- // refs/heads/main the shared contract, one commit per amendment
3
- // refs/heads/<room> the room: one linear branch, like a chat. Its first commit is the room's genesis
4
- // (the root's, on top of main); then every message is a commit by its author, and
5
- // every control record (Kind: room) a commit by the root
6
- // refs/tags/<agent>.<signal>.<message12> signals: annotated tags without text on the message's commit
7
- // refs/ringi/accepted/<genesis>/<reader>/<author> readers' pins of each author's accepted last message
8
- // A member's log is its own commits in the room's branch, in branch order. The control files at the root of a room's
9
- // tree (members, profile, signers) change only in the root's control records.
10
- // A signed hub signs every commit and tag with its author's key and verifies what it fetches (remote.ts).
11
- // The class is layered by concern: repo.ts (repository, contract), branches.ts (rooms), marks.ts (signals, heartbeats)
12
- // and here the logs: messages, their files, staging and pins.
1
+ // Store on git/3: an explicit contract source or one self-contained room repository.
2
+ // main holds the frozen contract; chat holds root controls and participant messages. Actor signals/telemetry are
3
+ // append-only commit streams. Reader evidence lives below refs/ringi/accepted; message files remain in chat trees.
4
+ // Signing is injected for every published commit. Repo, Branches and Marks separate storage from verification.
13
5
  import fs from 'node:fs';
14
6
  import path from 'node:path';
15
7
  import { fail } from '../../lib/index.js';
@@ -29,7 +21,7 @@ export class GitStore extends Marks {
29
21
  const { home, signing } = typeof connection === 'string' ? { home: connection, signing: undefined } : connection;
30
22
  if (d.trust === 'signed')
31
23
  signingContext({ name: d.name, signing });
32
- const dir = path.join(hubDir, d.store.path, '.git');
24
+ const dir = path.join(hubDir, d.contract?.path ?? fail('no operator contract source'), '.git');
33
25
  // A signed hub's repository already exists: rootFor made it with the root key.
34
26
  if (!fs.existsSync(dir)) {
35
27
  mkdirIn(home, path.dirname(dir));
@@ -37,8 +29,7 @@ export class GitStore extends Marks {
37
29
  }
38
30
  const s = new GitStore(hubDir, d, home, signing);
39
31
  const sha = s.commit('operator', text, s.tree(null, Object.entries(contract).map(([p, c]) => ({ path: p, content: c, mode: '100644' }))), []);
40
- if (d.trust === 'signed')
41
- d.genesis = sha;
32
+ d.genesis = sha;
42
33
  if (!s.advance('refs/heads/main', sha, null))
43
34
  fail(`hub ${d.name}: main already exists`);
44
35
  s.checkout();
@@ -47,10 +38,10 @@ export class GitStore extends Marks {
47
38
  // A new signed hub: the root key is generated on this machine and pinned in the descriptor.
48
39
  static rootFor(hubDir, d, home, signing) {
49
40
  signingContext({ name: d.name, signing });
50
- const dir = path.join(hubDir, d.store.path, '.git');
41
+ const dir = path.join(hubDir, d.contract?.path ?? fail('no operator contract source'), '.git');
51
42
  mkdirIn(home, path.dirname(dir));
52
43
  init(dir, home);
53
- return Remote.setupSigned({ name: d.name, dir, d, signing }, d.store.remote).root;
44
+ return Remote.setupSigned({ name: d.name, dir, d, signing }, d.contract?.remote).root;
54
45
  }
55
46
  logIds(room) { return [...new Set(this.live(room).map(e => e.author))]; }
56
47
  logHead(room, id) { return this.live(room).filter(e => e.author === id).at(-1)?.sha ?? null; }
@@ -77,15 +68,6 @@ export class GitStore extends Marks {
77
68
  const id = this.git(['hash-object', '-w', '--', file]).trim();
78
69
  return { id, size: Number(this.git(['cat-file', '-s', id]).trim()) };
79
70
  }
80
- // A tree of the staged files under refs/ringi/staged/<genesis>/<who>: git keeps what a ref reaches.
81
- retain(room, who, entries) {
82
- const ref = `refs/ringi/staged/${room.genesis}/${who}`;
83
- if (!entries.length) {
84
- this.gitOk(['update-ref', '-d', ref]);
85
- return;
86
- }
87
- this.git(['update-ref', ref, this.tree(null, entries)]);
88
- }
89
71
  // One message on top of the room's branch.
90
72
  append(room, who, text, entries) {
91
73
  if (checkOutgoing(text, s => this.isRef(s)).trailers['ringi-files'])
@@ -104,10 +86,10 @@ export class GitStore extends Marks {
104
86
  return this.trust === 'signed' ? Remote.verify(this.h, this.remote(room), id, head) : null;
105
87
  }
106
88
  pin(room, reader, id, rev) {
107
- this.git(['update-ref', `refs/ringi/accepted/${room.genesis}/${reader}/${id}`, rev]);
89
+ this.git(['update-ref', `refs/ringi/accepted/${room.genesis}/${reader}/logs/${id}`, rev]);
108
90
  }
109
91
  unpin(room, reader, id) {
110
- this.gitOk(['update-ref', '-d', `refs/ringi/accepted/${room.genesis}/${reader}/${id}`]);
92
+ this.gitOk(['update-ref', '-d', `refs/ringi/accepted/${room.genesis}/${reader}/logs/${id}`]);
111
93
  }
112
94
  file(rev, p) { return runGitRaw(this.args(['show', `${rev}:${p}`]), this.home); }
113
95
  sizes(rev, paths) {
@@ -0,0 +1,86 @@
1
+ // Signals and telemetry: one append-only stream per actor in the selected room repository.
2
+ import { Branches } from './branches.js';
3
+ import { fail } from '../../lib/index.js';
4
+ import { streamName, streamRef, scanStream, signalEvents } from './remote/streams.js';
5
+ import { heartbeatBody } from './remote/heartbeat-facts.js';
6
+ import { push } from './remote/push.js';
7
+ export class Marks extends Branches {
8
+ streamAlarms = new Map();
9
+ scannedStreams = new Map();
10
+ streams(_room, kind) {
11
+ return this.refsUnder('refs/heads/').flatMap(([ref, head]) => {
12
+ const s = streamName(ref);
13
+ return s?.kind === kind ? [{ actor: s.actor, head }] : [];
14
+ });
15
+ }
16
+ readStream(room, actor, kind, head) {
17
+ const ref = streamRef(actor, kind);
18
+ const chat = this.tip(room.name) ?? fail('room chat is missing');
19
+ const cached = this.scannedStreams.get(ref);
20
+ if (cached?.seen === head && cached.chat === chat)
21
+ return cached.stream;
22
+ const prefix = cached && this.extends(cached.chat, chat) && this.extends(cached.stream.head, head) ? cached.stream : undefined;
23
+ const s = scanStream({ H: this.h, R: this.remote(room), actor, kind, head, prefix });
24
+ // Telemetry has no domain fold: keep only its latest valid facts in this handle, without pruning Git history.
25
+ if (kind === 'telemetry')
26
+ s.records = s.records.slice(-1);
27
+ this.scannedStreams.set(ref, { seen: head, chat, stream: s });
28
+ if (s.why)
29
+ this.streamAlarms.set(ref, `signal stream ${actor}: ${s.why}; stopped at ${s.head.slice(0, 12)}`);
30
+ else
31
+ this.streamAlarms.delete(ref);
32
+ return s;
33
+ }
34
+ signalHeads(room) { return this.streams(room, 'signals'); }
35
+ signals(room) {
36
+ return this.streams(room, 'signals').flatMap(({ actor, head }) => signalEvents(this.remote(room), actor, this.readStream(room, actor, 'signals', head)));
37
+ }
38
+ pinSignals(room, reader, actor, head) {
39
+ streamRef(actor, 'signals');
40
+ this.git(['update-ref', `refs/ringi/accepted/${room.genesis}/${reader}/signals/${actor}`, head]);
41
+ }
42
+ alarms(room) { return [...super.alarms(room), ...this.streamAlarms.values()]; }
43
+ appendStream(room, who, kind, body, tuple) {
44
+ const ref = streamRef(who, kind);
45
+ for (let attempt = 0; attempt < 8; attempt++) {
46
+ const current = this.room(room.name) ?? fail(`room ${room.name} is gone`);
47
+ const old = this.rev(ref);
48
+ let prefix;
49
+ if (old) {
50
+ const checked = this.readStream(current, who, kind, old);
51
+ prefix = checked;
52
+ if (checked.why || checked.head !== old)
53
+ fail(`ALARM ${ref}: ${checked.why ?? 'unaccepted dependencies'}; nothing appended`);
54
+ if (tuple && checked.records.some(r => r.fields.get('Target') === tuple.target && r.fields.get('Signal') === tuple.signal)) {
55
+ push(this.h, ref);
56
+ return old;
57
+ }
58
+ }
59
+ const parent = old ?? room.genesis;
60
+ const tree = this.git(['rev-parse', `${parent}^{tree}`]).trim();
61
+ const sha = this.commit(who, body(current.head), tree, [parent]);
62
+ const checked = scanStream({ H: this.h, R: this.remote(current), actor: who, kind, head: sha, prefix });
63
+ if (checked.why || checked.head !== sha)
64
+ fail(checked.why ?? 'stream dependencies are not accepted');
65
+ if (this.advance(ref, sha, old))
66
+ return sha;
67
+ }
68
+ return fail(`${ref} kept moving; retry`);
69
+ }
70
+ signal(room, who, target, signal) {
71
+ this.appendStream(room, who, 'signals', control => `Room: ${room.genesis}\nControl: ${control}\nTarget: ${target}\nSignal: ${signal}\n`, { target, signal });
72
+ }
73
+ heartbeat(room, who, target, text) {
74
+ const body = /^Room:/m.test(text) ? text : `${text.trimEnd()}\nRoom: ${room.genesis}\n`;
75
+ if (heartbeatBody(body) !== room.genesis)
76
+ fail('heartbeat names another room');
77
+ return this.appendStream(room, who, 'telemetry', control => `${body.trimEnd()}\nControl: ${control}\nTarget: ${target}\n`);
78
+ }
79
+ heartbeats(room) {
80
+ return this.streams(room, 'telemetry').flatMap(({ actor, head }) => {
81
+ const latest = this.readStream(room, actor, 'telemetry', head).records.at(-1);
82
+ return latest ? [{ agent: actor, target: latest.fields.get('Target'), time: latest.raw.time, text: latest.raw.text }] : [];
83
+ });
84
+ }
85
+ }
86
+ //# sourceMappingURL=marks.js.map
@@ -19,7 +19,9 @@ export const readCommits = (H, shas) => {
19
19
  const parents = [...hdr.matchAll(/^parent ([0-9a-f]+)$/gm)].map(m => m[1]);
20
20
  const author = /^author (.*?) <[^>\n]*> \d+ [+-]\d{4}$/m.exec(hdr)?.[1] ?? '';
21
21
  const message = split < 0 ? Buffer.alloc(0) : body.subarray(split + 2);
22
- return { sha, parents, author, body: message, text: P.decodeText(message).text ?? '' };
22
+ const committer = /^committer (.*?) <[^>\n]*> (\d+) [+-]\d{4}$/m.exec(hdr);
23
+ const tree = /^tree ([0-9a-f]+)$/m.exec(hdr)?.[1] ?? '';
24
+ return { sha, parents, author, committer: committer?.[1] ?? '', time: Number(committer?.[2]), tree, body: message, text: P.decodeText(message).text ?? '' };
23
25
  });
24
26
  };
25
27
  //# sourceMappingURL=commits.js.map
@@ -4,6 +4,7 @@ import path from 'node:path';
4
4
  import * as C from '../../../lib/index.js';
5
5
  import * as FS from '../../fs/index.js';
6
6
  import * as P from '../../../core/hub/protocol/index.js';
7
+ import { storeOf } from '../../../core/hub/rooms/address.js';
7
8
  import { withVerification } from './cache.js';
8
9
  import { BASE, command } from './process.js';
9
10
  import { ACCEPT, TRACK } from './types.js';
@@ -32,7 +33,13 @@ export const isRemote = (H) => {
32
33
  C.fail(`unsupported hub trust ${String(H.d.trust)}`);
33
34
  return H.d.trust === 'signed';
34
35
  };
35
- export const origin = (H) => H.d.store.remote;
36
+ export const origin = (H) => {
37
+ const address = H.endpoint ? H.endpoint.store.remote : H.d.contract?.remote;
38
+ if (!address)
39
+ return undefined;
40
+ const { type, locator } = storeOf(address);
41
+ return type === 'git' ? locator : C.fail(`git cannot open a ${type} address`);
42
+ };
36
43
  export const suffix = (ref) => ref.replace(/^refs\/heads\//, '');
37
44
  export const accepted = (ref) => ACCEPT + suffix(ref);
38
45
  export const tracking = (ref) => TRACK + suffix(ref);