@amalgm/shell 0.1.17 → 0.1.19

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/PURPOSE.md CHANGED
@@ -93,6 +93,11 @@ shell only assembles.
93
93
  an in-flight registration. A gateway response belongs to the exact wire
94
94
  that delivered its request; if that source closes first, the late response
95
95
  is discarded cleanly rather than sent through a replacement or closed wire.
96
+ Closing is a one-way lifecycle boundary: a rescan that was already in
97
+ flight may finish its durable work, but it can never recreate watcher
98
+ handles afterward. Each tracked root owns one recursive Node watcher, not
99
+ one handle per descendant directory; the Node version floor supplies this
100
+ primitive on macOS, Linux, and Windows.
96
101
 
97
102
  17. **Independent content may travel concurrently; authority remains atomic.**
98
103
  The host bounds parallel uploads for small immutable objects and processes
@@ -100,13 +105,48 @@ shell only assembles.
100
105
  memory. The registry head advances only after every referenced object is
101
106
  durably acknowledged.
102
107
 
103
- 18. **A Git repository travels as one repository parcel.** The host uses Git
104
- itself to capture and restore the repository's Card + Checkpoint transport.
105
- `.git` is transport metadata rather than entity ground; worktree children
106
- keep their UUID rows locally and ride as an identity map inside the parcel,
107
- while the cloud registry carries the one `repo.git` record. A shallow
108
- boundary travels in that parcel and is installed before Git reads its
109
- bundle; it changes transport completeness, not the semantic repository id.
108
+ 18. **A Git repository travels through Git.** The host asks Git to pack the
109
+ declared refs against the authority's known object frontier and asks Git
110
+ to index received packs. `.git` is transport metadata rather than entity
111
+ ground; worktree children keep their UUID rows locally and ride in the
112
+ repository state metadata, while the cloud registry carries the one
113
+ `repo.git` record. A shallow boundary travels with that metadata and is
114
+ installed before Git reads the imported objects.
115
+
116
+ 19. **Live owns transfer; Shell owns transfer effects.** `@amalgm/live`
117
+ decides which entity types have artifacts, which chunks are missing, when
118
+ an upload manifest may commit, and when a download is verified. The Shell
119
+ adapter supplies seekable immutable-cache reads, the authority inventory
120
+ probe, bounded R2 requests, and a machine-local content-addressed chunk
121
+ cache; it never scans, registers, materializes, or publishes inside those
122
+ operations.
123
+ Control and integrity metadata remains JSON, while immutable block and Git
124
+ parcel bytes use the authenticated binary WebSocket rail without base64.
125
+
126
+ 20. **Git is the repository-transfer performance gate.** On the same source,
127
+ destination inventory, machine, and network path, cold upload sends the
128
+ same Git object pack as a native push and incremental upload sends only the
129
+ newly missing objects. Timing comparisons use repeated runs because wall
130
+ clocks are noisy; byte-work parity is exact and any fixed Amalgm metadata
131
+ overhead is reported separately.
132
+
133
+ 21. **Watch events preserve suspicion until proof.** A named filesystem event
134
+ scopes registration evidence to that path and its ancestors; a nameless
135
+ event, index-wide Git change, enrollment-policy change, watcher restart,
136
+ or command-end catch-up scopes the complete covered root. A scan settles
137
+ only the generations it observed, so an event received during that scan
138
+ remains pending.
139
+
140
+ 22. **Git supplies clean repository evidence.** Registration obtains clean
141
+ tracked leaf identity and text/binary classification from Git's index,
142
+ attributes, and object database. It reads worktree bytes only for dirty or
143
+ untracked leaves. Git ignore never becomes Amalgm enrollment policy.
144
+
145
+ 23. **Cold add never rereads a repository graph.** Download verifies and
146
+ assembles each content-addressed transport to a file, streams its Git pack
147
+ range directly into `index-pack`, and derives local SQLite rows from the
148
+ transported UUID/type/payload identity map plus filesystem stats. It does
149
+ not buffer the complete repository parcel or reclassify checked-out files.
110
150
 
111
151
  ## Relationship to amalgm-engine
112
152
 
@@ -1,5 +1,11 @@
1
1
  export declare function ensurePrivateDir(directory: string): void;
2
2
  export declare function atomicWrite(file: string, bytes: string | Uint8Array, mode?: number): void;
3
+ export declare function atomicCopy(source: string, destination: string, mode?: number): void;
4
+ /** Assemble verified chunk files without holding the complete artifact in RAM. */
5
+ export declare function atomicAssemble(destination: string, sources: readonly string[]): Promise<{
6
+ readonly bytes: number;
7
+ readonly sha256: string;
8
+ }>;
3
9
  export declare function readJson<T>(file: string): T | null;
4
10
  export declare function atomicJson(file: string, value: unknown): void;
5
11
  /** Commit related JSON documents without ever leaving a split public/secret
@@ -1,6 +1,7 @@
1
- import { randomUUID } from "node:crypto";
2
- import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { chmodSync, copyFileSync, createReadStream, createWriteStream, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
3
3
  import { dirname } from "node:path";
4
+ import { once } from "node:events";
4
5
  export function ensurePrivateDir(directory) {
5
6
  mkdirSync(directory, { recursive: true, mode: 0o700 });
6
7
  chmodSync(directory, 0o700);
@@ -17,6 +18,49 @@ export function atomicWrite(file, bytes, mode = 0o600) {
17
18
  rmSync(temporary, { force: true });
18
19
  }
19
20
  }
21
+ export function atomicCopy(source, destination, mode = 0o600) {
22
+ ensurePrivateDir(dirname(destination));
23
+ const temporary = `${destination}.${randomUUID()}.tmp`;
24
+ try {
25
+ copyFileSync(source, temporary);
26
+ chmodSync(temporary, mode);
27
+ renameSync(temporary, destination);
28
+ }
29
+ finally {
30
+ rmSync(temporary, { force: true });
31
+ }
32
+ }
33
+ /** Assemble verified chunk files without holding the complete artifact in RAM. */
34
+ export async function atomicAssemble(destination, sources) {
35
+ ensurePrivateDir(dirname(destination));
36
+ const temporary = `${destination}.${randomUUID()}.tmp`;
37
+ const output = createWriteStream(temporary, { flags: "wx", mode: 0o600 });
38
+ const hash = createHash("sha256");
39
+ let bytes = 0;
40
+ try {
41
+ for (const source of sources) {
42
+ for await (const chunk of createReadStream(source)) {
43
+ const value = chunk;
44
+ hash.update(value);
45
+ bytes += value.byteLength;
46
+ if (!output.write(value))
47
+ await once(output, "drain");
48
+ }
49
+ }
50
+ output.end();
51
+ await once(output, "close");
52
+ renameSync(temporary, destination);
53
+ chmodSync(destination, 0o600);
54
+ return { bytes, sha256: hash.digest("hex") };
55
+ }
56
+ catch (error) {
57
+ output.destroy();
58
+ throw error;
59
+ }
60
+ finally {
61
+ rmSync(temporary, { force: true });
62
+ }
63
+ }
20
64
  export function readJson(file) {
21
65
  try {
22
66
  return JSON.parse(readFileSync(file, "utf8"));
@@ -1 +1 @@
1
- {"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../src/filesystem.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../src/filesystem.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare function runGit(cwd: string, args: readonly string[], input?: Uint8Array): Buffer;
2
+ /** Git grep uses exit 1 to mean a valid search with no matches. */
3
+ export declare function runGitSearch(cwd: string, args: readonly string[]): Buffer;
4
+ /** Stream a potentially large Git result directly to a private destination. */
5
+ export declare function runGitToFile(cwd: string, args: readonly string[], input: Uint8Array, file: string): void;
6
+ export declare function tryGit(cwd: string, args: readonly string[]): Buffer | null;
7
+ export declare const gitText: (cwd: string, args: readonly string[]) => string;
8
+ export declare function tryGitText(cwd: string, args: readonly string[]): string | null;
@@ -0,0 +1,68 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { closeSync, openSync } from "node:fs";
3
+ const MAX_GIT_BUFFER = 512 * 1024 * 1024;
4
+ function explainGitFailure(error, args) {
5
+ const failure = error;
6
+ const stderr = failure.stderr?.toString("utf8").trim();
7
+ failure.message = `git ${args.join(" ")} failed${stderr ? `: ${stderr}` : ""}`;
8
+ throw failure;
9
+ }
10
+ export function runGit(cwd, args, input) {
11
+ try {
12
+ return execFileSync("git", [...args], {
13
+ cwd,
14
+ input,
15
+ maxBuffer: MAX_GIT_BUFFER,
16
+ stdio: ["pipe", "pipe", "pipe"],
17
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
18
+ });
19
+ }
20
+ catch (error) {
21
+ explainGitFailure(error, args);
22
+ }
23
+ }
24
+ /** Git grep uses exit 1 to mean a valid search with no matches. */
25
+ export function runGitSearch(cwd, args) {
26
+ try {
27
+ return runGit(cwd, args);
28
+ }
29
+ catch (error) {
30
+ const failure = error;
31
+ if (failure.status === 1)
32
+ return failure.stdout ?? Buffer.alloc(0);
33
+ throw error;
34
+ }
35
+ }
36
+ /** Stream a potentially large Git result directly to a private destination. */
37
+ export function runGitToFile(cwd, args, input, file) {
38
+ const descriptor = openSync(file, "wx", 0o600);
39
+ try {
40
+ execFileSync("git", [...args], {
41
+ cwd,
42
+ input,
43
+ maxBuffer: MAX_GIT_BUFFER,
44
+ stdio: ["pipe", descriptor, "pipe"],
45
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
46
+ });
47
+ }
48
+ catch (error) {
49
+ explainGitFailure(error, args);
50
+ }
51
+ finally {
52
+ closeSync(descriptor);
53
+ }
54
+ }
55
+ export function tryGit(cwd, args) {
56
+ try {
57
+ return runGit(cwd, args);
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ export const gitText = (cwd, args) => runGit(cwd, args).toString("utf8").trim();
64
+ export function tryGitText(cwd, args) {
65
+ const value = tryGit(cwd, args);
66
+ return value === null ? null : value.toString("utf8").trim();
67
+ }
68
+ //# sourceMappingURL=git-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-command.js","sourceRoot":"","sources":["../src/git-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { type EntityType } from "@amalgm/live";
2
+ export interface GitRegisteredLeaf {
3
+ readonly type: Extract<EntityType, "file.text" | "file.binary" | "link">;
4
+ /** Git's indexed blob is the content witness; Shell does not hash it again. */
5
+ readonly payloadVersion: string;
6
+ }
7
+ export interface GitRegistrationEvidence {
8
+ /** Present only while the worktree path still agrees with the indexed blob. */
9
+ readonly cleanLeaves: ReadonlyMap<string, GitRegisteredLeaf>;
10
+ }
11
+ /**
12
+ * Obtain registration evidence from Git's index and object database.
13
+ *
14
+ * Git is authoritative only for stage-zero paths whose worktree stat/content
15
+ * still agrees with the index. Dirty and untracked paths are deliberately
16
+ * absent so the ordinary scanner must read their current worktree bytes.
17
+ */
18
+ export declare function inspectGitRegistration(repository: string, paths?: readonly string[] | null): GitRegistrationEvidence;
@@ -0,0 +1,107 @@
1
+ import { classifyFile } from "@amalgm/live";
2
+ import { gitText, runGit, runGitSearch, tryGitText } from "./git-command.js";
3
+ const zeroFields = (bytes) => Buffer.from(bytes).toString("utf8").split("\0").filter((field) => field.length > 0);
4
+ const literalPathspecs = (paths) => paths.map((path) => {
5
+ const segments = path.split("/");
6
+ if (!path || path.startsWith("/") || segments.some((segment) => segment === "..")) {
7
+ throw new Error(`Git registration path is unsafe: ${path}`);
8
+ }
9
+ return `:(literal)${path}`;
10
+ });
11
+ function indexedBlobs(repository, paths) {
12
+ if (paths?.length === 0)
13
+ return new Map();
14
+ const fields = zeroFields(runGit(repository, [
15
+ "ls-files", "--stage", "-z",
16
+ ...(paths ? ["--", ...literalPathspecs(paths)] : []),
17
+ ]));
18
+ const entries = new Map();
19
+ for (const field of fields) {
20
+ const separator = field.indexOf("\t");
21
+ if (separator < 0)
22
+ throw new Error("Git returned an invalid index entry");
23
+ const [mode, objectId, stage] = field.slice(0, separator).split(" ");
24
+ const path = field.slice(separator + 1);
25
+ if (!mode || !objectId || !stage || !path)
26
+ throw new Error("Git returned an invalid index entry");
27
+ if (stage !== "0")
28
+ throw new Error(`repository index has unresolved entry: ${path}`);
29
+ entries.set(path, { mode, objectId });
30
+ }
31
+ return entries;
32
+ }
33
+ function blobSizes(repository, blobs) {
34
+ const objectIds = [...new Set([...blobs.values()]
35
+ .filter((blob) => blob.mode !== "160000")
36
+ .map((blob) => blob.objectId))];
37
+ if (objectIds.length === 0)
38
+ return new Map();
39
+ const output = runGit(repository, ["cat-file", "--batch-check=%(objectname) %(objectsize)"], Buffer.from(`${objectIds.join("\n")}\n`, "utf8")).toString("utf8");
40
+ const result = new Map();
41
+ for (const line of output.split("\n").filter(Boolean)) {
42
+ const separator = line.lastIndexOf(" ");
43
+ const objectId = line.slice(0, separator);
44
+ const size = Number(line.slice(separator + 1));
45
+ if (!objectId || !Number.isSafeInteger(size) || size < 0) {
46
+ throw new Error("Git returned invalid indexed blob metadata");
47
+ }
48
+ result.set(objectId, size);
49
+ }
50
+ return result;
51
+ }
52
+ function diffAttributes(repository, paths) {
53
+ if (paths.length === 0)
54
+ return new Map();
55
+ const output = zeroFields(runGit(repository, ["check-attr", "--cached", "-z", "--stdin", "diff"], Buffer.from(`${paths.join("\0")}\0`, "utf8")));
56
+ if (output.length !== paths.length * 3)
57
+ throw new Error("Git returned invalid diff attributes");
58
+ const result = new Map();
59
+ for (let index = 0; index < output.length; index += 3) {
60
+ if (output[index + 1] !== "diff")
61
+ throw new Error("Git returned the wrong requested attribute");
62
+ result.set(output[index], output[index + 2]);
63
+ }
64
+ return result;
65
+ }
66
+ function binaryDrivers(repository, attributes) {
67
+ const drivers = new Set([...attributes.values()].filter((value) => !["set", "unset", "unspecified"].includes(value)));
68
+ return new Set([...drivers].filter((driver) => tryGitText(repository, ["config", "--bool", "--get", `diff.${driver}.binary`]) === "true"));
69
+ }
70
+ /**
71
+ * Obtain registration evidence from Git's index and object database.
72
+ *
73
+ * Git is authoritative only for stage-zero paths whose worktree stat/content
74
+ * still agrees with the index. Dirty and untracked paths are deliberately
75
+ * absent so the ordinary scanner must read their current worktree bytes.
76
+ */
77
+ export function inspectGitRegistration(repository, paths = null) {
78
+ const blobs = indexedBlobs(repository, paths);
79
+ if (blobs.size === 0)
80
+ return { cleanLeaves: new Map() };
81
+ const pathspecs = paths ? literalPathspecs(paths) : [];
82
+ const dirty = new Set(zeroFields(runGit(repository, [
83
+ "diff-files", "--name-only", "-z", "--", ...pathspecs,
84
+ ])));
85
+ const text = new Set(zeroFields(runGitSearch(repository, [
86
+ "grep", "--cached", "-I", "-l", "-z", "-e", "", "--", ...pathspecs,
87
+ ])).filter((path) => blobs.has(path)));
88
+ const blobPaths = [...blobs.keys()];
89
+ const sizes = blobSizes(repository, blobs);
90
+ const attributes = diffAttributes(repository, blobPaths);
91
+ const forcedBinaryDrivers = binaryDrivers(repository, attributes);
92
+ const objectFormat = gitText(repository, ["rev-parse", "--show-object-format"]);
93
+ const cleanLeaves = new Map();
94
+ for (const [path, blob] of blobs) {
95
+ if (dirty.has(path) || blob.mode === "160000")
96
+ continue;
97
+ const attribute = attributes.get(path) ?? "unspecified";
98
+ const forcedBinary = attribute === "unset" || forcedBinaryDrivers.has(attribute);
99
+ const binary = forcedBinary || (!text.has(path) && (sizes.get(blob.objectId) ?? 0) > 0);
100
+ cleanLeaves.set(path, {
101
+ type: blob.mode === "120000" ? "link" : classifyFile({ binary }),
102
+ payloadVersion: `git:${objectFormat}:${blob.objectId}`,
103
+ });
104
+ }
105
+ return { cleanLeaves };
106
+ }
107
+ //# sourceMappingURL=git-registration-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-registration-host.js","sourceRoot":"","sources":["../src/git-registration-host.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type LocalRepoState, type RepoIdentityEntry, type RepoState } from "@amalgm/live";
1
+ import { type RepoIdentityEntry, type RepoState, type RepositoryTransportLayout } from "@amalgm/live";
2
2
  /** A `.git` directory or linked-worktree file is evidence only when Git says
3
3
  * this exact directory is the worktree root. Stale marker files remain
4
4
  * ordinary folder ground. */
@@ -6,15 +6,34 @@ export declare function isRepository(directory: string): boolean;
6
6
  export interface PriorRepositoryTransport {
7
7
  readonly stateId: string;
8
8
  readonly transportVersion: string;
9
- readonly bytes: Uint8Array;
9
+ readonly card: RepoState["card"];
10
+ readonly identityHash: string;
10
11
  }
11
12
  export interface CapturedRepositoryTransport extends PriorRepositoryTransport {
12
13
  readonly state: RepoState;
14
+ /** null means the prior immutable transport is already the exact result. */
15
+ readonly bytes: Uint8Array | null;
13
16
  }
14
- /** Capture one semantic repository state. An unchanged state and identity map
15
- * reuse their prior immutable transport head; a new state creates one Git
16
- * bundle parcel, never one cloud object per worktree file. */
17
- export declare function captureRepository(repository: string, identity: readonly RepoIdentityEntry[], prior: PriorRepositoryTransport | null): CapturedRepositoryTransport;
18
- /** Materialize and then re-derive the semantic ids. Only a proved return is
19
- * accepted as the repository state described by the transport. */
20
- export declare function applyRepository(repository: string, bytes: Uint8Array): LocalRepoState;
17
+ /** Capture one semantic repository state. A chainable capture packs only Git
18
+ * objects absent from its parent and only changed identity-map paths. */
19
+ export declare function captureRepository(repository: string, identity: readonly RepoIdentityEntry[], prior: PriorRepositoryTransport | null, previousIdentity?: readonly RepoIdentityEntry[] | null): CapturedRepositoryTransport;
20
+ export interface AppliedRepositoryState {
21
+ readonly stateId: string;
22
+ readonly cardId: string;
23
+ readonly checkpointId: string;
24
+ readonly card: RepoState["card"];
25
+ readonly transportVersion: string;
26
+ readonly identity: readonly RepoIdentityEntry[];
27
+ }
28
+ /** Materialize a complete transport chain and then re-derive its semantic
29
+ * state. The oldest node must be self-contained; every later node must name
30
+ * the exact predecessor whose Git objects and identity map it extends. */
31
+ export declare function applyRepository(repository: string, chain: readonly Uint8Array[]): AppliedRepositoryState;
32
+ export interface SealedRepositoryTransport {
33
+ readonly file: string;
34
+ readonly transportVersion: string;
35
+ }
36
+ export declare function inspectRepositoryTransportFile(file: string): RepositoryTransportLayout;
37
+ /** Apply sealed repository artifacts by streaming each Git range directly
38
+ * into index-pack. Download already verified each complete transport hash. */
39
+ export declare function applyRepositoryFiles(repository: string, chain: readonly SealedRepositoryTransport[]): Promise<AppliedRepositoryState>;