@lmzhen/dsh-evolution-core 0.1.0-rc.68 → 0.1.0-rc.69
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/lib/index.js +18 -9
- package/lib/types/evolution-events.d.ts +8 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -67,11 +67,14 @@ function nodeEvolutionIo() {
|
|
|
67
67
|
* the holder pid it carries (rc.66): a LIVE holder is never stolen, so a
|
|
68
68
|
* slow writer no longer loses its lock to a peer at the 5s mark (the
|
|
69
69
|
* takeover is the only best-effort surface; the retry budget fails loud —
|
|
70
|
-
* rc.65 — instead of ever proceeding unlocked).
|
|
70
|
+
* rc.65 — instead of ever proceeding unlocked). Budget = 40 * 50ms (~2s,
|
|
71
|
+
* rc.69): 8-writer contention bursts on a loaded CI runner exceed 10
|
|
72
|
+
* attempts (500ms), and a fail-loud throw was observed instead of a clean
|
|
73
|
+
* serialization.
|
|
71
74
|
*/
|
|
72
75
|
const withWriteLock = async (path, task) => {
|
|
73
76
|
const lock = `${path}.lock`;
|
|
74
|
-
for (let attempt = 0; attempt <
|
|
77
|
+
for (let attempt = 0; attempt < 40; attempt += 1) try {
|
|
75
78
|
await writeFile(lock, String(process.pid), { flag: "wx" });
|
|
76
79
|
try {
|
|
77
80
|
return await task();
|
|
@@ -735,8 +738,13 @@ function eventsFile(home) {
|
|
|
735
738
|
function isEventRecord(event) {
|
|
736
739
|
return typeof event === "object" && event !== null && typeof event.seq === "number";
|
|
737
740
|
}
|
|
738
|
-
|
|
739
|
-
|
|
741
|
+
/**
|
|
742
|
+
* Parse an event log body. A missing file, a whitespace-only file (rc.69:
|
|
743
|
+
* rebuildable, NOT malformed) or a corrupt one reads as empty; corrupt content
|
|
744
|
+
* is still refused on append, never overwritten.
|
|
745
|
+
*/
|
|
746
|
+
function parseEvolutionEvents(raw) {
|
|
747
|
+
if (raw === null || raw.trim() === "") return [];
|
|
740
748
|
try {
|
|
741
749
|
const parsed = JSON.parse(raw);
|
|
742
750
|
if (!Array.isArray(parsed.events)) return [];
|
|
@@ -754,12 +762,12 @@ function parseEventList(raw) {
|
|
|
754
762
|
async function appendEvolutionEvent(io, path, event) {
|
|
755
763
|
let assigned = 0;
|
|
756
764
|
await transactIo(io, path, (current) => {
|
|
757
|
-
if (current !== null) try {
|
|
765
|
+
if (current !== null && current.trim() !== "") try {
|
|
758
766
|
JSON.parse(current);
|
|
759
767
|
} catch {
|
|
760
768
|
return Promise.resolve(current);
|
|
761
769
|
}
|
|
762
|
-
const events =
|
|
770
|
+
const events = parseEvolutionEvents(current);
|
|
763
771
|
const maxSeq = events.reduce((max, entry) => Math.max(max, entry.seq), 0);
|
|
764
772
|
const record = {
|
|
765
773
|
...event,
|
|
@@ -775,10 +783,11 @@ async function appendEvolutionEvent(io, path, event) {
|
|
|
775
783
|
if (assigned === 0) throw new Error(`evolution event log is malformed and was not touched: ${path}`);
|
|
776
784
|
return assigned;
|
|
777
785
|
}
|
|
778
|
-
/** Read the event log; a missing file reads as empty,
|
|
786
|
+
/** Read the event log; a missing/whitespace-only file reads as empty,
|
|
787
|
+
* corrupt content is flagged (and refused on append). */
|
|
779
788
|
async function readEvolutionEvents(io, path) {
|
|
780
789
|
const raw = await io.readText(path);
|
|
781
|
-
if (raw === null) return {
|
|
790
|
+
if (raw === null || raw.trim() === "") return {
|
|
782
791
|
events: [],
|
|
783
792
|
malformed: false
|
|
784
793
|
};
|
|
@@ -3116,4 +3125,4 @@ function evolutionHome(env = process.env) {
|
|
|
3116
3125
|
return join(env.DSH_HOME ?? join(homedir(), ".dsh"), "evolution");
|
|
3117
3126
|
}
|
|
3118
3127
|
//#endregion
|
|
3119
|
-
export { AUTHORING_DESCRIPTION_BAR, COMBINED_REVIEW_PLAN_PROMPT, COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CONSOLIDATION_FAILURES, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_MIN_IDLE_HOURS, DEFAULT_MUTATION_CAP, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_LIMITS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_STALE_AFTER_DAYS, DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS, DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS, DEFAULT_SUBSTANTIVE_MIN_USER_CHARS, DEFAULT_USER_CHAR_LIMIT, DSH_AUTHORING_STANDARDS, ENTRY_DELIMITER, EVENT_LOG_VERSION, EvolutionGateSet, LOW_QUALITY_THRESHOLD, MAX_DESCRIPTION_LENGTH, MAX_SKILL_CONTENT_CHARS, MAX_SKILL_FILE_BYTES, MAX_SKILL_NAME_LENGTH, MEMORY_REVIEW_PROMPT, MUTATIONS_FILE_VERSION, MemoryStore, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, PROMPT_BUNDLE_VERSION, PROTECTED_BUILTIN_SKILLS, QUALITY_WEIGHTS, SKILLS_GUIDANCE, SKILL_NAME_RE, SKILL_REVIEW_PLAN_PROMPT, SKILL_REVIEW_PROMPT, SNAPSHOT_EXTRA_NAME_RE, SUPPORT_DIRS, SUPPRESSED_FILE_VERSION, SkillLibrary, advanceReview, appendEvolutionEvent, applyCuratorFields, authoringFeedback, buildCuratorRunReport, buildLearnPrompt, bumpPatch, bumpUse, bumpView, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, createGateSet, emptyRecord, evaluateThreat, eventsFile, evolutionHome, evolutionIoAdapter, foldCuratorFields, foldTurn, getRecord, latestActivityAt, lifecycleCandidate, loadMutations, loadSuppressedNames, loadUsage, markAgentCreated, memoryRoot, mutateUsage, mutationsFile, nodeEvolutionIo, normalizeUsageRecord, observeEvent, parseCuratorNominations, parseFrontmatter, readEvolutionEvents, recordMutation, relatedSkillNames, renderCuratorReportMarkdown, resolveOrigins, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, transactIo, updateSuppressedNames, usageFile, validateFrontmatter, verifyPromptBundle };
|
|
3128
|
+
export { AUTHORING_DESCRIPTION_BAR, COMBINED_REVIEW_PLAN_PROMPT, COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CONSOLIDATION_FAILURES, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_MIN_IDLE_HOURS, DEFAULT_MUTATION_CAP, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_LIMITS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_STALE_AFTER_DAYS, DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS, DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS, DEFAULT_SUBSTANTIVE_MIN_USER_CHARS, DEFAULT_USER_CHAR_LIMIT, DSH_AUTHORING_STANDARDS, ENTRY_DELIMITER, EVENT_LOG_VERSION, EvolutionGateSet, LOW_QUALITY_THRESHOLD, MAX_DESCRIPTION_LENGTH, MAX_SKILL_CONTENT_CHARS, MAX_SKILL_FILE_BYTES, MAX_SKILL_NAME_LENGTH, MEMORY_REVIEW_PROMPT, MUTATIONS_FILE_VERSION, MemoryStore, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, PROMPT_BUNDLE_VERSION, PROTECTED_BUILTIN_SKILLS, QUALITY_WEIGHTS, SKILLS_GUIDANCE, SKILL_NAME_RE, SKILL_REVIEW_PLAN_PROMPT, SKILL_REVIEW_PROMPT, SNAPSHOT_EXTRA_NAME_RE, SUPPORT_DIRS, SUPPRESSED_FILE_VERSION, SkillLibrary, advanceReview, appendEvolutionEvent, applyCuratorFields, authoringFeedback, buildCuratorRunReport, buildLearnPrompt, bumpPatch, bumpUse, bumpView, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, createGateSet, emptyRecord, evaluateThreat, eventsFile, evolutionHome, evolutionIoAdapter, foldCuratorFields, foldTurn, getRecord, latestActivityAt, lifecycleCandidate, loadMutations, loadSuppressedNames, loadUsage, markAgentCreated, memoryRoot, mutateUsage, mutationsFile, nodeEvolutionIo, normalizeUsageRecord, observeEvent, parseCuratorNominations, parseEvolutionEvents, parseFrontmatter, readEvolutionEvents, recordMutation, relatedSkillNames, renderCuratorReportMarkdown, resolveOrigins, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, transactIo, updateSuppressedNames, usageFile, validateFrontmatter, verifyPromptBundle };
|
|
@@ -26,6 +26,12 @@ export interface EvolutionEvent {
|
|
|
26
26
|
request?: string | undefined;
|
|
27
27
|
}
|
|
28
28
|
export declare function eventsFile(home: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Parse an event log body. A missing file, a whitespace-only file (rc.69:
|
|
31
|
+
* rebuildable, NOT malformed) or a corrupt one reads as empty; corrupt content
|
|
32
|
+
* is still refused on append, never overwritten.
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseEvolutionEvents(raw: string | null): EvolutionEvent[];
|
|
29
35
|
/**
|
|
30
36
|
* Append one event under the write lock (rc.68): `seq` = current max + 1
|
|
31
37
|
* computed inside the transact, so two processes appending concurrently never
|
|
@@ -38,6 +44,7 @@ export interface EventLogRead {
|
|
|
38
44
|
/** True when the file existed but could not be parsed (loss case; never overwritten). */
|
|
39
45
|
malformed: boolean;
|
|
40
46
|
}
|
|
41
|
-
/** Read the event log; a missing file reads as empty,
|
|
47
|
+
/** Read the event log; a missing/whitespace-only file reads as empty,
|
|
48
|
+
* corrupt content is flagged (and refused on append). */
|
|
42
49
|
export declare function readEvolutionEvents(io: EvolutionIoLike, path: string): Promise<EventLogRead>;
|
|
43
50
|
//# sourceMappingURL=evolution-events.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-core",
|
|
3
3
|
"description": "Shared stores, prompts, signals and lifecycle logic for the dsh-evolution plugin family (community build)",
|
|
4
|
-
"version": "0.1.0-rc.
|
|
4
|
+
"version": "0.1.0-rc.69",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|