amalgm 0.1.245 → 0.1.246
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 +12 -0
- package/lib/cli.js +146 -8
- package/lib/layout.js +89 -4
- package/lib/shared-realtime-tunnel.js +384 -43
- package/lib/supervisor.js +0 -3
- package/package.json +2 -2
- package/runtime/scripts/amalgm-mcp/adapters/contract.js +197 -0
- package/runtime/scripts/amalgm-mcp/adapters/filesystem.js +135 -0
- package/runtime/scripts/amalgm-mcp/adapters/git.js +84 -0
- package/runtime/scripts/amalgm-mcp/adapters/index.js +43 -0
- package/runtime/scripts/amalgm-mcp/adapters/reference.js +31 -0
- package/runtime/scripts/amalgm-mcp/adapters/truth.js +19 -0
- package/runtime/scripts/amalgm-mcp/browser/cookie-jar.js +20 -68
- package/runtime/scripts/amalgm-mcp/index.js +4 -0
- package/runtime/scripts/amalgm-mcp/lib/layout.js +89 -4
- package/runtime/scripts/amalgm-mcp/observer/README.md +259 -0
- package/runtime/scripts/amalgm-mcp/observer/apply.js +150 -0
- package/runtime/scripts/amalgm-mcp/observer/continuity.js +111 -0
- package/runtime/scripts/amalgm-mcp/observer/edges.js +111 -0
- package/runtime/scripts/amalgm-mcp/observer/index.js +1146 -0
- package/runtime/scripts/amalgm-mcp/observer/scan.js +387 -0
- package/runtime/scripts/amalgm-mcp/observer/store.js +262 -0
- package/runtime/scripts/amalgm-mcp/observer/verify.js +200 -0
- package/runtime/scripts/amalgm-mcp/observer/watch.js +62 -0
- package/runtime/scripts/amalgm-mcp/project-context/store.js +19 -87
- package/runtime/scripts/amalgm-mcp/registration/classify.js +33 -0
- package/runtime/scripts/amalgm-mcp/registration/entity-cloud.js +456 -0
- package/runtime/scripts/amalgm-mcp/registration/entity-content.js +345 -0
- package/runtime/scripts/amalgm-mcp/registration/index.js +752 -0
- package/runtime/scripts/amalgm-mcp/registration/refusal.js +42 -0
- package/runtime/scripts/amalgm-mcp/registration/repo-followers.js +127 -0
- package/runtime/scripts/amalgm-mcp/registration/repo-states.js +109 -0
- package/runtime/scripts/amalgm-mcp/registration/service.js +310 -0
- package/runtime/scripts/amalgm-mcp/registration/tree.js +178 -0
- package/runtime/scripts/amalgm-mcp/registry/evidence.js +826 -0
- package/runtime/scripts/amalgm-mcp/registry/index.js +666 -0
- package/runtime/scripts/amalgm-mcp/registry/store.js +290 -0
- package/runtime/scripts/amalgm-mcp/repocard/README.md +103 -0
- package/runtime/scripts/amalgm-mcp/repocard/apply.js +111 -0
- package/runtime/scripts/amalgm-mcp/repocard/capture-worker.js +94 -0
- package/runtime/scripts/amalgm-mcp/repocard/capture.js +149 -0
- package/runtime/scripts/amalgm-mcp/repocard/follow.js +310 -0
- package/runtime/scripts/amalgm-mcp/repocard/git.js +48 -0
- package/runtime/scripts/amalgm-mcp/repocard/index.js +48 -0
- package/runtime/scripts/amalgm-mcp/server/local-service-router.js +2 -0
- package/runtime/scripts/amalgm-mcp/server/routes/entities.js +287 -0
- package/runtime/scripts/amalgm-mcp/server/routes/state.js +0 -13
- package/runtime/scripts/amalgm-mcp/state/attachments.js +11 -45
- package/runtime/scripts/amalgm-mcp/state/db.js +46 -215
- package/runtime/scripts/amalgm-mcp/state/docs.js +301 -1101
- package/runtime/scripts/amalgm-mcp/state/mutation-contracts.js +0 -99
- package/runtime/scripts/amalgm-mcp/state/mutations.js +130 -507
- package/runtime/scripts/amalgm-mcp/state/promotions.js +1 -21
- package/runtime/scripts/amalgm-mcp/state/replicas.js +13 -134
- package/runtime/scripts/amalgm-mcp/state/shared-rest.js +3 -46
- package/runtime/scripts/amalgm-mcp/tests/adapters.test.js +379 -0
- package/runtime/scripts/amalgm-mcp/tests/browser-cookie-cloud.test.js +0 -193
- package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.life.test.js +449 -0
- package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.rig.js +107 -0
- package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.watch.test.js +213 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/adapter.js +72 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/assert.js +497 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/bind.js +91 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/graph.js +1031 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/ledger.js +234 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/referee.js +118 -0
- package/runtime/scripts/amalgm-mcp/tests/entity.oracle.test.js +1365 -0
- package/runtime/scripts/amalgm-mcp/tests/entity.registry.test.js +967 -0
- package/runtime/scripts/amalgm-mcp/tests/entity.rig.js +239 -0
- package/runtime/scripts/amalgm-mcp/tests/entity.storm.test.js +486 -0
- package/runtime/scripts/amalgm-mcp/tests/fake-watch.js +35 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.links.test.js +289 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.rig.js +103 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.roots.test.js +505 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.storm.test.js +389 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.territory.test.js +845 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.test.js +657 -0
- package/runtime/scripts/amalgm-mcp/tests/project-context.test.js +17 -32
- package/runtime/scripts/amalgm-mcp/tests/registration.service.test.js +256 -0
- package/runtime/scripts/amalgm-mcp/tests/registration.test.js +931 -0
- package/runtime/scripts/amalgm-mcp/tests/repocard.storm.test.js +284 -0
- package/runtime/scripts/amalgm-mcp/tests/repocard.test.js +371 -0
- package/runtime/scripts/amalgm-mcp/tests/repofollow.storm.test.js +435 -0
- package/runtime/scripts/amalgm-mcp/tests/repofollow.test.js +675 -0
- package/runtime/scripts/amalgm-mcp/tests/shared-tunnel-rehydration.test.js +0 -84
- package/runtime/scripts/amalgm-mcp/tests/state-docs.test.js +13 -376
- package/runtime/scripts/amalgm-mcp/tests/state-mutations.test.js +0 -309
- package/runtime/scripts/amalgm-mcp/tests/state-shared-replica.test.js +30 -758
- package/runtime/scripts/amalgm-mcp/tests/workspace-cards-store.test.js +3 -72
- package/runtime/scripts/amalgm-mcp/tests/workspace-cards.test.js +1 -89
- package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint-reducer.test.js +24 -55
- package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint.test.js +141 -424
- package/runtime/scripts/amalgm-mcp/tests/workspace-object-tunnel.test.js +3 -171
- package/runtime/scripts/amalgm-mcp/tests/workspace-objects.test.js +7 -220
- package/runtime/scripts/amalgm-mcp/tests/workspace-publication-invariants.test.js +236 -179
- package/runtime/scripts/amalgm-mcp/tests/workspace-reducer.test.js +326 -2228
- package/runtime/scripts/amalgm-mcp/tests/workspace-tree-cloud.test.js +3 -5319
- package/runtime/scripts/amalgm-mcp/tests/workspace-tree-core.test.js +1 -191
- package/runtime/scripts/amalgm-mcp/tests/workspace-tree-store.test.js +17 -3140
- package/runtime/scripts/amalgm-mcp/tests/workspace-wall.test.js +740 -137
- package/runtime/scripts/amalgm-mcp/workspace/access-store.js +1 -5
- package/runtime/scripts/amalgm-mcp/workspace/card.js +11 -35
- package/runtime/scripts/amalgm-mcp/workspace/cards.js +14 -39
- package/runtime/scripts/amalgm-mcp/workspace/checkpoint.js +147 -587
- package/runtime/scripts/amalgm-mcp/workspace/git.js +34 -406
- package/runtime/scripts/amalgm-mcp/workspace/merge.js +181 -102
- package/runtime/scripts/amalgm-mcp/workspace/objects.js +56 -221
- package/runtime/scripts/amalgm-mcp/workspace/reducer.js +538 -1964
- package/runtime/scripts/amalgm-mcp/workspace/rest.js +28 -49
- package/runtime/scripts/amalgm-mcp/workspace/store.js +4 -77
- package/runtime/scripts/amalgm-mcp/workspace/transition.js +192 -1734
- package/runtime/scripts/amalgm-mcp/workspace/tree/inclusion.js +1 -7
- package/runtime/scripts/amalgm-mcp/workspace/tree/local-state.js +61 -73
- package/runtime/scripts/amalgm-mcp/workspace/tree/reducer.js +6 -51
- package/runtime/scripts/amalgm-mcp/workspace/tree/snapshot.js +8 -79
- package/runtime/scripts/amalgm-mcp/workspace/tree-cloud.js +146 -3461
- package/runtime/scripts/amalgm-mcp/workspace/tree-store.js +71 -899
- package/runtime/scripts/amalgm-mcp/workspace/wall.js +538 -370
- package/runtime/scripts/local-gateway.js +1 -0
- package/runtime/scripts/amalgm-mcp/state/doc-disk.js +0 -550
- package/runtime/scripts/amalgm-mcp/tests/code-project-stream.test.js +0 -399
- package/runtime/scripts/amalgm-mcp/tests/fixtures/code-project-stream-v2.json +0 -1
- package/runtime/scripts/amalgm-mcp/tests/workspace-durable.test.js +0 -24
- package/runtime/scripts/amalgm-mcp/tests/workspace-local-intent.test.js +0 -1999
- package/runtime/scripts/amalgm-mcp/tests/workspace-native-file-transaction.test.js +0 -364
- package/runtime/scripts/amalgm-mcp/tests/workspace-provenance.test.js +0 -185
- package/runtime/scripts/amalgm-mcp/tests/workspace-reducer-liveness.test.js +0 -26
- package/runtime/scripts/amalgm-mcp/tests/workspace-sync-stats.test.js +0 -119
- package/runtime/scripts/amalgm-mcp/tests/workspace-transition.test.js +0 -1446
- package/runtime/scripts/amalgm-mcp/workspace/content.js +0 -32
- package/runtime/scripts/amalgm-mcp/workspace/durable.js +0 -45
- package/runtime/scripts/amalgm-mcp/workspace/intent.js +0 -535
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/BUILD.md +0 -31
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/darwin-arm64/amalgm-file-transaction +0 -0
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/linux-x64/amalgm-file-transaction +0 -0
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/build.mjs +0 -72
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/client.js +0 -165
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.mod +0 -5
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.sum +0 -2
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/main.go +0 -2201
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/manifest.json +0 -19
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_darwin.go +0 -18
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_linux.go +0 -18
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_darwin.go +0 -33
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_linux.go +0 -47
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/verify.mjs +0 -43
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_darwin.go +0 -114
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_linux.go +0 -84
- package/runtime/scripts/amalgm-mcp/workspace/project-stream.js +0 -771
- package/runtime/scripts/amalgm-mcp/workspace/provenance.js +0 -240
- package/runtime/scripts/amalgm-mcp/workspace/sync-stats.js +0 -240
- package/runtime/scripts/amalgm-mcp/workspace/tree/floor.js +0 -100
- package/runtime/scripts/amalgm-mcp/workspace/tree/observation-holds.js +0 -127
- package/runtime/scripts/amalgm-mcp/workspace/tree/path-state.js +0 -12
- package/runtime/scripts/amalgm-mcp/workspace/tree/root-binding.js +0 -125
- package/runtime/scripts/amalgm-mcp/workspace/tree/symlinks.js +0 -76
- package/runtime/scripts/amalgm-mcp/workspace/tree-materialization.js +0 -3766
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The shared rig for the entity oracle suites — the sandbox with the full
|
|
5
|
+
* cast (real observer, registry, evidence intake, operation model, ledger,
|
|
6
|
+
* binders) and the generator helpers that perform each real filesystem
|
|
7
|
+
* operation AND record it in the model. The exams live in
|
|
8
|
+
* entity.oracle.test.js; the storms in entity.storm.test.js.
|
|
9
|
+
*
|
|
10
|
+
* This file may require production code — it drives the system under exam.
|
|
11
|
+
* The judge itself (tests/entity-oracle/) may not, and a meta-test holds it
|
|
12
|
+
* to that.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const assert = require('node:assert/strict');
|
|
16
|
+
const { execFileSync } = require('child_process');
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const os = require('os');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
const Database = require('better-sqlite3');
|
|
22
|
+
const { createObserver } = require('../observer');
|
|
23
|
+
const { createRegistry } = require('../registry');
|
|
24
|
+
const { createEvidence, createEvidenceMemory } = require('../registry/evidence');
|
|
25
|
+
const { createModel } = require('./entity-oracle/graph');
|
|
26
|
+
const { createLedger } = require('./entity-oracle/ledger');
|
|
27
|
+
const { createBinder, createChannelBinder } = require('./entity-oracle/bind');
|
|
28
|
+
const { assertQuietPoint } = require('./entity-oracle/assert');
|
|
29
|
+
|
|
30
|
+
const defaultPolicy = require('../workspace/tree/inclusion').shouldEnroll;
|
|
31
|
+
|
|
32
|
+
// The RIG's explicit classification policy — injected into the model
|
|
33
|
+
// exactly like the enrollment policy. "NUL byte means binary" is a choice
|
|
34
|
+
// these tests make; the model owns no such rule.
|
|
35
|
+
const classify = (bytes) => (
|
|
36
|
+
(Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes)).includes(0) ? 'file.binary' : 'file.text');
|
|
37
|
+
|
|
38
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'amalgm-entity-rig-'));
|
|
39
|
+
|
|
40
|
+
function cleanup() {
|
|
41
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Read-only convergence for event-only exams. `act` rings doorbells; the
|
|
48
|
+
* production chain those doorbells drive — the settle scan, then the
|
|
49
|
+
* scheduled registry intake — must finish ON ITS OWN. This waits by
|
|
50
|
+
* looking only (the detector spoke: events grew; the intake drained:
|
|
51
|
+
* dirty is false); it never scans, flushes, or repairs, so a system
|
|
52
|
+
* that needed help still fails — loudly at the deadline, never by
|
|
53
|
+
* stopwatch luck under parallel load. (The settle scan is one
|
|
54
|
+
* synchronous batch and its scheduled reconcile runs before the next
|
|
55
|
+
* timer tick, so "grew and drained" observed from a timer callback
|
|
56
|
+
* means the whole chain completed.)
|
|
57
|
+
*/
|
|
58
|
+
async function converged(kit, act, deadlineMs = 5_000) {
|
|
59
|
+
const before = kit.events.length;
|
|
60
|
+
act();
|
|
61
|
+
const deadline = Date.now() + deadlineMs;
|
|
62
|
+
while (kit.events.length === before || kit.evidence.dirty()) {
|
|
63
|
+
assert.ok(Date.now() < deadline,
|
|
64
|
+
'oracle: the event-driven chain did not converge before the deadline');
|
|
65
|
+
await sleep(5);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A sandbox with the full cast: real observer, operation model, ledger,
|
|
71
|
+
* binder, and generator helpers that perform each real filesystem operation
|
|
72
|
+
* AND record it in the model.
|
|
73
|
+
*/
|
|
74
|
+
function makeKit(name, { policy = defaultPolicy, watch, settleMs } = {}) {
|
|
75
|
+
const dir = fs.realpathSync(fs.mkdtempSync(path.join(tempRoot, `${name}-`)));
|
|
76
|
+
const events = [];
|
|
77
|
+
const regEvents = [];
|
|
78
|
+
let evidence; // wired below; observer events are hints into its intake
|
|
79
|
+
const observer = createObserver({
|
|
80
|
+
db: new Database(':memory:'),
|
|
81
|
+
emit: (event) => {
|
|
82
|
+
events.push(event);
|
|
83
|
+
evidence?.onEvent();
|
|
84
|
+
},
|
|
85
|
+
shouldEnroll: policy,
|
|
86
|
+
...(watch ? { watch } : {}),
|
|
87
|
+
...(settleMs !== undefined ? { settleMs } : {}),
|
|
88
|
+
});
|
|
89
|
+
const registryDb = new Database(':memory:');
|
|
90
|
+
const registry = createRegistry({
|
|
91
|
+
db: registryDb,
|
|
92
|
+
ephemeral: true,
|
|
93
|
+
emit: (event) => regEvents.push(event),
|
|
94
|
+
});
|
|
95
|
+
const memory = createEvidenceMemory(registryDb);
|
|
96
|
+
const model = createModel({ shouldEnroll: policy, classify });
|
|
97
|
+
const kit = {
|
|
98
|
+
dir, events, observer, model, policy,
|
|
99
|
+
registry, evidence, regEvents,
|
|
100
|
+
ledger: createLedger(),
|
|
101
|
+
binder: createChannelBinder(),
|
|
102
|
+
// Model uuid ↔ registry uuid, observe-only: records are permanent
|
|
103
|
+
// identity, so a registry-side rebind is an identity break.
|
|
104
|
+
registryBinder: createBinder(),
|
|
105
|
+
cursor: { value: 0 },
|
|
106
|
+
rootPath: dir,
|
|
107
|
+
rootId: null,
|
|
108
|
+
|
|
109
|
+
abs: (rel) => path.join(dir, rel),
|
|
110
|
+
enroll() {
|
|
111
|
+
kit.rootId = observer.enrollRoot(dir).rootId;
|
|
112
|
+
// The lens is keyed by the tree's permanent identity, so it is
|
|
113
|
+
// born here — birth reads store truth, exactly like the boundary.
|
|
114
|
+
evidence = createEvidence({
|
|
115
|
+
observer, registry, memory, rootId: kit.rootId,
|
|
116
|
+
// The evidence layer's injected classification policy reads the
|
|
117
|
+
// ground it is classifying — the same NUL rule the model got.
|
|
118
|
+
classify: (absPath) => classify(fs.readFileSync(absPath)),
|
|
119
|
+
});
|
|
120
|
+
kit.evidence = evidence;
|
|
121
|
+
evidence.reconcile();
|
|
122
|
+
return kit.rootId;
|
|
123
|
+
},
|
|
124
|
+
point(options) {
|
|
125
|
+
return assertQuietPoint(kit, options);
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
// --- generator: real op + model record, always in that order ---------
|
|
129
|
+
write(rel, data) {
|
|
130
|
+
fs.mkdirSync(path.dirname(kit.abs(rel)), { recursive: true });
|
|
131
|
+
fs.writeFileSync(kit.abs(rel), data);
|
|
132
|
+
model.write(rel, data);
|
|
133
|
+
},
|
|
134
|
+
replace(rel, data) {
|
|
135
|
+
const tmp = `${kit.abs(rel)}.tmp`;
|
|
136
|
+
fs.writeFileSync(tmp, data);
|
|
137
|
+
fs.renameSync(tmp, kit.abs(rel));
|
|
138
|
+
model.replace(rel, data);
|
|
139
|
+
},
|
|
140
|
+
touchSame(rel) {
|
|
141
|
+
const future = new Date(Date.now() + 5_000);
|
|
142
|
+
fs.utimesSync(kit.abs(rel), future, future);
|
|
143
|
+
model.touch();
|
|
144
|
+
},
|
|
145
|
+
mv(from, to) {
|
|
146
|
+
fs.mkdirSync(path.dirname(kit.abs(to)), { recursive: true });
|
|
147
|
+
fs.renameSync(kit.abs(from), kit.abs(to));
|
|
148
|
+
model.rename(from, to);
|
|
149
|
+
},
|
|
150
|
+
mvDir(from, to) {
|
|
151
|
+
fs.renameSync(kit.abs(from), kit.abs(to));
|
|
152
|
+
model.renameDir(from, to);
|
|
153
|
+
},
|
|
154
|
+
mkdir(rel) {
|
|
155
|
+
fs.mkdirSync(kit.abs(rel), { recursive: true });
|
|
156
|
+
model.mkdir(rel);
|
|
157
|
+
},
|
|
158
|
+
copy(from, to, data) {
|
|
159
|
+
fs.copyFileSync(kit.abs(from), kit.abs(to));
|
|
160
|
+
model.write(to, data);
|
|
161
|
+
},
|
|
162
|
+
rm(rel) {
|
|
163
|
+
fs.rmSync(kit.abs(rel));
|
|
164
|
+
model.remove(rel);
|
|
165
|
+
},
|
|
166
|
+
rmDir(rel) {
|
|
167
|
+
fs.rmSync(kit.abs(rel), { recursive: true, force: true });
|
|
168
|
+
model.removeDir(rel);
|
|
169
|
+
},
|
|
170
|
+
gitInit(rel) {
|
|
171
|
+
fs.mkdirSync(kit.abs(rel), { recursive: true });
|
|
172
|
+
execFileSync('git', ['init', '--quiet'], { cwd: kit.abs(rel) });
|
|
173
|
+
model.gitInit(rel);
|
|
174
|
+
},
|
|
175
|
+
gitRemove(rel) {
|
|
176
|
+
fs.rmSync(path.join(kit.abs(rel), '.git'), { recursive: true, force: true });
|
|
177
|
+
model.gitRemove(rel);
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
// --- link ground: a pointer's whole payload is its written target ----
|
|
181
|
+
symlink(rel, target) {
|
|
182
|
+
fs.mkdirSync(path.dirname(kit.abs(rel)), { recursive: true });
|
|
183
|
+
fs.symlinkSync(target, kit.abs(rel));
|
|
184
|
+
model.writeLink(rel, target);
|
|
185
|
+
},
|
|
186
|
+
/** Retarget IS unlink + recreate — the address absorbs the churn. */
|
|
187
|
+
retarget(rel, target) {
|
|
188
|
+
fs.rmSync(kit.abs(rel));
|
|
189
|
+
fs.symlinkSync(target, kit.abs(rel));
|
|
190
|
+
model.writeLink(rel, target);
|
|
191
|
+
},
|
|
192
|
+
mvLink(from, to) {
|
|
193
|
+
fs.mkdirSync(path.dirname(kit.abs(to)), { recursive: true });
|
|
194
|
+
fs.renameSync(kit.abs(from), kit.abs(to));
|
|
195
|
+
model.renameLink(from, to);
|
|
196
|
+
},
|
|
197
|
+
rmLink(rel) {
|
|
198
|
+
fs.rmSync(kit.abs(rel));
|
|
199
|
+
model.removeLink(rel);
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
return kit;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function fakeWatchKit() {
|
|
206
|
+
const bells = new Map();
|
|
207
|
+
return {
|
|
208
|
+
watch: (rootPath, onDirty) => {
|
|
209
|
+
bells.set(rootPath, onDirty);
|
|
210
|
+
return { degraded: false, close: () => bells.delete(rootPath) };
|
|
211
|
+
},
|
|
212
|
+
ring: (rootPath, relPath) => bells.get(rootPath)(relPath),
|
|
213
|
+
/** Every open watcher whose ground covers this absolute path rings,
|
|
214
|
+
* exactly as a real OS event fans out to nested recursive watchers. */
|
|
215
|
+
ringAt(absPath) {
|
|
216
|
+
for (const [watched, onDirty] of bells) {
|
|
217
|
+
if (absPath === watched) onDirty('');
|
|
218
|
+
else if (absPath.startsWith(`${watched}/`)) onDirty(absPath.slice(watched.length + 1));
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function fileIdAt(kit, rel) {
|
|
225
|
+
const row = kit.observer.filesForRoot(kit.rootId).find((r) => r.relPath === rel);
|
|
226
|
+
assert.ok(row, `expected a store row at ${rel}`);
|
|
227
|
+
return row.fileId;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function linkIdAt(kit, rel) {
|
|
231
|
+
const row = kit.observer.linksForRoot(kit.rootId).find((r) => r.relPath === rel);
|
|
232
|
+
assert.ok(row, `expected a link row at ${rel}`);
|
|
233
|
+
return row.linkId;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
module.exports = {
|
|
237
|
+
cleanup, converged, defaultPolicy, fakeWatchKit, fileIdAt,
|
|
238
|
+
linkIdAt, makeKit, sleep,
|
|
239
|
+
};
|