@agentshouse/kit 0.1.0-alpha.3 → 0.1.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/package.json +1 -1
- package/src/contract.js +2 -2
- package/src/mount.js +7 -7
- package/src/sync-state.js +4 -0
- package/src/sync.js +11 -6
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ On Linux `amd64` or `arm64` with a working Docker Engine, run the published,
|
|
|
10
10
|
versioned bootstrap once:
|
|
11
11
|
|
|
12
12
|
```sh
|
|
13
|
-
bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.
|
|
13
|
+
bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.5/connect-linux.sh)
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
The release asset pins one immutable multi-architecture image digest. It creates
|
|
@@ -1111,8 +1111,11 @@ It selects prefixes over the User root, materializes them into a named local
|
|
|
1111
1111
|
directory, enumerates whole content and removals after the recorded positions,
|
|
1112
1112
|
and submits a resolved exact-base change set the caller prepared. Kit does no
|
|
1113
1113
|
local reconciliation. The mode shares no Working Copy manifest, never infers a
|
|
1114
|
-
removal from a locally absent file, and writes authored mutations only
|
|
1115
|
-
|
|
1114
|
+
removal from a locally absent file, and writes authored mutations only within
|
|
1115
|
+
House's declared write scopes: a selected Room's Library and, where granted,
|
|
1116
|
+
`ROOM.md`. `/private` selects the Private Room by its Room reference, records an independent Room
|
|
1117
|
+
position, and keeps its `agents/` cards and Room-specific private `AGENTS.md`
|
|
1118
|
+
beside `library/**`.
|
|
1116
1119
|
|
|
1117
1120
|
```sh
|
|
1118
1121
|
kit sync bootstrap ./replica \
|
|
@@ -1179,7 +1182,7 @@ for a batch that reaches it.
|
|
|
1179
1182
|
|
|
1180
1183
|
## Attachments
|
|
1181
1184
|
|
|
1182
|
-
Upload one local file as an attachment to a Room or to your
|
|
1185
|
+
Upload one local file as an attachment to a Room or to your Private Room. Name
|
|
1183
1186
|
the place explicitly. Kit sends the descriptor and the selected bytes; it does
|
|
1184
1187
|
not scan a directory, convert a URL, or attach sibling files, credentials, or
|
|
1185
1188
|
absolute paths.
|
|
@@ -1583,7 +1586,7 @@ prepared model definitions survive a later content-mount refusal or unmount.
|
|
|
1583
1586
|
|
|
1584
1587
|
The atomic text mount includes a report with pending transfer rows. Kit then
|
|
1585
1588
|
uploads each downloaded file once as an attachment to the mount's Room or
|
|
1586
|
-
|
|
1589
|
+
Private Room, independently retrieves and compares the saved bytes, and only
|
|
1587
1590
|
after that proof succeeds rewrites every link to it, in every referring
|
|
1588
1591
|
document, to its attachment reference, such as `at_1x.q`. The reference is an
|
|
1589
1592
|
identity House resolves, not an HTTP download URL. A link's query and fragment
|
package/package.json
CHANGED
package/src/contract.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CLAUDE_PASTED_CODE, CODEX_DEVICE_CODE, GROK_DEVICE_CODE } from "./agent-logins.js";
|
|
2
2
|
|
|
3
|
-
export const KIT_CONTRACT_VERSION = "2026-09-
|
|
3
|
+
export const KIT_CONTRACT_VERSION = "2026-09-27-private-room-scope";
|
|
4
4
|
export const KIT_CAPTURE_BATCH_MAX = 100;
|
|
5
5
|
export const COMMAND_INPUT_MAX_BYTES = 4 * 1024;
|
|
6
6
|
export const AUTHORIZATION_OUTPUT_MAX_BYTES = 4 * 1024;
|
|
@@ -288,7 +288,7 @@ export const KIT_DOOR_DISCOVER_PATH = "/kit/door/discover";
|
|
|
288
288
|
export const KIT_DOOR_BOOTSTRAP_PATH = "/kit/door/bootstrap";
|
|
289
289
|
export const KIT_DOOR_ENUMERATE_PATH = "/kit/door/enumerate";
|
|
290
290
|
export const KIT_DOOR_BATCH_PATH = "/kit/door/batch";
|
|
291
|
-
export const EXPLICIT_SYNC_VERSION = "explicit-sync/
|
|
291
|
+
export const EXPLICIT_SYNC_VERSION = "explicit-sync/2";
|
|
292
292
|
export const KIT_DOOR_UNMOUNT_PATH = "/kit/door/unmount";
|
|
293
293
|
|
|
294
294
|
export const MIGRATOR_CONTRACT = "kit-migrator/1";
|
package/src/mount.js
CHANGED
|
@@ -84,7 +84,6 @@ export function mountTarget(subtree) {
|
|
|
84
84
|
refuse("kit_mount_subtree_invalid", subtree);
|
|
85
85
|
}
|
|
86
86
|
return {
|
|
87
|
-
kind: own ? "private" : "room",
|
|
88
87
|
handle: own ? null : segments[1],
|
|
89
88
|
root: own ? "/private" : `/rooms/${segments[1]}`,
|
|
90
89
|
subtree,
|
|
@@ -107,10 +106,11 @@ function discoveryOf(value) {
|
|
|
107
106
|
|
|
108
107
|
function authorityFor(discovery, target) {
|
|
109
108
|
const found = discovery.authorities.find((entry) =>
|
|
110
|
-
|
|
109
|
+
entry.kind === "room" && entry.room_handle === target.handle,
|
|
111
110
|
);
|
|
112
111
|
if (found === undefined) refuse("kit_mount_authority_unknown", target.root);
|
|
113
112
|
if (
|
|
113
|
+
typeof found.room_ref !== "string" ||
|
|
114
114
|
!Array.isArray(found.protected_paths) ||
|
|
115
115
|
found.operations === null ||
|
|
116
116
|
typeof found.operations !== "object" ||
|
|
@@ -119,8 +119,8 @@ function authorityFor(discovery, target) {
|
|
|
119
119
|
refuse("kit_mount_rejected", "discover");
|
|
120
120
|
}
|
|
121
121
|
return {
|
|
122
|
-
kind:
|
|
123
|
-
authority: found.
|
|
122
|
+
kind: "room",
|
|
123
|
+
authority: found.room_ref,
|
|
124
124
|
path: target.root,
|
|
125
125
|
protected_paths: found.protected_paths,
|
|
126
126
|
operations: found.operations,
|
|
@@ -326,7 +326,7 @@ function pendingTransfer(held, save) {
|
|
|
326
326
|
};
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
-
async function submitAttachments(session, held,
|
|
329
|
+
async function submitAttachments(session, held, authority, plan, signal) {
|
|
330
330
|
const transfers = [];
|
|
331
331
|
for (const save of plan.saves) {
|
|
332
332
|
const local = held.attachments.get(save.path);
|
|
@@ -341,7 +341,7 @@ async function submitAttachments(session, held, target, authority, plan, signal)
|
|
|
341
341
|
version: save.version,
|
|
342
342
|
name: declared.name,
|
|
343
343
|
mediaType: declared.mediaType ?? undefined,
|
|
344
|
-
room:
|
|
344
|
+
room: authority.authority,
|
|
345
345
|
body,
|
|
346
346
|
signal,
|
|
347
347
|
});
|
|
@@ -471,7 +471,7 @@ export async function mountPackage(held, options, dependencies = {}) {
|
|
|
471
471
|
};
|
|
472
472
|
const localReport = join(held.root, "MIGRATION.json");
|
|
473
473
|
await writeFile(localReport, `${JSON.stringify(result, null, 2)}\n`);
|
|
474
|
-
result.transfers = await submitAttachments(session, held,
|
|
474
|
+
result.transfers = await submitAttachments(session, held, authority, plan, signal);
|
|
475
475
|
|
|
476
476
|
const report = `${target.subtree}/${MOUNT_REPORT_NAME}`;
|
|
477
477
|
await writeFile(localReport, `${JSON.stringify(result, null, 2)}\n`);
|
package/src/sync-state.js
CHANGED
|
@@ -26,6 +26,9 @@ function syncFile(directory, key, kind = "") {
|
|
|
26
26
|
function recordedAuthority(authority) {
|
|
27
27
|
const operations = authority?.operations;
|
|
28
28
|
return (
|
|
29
|
+
authority?.kind === "room" &&
|
|
30
|
+
typeof authority.authority === "string" &&
|
|
31
|
+
typeof authority.path === "string" &&
|
|
29
32
|
typeof authority?.log_epoch === "string" &&
|
|
30
33
|
operations !== null &&
|
|
31
34
|
typeof operations === "object" &&
|
|
@@ -43,6 +46,7 @@ export async function readReplicaState(directory, replica) {
|
|
|
43
46
|
}
|
|
44
47
|
const state = await readNote(syncFile(directory, replicaKey(canonical)), null);
|
|
45
48
|
if (state === null) return null;
|
|
49
|
+
if (state.version !== EXPLICIT_SYNC_VERSION) return null;
|
|
46
50
|
if (!Array.isArray(state.authorities) || !state.authorities.every(recordedAuthority)) return null;
|
|
47
51
|
return state;
|
|
48
52
|
}
|
package/src/sync.js
CHANGED
|
@@ -105,9 +105,6 @@ async function bootstrapBundle(session, prefixes, signal) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
function matchedDiscovery(discovery, scope) {
|
|
108
|
-
if (scope.manifest?.scope === "private") {
|
|
109
|
-
return discovery.authorities.find((entry) => entry.kind === "private");
|
|
110
|
-
}
|
|
111
108
|
return discovery.authorities.find(
|
|
112
109
|
(entry) => entry.kind === "room" && entry.room_ref === scope.manifest?.anchor,
|
|
113
110
|
);
|
|
@@ -173,11 +170,17 @@ function operationsOf(value) {
|
|
|
173
170
|
function authorityRecord(scope, discovery, files) {
|
|
174
171
|
const found = matchedDiscovery(discovery, scope);
|
|
175
172
|
const operations = found === undefined ? null : operationsOf(found.operations);
|
|
176
|
-
if (
|
|
173
|
+
if (
|
|
174
|
+
scope.manifest?.scope !== "room" ||
|
|
175
|
+
typeof scope.manifest.anchor !== "string" ||
|
|
176
|
+
found === undefined ||
|
|
177
|
+
!stringList(found.protected_paths) ||
|
|
178
|
+
operations === null
|
|
179
|
+
) {
|
|
177
180
|
throw new KitRefusal("kit_bootstrap_rejected");
|
|
178
181
|
}
|
|
179
182
|
return {
|
|
180
|
-
kind:
|
|
183
|
+
kind: "room",
|
|
181
184
|
authority: scope.manifest.anchor,
|
|
182
185
|
room_handle: scope.manifest.room_handle,
|
|
183
186
|
path: scope.manifest.path,
|
|
@@ -192,9 +195,10 @@ function authorityRecord(scope, discovery, files) {
|
|
|
192
195
|
async function materialize(options, discovery, bundle, signal, previous = null) {
|
|
193
196
|
const authorities = [];
|
|
194
197
|
for (const scope of bundle.scopes) {
|
|
198
|
+
const record = authorityRecord(scope, discovery, []);
|
|
195
199
|
const held = previous?.authorities.find((entry) => entry.authority === scope.manifest?.anchor);
|
|
196
200
|
const files = await replaceScope(options.replica, held, scope, signal);
|
|
197
|
-
authorities.push(
|
|
201
|
+
authorities.push({ ...record, files });
|
|
198
202
|
}
|
|
199
203
|
const state = {
|
|
200
204
|
version: EXPLICIT_SYNC_VERSION,
|
|
@@ -409,6 +413,7 @@ export async function bootstrap(options, dependencies = {}) {
|
|
|
409
413
|
const canonical = await canonicalReplica(options.replica);
|
|
410
414
|
const existing = await readReplicaState(options.directory, canonical);
|
|
411
415
|
if (existing !== null) throw new KitRefusal("kit_sync_already_bootstrapped", canonical);
|
|
416
|
+
await clearPending(options.directory, canonical);
|
|
412
417
|
return withSession(options, dependencies, async (session, signal) => {
|
|
413
418
|
const discovery = discoveryOf(
|
|
414
419
|
await door(session, KIT_DOOR_DISCOVER_PATH, { prefixes: options.prefixes }, signal),
|