@amalgm/live 0.2.27 → 0.2.28
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 +38 -25
- package/README.md +1 -2
- package/dist/contracts/index.d.ts +0 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +0 -1
- package/dist/contracts/index.js.map +1 -1
- package/dist/detection/record-proposal.d.ts +3 -2
- package/dist/detection/record-proposal.d.ts.map +1 -1
- package/dist/detection/record-proposal.js +9 -7
- package/dist/detection/record-proposal.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/machines/index.d.ts +0 -2
- package/dist/machines/index.d.ts.map +1 -1
- package/dist/machines/index.js +0 -2
- package/dist/machines/index.js.map +1 -1
- package/dist/records/authority.d.ts +23 -0
- package/dist/records/authority.d.ts.map +1 -0
- package/dist/records/authority.js +28 -0
- package/dist/records/authority.js.map +1 -0
- package/dist/records/codec.d.ts +6 -0
- package/dist/records/codec.d.ts.map +1 -0
- package/dist/records/codec.js +42 -0
- package/dist/records/codec.js.map +1 -0
- package/dist/records/contracts.d.ts +46 -0
- package/dist/records/contracts.d.ts.map +1 -0
- package/dist/records/contracts.js +114 -0
- package/dist/records/contracts.js.map +1 -0
- package/dist/records/inbox.d.ts +18 -0
- package/dist/records/inbox.d.ts.map +1 -0
- package/dist/records/inbox.js +34 -0
- package/dist/records/inbox.js.map +1 -0
- package/dist/records/index.d.ts +7 -0
- package/dist/records/index.d.ts.map +1 -0
- package/dist/records/index.js +7 -0
- package/dist/records/index.js.map +1 -0
- package/dist/records/outbox.d.ts +20 -0
- package/dist/records/outbox.d.ts.map +1 -0
- package/dist/records/outbox.js +44 -0
- package/dist/records/outbox.js.map +1 -0
- package/dist/registration/user-ground.d.ts +4 -4
- package/dist/registration/user-ground.d.ts.map +1 -1
- package/dist/registration/user-ground.js +8 -3
- package/dist/registration/user-ground.js.map +1 -1
- package/dist-cjs/contracts/binding.js +26 -0
- package/dist-cjs/contracts/binding.js.map +1 -0
- package/dist-cjs/contracts/content.js +99 -0
- package/dist-cjs/contracts/content.js.map +1 -0
- package/dist-cjs/contracts/docs.js +56 -0
- package/dist-cjs/contracts/docs.js.map +1 -0
- package/dist-cjs/contracts/events.js +44 -0
- package/dist-cjs/contracts/events.js.map +1 -0
- package/dist-cjs/contracts/frames/gateway.js +39 -0
- package/dist-cjs/contracts/frames/gateway.js.map +1 -0
- package/dist-cjs/contracts/frames/stream.js +20 -0
- package/dist-cjs/contracts/frames/stream.js.map +1 -0
- package/dist-cjs/contracts/frames/tunnel.js +60 -0
- package/dist-cjs/contracts/frames/tunnel.js.map +1 -0
- package/dist-cjs/contracts/index.js +34 -0
- package/dist-cjs/contracts/index.js.map +1 -0
- package/dist-cjs/contracts/presence.js +38 -0
- package/dist-cjs/contracts/presence.js.map +1 -0
- package/dist-cjs/contracts/resources.js +114 -0
- package/dist-cjs/contracts/resources.js.map +1 -0
- package/dist-cjs/contracts/snapshot.js +31 -0
- package/dist-cjs/contracts/snapshot.js.map +1 -0
- package/dist-cjs/contracts/validate.js +34 -0
- package/dist-cjs/contracts/validate.js.map +1 -0
- package/dist-cjs/detection/adapter-contract.js +168 -0
- package/dist-cjs/detection/adapter-contract.js.map +1 -0
- package/dist-cjs/detection/batch.js +71 -0
- package/dist-cjs/detection/batch.js.map +1 -0
- package/dist-cjs/detection/classify.js +48 -0
- package/dist-cjs/detection/classify.js.map +1 -0
- package/dist-cjs/detection/content.js +122 -0
- package/dist-cjs/detection/content.js.map +1 -0
- package/dist-cjs/detection/continuity.js +88 -0
- package/dist-cjs/detection/continuity.js.map +1 -0
- package/dist-cjs/detection/diff.js +193 -0
- package/dist-cjs/detection/diff.js.map +1 -0
- package/dist-cjs/detection/echo.js +25 -0
- package/dist-cjs/detection/echo.js.map +1 -0
- package/dist-cjs/detection/enrollment.js +189 -0
- package/dist-cjs/detection/enrollment.js.map +1 -0
- package/dist-cjs/detection/index.js +57 -0
- package/dist-cjs/detection/index.js.map +1 -0
- package/dist-cjs/detection/record-proposal.js +170 -0
- package/dist-cjs/detection/record-proposal.js.map +1 -0
- package/dist-cjs/detection/refusal.js +44 -0
- package/dist-cjs/detection/refusal.js.map +1 -0
- package/dist-cjs/detection/repository.js +67 -0
- package/dist-cjs/detection/repository.js.map +1 -0
- package/dist-cjs/detection/territory.js +82 -0
- package/dist-cjs/detection/territory.js.map +1 -0
- package/dist-cjs/detection/watch-boundary.js +51 -0
- package/dist-cjs/detection/watch-boundary.js.map +1 -0
- package/dist-cjs/entities/bytes.js +92 -0
- package/dist-cjs/entities/bytes.js.map +1 -0
- package/dist-cjs/entities/cloud.js +171 -0
- package/dist-cjs/entities/cloud.js.map +1 -0
- package/dist-cjs/entities/index.js +39 -0
- package/dist-cjs/entities/index.js.map +1 -0
- package/dist-cjs/entities/moves.js +85 -0
- package/dist-cjs/entities/moves.js.map +1 -0
- package/dist-cjs/entities/repo-states.js +256 -0
- package/dist-cjs/entities/repo-states.js.map +1 -0
- package/dist-cjs/entities/rules.js +216 -0
- package/dist-cjs/entities/rules.js.map +1 -0
- package/dist-cjs/entities/types.js +44 -0
- package/dist-cjs/entities/types.js.map +1 -0
- package/dist-cjs/files/commands.js +120 -0
- package/dist-cjs/files/commands.js.map +1 -0
- package/dist-cjs/files/index.js +19 -0
- package/dist-cjs/files/index.js.map +1 -0
- package/dist-cjs/index.js +39 -0
- package/dist-cjs/index.js.map +1 -0
- package/dist-cjs/machines/arbitration.js +41 -0
- package/dist-cjs/machines/arbitration.js.map +1 -0
- package/dist-cjs/machines/backoff.js +38 -0
- package/dist-cjs/machines/backoff.js.map +1 -0
- package/dist-cjs/machines/bootstrap.js +110 -0
- package/dist-cjs/machines/bootstrap.js.map +1 -0
- package/dist-cjs/machines/chunks.js +72 -0
- package/dist-cjs/machines/chunks.js.map +1 -0
- package/dist-cjs/machines/index.js +28 -0
- package/dist-cjs/machines/index.js.map +1 -0
- package/dist-cjs/machines/presence.js +53 -0
- package/dist-cjs/machines/presence.js.map +1 -0
- package/dist-cjs/merge/index.js +25 -0
- package/dist-cjs/merge/index.js.map +1 -0
- package/dist-cjs/merge/merge3.js +191 -0
- package/dist-cjs/merge/merge3.js.map +1 -0
- package/dist-cjs/package.json +1 -0
- package/dist-cjs/records/authority.js +31 -0
- package/dist-cjs/records/authority.js.map +1 -0
- package/dist-cjs/records/codec.js +48 -0
- package/dist-cjs/records/codec.js.map +1 -0
- package/dist-cjs/records/contracts.js +121 -0
- package/dist-cjs/records/contracts.js.map +1 -0
- package/dist-cjs/records/inbox.js +37 -0
- package/dist-cjs/records/inbox.js.map +1 -0
- package/dist-cjs/records/index.js +23 -0
- package/dist-cjs/records/index.js.map +1 -0
- package/dist-cjs/records/outbox.js +48 -0
- package/dist-cjs/records/outbox.js.map +1 -0
- package/dist-cjs/registration/index.js +19 -0
- package/dist-cjs/registration/index.js.map +1 -0
- package/dist-cjs/registration/user-ground.js +183 -0
- package/dist-cjs/registration/user-ground.js.map +1 -0
- package/dist-cjs/transfer/artifacts.js +75 -0
- package/dist-cjs/transfer/artifacts.js.map +1 -0
- package/dist-cjs/transfer/batches.js +44 -0
- package/dist-cjs/transfer/batches.js.map +1 -0
- package/dist-cjs/transfer/download.js +88 -0
- package/dist-cjs/transfer/download.js.map +1 -0
- package/dist-cjs/transfer/index.js +21 -0
- package/dist-cjs/transfer/index.js.map +1 -0
- package/dist-cjs/transfer/parallel.js +35 -0
- package/dist-cjs/transfer/parallel.js.map +1 -0
- package/dist-cjs/transfer/upload.js +161 -0
- package/dist-cjs/transfer/upload.js.map +1 -0
- package/dist-cjs/watching/coverage.js +54 -0
- package/dist-cjs/watching/coverage.js.map +1 -0
- package/dist-cjs/watching/index.js +24 -0
- package/dist-cjs/watching/index.js.map +1 -0
- package/dist-cjs/watching/suspicion.js +105 -0
- package/dist-cjs/watching/suspicion.js.map +1 -0
- package/dist-cjs/workspace/api.js +66 -0
- package/dist-cjs/workspace/api.js.map +1 -0
- package/dist-cjs/workspace/identity.js +32 -0
- package/dist-cjs/workspace/identity.js.map +1 -0
- package/dist-cjs/workspace/index.js +14 -0
- package/dist-cjs/workspace/index.js.map +1 -0
- package/dist-cjs/workspace/memory-store.js +21 -0
- package/dist-cjs/workspace/memory-store.js.map +1 -0
- package/dist-cjs/workspace/registry.js +98 -0
- package/dist-cjs/workspace/registry.js.map +1 -0
- package/dist-cjs/workspace/types.js +3 -0
- package/dist-cjs/workspace/types.js.map +1 -0
- package/package.json +30 -8
- package/dist/contracts/mutation.d.ts +0 -51
- package/dist/contracts/mutation.d.ts.map +0 -1
- package/dist/contracts/mutation.js +0 -55
- package/dist/contracts/mutation.js.map +0 -1
- package/dist/machines/journal.d.ts +0 -63
- package/dist/machines/journal.d.ts.map +0 -1
- package/dist/machines/journal.js +0 -71
- package/dist/machines/journal.js.map +0 -1
- package/dist/machines/ordering.d.ts +0 -53
- package/dist/machines/ordering.d.ts.map +0 -1
- package/dist/machines/ordering.js +0 -87
- package/dist/machines/ordering.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-contract.js","sourceRoot":"","sources":["../../src/detection/adapter-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Net-difference planning for one settled Watch batch.
|
|
4
|
+
*
|
|
5
|
+
* Identity reconciliation and type-specific capture happen before this seam.
|
|
6
|
+
* This seam makes cancellation, unsettled truth, lifecycle authority, coverage
|
|
7
|
+
* requests, and Watch settlement one total decision.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.planDetectionBatch = planDetectionBatch;
|
|
11
|
+
const types_js_1 = require("../entities/types.js");
|
|
12
|
+
const record_proposal_js_1 = require("./record-proposal.js");
|
|
13
|
+
const watch_boundary_js_1 = require("./watch-boundary.js");
|
|
14
|
+
const newlyDirectoryGround = (transition) => transition.relPath !== ''
|
|
15
|
+
&&
|
|
16
|
+
types_js_1.CONTAINERS.has(transition.result.type)
|
|
17
|
+
&& (transition.base === null || !types_js_1.CONTAINERS.has(transition.base.type));
|
|
18
|
+
/** Plan the complete net difference. No partial proposals escape an unsettled batch. */
|
|
19
|
+
function planDetectionBatch(batch, transitions) {
|
|
20
|
+
const unsettled = transitions.filter((transition) => transition.truth === 'unsettled');
|
|
21
|
+
if (unsettled.length > 0) {
|
|
22
|
+
return Object.freeze({
|
|
23
|
+
kind: 'retry',
|
|
24
|
+
reasons: Object.freeze(unsettled.map((transition) => transition.reason ?? 'truth is unsettled')),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const proposals = [];
|
|
28
|
+
const missing = [];
|
|
29
|
+
const createdDirectories = [];
|
|
30
|
+
for (const transition of transitions) {
|
|
31
|
+
if (transition.truth === 'present') {
|
|
32
|
+
const proposal = (0, record_proposal_js_1.detectedChangeProposal)(transition);
|
|
33
|
+
if (proposal)
|
|
34
|
+
proposals.push(proposal);
|
|
35
|
+
if (newlyDirectoryGround(transition)) {
|
|
36
|
+
createdDirectories.push(transition.relPath);
|
|
37
|
+
}
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (transition.truth !== 'absent') {
|
|
41
|
+
throw new Error('unsettled truth escaped the batch retry gate');
|
|
42
|
+
}
|
|
43
|
+
if (transition.base === null)
|
|
44
|
+
continue; // absent before and after: no entity existed
|
|
45
|
+
if (transition.base.status !== 'active')
|
|
46
|
+
continue;
|
|
47
|
+
if (transition.lifecycleAuthorization !== 'trash') {
|
|
48
|
+
missing.push(transition.base);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (!transition.trashedResult) {
|
|
52
|
+
throw new Error('authorized Trash requires the entity law\'s exact trashed result');
|
|
53
|
+
}
|
|
54
|
+
const proposal = (0, record_proposal_js_1.detectedChangeProposal)({
|
|
55
|
+
base: transition.base,
|
|
56
|
+
result: transition.trashedResult,
|
|
57
|
+
replay: { kind: 'structure' },
|
|
58
|
+
lifecycleAuthorization: 'trash',
|
|
59
|
+
});
|
|
60
|
+
if (proposal)
|
|
61
|
+
proposals.push(proposal);
|
|
62
|
+
}
|
|
63
|
+
return Object.freeze({
|
|
64
|
+
kind: 'ready',
|
|
65
|
+
proposals: Object.freeze(proposals),
|
|
66
|
+
missing: Object.freeze(missing),
|
|
67
|
+
coverage: (0, watch_boundary_js_1.directoryCoverageRequests)(batch, createdDirectories),
|
|
68
|
+
settle: batch,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=batch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/detection/batch.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAiEH,gDAqDC;AAnHD,mDAAkD;AAClD,6DAI8B;AAC9B,2DAI6B;AA6C7B,MAAM,oBAAoB,GAAG,CAAC,UAA6B,EAAW,EAAE,CACtE,UAAU,CAAC,OAAO,KAAK,EAAE;;QAEzB,qBAAU,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;OACnC,CAAC,UAAU,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,qBAAU,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAEzE,wFAAwF;AACxF,SAAgB,kBAAkB,CAChC,KAAqB,EACrB,WAAyC;IAEzC,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAClC,CAAC,UAAU,EAAqC,EAAE,CAAC,UAAU,CAAC,KAAK,KAAK,WAAW,CACpF,CAAC;IACF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,IAAI,oBAAoB,CAAC,CAAC;SACjG,CAAC,CAAC;IACL,CAAC;IAED,MAAM,SAAS,GAA6B,EAAE,CAAC;IAC/C,MAAM,OAAO,GAAwB,EAAE,CAAC;IACxC,MAAM,kBAAkB,GAAa,EAAE,CAAC;IACxC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,QAAQ,GAAG,IAAA,2CAAsB,EAAC,UAAU,CAAC,CAAC;YACpD,IAAI,QAAQ;gBAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvC,IAAI,oBAAoB,CAAC,UAAU,CAAC,EAAE,CAAC;gBACrC,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAC9C,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,UAAU,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,KAAK,IAAI;YAAE,SAAS,CAAC,6CAA6C;QACrF,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ;YAAE,SAAS;QAClD,IAAI,UAAU,CAAC,sBAAsB,KAAK,OAAO,EAAE,CAAC;YAClD,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAC9B,SAAS;QACX,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,QAAQ,GAAG,IAAA,2CAAsB,EAAC;YACtC,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,MAAM,EAAE,UAAU,CAAC,aAAa;YAChC,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;YAC7B,sBAAsB,EAAE,OAAO;SAChC,CAAC,CAAC;QACH,IAAI,QAAQ;YAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,OAAO;QACb,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;QACnC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;QAC/B,QAAQ,EAAE,IAAA,6CAAyB,EAAC,KAAK,EAAE,kBAAkB,CAAC;QAC9D,MAAM,EAAE,KAAK;KACd,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Amalgm's file-type policy: which physical type a piece of file ground
|
|
4
|
+
* takes. Ratified by entity-model.md ("Formats live underneath the file
|
|
5
|
+
* types"; text versus binary is an adapter difference, never an
|
|
6
|
+
* identity difference).
|
|
7
|
+
*
|
|
8
|
+
* Classification is an INJECTED policy everywhere it is used — the
|
|
9
|
+
* registration boundary and its lenses refuse to construct without one
|
|
10
|
+
* — so it lives in its own file with no other job: one definition,
|
|
11
|
+
* replaceable whole.
|
|
12
|
+
*
|
|
13
|
+
* The rule is the oldest one there is: bytes holding a NUL are not
|
|
14
|
+
* text. What matters is WHERE that fact comes from. It is not read
|
|
15
|
+
* here. Detect's single read of a file produces its fingerprint and
|
|
16
|
+
* this report together, and this policy only names the type that report
|
|
17
|
+
* implies.
|
|
18
|
+
*
|
|
19
|
+
* That is the whole law: A FILE'S HASH AND ITS TYPE DESCRIBE THE SAME
|
|
20
|
+
* OBSERVED BYTES. A policy that opened the ground itself would be a
|
|
21
|
+
* second look — and a second look can meet different bytes, or none at
|
|
22
|
+
* all, leaving a record whose type contradicts the payload beside it.
|
|
23
|
+
* So this function takes evidence, never a path; it is total, and it
|
|
24
|
+
* cannot fail.
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.classifyFile = classifyFile;
|
|
28
|
+
exports.classifyDirectory = classifyDirectory;
|
|
29
|
+
exports.classifyRegisteredRoot = classifyRegisteredRoot;
|
|
30
|
+
exports.isRepositoryMetadataEntry = isRepositoryMetadataEntry;
|
|
31
|
+
function classifyFile({ binary }) {
|
|
32
|
+
return binary ? 'file.binary' : 'file.text';
|
|
33
|
+
}
|
|
34
|
+
function classifyDirectory({ repository }) {
|
|
35
|
+
return repository ? 'repo.git' : 'folder';
|
|
36
|
+
}
|
|
37
|
+
/** A deliberately registered external directory remains a tree root. A Git
|
|
38
|
+
* root wears `repo.git`; an ordinary root wears `workspace`. */
|
|
39
|
+
function classifyRegisteredRoot({ repository }) {
|
|
40
|
+
return repository ? 'repo.git' : 'workspace';
|
|
41
|
+
}
|
|
42
|
+
/** `.git` is cargo of a repository entity, never one of its worktree
|
|
43
|
+
* children. Marker presence makes the parent a repository before this rule is
|
|
44
|
+
* asked, regardless of whether Git can currently consume that marker. */
|
|
45
|
+
function isRepositoryMetadataEntry(parentType, name) {
|
|
46
|
+
return parentType === 'repo.git' && name === '.git';
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/detection/classify.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;;AAWH,oCAEC;AASD,8CAEC;AAID,wDAEC;AAKD,8DAEC;AA1BD,SAAgB,YAAY,CAAC,EAAE,MAAM,EAAoB;IACvD,OAAO,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC;AAC9C,CAAC;AASD,SAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAsB;IAClE,OAAO,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC5C,CAAC;AAED;gEACgE;AAChE,SAAgB,sBAAsB,CAAC,EAAE,UAAU,EAAsB;IACvE,OAAO,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;AAC/C,CAAC;AAED;;yEAEyE;AACzE,SAAgB,yBAAyB,CAAC,UAA8C,EAAE,IAAY;IACpG,OAAO,UAAU,KAAK,UAAU,IAAI,IAAI,KAAK,MAAM,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Type-sensitive content capture from Detection's one settled byte read. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.textSplice = textSplice;
|
|
5
|
+
exports.captureTextChange = captureTextChange;
|
|
6
|
+
exports.reproduceTextChange = reproduceTextChange;
|
|
7
|
+
exports.captureBinaryChange = captureBinaryChange;
|
|
8
|
+
exports.captureLinkChange = captureLinkChange;
|
|
9
|
+
const content_js_1 = require("../contracts/content.js");
|
|
10
|
+
const bytes_js_1 = require("../entities/bytes.js");
|
|
11
|
+
const upload_js_1 = require("../transfer/upload.js");
|
|
12
|
+
const capturedArtifact = (entityId, entityType, kind, input, sha256Hex) => {
|
|
13
|
+
const bytes = input.slice();
|
|
14
|
+
const artifact = {
|
|
15
|
+
entityId,
|
|
16
|
+
entityType,
|
|
17
|
+
kind,
|
|
18
|
+
contentHash: sha256Hex(bytes),
|
|
19
|
+
};
|
|
20
|
+
return Object.freeze({
|
|
21
|
+
artifact: Object.freeze(artifact),
|
|
22
|
+
bytes,
|
|
23
|
+
manifest: (0, upload_js_1.deriveUploadManifest)(artifact, bytes, sha256Hex),
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
/** The smallest single replacement span that transforms base bytes to result. */
|
|
27
|
+
function textSplice(base, result) {
|
|
28
|
+
let prefix = 0;
|
|
29
|
+
const shared = Math.min(base.byteLength, result.byteLength);
|
|
30
|
+
while (prefix < shared && base[prefix] === result[prefix])
|
|
31
|
+
prefix += 1;
|
|
32
|
+
let suffix = 0;
|
|
33
|
+
while (suffix < shared - prefix
|
|
34
|
+
&& base[base.byteLength - suffix - 1] === result[result.byteLength - suffix - 1]) {
|
|
35
|
+
suffix += 1;
|
|
36
|
+
}
|
|
37
|
+
return Object.freeze({
|
|
38
|
+
offset: prefix,
|
|
39
|
+
deleteBytes: base.byteLength - prefix - suffix,
|
|
40
|
+
insert: result.slice(prefix, result.byteLength - suffix),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Capture text as one verified byte splice when that instruction is smaller
|
|
45
|
+
* than the result bytes. The immutable snapshot is always sealed as repair and
|
|
46
|
+
* cold-materialization truth.
|
|
47
|
+
*/
|
|
48
|
+
function captureTextChange(entityId, base, result, sha256Hex) {
|
|
49
|
+
const cargo = capturedArtifact(entityId, 'file.text', 'file', result, sha256Hex);
|
|
50
|
+
const basePayloadVersion = base === null ? null : sha256Hex(base);
|
|
51
|
+
if (basePayloadVersion === cargo.artifact.contentHash)
|
|
52
|
+
return null;
|
|
53
|
+
const delta = base === null ? null : textSplice(base, result);
|
|
54
|
+
// Two numeric fields are fixed overhead on the wire. This conservative
|
|
55
|
+
// estimate keeps a replace-all operation on the snapshot path.
|
|
56
|
+
const useDelta = delta !== null && delta.insert.byteLength + 16 < result.byteLength;
|
|
57
|
+
return Object.freeze({
|
|
58
|
+
replay: Object.freeze({
|
|
59
|
+
kind: 'file.text',
|
|
60
|
+
mode: useDelta ? 'delta' : 'snapshot',
|
|
61
|
+
basePayloadVersion,
|
|
62
|
+
resultPayloadVersion: cargo.artifact.contentHash,
|
|
63
|
+
delta: useDelta ? delta : null,
|
|
64
|
+
}),
|
|
65
|
+
cargo,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** Apply a text replay and verify its exact result, falling back to snapshot. */
|
|
69
|
+
function reproduceTextChange(base, replay, snapshot, sha256Hex) {
|
|
70
|
+
const verifiedSnapshot = () => {
|
|
71
|
+
if (sha256Hex(snapshot) !== replay.resultPayloadVersion) {
|
|
72
|
+
throw new Error('text snapshot does not match its declared result');
|
|
73
|
+
}
|
|
74
|
+
return snapshot.slice();
|
|
75
|
+
};
|
|
76
|
+
if (replay.mode !== 'delta' || replay.delta === null || base === null
|
|
77
|
+
|| sha256Hex(base) !== replay.basePayloadVersion) {
|
|
78
|
+
return verifiedSnapshot();
|
|
79
|
+
}
|
|
80
|
+
const { offset, deleteBytes, insert } = replay.delta;
|
|
81
|
+
if (!Number.isSafeInteger(offset) || !Number.isSafeInteger(deleteBytes)
|
|
82
|
+
|| offset < 0 || deleteBytes < 0 || offset + deleteBytes > base.byteLength) {
|
|
83
|
+
return verifiedSnapshot();
|
|
84
|
+
}
|
|
85
|
+
const result = new Uint8Array(base.byteLength - deleteBytes + insert.byteLength);
|
|
86
|
+
result.set(base.subarray(0, offset), 0);
|
|
87
|
+
result.set(insert, offset);
|
|
88
|
+
result.set(base.subarray(offset + deleteBytes), offset + insert.byteLength);
|
|
89
|
+
return sha256Hex(result) === replay.resultPayloadVersion ? result : verifiedSnapshot();
|
|
90
|
+
}
|
|
91
|
+
/** Binary replay is the existing exact content manifest; Transfer moves gaps. */
|
|
92
|
+
function captureBinaryChange(entityId, previous, result, sha256Hex) {
|
|
93
|
+
if (previous !== null && !(0, content_js_1.checkContentManifest)(previous).ok) {
|
|
94
|
+
throw new Error('previous binary content manifest is invalid');
|
|
95
|
+
}
|
|
96
|
+
const cargo = capturedArtifact(entityId, 'file.binary', 'file', result, sha256Hex);
|
|
97
|
+
if (previous?.contentHash === cargo.artifact.contentHash)
|
|
98
|
+
return null;
|
|
99
|
+
return Object.freeze({
|
|
100
|
+
replay: Object.freeze({
|
|
101
|
+
kind: 'file.binary',
|
|
102
|
+
resultPayloadVersion: cargo.artifact.contentHash,
|
|
103
|
+
manifest: cargo.manifest,
|
|
104
|
+
}),
|
|
105
|
+
cargo,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/** A symlink's portable content is the literal target text, never its target. */
|
|
109
|
+
function captureLinkChange(entityId, previousTarget, target, sha256Hex) {
|
|
110
|
+
if (previousTarget === target)
|
|
111
|
+
return null;
|
|
112
|
+
const cargo = capturedArtifact(entityId, 'link', 'link', (0, bytes_js_1.utf8Encode)(target), sha256Hex);
|
|
113
|
+
return Object.freeze({
|
|
114
|
+
replay: Object.freeze({
|
|
115
|
+
kind: 'link',
|
|
116
|
+
resultPayloadVersion: cargo.artifact.contentHash,
|
|
117
|
+
target,
|
|
118
|
+
}),
|
|
119
|
+
cargo,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/detection/content.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Root continuity verdicts: what a root's WITNESSED physical identity
|
|
4
|
+
* is, whether its recorded address still holds its ground, and whether
|
|
5
|
+
* a piece of ground rescues a moved root. Ratified by entity-model.md
|
|
6
|
+
* ("Ground that moves is rescued by continuity" — the directory law
|
|
7
|
+
* lifted to roots; "the follow rides witnessed continuity, never
|
|
8
|
+
* clairvoyance").
|
|
9
|
+
*
|
|
10
|
+
* Pure verdicts over injected answers — the host supplies the one look
|
|
11
|
+
* at an address (`statAt`) and the store's witnessed channel row
|
|
12
|
+
* (`channelIdentity`); the ACTIONS a verdict triggers (rebind, presence
|
|
13
|
+
* transitions, the undecided-address decision) stay in the host's
|
|
14
|
+
* wiring, because they re-aim watchers and scans.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.createContinuity = createContinuity;
|
|
18
|
+
function createContinuity({ statAt, channelIdentity }) {
|
|
19
|
+
/**
|
|
20
|
+
* A root's WITNESSED physical identity, for continuity rescue.
|
|
21
|
+
* Directory roots carry their own device:inode (nothing replaces a
|
|
22
|
+
* directory's inode in place). A single-ground root's identity lives
|
|
23
|
+
* in its one channel row. Ground that changed inodes inside a
|
|
24
|
+
* still-open settle window is unwitnessed — no evidence, no claim.
|
|
25
|
+
*/
|
|
26
|
+
function rootIdentity(root) {
|
|
27
|
+
if (root.kind !== 'file') {
|
|
28
|
+
const { device, inode } = root;
|
|
29
|
+
return device == null || inode == null ? null : { device, inode };
|
|
30
|
+
}
|
|
31
|
+
return channelIdentity(root.rootId);
|
|
32
|
+
}
|
|
33
|
+
/** Orphaned means the recorded address no longer holds this ground. */
|
|
34
|
+
function orphanedAtAddress(root) {
|
|
35
|
+
const identity = rootIdentity(root);
|
|
36
|
+
if (!identity)
|
|
37
|
+
return false;
|
|
38
|
+
const stat = statAt(root.path);
|
|
39
|
+
if (!stat)
|
|
40
|
+
return true;
|
|
41
|
+
return stat.device !== identity.device || stat.inode !== identity.inode;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Continuity claims a root exactly like it claims the directories
|
|
45
|
+
* inside one: unique device:inode match, exactly one candidate, and
|
|
46
|
+
* only for a path-orphan — a root whose recorded address still holds
|
|
47
|
+
* its ground is never stolen by a lookalike.
|
|
48
|
+
*/
|
|
49
|
+
function findMovedRoot(stat, roots) {
|
|
50
|
+
const wantDir = stat.kind === 'dir';
|
|
51
|
+
const matches = roots.filter((root) => {
|
|
52
|
+
if (wantDir !== (root.kind !== 'file'))
|
|
53
|
+
return false;
|
|
54
|
+
const identity = rootIdentity(root);
|
|
55
|
+
return identity !== null && identity.device === stat.device && identity.inode === stat.inode;
|
|
56
|
+
});
|
|
57
|
+
const only = matches.length === 1 ? matches[0] : null;
|
|
58
|
+
return only && orphanedAtAddress(only) ? only : null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A scan's evidence horizon is the root's ground; the root's own
|
|
62
|
+
* address is the horizon's edge. Ground missing there — or a
|
|
63
|
+
* directory root's address wearing a different physical identity — is
|
|
64
|
+
* UNDECIDABLE from here: moved away, deleted, or replaced by a
|
|
65
|
+
* lookalike all present the same address, and concluding "deleted"
|
|
66
|
+
* would end every channel a rescue could have saved. So the scan
|
|
67
|
+
* concludes nothing: beliefs freeze, the referee convicts the
|
|
68
|
+
* divergence, and the next enrollment moment decides — naming the new
|
|
69
|
+
* address rescues, re-naming this one adopts, and explicit removal is
|
|
70
|
+
* the only deletion (an external filesystem change is never
|
|
71
|
+
* permission to end identity). A single-ground root's address
|
|
72
|
+
* lawfully churns inodes (atomic saves, retargets), so only absence —
|
|
73
|
+
* or foreign directory ground — freezes it; presence is the file
|
|
74
|
+
* laws' business.
|
|
75
|
+
*/
|
|
76
|
+
function addressUndecided(root) {
|
|
77
|
+
const stat = statAt(root.path);
|
|
78
|
+
if (!stat)
|
|
79
|
+
return true;
|
|
80
|
+
if (root.kind === 'file')
|
|
81
|
+
return stat.kind !== 'file' && stat.kind !== 'link';
|
|
82
|
+
if (stat.kind !== 'dir')
|
|
83
|
+
return true;
|
|
84
|
+
return root.device != null && (stat.device !== root.device || stat.inode !== root.inode);
|
|
85
|
+
}
|
|
86
|
+
return { rootIdentity, findMovedRoot, addressUndecided };
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=continuity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continuity.js","sourceRoot":"","sources":["../../src/detection/continuity.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;AA8CH,4CAmEC;AAnED,SAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,eAAe,EAAmB;IAC3E;;;;;;OAMG;IACH,SAAS,YAAY,CAAC,IAAoB;QACxC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;YAC/B,OAAO,MAAM,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QACpE,CAAC;QACD,OAAO,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,uEAAuE;IACvE,SAAS,iBAAiB,CAAC,IAAoB;QAC7C,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,CAAC;IAC1E,CAAC;IAED;;;;;OAKG;IACH,SAAS,aAAa,CAAC,IAAgB,EAAE,KAAgC;QACvE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC;QACpC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;YACpC,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;gBAAE,OAAO,KAAK,CAAC;YACrD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YACpC,OAAO,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC;QAC/F,CAAC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACvD,OAAO,IAAI,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACvD,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,SAAS,gBAAgB,CAAC,IAAoB;QAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;QAC9E,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK;YAAE,OAAO,IAAI,CAAC;QACrC,OAAO,IAAI,CAAC,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3F,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The compare core of detection: rows (store memory) + entries (disk
|
|
4
|
+
* truth) in, actions out. Pure — the walk that produces entries and the
|
|
5
|
+
* hashing that settles `checks` are the host's; only the identity
|
|
6
|
+
* verdicts live here. Ratified by entity-model.md ("Address and
|
|
7
|
+
* physical continuity are the two identity witnesses, never content").
|
|
8
|
+
*
|
|
9
|
+
* Three kinds of channel, three orderings of the same two witnesses:
|
|
10
|
+
*
|
|
11
|
+
* - Files: path claims first; the inode rescues path-orphans. An
|
|
12
|
+
* atomic save replaces a file's inode in place, so the address must
|
|
13
|
+
* absorb that churn.
|
|
14
|
+
* - Directories: physical continuity claims first; the address claims
|
|
15
|
+
* what no inode claims. Nothing replaces a directory's inode in
|
|
16
|
+
* place, so a known inode at a new address IS the directory, moved.
|
|
17
|
+
* - Links: the FILE rules, for the file reason — retarget is unlink +
|
|
18
|
+
* recreate, so the inode churns exactly like an atomic save.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.matchByInode = matchByInode;
|
|
22
|
+
exports.diffDirState = diffDirState;
|
|
23
|
+
exports.diffLinkState = diffLinkState;
|
|
24
|
+
exports.diffRootState = diffRootState;
|
|
25
|
+
/**
|
|
26
|
+
* Physical continuity, shared by every compare function: a row and an
|
|
27
|
+
* entry sharing one device:inode, exactly one match on both sides → the
|
|
28
|
+
* same physical thing. Anything else is never guessed. For files this
|
|
29
|
+
* rescues path-orphans (rule 2); for directories it IS rule 1.
|
|
30
|
+
*/
|
|
31
|
+
function matchByInode(rows, entries) {
|
|
32
|
+
const one = (map, key, value) => map.set(key, map.has(key) ? 'many' : value);
|
|
33
|
+
const rowsByInode = new Map();
|
|
34
|
+
for (const row of rows)
|
|
35
|
+
one(rowsByInode, `${row.device}:${row.inode}`, row);
|
|
36
|
+
const entriesByInode = new Map();
|
|
37
|
+
for (const entry of entries)
|
|
38
|
+
one(entriesByInode, `${entry.device}:${entry.inode}`, entry);
|
|
39
|
+
const matched = [];
|
|
40
|
+
for (const [key, entry] of entriesByInode) {
|
|
41
|
+
const row = rowsByInode.get(key);
|
|
42
|
+
if (entry === 'many' || !row || row === 'many')
|
|
43
|
+
continue;
|
|
44
|
+
matched.push({ row, entry });
|
|
45
|
+
}
|
|
46
|
+
return matched;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The compare function for directory channels — the file identity rules
|
|
50
|
+
* in the OPPOSITE order, for the mirror reason. A file's inode is
|
|
51
|
+
* replaced in place on every atomic save, so for files the path must
|
|
52
|
+
* absorb that churn (path claims first). Nothing replaces a directory's
|
|
53
|
+
* inode in place: a known inode at a new address IS the directory,
|
|
54
|
+
* moved — even when its old address was reoccupied in the same interval
|
|
55
|
+
* (two directories exchanging names cross by inode, exactly like the
|
|
56
|
+
* files inside them). So:
|
|
57
|
+
* 1. Physical continuity claims the channel: unique device:inode,
|
|
58
|
+
* whole sets, same path = continued, new path = rename.
|
|
59
|
+
* 2. The address claims what no inode claims — recreation under an old
|
|
60
|
+
* name is the same channel wearing a never-seen inode (`retags`,
|
|
61
|
+
* silent).
|
|
62
|
+
* 3. Leftover entries are creates; leftover rows are deletes.
|
|
63
|
+
* No content: a directory's membership is derived state upstream, so
|
|
64
|
+
* there is nothing to hash or check.
|
|
65
|
+
*/
|
|
66
|
+
function diffDirState(rows, entries) {
|
|
67
|
+
const matched = matchByInode(rows, entries);
|
|
68
|
+
const matchedRowIds = new Set(matched.map((pair) => pair.row.dirId));
|
|
69
|
+
const matchedEntries = new Set(matched.map((pair) => pair.entry));
|
|
70
|
+
const rowsByPath = new Map(rows.filter((row) => !matchedRowIds.has(row.dirId))
|
|
71
|
+
.map((row) => [row.relPath, row]));
|
|
72
|
+
const retags = [];
|
|
73
|
+
const creates = [];
|
|
74
|
+
for (const entry of entries) {
|
|
75
|
+
if (matchedEntries.has(entry))
|
|
76
|
+
continue;
|
|
77
|
+
const row = rowsByPath.get(entry.relPath);
|
|
78
|
+
if (row) {
|
|
79
|
+
rowsByPath.delete(entry.relPath);
|
|
80
|
+
retags.push({ row, entry });
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
creates.push(entry);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
renames: matched.filter((pair) => pair.row.relPath !== pair.entry.relPath),
|
|
88
|
+
retags,
|
|
89
|
+
creates,
|
|
90
|
+
deletes: [...rowsByPath.values()],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The compare function for link channels — the FILE identity rules, for
|
|
95
|
+
* the file reason: a symlink cannot be retargeted in place (retarget is
|
|
96
|
+
* unlink + recreate, so the inode churns exactly like an atomic save),
|
|
97
|
+
* so the path absorbs that churn and claims first; the inode rescues
|
|
98
|
+
* path-orphans (`mv` preserves a symlink's inode). The payload is the
|
|
99
|
+
* target string, already read at walk time. A consequence worth naming:
|
|
100
|
+
* two links exchanging names read as two retargets (path-first),
|
|
101
|
+
* because a link's meaning IS its written address.
|
|
102
|
+
* 1. Path claims the channel: same target = continued (a new inode
|
|
103
|
+
* under an old name with an old target is silent recreation),
|
|
104
|
+
* different target = changed.
|
|
105
|
+
* 2. Inode rescues path-orphans: renames.
|
|
106
|
+
* 3. Leftover entries are creates; leftover rows are deletes.
|
|
107
|
+
*/
|
|
108
|
+
function diffLinkState(rows, entries) {
|
|
109
|
+
const changes = [];
|
|
110
|
+
const retags = [];
|
|
111
|
+
const rowsByPath = new Map(rows.map((row) => [row.relPath, row]));
|
|
112
|
+
const claimedRowIds = new Set();
|
|
113
|
+
const orphanEntries = [];
|
|
114
|
+
for (const entry of entries) {
|
|
115
|
+
const row = rowsByPath.get(entry.relPath);
|
|
116
|
+
if (!row) {
|
|
117
|
+
orphanEntries.push(entry);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
claimedRowIds.add(row.linkId);
|
|
121
|
+
if (row.target !== entry.target)
|
|
122
|
+
changes.push({ row, entry });
|
|
123
|
+
else if (row.device !== entry.device || row.inode !== entry.inode)
|
|
124
|
+
retags.push({ row, entry });
|
|
125
|
+
}
|
|
126
|
+
const orphanRows = rows.filter((row) => !claimedRowIds.has(row.linkId));
|
|
127
|
+
const renames = matchByInode(orphanRows, orphanEntries);
|
|
128
|
+
const renamedRowIds = new Set(renames.map((pair) => pair.row.linkId));
|
|
129
|
+
const renamedEntries = new Set(renames.map((pair) => pair.entry));
|
|
130
|
+
return {
|
|
131
|
+
changes,
|
|
132
|
+
retags,
|
|
133
|
+
renames,
|
|
134
|
+
creates: orphanEntries.filter((entry) => !renamedEntries.has(entry)),
|
|
135
|
+
deletes: orphanRows.filter((row) => !renamedRowIds.has(row.linkId)),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* The compare function for file channels — doorbells and rescans both
|
|
140
|
+
* end here. Hashing is deferred — `checks` name the files whose content
|
|
141
|
+
* must be read before an event may be claimed.
|
|
142
|
+
*
|
|
143
|
+
* Identity rules, in order:
|
|
144
|
+
* 1. Path claims the channel. Same rel_path = same file_id, even when
|
|
145
|
+
* the inode changed (atomic saves replace the inode on every
|
|
146
|
+
* write).
|
|
147
|
+
* 2. Inode rescues path-orphans (matchByInode above).
|
|
148
|
+
* 3. Leftover entries are creates; leftover rows are deletes.
|
|
149
|
+
*
|
|
150
|
+
* The single stat-shortcut this layer allows itself: a (size, mtime,
|
|
151
|
+
* inode) triple identical to the stored one is skipped as unchanged —
|
|
152
|
+
* but only when the mtime is strictly older than the moment we last
|
|
153
|
+
* read the bytes (git's "racily clean" rule), and only when nothing
|
|
154
|
+
* pointed at the file. A path named in `mustCheck` (the doorbell said
|
|
155
|
+
* so) is always hashed: timestamps can lie, a delivered watcher event
|
|
156
|
+
* cannot be un-delivered.
|
|
157
|
+
*/
|
|
158
|
+
function diffRootState(rows, entries, mustCheck = null) {
|
|
159
|
+
const checks = [];
|
|
160
|
+
let unchanged = 0;
|
|
161
|
+
const rowsByPath = new Map(rows.map((row) => [row.relPath, row]));
|
|
162
|
+
const claimedRowIds = new Set();
|
|
163
|
+
const orphanEntries = [];
|
|
164
|
+
for (const entry of entries) {
|
|
165
|
+
const row = rowsByPath.get(entry.relPath);
|
|
166
|
+
if (!row) {
|
|
167
|
+
orphanEntries.push(entry);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
claimedRowIds.add(row.fileId);
|
|
171
|
+
const statsMatch = row.size === entry.size && row.mtimeMs === entry.mtimeMs && row.inode === entry.inode;
|
|
172
|
+
const provablyBeforeLastRead = typeof row.hashedAtMs === 'number' && entry.mtimeMs < row.hashedAtMs;
|
|
173
|
+
const named = mustCheck !== null && mustCheck.has(entry.relPath);
|
|
174
|
+
if (statsMatch && provablyBeforeLastRead && !named) {
|
|
175
|
+
unchanged += 1;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
checks.push({ row, entry });
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const orphanRows = rows.filter((row) => !claimedRowIds.has(row.fileId));
|
|
182
|
+
const renames = matchByInode(orphanRows, orphanEntries);
|
|
183
|
+
const renamedRowIds = new Set(renames.map((pair) => pair.row.fileId));
|
|
184
|
+
const renamedEntries = new Set(renames.map((pair) => pair.entry));
|
|
185
|
+
return {
|
|
186
|
+
checks,
|
|
187
|
+
renames,
|
|
188
|
+
creates: orphanEntries.filter((entry) => !renamedEntries.has(entry)),
|
|
189
|
+
deletes: orphanRows.filter((row) => !renamedRowIds.has(row.fileId)),
|
|
190
|
+
unchanged,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/detection/diff.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;AAyDH,oCAiBC;AA2BD,oCAwBC;AAyBD,sCA2BC;AA+BD,sCAwCC;AArMD;;;;;GAKG;AACH,SAAgB,YAAY,CAC1B,IAAoB,EACpB,OAAyB;IAEzB,MAAM,GAAG,GAAG,CAAQ,GAAgC,EAAE,GAAW,EAAE,KAAY,EAAE,EAAE,CACjF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAwB,CAAC;IACpD,KAAK,MAAM,GAAG,IAAI,IAAI;QAAE,GAAG,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;IAC5E,MAAM,cAAc,GAAG,IAAI,GAAG,EAA0B,CAAC;IACzD,KAAK,MAAM,KAAK,IAAI,OAAO;QAAE,GAAG,CAAC,cAAc,EAAE,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1F,MAAM,OAAO,GAA6B,EAAE,CAAC;IAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,cAAc,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,KAAK,KAAK,MAAM,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,MAAM;YAAE,SAAS;QACzD,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AASD;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,YAAY,CAAC,IAAuB,EAAE,OAA4B;IAChF,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5C,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACrE,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;SAC3E,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,MAAM,GAAmC,EAAE,CAAC;IAClD,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS;QACxC,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,GAAG,EAAE,CAAC;YACR,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACjC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QAC1E,MAAM;QACN,OAAO;QACP,OAAO,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;KAClC,CAAC;AACJ,CAAC;AAUD;;;;;;;;;;;;;;GAcG;AACH,SAAgB,aAAa,CAAC,IAAwB,EAAE,OAA6B;IACnF,MAAM,OAAO,GAAqC,EAAE,CAAC;IACrD,MAAM,MAAM,GAAqC,EAAE,CAAC;IACpD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,MAAM,aAAa,GAAgB,EAAE,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;aACzD,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK;YAAE,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IACjG,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACxD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACtE,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAClE,OAAO;QACL,OAAO;QACP,MAAM;QACN,OAAO;QACP,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpE,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;KACpE,CAAC;AACJ,CAAC;AAWD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAgB,aAAa,CAC3B,IAAwB,EACxB,OAA6B,EAC7B,YAAwC,IAAI;IAE5C,MAAM,MAAM,GAAqC,EAAE,CAAC;IACpD,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,MAAM,aAAa,GAAgB,EAAE,CAAC;IAEtC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,IAAI,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC;QACzG,MAAM,sBAAsB,GAAG,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC;QACpG,MAAM,KAAK,GAAG,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACjE,IAAI,UAAU,IAAI,sBAAsB,IAAI,CAAC,KAAK,EAAE,CAAC;YACnD,SAAS,IAAI,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACxD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACtE,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAElE,OAAO;QACL,MAAM;QACN,OAAO;QACP,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpE,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnE,SAAS;KACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Echo judgment after incoming Apply.
|
|
4
|
+
*
|
|
5
|
+
* Apply never suppresses watcher rings. It verifies the incoming result and
|
|
6
|
+
* advances the notebook. The retained suspicion then uses this ordinary
|
|
7
|
+
* equality judgment: exact expected truth is silence; different truth is a
|
|
8
|
+
* real local change; unreadable truth is retried.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.echoDecision = echoDecision;
|
|
12
|
+
function echoDecision(notebook, observed) {
|
|
13
|
+
if (observed.truth === 'unsettled') {
|
|
14
|
+
return observed.reason === undefined
|
|
15
|
+
? { kind: 'retry' }
|
|
16
|
+
: { kind: 'retry', reason: observed.reason };
|
|
17
|
+
}
|
|
18
|
+
if (notebook.status === 'active') {
|
|
19
|
+
return observed.truth === 'present' && observed.version === notebook.version
|
|
20
|
+
? { kind: 'silence' }
|
|
21
|
+
: { kind: 'detect' };
|
|
22
|
+
}
|
|
23
|
+
return observed.truth === 'absent' ? { kind: 'silence' } : { kind: 'detect' };
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=echo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"echo.js","sourceRoot":"","sources":["../../src/detection/echo.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAUH,oCAeC;AAfD,SAAgB,YAAY,CAC1B,QAAuD,EACvD,QAAsB;IAEtB,IAAI,QAAQ,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;QACnC,OAAO,QAAQ,CAAC,MAAM,KAAK,SAAS;YAClC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE;YACnB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IACjD,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,QAAQ,CAAC,KAAK,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,KAAK,QAAQ,CAAC,OAAO;YAC1E,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE;YACrB,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAChF,CAAC"}
|