@ricsam/r5d-worker 0.0.74 → 0.0.76

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 (32) hide show
  1. package/README.md +6 -4
  2. package/dist/cjs/main.cjs +1031 -976
  3. package/dist/cjs/package.json +1 -1
  4. package/dist/cjs/project-workspace-state.cjs +777 -0
  5. package/dist/cjs/project-worktrees.cjs +559 -0
  6. package/dist/cjs/working-tree-mirror.cjs +225 -0
  7. package/dist/cjs/workspace-git-sync.cjs +565 -0
  8. package/dist/cjs/workspace-incident-state.cjs +2 -38
  9. package/dist/mjs/main.mjs +1048 -987
  10. package/dist/mjs/package.json +1 -1
  11. package/dist/mjs/project-workspace-state.mjs +745 -0
  12. package/dist/mjs/project-worktrees.mjs +513 -0
  13. package/dist/mjs/working-tree-mirror.mjs +190 -0
  14. package/dist/mjs/workspace-git-sync.mjs +524 -0
  15. package/dist/mjs/workspace-incident-state.mjs +1 -35
  16. package/dist/types/main.d.ts +35 -55
  17. package/dist/types/project-workspace-state.d.ts +144 -0
  18. package/dist/types/project-worktrees.d.ts +112 -0
  19. package/dist/types/working-tree-mirror.d.ts +24 -0
  20. package/dist/types/workspace-git-sync.d.ts +97 -0
  21. package/dist/types/workspace-incident-state.d.ts +0 -17
  22. package/dist/types/workspace-mutation-gate.d.ts +3 -3
  23. package/package.json +1 -1
  24. package/dist/cjs/workspace-convergence.cjs +0 -280
  25. package/dist/cjs/workspace-manifest-admission.cjs +0 -60
  26. package/dist/cjs/workspace-sync.cjs +0 -2469
  27. package/dist/mjs/workspace-convergence.mjs +0 -236
  28. package/dist/mjs/workspace-manifest-admission.mjs +0 -26
  29. package/dist/mjs/workspace-sync.mjs +0 -2417
  30. package/dist/types/workspace-convergence.d.ts +0 -93
  31. package/dist/types/workspace-manifest-admission.d.ts +0 -22
  32. package/dist/types/workspace-sync.d.ts +0 -167
@@ -1,236 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- const WORKSPACE_PUBLICATION_QUIET_MS = 5e3;
4
- const WORKSPACE_IDLE_SAFETY_SCAN_MS = 6e4;
5
- const WORKSPACE_MANIFEST_REVISION_PATTERN = /^[0-9a-f]{64}$/;
6
- class WorkspaceManifestRevisionFence {
7
- sequence = 0;
8
- requestedRevision = null;
9
- completedRevision = null;
10
- begin(revision) {
11
- if (!WORKSPACE_MANIFEST_REVISION_PATTERN.test(revision)) {
12
- throw new Error("Workspace manifest revision must be a lowercase SHA-256 hash");
13
- }
14
- this.sequence += 1;
15
- this.requestedRevision = revision;
16
- this.completedRevision = null;
17
- return { sequence: this.sequence, revision };
18
- }
19
- isCurrent(token) {
20
- return token.sequence === this.sequence && token.revision === this.requestedRevision;
21
- }
22
- complete(token) {
23
- if (!this.isCurrent(token)) return false;
24
- this.completedRevision = token.revision;
25
- return true;
26
- }
27
- readyRevision() {
28
- return this.completedRevision === this.requestedRevision ? this.completedRevision : null;
29
- }
30
- }
31
- function workspacePublicationTelemetry(input) {
32
- return {
33
- totalMs: Math.max(0, input.finishedAt - input.requestedAt),
34
- queueMs: Math.max(0, input.prepareStartedAt - input.requestedAt),
35
- prepareMs: Math.max(0, input.synchronizeStartedAt - input.prepareStartedAt),
36
- synchronizeMs: Math.max(0, input.finishedAt - input.synchronizeStartedAt)
37
- };
38
- }
39
- function workspacePublicationIncidentAction(requestId) {
40
- return requestId ? "request_terminal_authority" : "defer_automatic";
41
- }
42
- class ExplicitWorkspacePublicationQueue {
43
- scheduled;
44
- queued = [];
45
- schedule(publication, pendingRequestId) {
46
- if (pendingRequestId === publication.requestId || this.scheduled?.requestId === publication.requestId || this.queued.some((queued) => queued.requestId === publication.requestId)) {
47
- return false;
48
- }
49
- if (pendingRequestId || this.scheduled) {
50
- this.queued.push(publication);
51
- return false;
52
- }
53
- this.scheduled = publication;
54
- return true;
55
- }
56
- hasScheduled() {
57
- return this.scheduled !== void 0;
58
- }
59
- consumeScheduled(requestId) {
60
- if (this.scheduled?.requestId === requestId) this.scheduled = void 0;
61
- }
62
- enqueue(publication, pendingRequestId) {
63
- if (pendingRequestId === publication.requestId || this.scheduled?.requestId === publication.requestId || this.queued.some((queued) => queued.requestId === publication.requestId)) {
64
- return;
65
- }
66
- this.queued.push(publication);
67
- }
68
- next() {
69
- return this.queued.shift();
70
- }
71
- }
72
- const EMPTY_STATE = {
73
- localHead: null,
74
- visibleBaselineHead: null,
75
- desiredCanonicalHead: null,
76
- dirtyGeneration: 0,
77
- publishedGeneration: 0
78
- };
79
- function validHead(value) {
80
- return value === null || typeof value === "string" && /^[0-9a-f]{40,64}$/.test(value);
81
- }
82
- function validGeneration(value) {
83
- return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
84
- }
85
- function readWorkspaceConvergenceState(statePath) {
86
- try {
87
- const parsed = JSON.parse(fs.readFileSync(statePath, "utf8"));
88
- if (!validHead(parsed.localHead) || !(parsed.visibleBaselineHead === void 0 || validHead(parsed.visibleBaselineHead)) || !validHead(parsed.desiredCanonicalHead) || !validGeneration(parsed.dirtyGeneration) || !validGeneration(parsed.publishedGeneration) || parsed.publishedGeneration > parsed.dirtyGeneration) {
89
- return { ...EMPTY_STATE };
90
- }
91
- return {
92
- localHead: parsed.localHead,
93
- visibleBaselineHead: parsed.visibleBaselineHead === void 0 ? parsed.localHead : parsed.visibleBaselineHead,
94
- desiredCanonicalHead: parsed.desiredCanonicalHead,
95
- dirtyGeneration: parsed.dirtyGeneration,
96
- publishedGeneration: parsed.publishedGeneration
97
- };
98
- } catch {
99
- return { ...EMPTY_STATE };
100
- }
101
- }
102
- class WorkspaceConvergenceState {
103
- constructor(statePath) {
104
- this.statePath = statePath;
105
- this.state = readWorkspaceConvergenceState(statePath);
106
- this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
107
- }
108
- statePath;
109
- state;
110
- publicationState;
111
- snapshot() {
112
- return {
113
- localHead: this.state.localHead,
114
- desiredCanonicalHead: this.state.desiredCanonicalHead,
115
- dirtyGeneration: this.state.dirtyGeneration,
116
- publishedGeneration: this.state.publishedGeneration,
117
- publicationState: this.publicationState
118
- };
119
- }
120
- visibleBaselineHead() {
121
- return this.state.visibleBaselineHead;
122
- }
123
- setLocalHead(localHead) {
124
- if (!validHead(localHead)) throw new Error("Invalid local workspace head");
125
- this.state.localHead = localHead;
126
- this.state.visibleBaselineHead = localHead;
127
- this.persist();
128
- }
129
- setVisibleBaselineHead(visibleBaselineHead) {
130
- if (!validHead(visibleBaselineHead)) throw new Error("Invalid visible workspace baseline head");
131
- this.state.visibleBaselineHead = visibleBaselineHead;
132
- this.persist();
133
- }
134
- observeCanonicalHead(canonicalHead) {
135
- if (!validHead(canonicalHead)) throw new Error("Invalid canonical workspace head");
136
- if (this.state.desiredCanonicalHead === canonicalHead) return false;
137
- this.state.desiredCanonicalHead = canonicalHead;
138
- this.persist();
139
- return true;
140
- }
141
- markDirty() {
142
- this.state.dirtyGeneration += 1;
143
- if (this.publicationState === "idle") this.publicationState = "scheduled";
144
- this.persist();
145
- return this.state.dirtyGeneration;
146
- }
147
- schedule() {
148
- if (this.publicationState === "idle") this.publicationState = "scheduled";
149
- }
150
- beginPreparing() {
151
- if (this.publicationState === "preparing" || this.publicationState === "submitting") {
152
- throw new Error("A workspace publication is already in flight");
153
- }
154
- this.publicationState = "preparing";
155
- }
156
- beginSubmitting() {
157
- if (this.publicationState !== "preparing") throw new Error("Workspace publication authority was not prepared");
158
- this.publicationState = "submitting";
159
- }
160
- defer() {
161
- this.publicationState = "scheduled";
162
- }
163
- block() {
164
- this.publicationState = "blocked";
165
- }
166
- releaseBlock() {
167
- this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
168
- }
169
- observeIncidentState(blocked) {
170
- if (this.publicationState === "preparing" || this.publicationState === "submitting") return;
171
- if (blocked) this.block();
172
- else this.releaseBlock();
173
- }
174
- resetTransientPublicationState() {
175
- this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
176
- }
177
- complete(input) {
178
- if (!validGeneration(input.generation) || input.generation > this.state.dirtyGeneration) {
179
- throw new Error("Invalid completed workspace generation");
180
- }
181
- if (!validHead(input.canonicalHead)) throw new Error("Invalid completed canonical workspace head");
182
- if (input.published) {
183
- this.state.publishedGeneration = Math.max(this.state.publishedGeneration, input.generation);
184
- this.state.localHead = input.canonicalHead;
185
- this.state.visibleBaselineHead = input.canonicalHead;
186
- this.state.desiredCanonicalHead = input.canonicalHead;
187
- }
188
- this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
189
- this.persist();
190
- }
191
- persist() {
192
- fs.mkdirSync(path.dirname(this.statePath), { recursive: true });
193
- const temporaryPath = `${this.statePath}.${process.pid}.${crypto.randomUUID()}.tmp`;
194
- fs.writeFileSync(temporaryPath, `${JSON.stringify(this.state)}
195
- `, { mode: 384 });
196
- fs.renameSync(temporaryPath, this.statePath);
197
- }
198
- }
199
- const PROCESS_WORKSPACE_CONVERGENCE_STATES = /* @__PURE__ */ new Map();
200
- function processWorkspaceConvergenceState(statePath) {
201
- const key = path.resolve(statePath);
202
- const existing = PROCESS_WORKSPACE_CONVERGENCE_STATES.get(key);
203
- if (existing) return existing;
204
- const created = new WorkspaceConvergenceState(key);
205
- PROCESS_WORKSPACE_CONVERGENCE_STATES.set(key, created);
206
- return created;
207
- }
208
- function workspaceBootstrapEstablishesVisibleBaseline(input) {
209
- if (input.hydrated) return true;
210
- return input.firstBootstrap && !input.incidentActive && input.currentLocalHead === null && input.currentVisibleBaselineHead === null;
211
- }
212
- async function waitForWorkspacePublicationOnShutdown(input) {
213
- input.forcePublication();
214
- const deadline = Date.now() + (input.timeoutMs ?? 1e4);
215
- const pollMs = input.pollMs ?? 50;
216
- while (Date.now() < deadline) {
217
- const snapshot = input.snapshot();
218
- if (snapshot.publicationState === "blocked") return "blocked";
219
- if (snapshot.publicationState === "idle" && snapshot.publishedGeneration >= snapshot.dirtyGeneration) return "settled";
220
- await new Promise((resolve) => setTimeout(resolve, pollMs));
221
- }
222
- return "timed_out";
223
- }
224
- export {
225
- ExplicitWorkspacePublicationQueue,
226
- WORKSPACE_IDLE_SAFETY_SCAN_MS,
227
- WORKSPACE_PUBLICATION_QUIET_MS,
228
- WorkspaceConvergenceState,
229
- WorkspaceManifestRevisionFence,
230
- processWorkspaceConvergenceState,
231
- readWorkspaceConvergenceState,
232
- waitForWorkspacePublicationOnShutdown,
233
- workspaceBootstrapEstablishesVisibleBaseline,
234
- workspacePublicationIncidentAction,
235
- workspacePublicationTelemetry
236
- };
@@ -1,26 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { managedProjectRoot } from "./managed-paths.mjs";
4
- function hasNormalGitDirectory(checkoutPath) {
5
- const gitPath = path.join(checkoutPath, ".git");
6
- return fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory();
7
- }
8
- function inspectWorkspaceManifestFilesystem(input) {
9
- const firstBootstrap = !hasNormalGitDirectory(input.workspaceShadowRoot);
10
- const missingCheckouts = [];
11
- for (const project of input.projects) {
12
- const projectRoot = managedProjectRoot(input.projectsRoot, project.checkoutPathSegments);
13
- for (const branchName of project.branches) {
14
- if (!hasNormalGitDirectory(path.join(projectRoot, branchName))) {
15
- missingCheckouts.push({ projectId: project.projectId, branchName });
16
- }
17
- }
18
- }
19
- return {
20
- firstBootstrap,
21
- missingCheckouts
22
- };
23
- }
24
- export {
25
- inspectWorkspaceManifestFilesystem
26
- };