amalgm 0.1.238 → 0.1.240

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 (86) hide show
  1. package/lib/shared-realtime-tunnel.js +22 -14
  2. package/package.json +1 -1
  3. package/runtime/scripts/amalgm-mcp/browser/cookie-jar.js +68 -20
  4. package/runtime/scripts/amalgm-mcp/project-context/store.js +87 -19
  5. package/runtime/scripts/amalgm-mcp/state/attachments.js +40 -12
  6. package/runtime/scripts/amalgm-mcp/state/db.js +216 -17
  7. package/runtime/scripts/amalgm-mcp/state/doc-disk.js +550 -0
  8. package/runtime/scripts/amalgm-mcp/state/docs.js +1101 -301
  9. package/runtime/scripts/amalgm-mcp/state/mutation-contracts.js +99 -0
  10. package/runtime/scripts/amalgm-mcp/state/mutations.js +507 -130
  11. package/runtime/scripts/amalgm-mcp/state/promotions.js +21 -1
  12. package/runtime/scripts/amalgm-mcp/state/replicas.js +134 -13
  13. package/runtime/scripts/amalgm-mcp/state/shared-rest.js +14 -8
  14. package/runtime/scripts/amalgm-mcp/tests/browser-cookie-cloud.test.js +193 -0
  15. package/runtime/scripts/amalgm-mcp/tests/code-project-stream.test.js +313 -94
  16. package/runtime/scripts/amalgm-mcp/tests/fixtures/code-project-stream-v2.json +1 -0
  17. package/runtime/scripts/amalgm-mcp/tests/project-context.test.js +32 -17
  18. package/runtime/scripts/amalgm-mcp/tests/shared-tunnel-rehydration.test.js +84 -0
  19. package/runtime/scripts/amalgm-mcp/tests/state-docs.test.js +376 -13
  20. package/runtime/scripts/amalgm-mcp/tests/state-mutations.test.js +309 -0
  21. package/runtime/scripts/amalgm-mcp/tests/state-shared-replica.test.js +758 -30
  22. package/runtime/scripts/amalgm-mcp/tests/workspace-cards-store.test.js +72 -3
  23. package/runtime/scripts/amalgm-mcp/tests/workspace-cards.test.js +33 -6
  24. package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint-reducer.test.js +27 -0
  25. package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint.test.js +334 -191
  26. package/runtime/scripts/amalgm-mcp/tests/workspace-durable.test.js +24 -0
  27. package/runtime/scripts/amalgm-mcp/tests/workspace-local-intent.test.js +1999 -0
  28. package/runtime/scripts/amalgm-mcp/tests/workspace-native-file-transaction.test.js +364 -0
  29. package/runtime/scripts/amalgm-mcp/tests/workspace-object-tunnel.test.js +81 -3
  30. package/runtime/scripts/amalgm-mcp/tests/workspace-objects.test.js +114 -8
  31. package/runtime/scripts/amalgm-mcp/tests/workspace-provenance.test.js +185 -0
  32. package/runtime/scripts/amalgm-mcp/tests/workspace-publication-invariants.test.js +174 -269
  33. package/runtime/scripts/amalgm-mcp/tests/workspace-reducer-liveness.test.js +26 -0
  34. package/runtime/scripts/amalgm-mcp/tests/workspace-reducer.test.js +2060 -407
  35. package/runtime/scripts/amalgm-mcp/tests/workspace-sync-stats.test.js +119 -0
  36. package/runtime/scripts/amalgm-mcp/tests/workspace-transition.test.js +1446 -0
  37. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-cloud.test.js +5319 -3
  38. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-core.test.js +191 -1
  39. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-store.test.js +3140 -17
  40. package/runtime/scripts/amalgm-mcp/tests/workspace-wall.test.js +135 -637
  41. package/runtime/scripts/amalgm-mcp/workspace/access-store.js +5 -1
  42. package/runtime/scripts/amalgm-mcp/workspace/card.js +7 -7
  43. package/runtime/scripts/amalgm-mcp/workspace/cards.js +36 -12
  44. package/runtime/scripts/amalgm-mcp/workspace/checkpoint.js +436 -173
  45. package/runtime/scripts/amalgm-mcp/workspace/content.js +32 -0
  46. package/runtime/scripts/amalgm-mcp/workspace/durable.js +45 -0
  47. package/runtime/scripts/amalgm-mcp/workspace/git.js +391 -37
  48. package/runtime/scripts/amalgm-mcp/workspace/intent.js +535 -0
  49. package/runtime/scripts/amalgm-mcp/workspace/merge.js +89 -6
  50. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/BUILD.md +31 -0
  51. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/darwin-arm64/amalgm-file-transaction +0 -0
  52. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/linux-x64/amalgm-file-transaction +0 -0
  53. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/build.mjs +72 -0
  54. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/client.js +165 -0
  55. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.mod +5 -0
  56. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.sum +2 -0
  57. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/main.go +2201 -0
  58. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/manifest.json +19 -0
  59. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_darwin.go +18 -0
  60. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_linux.go +18 -0
  61. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_darwin.go +33 -0
  62. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_linux.go +47 -0
  63. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/verify.mjs +43 -0
  64. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_darwin.go +114 -0
  65. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_linux.go +84 -0
  66. package/runtime/scripts/amalgm-mcp/workspace/objects.js +119 -54
  67. package/runtime/scripts/amalgm-mcp/workspace/project-stream.js +616 -168
  68. package/runtime/scripts/amalgm-mcp/workspace/provenance.js +240 -0
  69. package/runtime/scripts/amalgm-mcp/workspace/reducer.js +1979 -570
  70. package/runtime/scripts/amalgm-mcp/workspace/rest.js +49 -28
  71. package/runtime/scripts/amalgm-mcp/workspace/store.js +77 -4
  72. package/runtime/scripts/amalgm-mcp/workspace/sync-stats.js +240 -0
  73. package/runtime/scripts/amalgm-mcp/workspace/transition.js +1729 -192
  74. package/runtime/scripts/amalgm-mcp/workspace/tree/floor.js +100 -0
  75. package/runtime/scripts/amalgm-mcp/workspace/tree/inclusion.js +7 -1
  76. package/runtime/scripts/amalgm-mcp/workspace/tree/local-state.js +73 -61
  77. package/runtime/scripts/amalgm-mcp/workspace/tree/observation-holds.js +127 -0
  78. package/runtime/scripts/amalgm-mcp/workspace/tree/path-state.js +12 -0
  79. package/runtime/scripts/amalgm-mcp/workspace/tree/reducer.js +51 -6
  80. package/runtime/scripts/amalgm-mcp/workspace/tree/root-binding.js +125 -0
  81. package/runtime/scripts/amalgm-mcp/workspace/tree/snapshot.js +79 -8
  82. package/runtime/scripts/amalgm-mcp/workspace/tree/symlinks.js +76 -0
  83. package/runtime/scripts/amalgm-mcp/workspace/tree-cloud.js +3480 -165
  84. package/runtime/scripts/amalgm-mcp/workspace/tree-materialization.js +3766 -0
  85. package/runtime/scripts/amalgm-mcp/workspace/tree-store.js +899 -71
  86. package/runtime/scripts/amalgm-mcp/workspace/wall.js +352 -497
@@ -0,0 +1,31 @@
1
+ # Native workspace file transaction
2
+
3
+ This helper is the only code allowed to observe or cross an ordered file or
4
+ Git-metadata mutation. JavaScript cannot express
5
+ `openat`/`renameat`/`linkat`, so path confinement at that layer has an
6
+ unavoidable check/use race. The helper opens each parent directory with
7
+ `O_NOFOLLOW` and performs every observation and mutation relative to those
8
+ held descriptors.
9
+
10
+ `main.go` owns the transaction and crash ordering. `move_*.go` consumes a
11
+ prepared target without replacing a concurrent destination; its disappearance
12
+ is the crossing receipt. `writers_*.go` proves that an extracted source inode
13
+ has no pre-existing writer before it can be retired. The checked-in binaries
14
+ are required because managed runtimes do not include a Go compiler.
15
+ `manifest.json` binds them to the exact source bytes.
16
+
17
+ The `git-lock` backend prepares index or HEAD bytes inside the linked
18
+ worktree's private Git directory, hard-links them to Git's canonical lock, and
19
+ renames that lock over the destination. The retained hard link identifies the
20
+ crossing even after later Git activity changes the destination or creates a
21
+ new lock.
22
+
23
+ Rebuild and verify both release platforms:
24
+
25
+ ```sh
26
+ node build.mjs
27
+ node verify.mjs
28
+ ```
29
+
30
+ The ordinary JavaScript transition tests execute the host binary against real
31
+ Git repositories, crashes, open descriptors, and directory-swap races.
@@ -0,0 +1,72 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { spawnSync } from 'node:child_process';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const root = path.dirname(fileURLToPath(import.meta.url));
8
+ const sources = fs.readdirSync(root)
9
+ .filter((name) => name.endsWith('.go') || name === 'go.mod' || name === 'go.sum')
10
+ .sort();
11
+ const platforms = [
12
+ { directory: 'darwin-arm64', goos: 'darwin', goarch: 'arm64', cgo: '1' },
13
+ { directory: 'linux-x64', goos: 'linux', goarch: 'amd64', cgo: '0' },
14
+ ];
15
+
16
+ function digestFiles(names) {
17
+ const hash = crypto.createHash('sha256');
18
+ for (const name of names) {
19
+ hash.update(name);
20
+ hash.update('\0');
21
+ hash.update(fs.readFileSync(path.join(root, name)));
22
+ hash.update('\0');
23
+ }
24
+ return hash.digest('hex');
25
+ }
26
+
27
+ function run(command, args, env = {}) {
28
+ const result = spawnSync(command, args, {
29
+ cwd: root,
30
+ env: { ...process.env, ...env },
31
+ stdio: 'inherit',
32
+ });
33
+ if (result.error) throw result.error;
34
+ if (result.status !== 0) {
35
+ throw new Error(`${command} exited ${result.status}`);
36
+ }
37
+ }
38
+
39
+ run('go', ['test', './...']);
40
+ const binaries = {};
41
+ for (const platform of platforms) {
42
+ const directory = path.join(root, 'bin', platform.directory);
43
+ fs.mkdirSync(directory, { recursive: true });
44
+ const output = path.join(directory, 'amalgm-file-transaction');
45
+ run('go', [
46
+ 'build',
47
+ '-trimpath',
48
+ '-ldflags=-s -w',
49
+ '-o',
50
+ output,
51
+ '.',
52
+ ], {
53
+ GOOS: platform.goos,
54
+ GOARCH: platform.goarch,
55
+ CGO_ENABLED: platform.cgo,
56
+ });
57
+ fs.chmodSync(output, 0o755);
58
+ binaries[platform.directory] = crypto
59
+ .createHash('sha256')
60
+ .update(fs.readFileSync(output))
61
+ .digest('hex');
62
+ }
63
+
64
+ fs.writeFileSync(
65
+ path.join(root, 'manifest.json'),
66
+ `${JSON.stringify({
67
+ contract: 'amalgm-native-file-transaction-build@1',
68
+ sourceSha256: digestFiles(sources),
69
+ sources,
70
+ binaries,
71
+ }, null, 2)}\n`,
72
+ );
@@ -0,0 +1,165 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { execFileSync } = require('child_process');
6
+
7
+ function executable() {
8
+ const platform = `${process.platform}-${process.arch}`;
9
+ if (!['darwin-arm64', 'linux-x64'].includes(platform)) {
10
+ throw new Error(`native file transactions do not support ${platform}`);
11
+ }
12
+ const file = path.join(
13
+ __dirname,
14
+ 'bin',
15
+ platform,
16
+ 'amalgm-file-transaction',
17
+ );
18
+ if (!fs.existsSync(file)) {
19
+ throw new Error(`native file transaction helper is missing for ${platform}`);
20
+ }
21
+ return file;
22
+ }
23
+
24
+ function run(transaction, action, content = null, testHooks = {}) {
25
+ const target = transaction.target == null
26
+ ? null
27
+ : {
28
+ ...transaction.target,
29
+ ...(content === null ? {} : { content: content.toString('base64') }),
30
+ };
31
+ let stdout;
32
+ try {
33
+ stdout = execFileSync(executable(), [], {
34
+ input: JSON.stringify({
35
+ action,
36
+ ...(transaction.backend ? { backend: transaction.backend } : {}),
37
+ ...(transaction.pid ? { pid: transaction.pid } : {}),
38
+ ...(transaction.root ? {
39
+ root: transaction.root,
40
+ rootDev: transaction.rootDev,
41
+ rootIno: transaction.rootIno,
42
+ ...(transaction.source ? { source: transaction.source } : {}),
43
+ ...(transaction.sourceIdentity
44
+ ? { sourceIdentity: transaction.sourceIdentity }
45
+ : {}),
46
+ ...(transaction.sourceParentIdentity
47
+ ? { sourceParentIdentity: transaction.sourceParentIdentity }
48
+ : {}),
49
+ ...(transaction.targetParentIdentity
50
+ ? { targetParentIdentity: transaction.targetParentIdentity }
51
+ : {}),
52
+ path: transaction.path,
53
+ id: transaction.id,
54
+ operation: transaction.operation,
55
+ expected: transaction.expected,
56
+ target,
57
+ } : {}),
58
+ ...(testHooks.pauseAfterParentOpen > 0
59
+ ? { testPauseAfterParentOpenMillis: testHooks.pauseAfterParentOpen }
60
+ : {}),
61
+ ...(testHooks.pauseAfterExtraction > 0
62
+ ? { testPauseAfterExtractionMillis: testHooks.pauseAfterExtraction }
63
+ : {}),
64
+ ...(testHooks.pauseBeforeInstall > 0
65
+ ? { testPauseBeforeInstallMillis: testHooks.pauseBeforeInstall }
66
+ : {}),
67
+ ...(testHooks.pauseAfterTreeMove > 0
68
+ ? { testPauseAfterTreeMoveMillis: testHooks.pauseAfterTreeMove }
69
+ : {}),
70
+ ...(testHooks.crashAfterExtraction === true
71
+ ? { testCrashAfterExtraction: true }
72
+ : {}),
73
+ ...(testHooks.crashBeforeInstall === true
74
+ ? { testCrashBeforeInstall: true }
75
+ : {}),
76
+ ...(testHooks.crashAfterInstall === true
77
+ ? { testCrashAfterInstall: true }
78
+ : {}),
79
+ ...(testHooks.crashAfterTreeMove === true
80
+ ? { testCrashAfterTreeMove: true }
81
+ : {}),
82
+ }),
83
+ encoding: 'utf8',
84
+ maxBuffer: action === 'observe' ? 32 * 1024 * 1024 : 1024 * 1024,
85
+ timeout: transaction.backend === 'process-identity' ? 5_000 : 30_000,
86
+ });
87
+ } catch (error) {
88
+ const detail = String(error.stdout || error.stderr || error.message).trim();
89
+ throw new Error(`native file transaction failed: ${detail}`);
90
+ }
91
+ let result;
92
+ try {
93
+ result = JSON.parse(stdout);
94
+ } catch (error) {
95
+ throw new Error(`native file transaction returned invalid output: ${error.message}`);
96
+ }
97
+ if (![
98
+ 'applied',
99
+ 'changed',
100
+ 'pending',
101
+ 'crossed',
102
+ 'not-crossed',
103
+ 'released',
104
+ 'guarded',
105
+ 'identified',
106
+ 'exited',
107
+ 'observed',
108
+ ].includes(result?.status)) {
109
+ throw new Error(`native file transaction returned ${result?.status || 'no status'}`);
110
+ }
111
+ return result;
112
+ }
113
+
114
+ function observe(transaction, testHooks = {}) {
115
+ return run({
116
+ root: transaction.root,
117
+ rootDev: transaction.rootDev,
118
+ rootIno: transaction.rootIno,
119
+ path: transaction.path,
120
+ target: null,
121
+ }, 'observe', null, testHooks);
122
+ }
123
+
124
+ function processLifetime(pid) {
125
+ try {
126
+ const result = run({
127
+ backend: 'process-identity',
128
+ pid,
129
+ target: null,
130
+ }, 'identity');
131
+ if (result.status === 'exited') return { live: false, identity: null };
132
+ if (result.status === 'identified' && typeof result.identity === 'string') {
133
+ return { live: true, identity: result.identity };
134
+ }
135
+ return null;
136
+ } catch {
137
+ return null;
138
+ }
139
+ }
140
+
141
+ function moveNoReplace(transaction, testHooks = {}) {
142
+ return run({
143
+ backend: 'tree-rename',
144
+ root: transaction.root,
145
+ rootDev: transaction.rootDev,
146
+ rootIno: transaction.rootIno,
147
+ source: transaction.source,
148
+ sourceIdentity: transaction.sourceIdentity,
149
+ sourceParentIdentity: transaction.sourceParentIdentity,
150
+ targetParentIdentity: transaction.targetParentIdentity,
151
+ path: transaction.path,
152
+ id: transaction.id,
153
+ operation: transaction.operation,
154
+ expected: null,
155
+ target: null,
156
+ }, 'move', null, testHooks);
157
+ }
158
+
159
+ module.exports = {
160
+ executable,
161
+ moveNoReplace,
162
+ observe,
163
+ processLifetime,
164
+ run,
165
+ };
@@ -0,0 +1,5 @@
1
+ module amalgm.ai/native-file-transaction
2
+
3
+ go 1.25.0
4
+
5
+ require golang.org/x/sys v0.42.0
@@ -0,0 +1,2 @@
1
+ golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
2
+ golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=