@claudexor/daemon 3.11.0 → 3.12.1
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/dist/client.d.ts +6 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +6 -2
- package/dist/client.js.map +1 -1
- package/dist/command-retention.d.ts +27 -2
- package/dist/command-retention.d.ts.map +1 -1
- package/dist/command-retention.js +119 -17
- package/dist/command-retention.js.map +1 -1
- package/dist/command-scope-roots.d.ts +7 -0
- package/dist/command-scope-roots.d.ts.map +1 -0
- package/dist/command-scope-roots.js +14 -0
- package/dist/command-scope-roots.js.map +1 -0
- package/dist/command-store.d.ts +5 -0
- package/dist/command-store.d.ts.map +1 -1
- package/dist/command-store.js +36 -22
- package/dist/command-store.js.map +1 -1
- package/dist/delegation-admission.d.ts +0 -1
- package/dist/delegation-admission.d.ts.map +1 -1
- package/dist/delegation-admission.js +1 -6
- package/dist/delegation-admission.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/journal-fold-policy.d.ts +51 -0
- package/dist/journal-fold-policy.d.ts.map +1 -0
- package/dist/journal-fold-policy.js +174 -0
- package/dist/journal-fold-policy.js.map +1 -0
- package/dist/journal-maintenance.d.ts +27 -4
- package/dist/journal-maintenance.d.ts.map +1 -1
- package/dist/journal-maintenance.js +59 -9
- package/dist/journal-maintenance.js.map +1 -1
- package/dist/journal-manager-journal.d.ts +18 -0
- package/dist/journal-manager-journal.d.ts.map +1 -0
- package/dist/journal-manager-journal.js +25 -0
- package/dist/journal-manager-journal.js.map +1 -0
- package/dist/journal-manager.d.ts +1 -0
- package/dist/journal-manager.d.ts.map +1 -1
- package/dist/journal-manager.js +11 -12
- package/dist/journal-manager.js.map +1 -1
- package/dist/journal-recovery-files.d.ts +5 -0
- package/dist/journal-recovery-files.d.ts.map +1 -1
- package/dist/journal-recovery-files.js +42 -3
- package/dist/journal-recovery-files.js.map +1 -1
- package/dist/journaled-run-events.d.ts +20 -0
- package/dist/journaled-run-events.d.ts.map +1 -0
- package/dist/journaled-run-events.js +46 -0
- package/dist/journaled-run-events.js.map +1 -0
- package/dist/model-operations.d.ts +1 -1
- package/dist/model-operations.d.ts.map +1 -1
- package/dist/model-operations.js +18 -8
- package/dist/model-operations.js.map +1 -1
- package/dist/project-partitions.d.ts +6 -0
- package/dist/project-partitions.d.ts.map +1 -1
- package/dist/project-partitions.js +13 -1
- package/dist/project-partitions.js.map +1 -1
- package/dist/quota-registry-support.d.ts +15 -1
- package/dist/quota-registry-support.d.ts.map +1 -1
- package/dist/quota-registry-support.js +49 -1
- package/dist/quota-registry-support.js.map +1 -1
- package/dist/quota-registry.d.ts.map +1 -1
- package/dist/quota-registry.js +18 -40
- package/dist/quota-registry.js.map +1 -1
- package/dist/run-event-terminal-index.d.ts +13 -0
- package/dist/run-event-terminal-index.d.ts.map +1 -0
- package/dist/run-event-terminal-index.js +38 -0
- package/dist/run-event-terminal-index.js.map +1 -0
- package/dist/run-events.d.ts +2 -0
- package/dist/run-events.d.ts.map +1 -1
- package/dist/run-events.js +4 -4
- package/dist/run-events.js.map +1 -1
- package/dist/server.d.ts +2 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +8 -7
- package/dist/server.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -16,7 +16,9 @@ export * from "./thread-head-ping.js";
|
|
|
16
16
|
export * from "./projects.js";
|
|
17
17
|
export * from "./journal-manager.js";
|
|
18
18
|
export * from "./journal-maintenance.js";
|
|
19
|
+
export * from "./journal-fold-policy.js";
|
|
19
20
|
export * from "./command-store.js";
|
|
21
|
+
export * from "./command-scope-roots.js";
|
|
20
22
|
export * from "./command-authority.js";
|
|
21
23
|
export * from "./resource-store.js";
|
|
22
24
|
export * from "./quota-registry.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,cAAc,iCAAiC,CAAC;AAChD,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,cAAc,iCAAiC,CAAC;AAChD,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The daemon's journal fold policy: which retained records a partition may
|
|
3
|
+
* forget at replay and at compaction (journal sprint owner decision D1). The
|
|
4
|
+
* journal package stays generic — it applies these verdicts in seq order — and
|
|
5
|
+
* this module decides WHAT is dead, per record type, from the payload alone.
|
|
6
|
+
*
|
|
7
|
+
* Every verdict is a pure function of the record: no state between records,
|
|
8
|
+
* so the one frozen policy serves every partition and every pass (read-only
|
|
9
|
+
* preparation, activation, background compaction). An unknown or malformed
|
|
10
|
+
* record is always kept — the fold forgets superseded history, never evidence
|
|
11
|
+
* it cannot classify.
|
|
12
|
+
*
|
|
13
|
+
* Invariants the projections replay under (the equivalence test pins them):
|
|
14
|
+
* - a command keeps its `command.accepted` (a group per id, so a duplicate
|
|
15
|
+
* acceptance survives) and its latest `command.updated`;
|
|
16
|
+
* `command.pruned` forgets both plus the pruned runs' journaled run events,
|
|
17
|
+
* and survives itself as the latest tombstone per root set so crash-GC keeps
|
|
18
|
+
* the pruned commands' project roots (model-operation receipts are never
|
|
19
|
+
* pruned by retention — INV-064);
|
|
20
|
+
* - a terminal run keeps its terminal `run.event` (exactly one in a
|
|
21
|
+
* well-formed journal; duplicate terminals survive until the run's prune
|
|
22
|
+
* tombstone retires the whole group, so replay validation fails on them
|
|
23
|
+
* as loudly as on an unfolded journal); a live run keeps `run.created`
|
|
24
|
+
* plus its journaled progress events;
|
|
25
|
+
* - a resolved interaction forgets its request AND its resolution as a pair
|
|
26
|
+
* through the resolution (a resolution follows its request, so retiring
|
|
27
|
+
* on the resolution can never leave a partial pair — an `interrupted` or
|
|
28
|
+
* `run_terminal` resolution lands AFTER the run's terminal event); a
|
|
29
|
+
* pending request is kept per id as a group, so a duplicate request frame
|
|
30
|
+
* survives for the InteractionStore's own duplicate check until its
|
|
31
|
+
* resolution retires the whole group. Every `interaction.resolved` frame
|
|
32
|
+
* is dropped, so an orphan or duplicate resolution the unfolded replay
|
|
33
|
+
* refuses ("interaction resolution precedes request") is forgotten on the
|
|
34
|
+
* folded path — inherent in the pair rule, disclosed;
|
|
35
|
+
* - quota keeps the latest projection marker and, per subject key, two
|
|
36
|
+
* slots: the latest scoped prepare and the latest upsert. Sequence numbers
|
|
37
|
+
* are preserved, so the registry's adjacency check (`upsert.seq ===
|
|
38
|
+
* prepare.seq + 1`) commits exactly the pairs that were adjacent on disk;
|
|
39
|
+
* a prepare left behind by a later plain upsert is non-adjacent and ignored
|
|
40
|
+
* on replay like any orphan prepare today (residual: at most one stale
|
|
41
|
+
* prepare frame per subject). `quota.subject.removed` retires both slots
|
|
42
|
+
* of that (harness, subject_id) across routes and sources;
|
|
43
|
+
* - `thread.head.updated` keeps the latest revision per thread;
|
|
44
|
+
* - `setup.job.saved` is kept whole (the setup reducer validates every
|
|
45
|
+
* state/phase/evidence transition, so intermediate saves are replay
|
|
46
|
+
* authority); a terminal save retires the job's `setup.job.log` lines.
|
|
47
|
+
*/
|
|
48
|
+
import type { JournalFold } from "@claudexor/journal";
|
|
49
|
+
/** The one frozen policy for every partition and every pass. */
|
|
50
|
+
export declare const journalFoldPolicy: JournalFold;
|
|
51
|
+
//# sourceMappingURL=journal-fold-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal-fold-policy.d.ts","sourceRoot":"","sources":["../src/journal-fold-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,OAAO,KAAK,EAA2B,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAa/E,gEAAgE;AAChE,eAAO,MAAM,iBAAiB,EAAE,WAA4D,CAAC"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { CredentialRoute, QuotaSnapshot as QuotaSnapshotSchema, QuotaSource, TERMINAL_CONTROL_SETUP_JOB_STATES, } from "@claudexor/schema";
|
|
2
|
+
import { legacyV320Snapshot, snapshotKey } from "./quota-registry-support.js";
|
|
3
|
+
const KEEP = Object.freeze({});
|
|
4
|
+
const TERMINAL_RUN_EVENTS = new Set(["run.completed", "run.failed", "run.blocked"]);
|
|
5
|
+
const TERMINAL_SETUP_STATES = new Set(TERMINAL_CONTROL_SETUP_JOB_STATES);
|
|
6
|
+
/** The one frozen policy for every partition and every pass. */
|
|
7
|
+
export const journalFoldPolicy = Object.freeze({ verdict: journalFoldVerdict });
|
|
8
|
+
function journalFoldVerdict(record) {
|
|
9
|
+
try {
|
|
10
|
+
switch (record.type) {
|
|
11
|
+
case "command.accepted":
|
|
12
|
+
// A group per id, never a slot: a duplicate acceptance (same id,
|
|
13
|
+
// conflicting digest) must survive for the CommandStore's own
|
|
14
|
+
// idempotency-history check, as on an unfolded journal.
|
|
15
|
+
return groupOrKeep(commandId(record.payload), (id) => `c:${id}:a`);
|
|
16
|
+
case "command.updated":
|
|
17
|
+
return slotOrKeep(commandId(record.payload), (id) => `c:${id}:u`);
|
|
18
|
+
case "command.pruned":
|
|
19
|
+
return prunedVerdict(record.payload);
|
|
20
|
+
case "run.event":
|
|
21
|
+
return runEventVerdict(record.payload);
|
|
22
|
+
case "interaction.requested":
|
|
23
|
+
return interactionRequestedVerdict(record.payload);
|
|
24
|
+
case "interaction.resolved":
|
|
25
|
+
return interactionResolvedVerdict(record.payload);
|
|
26
|
+
case "quota.projection.updated":
|
|
27
|
+
return { slot: "q:marker" };
|
|
28
|
+
case "quota.snapshot.scoped_prepared":
|
|
29
|
+
return slotOrKeep(scopedPreparedKey(record.payload), (key) => `q:${key}:p`);
|
|
30
|
+
case "quota.snapshot.upserted":
|
|
31
|
+
return slotOrKeep(upsertedKey(record.payload), (key) => `q:${key}:u`);
|
|
32
|
+
case "quota.subject.removed":
|
|
33
|
+
return removedSubjectVerdict(record.payload);
|
|
34
|
+
case "thread.head.updated":
|
|
35
|
+
return slotOrKeep(stringField(record.payload, "thread_id"), (id) => `t:${id}`);
|
|
36
|
+
case "setup.job.saved":
|
|
37
|
+
return setupSavedVerdict(record.payload);
|
|
38
|
+
case "setup.job.log":
|
|
39
|
+
return groupOrKeep(stringField(record.payload, "jobId"), (id) => `s:${id}:log`);
|
|
40
|
+
default:
|
|
41
|
+
return KEEP;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return KEEP;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function slotOrKeep(key, name) {
|
|
49
|
+
return key === null ? KEEP : { slot: name(key) };
|
|
50
|
+
}
|
|
51
|
+
function groupOrKeep(key, name) {
|
|
52
|
+
return key === null ? KEEP : { group: name(key) };
|
|
53
|
+
}
|
|
54
|
+
function object(value) {
|
|
55
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
56
|
+
? value
|
|
57
|
+
: null;
|
|
58
|
+
}
|
|
59
|
+
function stringField(value, key) {
|
|
60
|
+
const field = object(value)?.[key];
|
|
61
|
+
return typeof field === "string" && field.length > 0 ? field : null;
|
|
62
|
+
}
|
|
63
|
+
function stringList(value) {
|
|
64
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
65
|
+
return null;
|
|
66
|
+
return value.every((item) => typeof item === "string" && item.length > 0)
|
|
67
|
+
? value
|
|
68
|
+
: null;
|
|
69
|
+
}
|
|
70
|
+
function commandId(payload) {
|
|
71
|
+
return stringField(object(payload)?.record, "id");
|
|
72
|
+
}
|
|
73
|
+
/** Every run event of a run is keyed under its run id; the terminal retires
|
|
74
|
+
* the live group and the created slot, and a prune tombstone retires all three. */
|
|
75
|
+
function runEventNames(runId) {
|
|
76
|
+
return [`r:${runId}:t`, `r:${runId}:live`, `r:${runId}:c`];
|
|
77
|
+
}
|
|
78
|
+
/** A prune tombstone retires its commands' records AND every journaled run
|
|
79
|
+
* event of the runs those commands owned (`run_ids`, written since this
|
|
80
|
+
* change; legacy tombstones without it retire the commands only), and is
|
|
81
|
+
* itself kept — the latest per set of project roots it names — because
|
|
82
|
+
* crash-GC reads the roots of pruned commands from it. Ids in a superseded
|
|
83
|
+
* tombstone are dead weight: its retire already ran when it was folded. */
|
|
84
|
+
function prunedVerdict(payload) {
|
|
85
|
+
const value = object(payload);
|
|
86
|
+
const ids = stringList(value?.ids);
|
|
87
|
+
if (!ids)
|
|
88
|
+
return KEEP;
|
|
89
|
+
const roots = stringList(value?.roots) ?? [];
|
|
90
|
+
const runIds = stringList(value?.run_ids) ?? [];
|
|
91
|
+
return {
|
|
92
|
+
slot: `c:pruned:${[...roots].sort().join("\0")}`,
|
|
93
|
+
retire: [...ids.flatMap((id) => [`c:${id}:a`, `c:${id}:u`]), ...runIds.flatMap(runEventNames)],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** A terminal run keeps only its terminal: `run.created` and the journaled
|
|
97
|
+
* progress events are forgotten with it (the macOS app auto-attaches on
|
|
98
|
+
* `run.created` only for live runs; durable terminal recovery reads terminals
|
|
99
|
+
* only; the per-run stream replays `events.jsonl`). Terminals are a GROUP per
|
|
100
|
+
* run, never a slot: a second terminal for the same run is corruption the
|
|
101
|
+
* terminal index must still see and refuse, exactly as on an unfolded journal,
|
|
102
|
+
* until the run's prune tombstone retires the whole group. */
|
|
103
|
+
function runEventVerdict(payload) {
|
|
104
|
+
const runId = stringField(payload, "run_id");
|
|
105
|
+
const type = stringField(payload, "type");
|
|
106
|
+
if (runId === null || type === null)
|
|
107
|
+
return KEEP;
|
|
108
|
+
if (TERMINAL_RUN_EVENTS.has(type)) {
|
|
109
|
+
return { group: `r:${runId}:t`, retire: [`r:${runId}:live`, `r:${runId}:c`] };
|
|
110
|
+
}
|
|
111
|
+
if (type === "run.created")
|
|
112
|
+
return { slot: `r:${runId}:c` };
|
|
113
|
+
return { group: `r:${runId}:live` };
|
|
114
|
+
}
|
|
115
|
+
/** A group per id, never a slot: a duplicate request frame must survive for
|
|
116
|
+
* the InteractionStore's own duplicate check, as on an unfolded journal. */
|
|
117
|
+
function interactionRequestedVerdict(payload) {
|
|
118
|
+
const runId = stringField(payload, "runId");
|
|
119
|
+
const interactionId = stringField(payload, "interactionId");
|
|
120
|
+
if (runId === null || interactionId === null)
|
|
121
|
+
return KEEP;
|
|
122
|
+
return { group: `i:${runId}:${interactionId}` };
|
|
123
|
+
}
|
|
124
|
+
/** The resolution retires exactly the requests it settles and is itself
|
|
125
|
+
* forgotten: the InteractionStore rebuilds only still-pending questions. */
|
|
126
|
+
function interactionResolvedVerdict(payload) {
|
|
127
|
+
const runId = stringField(payload, "runId");
|
|
128
|
+
const interactionIds = stringList(object(payload)?.interactionIds);
|
|
129
|
+
if (runId === null || !interactionIds)
|
|
130
|
+
return KEEP;
|
|
131
|
+
return { drop: true, retire: interactionIds.map((id) => `i:${runId}:${id}`) };
|
|
132
|
+
}
|
|
133
|
+
/** Both quota slots are keyed by the LEGACY base snapshot, which is the key
|
|
134
|
+
* the committing upsert carries on the wire (sources are harness-specific, so
|
|
135
|
+
* the only legacy remap — cursor_rate_limit to claude_api_retry — never
|
|
136
|
+
* collides with a genuine legacy-source snapshot of the same subject). */
|
|
137
|
+
function scopedPreparedKey(payload) {
|
|
138
|
+
const snapshot = QuotaSnapshotSchema.safeParse(object(payload)?.snapshot);
|
|
139
|
+
return snapshot.success ? snapshotKey(legacyV320Snapshot(snapshot.data)) : null;
|
|
140
|
+
}
|
|
141
|
+
function upsertedKey(payload) {
|
|
142
|
+
const snapshot = QuotaSnapshotSchema.safeParse(payload);
|
|
143
|
+
return snapshot.success ? snapshotKey(snapshot.data) : null;
|
|
144
|
+
}
|
|
145
|
+
/** `quota.subject.removed` names only (harness, subject_id); the registry
|
|
146
|
+
* removes every snapshot of that subject across routes and sources, so the
|
|
147
|
+
* retire list enumerates the schema's route and source vocabularies. A journal
|
|
148
|
+
* can only replay sources the schema still knows, so the enumeration is
|
|
149
|
+
* complete for every replayable record. */
|
|
150
|
+
function removedSubjectVerdict(payload) {
|
|
151
|
+
const value = object(payload);
|
|
152
|
+
const harness = typeof value?.harness === "string" ? value.harness : null;
|
|
153
|
+
const subjectId = value?.subject_id;
|
|
154
|
+
if (harness === null || (typeof subjectId !== "string" && subjectId !== null))
|
|
155
|
+
return KEEP;
|
|
156
|
+
const subject = subjectId ?? "";
|
|
157
|
+
const retire = [];
|
|
158
|
+
for (const route of CredentialRoute.options) {
|
|
159
|
+
for (const source of QuotaSource.options) {
|
|
160
|
+
const key = [harness, route, subject, source].join("\0");
|
|
161
|
+
retire.push(`q:${key}:p`, `q:${key}:u`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return { slot: `q:${harness}\0${subject}:removed`, retire };
|
|
165
|
+
}
|
|
166
|
+
function setupSavedVerdict(payload) {
|
|
167
|
+
const job = object(object(payload)?.job);
|
|
168
|
+
const jobId = stringField(job, "jobId");
|
|
169
|
+
const state = stringField(job, "state");
|
|
170
|
+
if (jobId === null || state === null || !TERMINAL_SETUP_STATES.has(state))
|
|
171
|
+
return KEEP;
|
|
172
|
+
return { retire: [`s:${jobId}:log`] };
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=journal-fold-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal-fold-policy.js","sourceRoot":"","sources":["../src/journal-fold-policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
import type { DurableJournal } from "@claudexor/journal";
|
|
1
|
+
import type { DurableJournal, JournalCompactionOutcome } from "@claudexor/journal";
|
|
2
2
|
/** One cancelable maintenance flight under the daemon's existing root writer.
|
|
3
3
|
* A manager creates a new journal object per generation and closes the old one;
|
|
4
4
|
* those exact objects are the dedupe keys, never another durable authority. */
|
|
5
5
|
export declare class JournalMaintenance {
|
|
6
|
-
|
|
6
|
+
/** One sink for failures, typed declines and `journal.records_retired`
|
|
7
|
+
* receipts (the daemon log plus startup diagnostics in the composition root). */
|
|
8
|
+
private readonly log;
|
|
7
9
|
private readonly pending;
|
|
8
|
-
private readonly attempted;
|
|
9
10
|
private readonly controller;
|
|
10
11
|
private flight;
|
|
11
12
|
private armed;
|
|
12
13
|
private stopped;
|
|
13
14
|
private cleaned;
|
|
14
15
|
private readonly stagingDir;
|
|
15
|
-
constructor(rootDir: string,
|
|
16
|
+
constructor(rootDir: string,
|
|
17
|
+
/** One sink for failures, typed declines and `journal.records_retired`
|
|
18
|
+
* receipts (the daemon log plus startup diagnostics in the composition root). */
|
|
19
|
+
log: (message: string) => void);
|
|
20
|
+
/** Request one pass for this generation. Requests coalesce while pending; a
|
|
21
|
+
* request that arrives during the generation's own flight runs one more pass
|
|
22
|
+
* after it — the journal's threshold hook is edge-triggered, so that request
|
|
23
|
+
* means the file crossed the threshold again. */
|
|
16
24
|
request: (journal: DurableJournal) => void;
|
|
17
25
|
/** Called only after normal admission, including recovery-route reopen. */
|
|
18
26
|
arm(): void;
|
|
@@ -24,4 +32,19 @@ export declare class JournalMaintenance {
|
|
|
24
32
|
private removeCrashCandidates;
|
|
25
33
|
private warnFailure;
|
|
26
34
|
}
|
|
35
|
+
/** The process footprint as log-line fields (`rssMb=… heapUsedMb=… externalMb=…`,
|
|
36
|
+
* whole mebibytes). The daemon's retained journal set lives on its heap, so
|
|
37
|
+
* the lines that already exist — the normal-admission line and every journal
|
|
38
|
+
* maintenance receipt — carry it, and the memory class stays observable on
|
|
39
|
+
* every install without a new mechanism. */
|
|
40
|
+
export declare function processMemoryFields(usage?: Pick<NodeJS.MemoryUsage, "rss" | "heapUsed" | "external">): string;
|
|
41
|
+
/** One log line per maintenance outcome: the typed decline with its reason and
|
|
42
|
+
* bounds, or the `journal.records_retired` receipt — compaction-time counts
|
|
43
|
+
* beside what the fold already retired while replaying this generation at
|
|
44
|
+
* open (`retiredAtReplay`). Both end with the process memory fields. The quiet
|
|
45
|
+
* no-ops (below the threshold, an empty journal) produce no line. */
|
|
46
|
+
export declare function describeCompactionOutcome(partition: string, outcome: JournalCompactionOutcome, replay?: {
|
|
47
|
+
count: number;
|
|
48
|
+
bytes: number;
|
|
49
|
+
}, memory?: string): string | null;
|
|
27
50
|
//# sourceMappingURL=journal-maintenance.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journal-maintenance.d.ts","sourceRoot":"","sources":["../src/journal-maintenance.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"journal-maintenance.d.ts","sourceRoot":"","sources":["../src/journal-maintenance.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAGnF;;+EAE+E;AAC/E,qBAAa,kBAAkB;IAW3B;qFACiF;IACjF,OAAO,CAAC,QAAQ,CAAC,GAAG;IAZtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,YACE,OAAO,EAAE,MAAM;IACf;qFACiF;IAChE,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EAGhD;IAED;;;qDAGiD;IACjD,OAAO,YAAa,cAAc,KAAG,IAAI,CAIvC;IAEF,2EAA2E;IAC3E,GAAG,IAAI,IAAI,CAWV;IAED;kFAC8E;IAC9E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAKpB;IAED,OAAO,CAAC,WAAW;YAaL,GAAG;YA+BH,qBAAqB;IAanC,OAAO,CAAC,WAAW;CAKpB;AAED;;;;4CAI4C;AAC5C,wBAAgB,mBAAmB,CACjC,KAAK,GAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,UAAU,GAAG,UAAU,CAAyB,GACvF,MAAM,CAGR;AAED;;;;qEAIqE;AACrE,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,wBAAwB,EACjC,MAAM,GAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAA2B,EACjE,MAAM,GAAE,MAA8B,GACrC,MAAM,GAAG,IAAI,CA0Bf"}
|
|
@@ -6,21 +6,27 @@ import { ensureCanonicalPrivateDirectory } from "@claudexor/util";
|
|
|
6
6
|
* A manager creates a new journal object per generation and closes the old one;
|
|
7
7
|
* those exact objects are the dedupe keys, never another durable authority. */
|
|
8
8
|
export class JournalMaintenance {
|
|
9
|
-
|
|
9
|
+
log;
|
|
10
10
|
pending = new Set();
|
|
11
|
-
attempted = new WeakSet();
|
|
12
11
|
controller = new AbortController();
|
|
13
12
|
flight = null;
|
|
14
13
|
armed = false;
|
|
15
14
|
stopped = false;
|
|
16
15
|
cleaned = false;
|
|
17
16
|
stagingDir;
|
|
18
|
-
constructor(rootDir,
|
|
19
|
-
|
|
17
|
+
constructor(rootDir,
|
|
18
|
+
/** One sink for failures, typed declines and `journal.records_retired`
|
|
19
|
+
* receipts (the daemon log plus startup diagnostics in the composition root). */
|
|
20
|
+
log) {
|
|
21
|
+
this.log = log;
|
|
20
22
|
this.stagingDir = join(rootDir, "journal-compaction");
|
|
21
23
|
}
|
|
24
|
+
/** Request one pass for this generation. Requests coalesce while pending; a
|
|
25
|
+
* request that arrives during the generation's own flight runs one more pass
|
|
26
|
+
* after it — the journal's threshold hook is edge-triggered, so that request
|
|
27
|
+
* means the file crossed the threshold again. */
|
|
22
28
|
request = (journal) => {
|
|
23
|
-
if (this.stopped
|
|
29
|
+
if (this.stopped)
|
|
24
30
|
return;
|
|
25
31
|
this.pending.add(journal);
|
|
26
32
|
this.startFlight();
|
|
@@ -73,7 +79,6 @@ export class JournalMaintenance {
|
|
|
73
79
|
while (!this.stopped && this.pending.size > 0) {
|
|
74
80
|
const journal = this.pending.values().next().value;
|
|
75
81
|
this.pending.delete(journal);
|
|
76
|
-
this.attempted.add(journal);
|
|
77
82
|
try {
|
|
78
83
|
if (journal.state().status !== "ready")
|
|
79
84
|
continue;
|
|
@@ -82,10 +87,13 @@ export class JournalMaintenance {
|
|
|
82
87
|
continue;
|
|
83
88
|
} // the manager retired this exact generation
|
|
84
89
|
try {
|
|
85
|
-
await journal.compactInBackground({
|
|
90
|
+
const outcome = await journal.compactInBackground({
|
|
86
91
|
stagingDir: this.stagingDir,
|
|
87
92
|
signal: this.controller.signal,
|
|
88
93
|
});
|
|
94
|
+
const line = describeCompactionOutcome(journal.options.partition, outcome, journal.retiredAtReplay());
|
|
95
|
+
if (line)
|
|
96
|
+
this.log(line);
|
|
89
97
|
}
|
|
90
98
|
catch (error) {
|
|
91
99
|
this.warnFailure(error);
|
|
@@ -96,7 +104,7 @@ export class JournalMaintenance {
|
|
|
96
104
|
for (const name of await readdir(this.stagingDir)) {
|
|
97
105
|
this.controller.signal.throwIfAborted();
|
|
98
106
|
// Only this producer's UUID-shaped scratch files, never journal.bin,
|
|
99
|
-
// append.pending, recovery receipts, archives or unrelated entries.
|
|
107
|
+
// append.pending.json, recovery receipts, archives or unrelated entries.
|
|
100
108
|
if (!/^journal-compaction-[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}\.compact$/.test(name))
|
|
101
109
|
continue;
|
|
102
110
|
const path = join(this.stagingDir, name);
|
|
@@ -106,7 +114,49 @@ export class JournalMaintenance {
|
|
|
106
114
|
}
|
|
107
115
|
}
|
|
108
116
|
warnFailure(error) {
|
|
109
|
-
this.
|
|
117
|
+
this.log(`journal maintenance failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
110
118
|
}
|
|
111
119
|
}
|
|
120
|
+
/** The process footprint as log-line fields (`rssMb=… heapUsedMb=… externalMb=…`,
|
|
121
|
+
* whole mebibytes). The daemon's retained journal set lives on its heap, so
|
|
122
|
+
* the lines that already exist — the normal-admission line and every journal
|
|
123
|
+
* maintenance receipt — carry it, and the memory class stays observable on
|
|
124
|
+
* every install without a new mechanism. */
|
|
125
|
+
export function processMemoryFields(usage = process.memoryUsage()) {
|
|
126
|
+
const mb = (bytes) => Math.round(bytes / (1024 * 1024));
|
|
127
|
+
return `rssMb=${mb(usage.rss)} heapUsedMb=${mb(usage.heapUsed)} externalMb=${mb(usage.external)}`;
|
|
128
|
+
}
|
|
129
|
+
/** One log line per maintenance outcome: the typed decline with its reason and
|
|
130
|
+
* bounds, or the `journal.records_retired` receipt — compaction-time counts
|
|
131
|
+
* beside what the fold already retired while replaying this generation at
|
|
132
|
+
* open (`retiredAtReplay`). Both end with the process memory fields. The quiet
|
|
133
|
+
* no-ops (below the threshold, an empty journal) produce no line. */
|
|
134
|
+
export function describeCompactionOutcome(partition, outcome, replay = { count: 0, bytes: 0 }, memory = processMemoryFields()) {
|
|
135
|
+
if ("declined" in outcome) {
|
|
136
|
+
if (outcome.reason === "below_threshold" || outcome.reason === "empty")
|
|
137
|
+
return null;
|
|
138
|
+
const bounds = [];
|
|
139
|
+
if (outcome.compressedBytes !== undefined)
|
|
140
|
+
bounds.push(`compressedBytes=${outcome.compressedBytes}`);
|
|
141
|
+
// Only a capacity decline names a cap that fired; a no-reclaim decline's
|
|
142
|
+
// cap is the current file size, which `compressedBytes` already exceeds.
|
|
143
|
+
if (outcome.reason === "capacity" && outcome.cap !== undefined)
|
|
144
|
+
bounds.push(`cap=${outcome.cap}`);
|
|
145
|
+
return ["journal.compaction_declined", `partition=${partition}`, `reason=${outcome.reason}`]
|
|
146
|
+
.concat(bounds, memory)
|
|
147
|
+
.join(" ");
|
|
148
|
+
}
|
|
149
|
+
return [
|
|
150
|
+
"journal.records_retired",
|
|
151
|
+
`partition=${partition}`,
|
|
152
|
+
`retainedCount=${outcome.retainedCount}`,
|
|
153
|
+
`retiredCount=${outcome.retiredCount}`,
|
|
154
|
+
`retiredBytes=${outcome.retiredBytes}`,
|
|
155
|
+
`retiredAtReplayCount=${replay.count}`,
|
|
156
|
+
`retiredAtReplayBytes=${replay.bytes}`,
|
|
157
|
+
`beforeBytes=${outcome.beforeBytes}`,
|
|
158
|
+
`afterBytes=${outcome.afterBytes}`,
|
|
159
|
+
memory,
|
|
160
|
+
].join(" ");
|
|
161
|
+
}
|
|
112
162
|
//# sourceMappingURL=journal-maintenance.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journal-maintenance.js","sourceRoot":"","sources":["../src/journal-maintenance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,+BAA+B,EAAE,MAAM,iBAAiB,CAAC;AAElE;;+EAE+E;AAC/E,MAAM,OAAO,kBAAkB;
|
|
1
|
+
{"version":3,"file":"journal-maintenance.js","sourceRoot":"","sources":["../src/journal-maintenance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DurableJournal, DurableJournalOptions } from "@claudexor/journal";
|
|
2
|
+
/**
|
|
3
|
+
* The daemon's journal options for one manager: every partition replays and
|
|
4
|
+
* compacts through the daemon fold policy (one frozen policy shared by every
|
|
5
|
+
* manager and every pass), opts into deferred maintenance
|
|
6
|
+
* whenever a maintenance callback exists, and re-requests maintenance for the
|
|
7
|
+
* live generation when an append crosses the compaction threshold — the
|
|
8
|
+
* journal fires that hook once per crossing and re-arms it when the pass
|
|
9
|
+
* settles (install, typed decline or a failed pass).
|
|
10
|
+
*/
|
|
11
|
+
export declare function daemonJournalOptions(input: {
|
|
12
|
+
rootDir: string;
|
|
13
|
+
partition: string;
|
|
14
|
+
now: () => Date;
|
|
15
|
+
requestMaintenance: ((journal: DurableJournal) => void) | undefined;
|
|
16
|
+
current: () => DurableJournal | null;
|
|
17
|
+
}): DurableJournalOptions;
|
|
18
|
+
//# sourceMappingURL=journal-manager-journal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal-manager-journal.d.ts","sourceRoot":"","sources":["../src/journal-manager-journal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAGhF;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACpE,OAAO,EAAE,MAAM,cAAc,GAAG,IAAI,CAAC;CACtC,GAAG,qBAAqB,CAYxB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { journalFoldPolicy } from "./journal-fold-policy.js";
|
|
2
|
+
/**
|
|
3
|
+
* The daemon's journal options for one manager: every partition replays and
|
|
4
|
+
* compacts through the daemon fold policy (one frozen policy shared by every
|
|
5
|
+
* manager and every pass), opts into deferred maintenance
|
|
6
|
+
* whenever a maintenance callback exists, and re-requests maintenance for the
|
|
7
|
+
* live generation when an append crosses the compaction threshold — the
|
|
8
|
+
* journal fires that hook once per crossing and re-arms it when the pass
|
|
9
|
+
* settles (install, typed decline or a failed pass).
|
|
10
|
+
*/
|
|
11
|
+
export function daemonJournalOptions(input) {
|
|
12
|
+
return {
|
|
13
|
+
rootDir: input.rootDir,
|
|
14
|
+
partition: input.partition,
|
|
15
|
+
now: input.now,
|
|
16
|
+
deferCompaction: input.requestMaintenance !== undefined,
|
|
17
|
+
fold: journalFoldPolicy,
|
|
18
|
+
onCompactionThreshold: () => {
|
|
19
|
+
const journal = input.current();
|
|
20
|
+
if (journal)
|
|
21
|
+
input.requestMaintenance?.(journal);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=journal-manager-journal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal-manager-journal.js","sourceRoot":"","sources":["../src/journal-manager-journal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAMpC;IACC,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,eAAe,EAAE,KAAK,CAAC,kBAAkB,KAAK,SAAS;QACvD,IAAI,EAAE,iBAAiB;QACvB,qBAAqB,EAAE,GAAG,EAAE;YAC1B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;YAChC,IAAI,OAAO;gBAAE,KAAK,CAAC,kBAAkB,EAAE,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journal-manager.d.ts","sourceRoot":"","sources":["../src/journal-manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"journal-manager.d.ts","sourceRoot":"","sources":["../src/journal-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/journal-manager.js
CHANGED
|
@@ -6,6 +6,7 @@ import { ensureCanonicalPrivateDirectory, fsyncDirectory } from "@claudexor/util
|
|
|
6
6
|
import { exportJournalRecovery, fingerprintPartition, cloneRecovery, recoveryAt, recoveryFrom, safeMessage, sha256, writeAtomicPrivateJson, } from "./journal-recovery-files.js";
|
|
7
7
|
import { conflict, matchingReceipt, quarantineRequestDigest, readOperation, typedError, validateRequest, } from "./journal-recovery-operation.js";
|
|
8
8
|
import { journalEvents } from "./journal-events.js";
|
|
9
|
+
import { daemonJournalOptions } from "./journal-manager-journal.js";
|
|
9
10
|
import { applyPreparedOperation, completePreparedReceipt, inspectPreparedOperation, preparationFingerprint, reconcilePreparedOperationOnStart, revalidatePreparedState, } from "./journal-prepared-operation.js";
|
|
10
11
|
import { prepareProjectionSlots, ProjectionSlot, } from "./journal-projection-slot.js";
|
|
11
12
|
export class JournalManager {
|
|
@@ -20,6 +21,7 @@ export class JournalManager {
|
|
|
20
21
|
now;
|
|
21
22
|
faults;
|
|
22
23
|
registrations = new Map();
|
|
24
|
+
journalOptions;
|
|
23
25
|
journal = null;
|
|
24
26
|
recovery = { status: "ready", discardedTailBytes: 0 };
|
|
25
27
|
generationValue = 0;
|
|
@@ -37,6 +39,13 @@ export class JournalManager {
|
|
|
37
39
|
this.artifactPrefix = basename(this.partitionDir);
|
|
38
40
|
this.operationsDir = join(this.rootDir, "recovery-operations", basename(this.partitionDir));
|
|
39
41
|
this.quarantineDir = join(this.rootDir, "journal-quarantine");
|
|
42
|
+
this.journalOptions = daemonJournalOptions({
|
|
43
|
+
rootDir: this.journalRoot,
|
|
44
|
+
partition: this.partition,
|
|
45
|
+
now: this.now,
|
|
46
|
+
requestMaintenance: options.requestMaintenance,
|
|
47
|
+
current: () => this.journal,
|
|
48
|
+
});
|
|
40
49
|
}
|
|
41
50
|
registerProjection(descriptor) {
|
|
42
51
|
this.assertOpen();
|
|
@@ -74,12 +83,7 @@ export class JournalManager {
|
|
|
74
83
|
this.generationValue += 1;
|
|
75
84
|
const projectionStatus = [];
|
|
76
85
|
try {
|
|
77
|
-
this.journal = DurableJournal.prepare(
|
|
78
|
-
rootDir: this.journalRoot,
|
|
79
|
-
partition: this.partition,
|
|
80
|
-
now: this.now,
|
|
81
|
-
deferCompaction: this.options.requestMaintenance !== undefined,
|
|
82
|
-
});
|
|
86
|
+
this.journal = DurableJournal.prepare(this.journalOptions);
|
|
83
87
|
this.recovery = this.journal.state();
|
|
84
88
|
this.preparedOperation = inspectPreparedOperation({
|
|
85
89
|
rootDir: this.rootDir,
|
|
@@ -396,12 +400,7 @@ export class JournalManager {
|
|
|
396
400
|
this.clearSlots();
|
|
397
401
|
this.generationValue += 1;
|
|
398
402
|
try {
|
|
399
|
-
this.journal = new DurableJournal(
|
|
400
|
-
rootDir: this.journalRoot,
|
|
401
|
-
partition: this.partition,
|
|
402
|
-
now: this.now,
|
|
403
|
-
deferCompaction: this.options.requestMaintenance !== undefined,
|
|
404
|
-
});
|
|
403
|
+
this.journal = new DurableJournal(this.journalOptions);
|
|
405
404
|
this.recovery = this.journal.state();
|
|
406
405
|
if (this.recovery.status === "recovery_required") {
|
|
407
406
|
this.enterRecovery(this.recovery);
|