@lmzhen/dsh-evolution-core 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/lib/index.js +28 -28
- package/lib/types/constants.d.ts +0 -1
- package/lib/types/constants.js +0 -1
- package/lib/types/events.d.ts +2 -47
- package/lib/types/evidence.d.ts +3 -5
- package/lib/types/evidence.js +2 -3
- package/lib/types/instance-scope.d.ts +6 -4
- package/lib/types/instance-scope.js +6 -4
- package/lib/types/io.d.ts +7 -0
- package/lib/types/io.js +2 -0
- package/lib/types/params.js +0 -1
- package/lib/types/platform-services.d.ts +2 -9
- package/lib/types/platform-services.js +1 -0
- package/lib/types/run-registry.js +2 -1
- package/lib/types/serial.d.ts +4 -3
- package/lib/types/serial.js +4 -3
- package/lib/types/tree-lock.js +6 -5
- package/package.json +3 -2
- package/persisted-write-inventory.json +9 -0
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ section, and importing the package root is its only entry.
|
|
|
50
50
|
|
|
51
51
|
## Events (the family's own, process-local)
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Eight process events ride the cordis bus (`evolution-core/src/events.ts` declares the payloads;
|
|
54
54
|
producers call `ctx.emit`, consumers `ctx.on`). They are NOT session events — appending one to a
|
|
55
55
|
session log made the session unresumable (A-line P0-1), which is why the payload file says so.
|
|
56
56
|
|
|
@@ -62,9 +62,10 @@ session log made the session unresumable (A-line P0-1), which is why the payload
|
|
|
62
62
|
| `evolution/review-error` | emit (notification) | `evolution-review` failure paths |
|
|
63
63
|
| `evolution/review-completed` | emit (notification) | `evolution-review` after a plugin branch settles |
|
|
64
64
|
| `evolution/memory-applied` | emit (notification) | `memory` after a memory write |
|
|
65
|
+
| `evolution/memory-provider-registered` | emit (notification) | `memory` when a provider registers |
|
|
65
66
|
| `evolution/approval-decided` | emit (notification) | `evolution-approval` after an approval decision lands |
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
`evolution/plan-applied` is declared for old activity ledgers; `evolution-review` now emits it from a branch review once that branch settles, with real action counts. `reviewMode: "inject"` still emits none by design.
|
|
68
69
|
|
|
69
70
|
The mode column is what the code does today: every one of them is an announcement, and each
|
|
70
71
|
declaration carries it as a `@mode` tag (finding O-1, landed) — `verify-arch-guards`' rule **N33** checks that
|
package/lib/index.js
CHANGED
|
@@ -573,6 +573,9 @@ function transactTaskGuard(what) {
|
|
|
573
573
|
/** Lazy adapter over an IO provider registry, shared by every evolution consumer. */
|
|
574
574
|
function evolutionIoAdapter(provider) {
|
|
575
575
|
return {
|
|
576
|
+
get processScope() {
|
|
577
|
+
return provider().processScope;
|
|
578
|
+
},
|
|
576
579
|
readText: (path) => provider().readText(path),
|
|
577
580
|
writeText: (path, content) => provider().writeText(path, content),
|
|
578
581
|
remove: (path) => provider().remove(path),
|
|
@@ -824,6 +827,7 @@ function nodeEvolutionIo() {
|
|
|
824
827
|
}
|
|
825
828
|
};
|
|
826
829
|
return {
|
|
830
|
+
processScope: "single-process",
|
|
827
831
|
async readText(path) {
|
|
828
832
|
try {
|
|
829
833
|
return await readFile(path, "utf8");
|
|
@@ -1037,13 +1041,14 @@ function atomicWriteFiles(targetDir, writes, fs = defaultFs, logger = console.wa
|
|
|
1037
1041
|
//#endregion
|
|
1038
1042
|
//#region lib/types/tree-lock.js
|
|
1039
1043
|
/**
|
|
1040
|
-
*
|
|
1044
|
+
* Tree write lock.
|
|
1041
1045
|
*
|
|
1042
1046
|
* The merge run holds this lock for its whole lifetime; curator's pass takes the same
|
|
1043
|
-
* lock. The
|
|
1044
|
-
*
|
|
1045
|
-
*
|
|
1046
|
-
*
|
|
1047
|
+
* lock. The record is created through `transactIo`, so exclusion is exactly as strong as
|
|
1048
|
+
* the IO backend's `transact`: the platform `ctx.fs` provider is cross-process, while the
|
|
1049
|
+
* standalone `nodeEvolutionIo` is explicitly single-process (G2 S4). This module builds no
|
|
1050
|
+
* file lock or WAL of its own. A holder whose pid is gone is stale and may be taken over;
|
|
1051
|
+
* a live pid is respected, even for a long run (a live long run is what the lock protects).
|
|
1047
1052
|
*
|
|
1048
1053
|
* `commitMerge` deliberately does NOT take this lock itself: the run shell owns it, so a
|
|
1049
1054
|
* run and its commit share one acquisition. Taking it inside the store would also
|
|
@@ -2402,7 +2407,6 @@ const DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS = 20;
|
|
|
2402
2407
|
const DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS = 3;
|
|
2403
2408
|
const DEFAULT_SUBSTANTIVE_MIN_USER_CHARS = 200;
|
|
2404
2409
|
const DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS = 500;
|
|
2405
|
-
const DEFAULT_MAX_OPS_PER_PLAN = 32;
|
|
2406
2410
|
const DEFAULT_CURATOR_INTERVAL_HOURS = 168;
|
|
2407
2411
|
const DEFAULT_MIN_IDLE_HOURS = 2;
|
|
2408
2412
|
const DEFAULT_STALE_AFTER_DAYS = 30;
|
|
@@ -5905,9 +5909,10 @@ function buildLearnPrompt(userRequest) {
|
|
|
5905
5909
|
/**
|
|
5906
5910
|
* A process-local serial task queue: each task starts only after the previous
|
|
5907
5911
|
* one settles (success or failure), so read-modify-write sequences that share
|
|
5908
|
-
* one file never interleave inside this process.
|
|
5909
|
-
*
|
|
5910
|
-
*
|
|
5912
|
+
* one file never interleave inside this process. When the IO backend provides
|
|
5913
|
+
* a cross-process transact lock, that is the first layer; the node backend does
|
|
5914
|
+
* not, so this chain is its only serialization. (0.3.17 S2.8, T-1: the shape was
|
|
5915
|
+
* duplicated in state-json and
|
|
5911
5916
|
* memory-files — one factory now).
|
|
5912
5917
|
*/
|
|
5913
5918
|
function makeSerialQueue() {
|
|
@@ -9160,6 +9165,11 @@ const PLATFORM_SERVICE_PROBES = Object.freeze([
|
|
|
9160
9165
|
feature: "the state facade behind activity and replay",
|
|
9161
9166
|
side: "host"
|
|
9162
9167
|
},
|
|
9168
|
+
{
|
|
9169
|
+
service: "evolutionStateStore",
|
|
9170
|
+
feature: "generic durable state store for assignment queue and future collections",
|
|
9171
|
+
side: "host"
|
|
9172
|
+
},
|
|
9163
9173
|
{
|
|
9164
9174
|
service: "llm",
|
|
9165
9175
|
feature: "the curator one-shot review model call",
|
|
@@ -9247,8 +9257,9 @@ function absentHostServices(has) {
|
|
|
9247
9257
|
* B3 / G4 (0.3.78): the family's single-instance contract, made explicit.
|
|
9248
9258
|
*
|
|
9249
9259
|
* Every persisted sidecar is written under TWO assumptions: the IO backend's
|
|
9250
|
-
*
|
|
9251
|
-
*
|
|
9260
|
+
* transact serializes different processes when the provider guarantees it (the
|
|
9261
|
+
* node backend is process-local only), and exactly ONE instance of each writer
|
|
9262
|
+
* service exists per evolution home. The second half
|
|
9252
9263
|
* was implicit — `makeSerialQueue()` and the module-scope stores are
|
|
9253
9264
|
* per-instance, so two rows writing one home interleave inside one file (the
|
|
9254
9265
|
* "two instances, one file" class). This module makes that half enforceable: a
|
|
@@ -9265,8 +9276,9 @@ function absentHostServices(has) {
|
|
|
9265
9276
|
* `claims` below is a module-scope Map: two ROWS over one home in ONE process
|
|
9266
9277
|
* contend, while the SAME home in another process gets its own Map and is
|
|
9267
9278
|
* granted the key. That is by construction, not a gap to close here — the
|
|
9268
|
-
* cross-process half of the contract is the IO backend's
|
|
9269
|
-
* (`transactIo`, core/io.ts)
|
|
9279
|
+
* cross-process half of the contract is the IO backend's transact
|
|
9280
|
+
* (`transactIo`, core/io.ts) when the provider guarantees it; the node backend
|
|
9281
|
+
* is process-local, so a shared home across processes is not protected by it alone.
|
|
9270
9282
|
* The FLOW2-1 finding was three call sites reading a GRANTED claim as "no other
|
|
9271
9283
|
* process can be doing this work", so the caller contract is stated here:
|
|
9272
9284
|
* - granted means "no other row OF THIS PROCESS owns the key";
|
|
@@ -10216,9 +10228,8 @@ function foldTurnEvents(events, fromSeq = 0) {
|
|
|
10216
10228
|
/**
|
|
10217
10229
|
* Which session frames are EVIDENCE, and which are bookkeeping.
|
|
10218
10230
|
*
|
|
10219
|
-
*
|
|
10220
|
-
*
|
|
10221
|
-
* the window the plan was authored against". A boundary frame satisfies that while carrying
|
|
10231
|
+
* The session's evidence index answers "does this seq carry content"; a bare range check used
|
|
10232
|
+
* to accept any integer inside the authoring window. A boundary frame satisfies that while carrying
|
|
10222
10233
|
* nothing a claim can rest on: the `turn/start` seq is the frame a claim about that turn was
|
|
10223
10234
|
* most likely read out of, and citing it is indistinguishable from citing a real exchange. This
|
|
10224
10235
|
* module owns the ONE classification of a session frame by what it CARRIES, so the plan path can
|
|
@@ -17299,17 +17310,6 @@ const PARAM_EXPOSURE = Object.freeze([
|
|
|
17299
17310
|
summary: "Name this package registers as the memory provider.",
|
|
17300
17311
|
why: "identity"
|
|
17301
17312
|
},
|
|
17302
|
-
{
|
|
17303
|
-
id: "maxOpsPerPlan",
|
|
17304
|
-
group: "deployment",
|
|
17305
|
-
tier: "E2",
|
|
17306
|
-
authority: "cordis",
|
|
17307
|
-
owner: "evolution-plan-validator",
|
|
17308
|
-
applies: "none",
|
|
17309
|
-
docAnchor: "PARAMETERS.md#deployment",
|
|
17310
|
-
summary: "Operation cap one staged plan may carry.",
|
|
17311
|
-
why: "internal"
|
|
17312
|
-
},
|
|
17313
17313
|
{
|
|
17314
17314
|
id: "substantiveMinToolCalls",
|
|
17315
17315
|
group: "deployment",
|
|
@@ -18247,4 +18247,4 @@ function isIgnorableEvent(event) {
|
|
|
18247
18247
|
return classifySessionEvent(event) !== "model";
|
|
18248
18248
|
}
|
|
18249
18249
|
//#endregion
|
|
18250
|
-
export { AUTHORING_DESCRIPTION_BAR, AUTHORING_SPLIT_LINE_CHARS, BASELINE_ACTION, CITATION_SUPPORT_DIRS, COMBINED_REVIEW_PLAN_PROMPT, COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CONTENT_SPLIT_HINT, COST_ASCII_TOKEN_HIGH, COST_ASCII_TOKEN_LOW, COST_CJK_TOKEN_HIGH, COST_CJK_TOKEN_LOW, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEDUP_MAX_PAIR_COMPARISONS, DEDUP_SIMILARITY_THRESHOLD, DEFAULT_ADMISSION, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_ARCHIVE_RETENTION_POLICY, DEFAULT_CITATION_POLICY, DEFAULT_CITATION_REF_BUDGET, DEFAULT_CONSOLIDATION_FAILURES, DEFAULT_CURATOR_BOOT_GRACE_SECONDS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_CURATOR_MODEL, DEFAULT_CURATOR_REVIEW_MAX_TOKENS, DEFAULT_HEALTH_THRESHOLDS,
|
|
18250
|
+
export { AUTHORING_DESCRIPTION_BAR, AUTHORING_SPLIT_LINE_CHARS, BASELINE_ACTION, CITATION_SUPPORT_DIRS, COMBINED_REVIEW_PLAN_PROMPT, COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CONTENT_SPLIT_HINT, COST_ASCII_TOKEN_HIGH, COST_ASCII_TOKEN_LOW, COST_CJK_TOKEN_HIGH, COST_CJK_TOKEN_LOW, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEDUP_MAX_PAIR_COMPARISONS, DEDUP_SIMILARITY_THRESHOLD, DEFAULT_ADMISSION, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_ARCHIVE_RETENTION_POLICY, DEFAULT_CITATION_POLICY, DEFAULT_CITATION_REF_BUDGET, DEFAULT_CONSOLIDATION_FAILURES, DEFAULT_CURATOR_BOOT_GRACE_SECONDS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_CURATOR_MODEL, DEFAULT_CURATOR_REVIEW_MAX_TOKENS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_MIN_IDLE_HOURS, DEFAULT_MUTATION_CAP, DEFAULT_PROBE_TIMEOUT_MS, DEFAULT_REFERENCE_REWRITE_POLICY, DEFAULT_REVIEW_CONTEXT_MESSAGES, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_MESSAGE_CHARS, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_REVIEW_TIMEOUT_MS, DEFAULT_RUN_RECORDS, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_LIMITS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_SKILL_VERSION_KEEP, DEFAULT_STALE_AFTER_DAYS, DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS, DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS, DEFAULT_SUBSTANTIVE_MIN_USER_CHARS, DEFAULT_SUPPORT_FILE_CHAR_POLICY, DEFAULT_SUPPORT_READ_TOOL_NAMES, DEFAULT_THREAT_MAX_SCAN_CHARS, DEFAULT_USER_CHAR_LIMIT, DEFAULT_WRITE_CONFIRM_MODE, DEFAULT_WRITE_CONFIRM_TIMEOUT_SECONDS, DIAGNOSTICS_FACT_KEYS, DIAGNOSTICS_RUNTIME_KEYS, DIAGNOSTICS_VIEW_SCHEMA_VERSION, DISPATCH_EVENT_TYPES, DRIFT_MAX_LINE_CHARS, DRIFT_SIGNALS_VERSION, DRIFT_SIGNAL_NOUNS, DSH_AUTHORING_STANDARDS, ENTRY_DELIMITER, EVENT_ARCHIVE_PREFIX, EVENT_LOG_RETAIN_ARCHIVES, EVENT_LOG_ROTATE_AT, EVENT_LOG_VERSION, EVOLUTION_ERRORS, EVOLUTION_PRESET_IDS, EVOLUTION_WRITE_TOOLS, EXTRACT_PROMPT_HASH, EXTRACT_PROMPT_V1, EXTRACT_PROMPT_VERSION, EvolutionGateSet, FAMILY_SESSION_TOOL_NAMES, FORBIDDEN_CONTROL_KEYS, FUZZY_MAX_PATTERN_CHARS, FUZZY_MAX_WORK, HEALTH_STAMP_RE, HISTORY_DIR, HISTORY_INDEX_VERSION, HOOK_LINE_RE, HOST_ROUTES, INSTANCE_KEYS, KEEP_LINE_RE, LONG_RUNS, LOW_QUALITY_THRESHOLD, MAINTAINER_PRESET_ID, MAINTAIN_OUTPUT_INSTRUCTION, MAINTAIN_PROMPT, MAX_DESCRIPTION_LENGTH, MAX_REQUEST_BODY_BYTES, MAX_RESTRUCTURE_MOVES, MAX_SKILL_CONTENT_CHARS, MAX_SKILL_FILE_BYTES, MAX_SKILL_NAME_LENGTH, MAX_SUPPORT_READ_PATHS, MAX_TIMER_DELAY_MS, MEMORY_GUIDANCE_SECTION_ORDER, MEMORY_REVIEW_PROMPT, MIN_STAMP_BODY_CHARS, MODEL_SESSION_EVENT_TYPES as MODEL_SESSION_EVENTS, MODEL_SESSION_EVENT_TYPES, MUTATIONS_FILE_VERSION, MemoryStore, MutationUnit, NAMESPACE_MIGRATIONS, NATIVE_CALL_EVENT, NATIVE_RESULT_EVENT, PARAM_ALIASES, PARAM_EXPOSURE, PARAM_GROUP_LABELS, PARAM_NAMESPACES, PATTERN_OVERLAP, PLATFORM_CATALOG_DESCRIPTION_DEFAULT, PLATFORM_ESTIMATE_CHARS_PER_TOKEN, PLATFORM_LINE, PLATFORM_SERVICE_PROBES, POLICY_STAGE_DEFAULTS, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, PROMPT_BUNDLE_VERSION, PROTECTED_BUILTIN_SKILLS, PTC_DISPATCH_EVENT, PTC_DISPATCH_START_EVENT, QUALITY_WEIGHTS, READ_REQUIRED_ACTIONS, RESTRICTED_PRESET_DISPLAY, RESTRICTED_TOOLS_ROW_ID, RESTRICTOR_MODULE, RESTRUCTURE_TARGET_RE, RETENTION_FEEDBACK_KEEP_RATIO, RETENTION_FEEDBACK_MIN_CHARS, REVIEWER_PRESET_ID, RULES, RUNS_SCHEMA_VERSION, SKILLS_GUIDANCE, SKILLS_GUIDANCE_SECTION_ORDER, SKILL_ACTION_REQUIRED_FIELDS, SKILL_NAME_RE, SKILL_REVIEW_PLAN_PROMPT, SKILL_REVIEW_PROMPT, SNAPSHOT_EXTRA_NAME_RE, STORE_LEDGER, SUMMARY_DUPLICATE_HINT_THRESHOLD, SUPPORT_DIRS, SUPPORT_SPRAWL_FILES, SUPPRESSED_FILE_VERSION, SkillLibrary, SkillModel, TEXT_DIFF_MAX_CHARS, TEXT_DIFF_MAX_LINES, THREAT_EXEMPTION_HINT, TOKEN_ASCII_WEIGHT, TOKEN_CJK_WEIGHT, ToolDispatchNormalizer, ToolDispatchPayloadError, UNIT_JOURNAL_PHASES, UNIT_JOURNAL_SCHEMA_VERSION, UNIT_STORAGE_SCHEMA_VERSION, UNTRUSTED_LINE_BREAK, UNTRUSTED_LINE_MARK, UPSTREAM_LIMIT_CHARS_PER_TOKEN, UnitTransactions, VERSION_SUMMARY_MAX_CHARS, absentHostServices, acquireTreeWriteLock, admissionVerdict, advanceReview, affinity, ageCopyKey, allowRowCollisions, anchorVerdict, appendEvolutionEvent, applyCuratorLifecycleFields, applyCuratorMetaFields, applyNamespaceMigration, applyReferenceRewrite, asRecord, assertDispatchPayload, assertSkillsRootAliasRetired, assertUnitJournalTransition, assessStructureHealth, atomicWriteFiles, authoringFeedback, authorityFrom, backupsReachability, blobPath, bodyCost, buildCuratorRunReport, buildExtractPlanFromLibrary, buildHealthBaseline, buildLearnPrompt, bumpPatch, bumpSupportRead, bumpUse, bumpView, callingScope, candidateSkills, canonicalWriteId, claimInstance, clampOnce, clampedNumber, classifyNamespaceMigration, classifySessionEvent, clearReviewChannel, collectReadSkillNames, computeDedupGroups, computeDriftSignals, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, contentRetentionFeedback, countDispatches, countReferenceFiles, createGateSet, createSubagentChannel, daysSinceIso, declaredReportStamp, describeReferenceRewrite, diffFindings, dispatchKeyOf, dispatchStepOf, displayBodyOf, duplicateHeadings, elapsedSince, emptyRecord, ensureSkillFrontmatter, entryTarget, errorText, evaluateThreat, eventsFile, evidenceKindIndex, evolutionActivityProjection, evolutionEventPayloadIssue, evolutionEvidenceProjection, evolutionHome, evolutionIoAdapter, evolutionReadsProjection, evolutionRoot, evolutionSignalsProjection, executeUnitUndo, externalRefs, fileMutationLock, filterUnreadSkillOps, findDriftSignal, findOwnerCandidate, foldCuratorFields, foldToolDispatches, foldTurnEvent, foldTurnEvents, foldUntrustedLines, frontmatterBlock, frontmatterCatalogInvalid, fuzzyPatch, getRecord, h2Sections, historyIndexFile, historyReachability, historyRoot, hostSurface, identity, idleDays, initialTurnFold, installEvolutionProjections, instanceClaimKey, instanceClaimedWriteSites, instanceHolder, isAbsent, isBookkeepingFrame, isCommittedWarning, isDeprecatedParamId, isFileShapedPath, isIgnorableEvent, isLandmark, isMissingPath, isPresent, isProcessAlive, isProgramToolName, isRecord, isReviewChannelSession, isSkillReadToolName, isSkillToolName, isUnknown, isUnreadWrite, json, landmarkVerdict, latestActivityAt, latestVersionAt, lifecycleCandidate, lintBody, lintSkill, listEventArchives, liveBool, liveEnum, liveNumber, liveString, loadMutations, loadSuppressedNames, loadUsage, loadVersionContent, loadVersions, makeSerialQueue, mapProbe, markAgentCreated, markReviewChannel, markerEntryName, memoryRoot, methodNotAllowed, missingSupportPointers, mutateUsage, mutationsFile, narrowNameMatches, nearDuplicateSummaries, newRunRegistry, newSkillLibrary, nextHistoryIndex, nodeEvolutionIo, normalizeFrontmatter, normalizeUsageRecord, normalizeVersionSummary, observeEvent, orderVersions, overlongLines, ownerCandidatesFromSummaries, ownerDecisionText, paramNamespace, paramRowId, paramSettingsId, parseCuratorNominations, parseEvolutionEvents, parseFrontmatter, parseHistoryIndex, partitionVersions, payloadText, persistedWriteSite, persistedWriteSites, pickWithPolicy, planExtract, planNamespaceMigration, planReferenceRewrite, planRehoming, planUnitUndoAcross, policyStageLimits, probeAbsent, probeChannelState, probeList, probeMtime, probePresent, probeReason, probeText, probeUnknown, projectExtractBodies, projectionText, proposalFromPlan, proposalReportDir, proposalReportName, protectedSkillNamesOf, readDispatchSignal, readEvolutionEvents, readEvolutionTimeline, readExternalSupport, readHistoryIndex, readJsonObject, readNumberParam, readParam, readProposalReports, readTreeLock, readUnitEvidence, readUnitIndex, readUnitJournal, readUnitReceipt, readUnitSnapshot, readingStats, recordMutation, recordVersions, redactSecrets, referencedBlobs, registerHostRoutes, relatedSkillNames, releaseInstance, renameWithRetry, renderCuratorReportMarkdown, renderLongRunTable, reportTime, reportsReachability, reportsSweepLockTarget, resolveCitations, resolveExecOrigins, resolveOrigins, resolveParamId, resolveRootConfig, resolveSkillsRoot, resolveUnitMembers, resolveUnitMembersFromIndexes, restructureCandidates, retainEventArchives, retirementReport, reviewPrompt, revisionAnchor, revisionAnchorOf, revisionFingerprint, revisionSupportDigest, runWriteGates, runsFile, saveSuppressedNames, saveUsage, scanBodyHooks, scanContentThreats, scanMemoryThreats, scanThreats, scopeOfNearestManifest, scopedPackageName, scopedProbeReport, selectSections, sessionAudited, sessionEvidenceIndex, sessionLastEventTime, sessionReadNames, sessionReadSkillNames, sessionSeesFamilyTools, sessionTurnSignals, skillLibraryUnitBackend, skillReadNameOf, skillRowCells, skillStateKey, skillWriteGateContext, skillsRoot, staleRouteStubs, subagentChannelState, supportFileReadOf, supportRefs, suppressedFile, sweepReports, sweepReviewChannelSessions, textDiffFacts, tokenLineFor, transactIo, transactTaskGuard, treeLockFile, trimPatternBoundaries, unhookedSupportPointers, unitEvidenceDigest, unitEvidencePath, unitIndexPath, unitJournalPath, unitJournalPhaseRank, unitJournalPort, unitMembersAreComplete, unitReceiptPath, unitSnapshotPath, unitSnapshotPort, unitSnapshotsDir, unitStorageKey, unwrapLive, updateSuppressedNames, upsertUnitIndex, usageFile, usageObserved, userSetKeys, validateFrontmatter, validateMutationRequest, validateRestructureTarget, validateSupportPath, valueOr, verifyPromptBundle, versionActionKind, versionRowCells, versionSummaryPrompt, versionTarget, vocabulary, withTreeWrite, withTreeWriteLock, writeDurableTmp, writePathSymbols, writeProposalReport, writeUnitEvidence, writeUnitJournal, writeUnitReceipt, writeUnitSnapshot, yamlPlainScalarNeedsQuotes };
|
package/lib/types/constants.d.ts
CHANGED
|
@@ -90,7 +90,6 @@ export declare const DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS = 20;
|
|
|
90
90
|
export declare const DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS = 3;
|
|
91
91
|
export declare const DEFAULT_SUBSTANTIVE_MIN_USER_CHARS = 200;
|
|
92
92
|
export declare const DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS = 500;
|
|
93
|
-
export declare const DEFAULT_MAX_OPS_PER_PLAN = 32;
|
|
94
93
|
export declare const DEFAULT_CURATOR_INTERVAL_HOURS = 168;
|
|
95
94
|
export declare const DEFAULT_MIN_IDLE_HOURS = 2;
|
|
96
95
|
export declare const DEFAULT_STALE_AFTER_DAYS = 30;
|
package/lib/types/constants.js
CHANGED
|
@@ -109,7 +109,6 @@ export const DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS = 20;
|
|
|
109
109
|
export const DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS = 3;
|
|
110
110
|
export const DEFAULT_SUBSTANTIVE_MIN_USER_CHARS = 200;
|
|
111
111
|
export const DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS = 500;
|
|
112
|
-
export const DEFAULT_MAX_OPS_PER_PLAN = 32;
|
|
113
112
|
export const DEFAULT_CURATOR_INTERVAL_HOURS = 168;
|
|
114
113
|
export const DEFAULT_MIN_IDLE_HOURS = 2;
|
|
115
114
|
export const DEFAULT_STALE_AFTER_DAYS = 30;
|
package/lib/types/events.d.ts
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* these events off `session.append`). Plan-outcome durability lives in the
|
|
13
13
|
* evolution-activity store, not the session log.
|
|
14
14
|
*/
|
|
15
|
+
import type { EvolutionPlanAppliedEvent, EvolutionSkillMutatedEvent } from '@lmzhen/dsh-evolution-contract';
|
|
16
|
+
export type { EvolutionPlanAppliedEvent, EvolutionSkillMutatedEvent } from '@lmzhen/dsh-evolution-contract';
|
|
15
17
|
import type { ReviewKind } from './signals.ts';
|
|
16
18
|
export interface EvolutionReviewScheduledEvent {
|
|
17
19
|
/** Owning session (payload v2): process events carry no session envelope. */
|
|
@@ -71,52 +73,6 @@ export interface EvolutionReviewCompletedEvent {
|
|
|
71
73
|
readonly promptVersion?: string | undefined;
|
|
72
74
|
readonly error?: string | undefined;
|
|
73
75
|
}
|
|
74
|
-
export interface EvolutionPlanAppliedEvent {
|
|
75
|
-
/** Owning session (payload v2): process events carry no session envelope. */
|
|
76
|
-
sessionId: string;
|
|
77
|
-
planId: string;
|
|
78
|
-
/** Stable fingerprint of the policy snapshot that produced this plan. */
|
|
79
|
-
policyFingerprint?: string | undefined;
|
|
80
|
-
memoryApplied: number;
|
|
81
|
-
skillApplied: number;
|
|
82
|
-
/** Validation rejects ONLY (see the contract note below). V27 R-03: a plan op
|
|
83
|
-
* that was skipped because the session had not read the skill is NOT a
|
|
84
|
-
* validation reject and now travels in `skippedUnread`. */
|
|
85
|
-
rejectedOps: number;
|
|
86
|
-
/** 0.3.31 (V5-19): execution-layer failures — ops that reached execution but
|
|
87
|
-
* did not land (non-throw `ok:false` results). `rejectedOps` counts only
|
|
88
|
-
* VALIDATION rejects; a consumer that treats rejectedOps as "work not done"
|
|
89
|
-
* would otherwise miss a partial application. */
|
|
90
|
-
executionFailures?: number | undefined;
|
|
91
|
-
/** V27 R-03: "not done" has a third, independent cause — an op naming a skill
|
|
92
|
-
* this session never read (the review pipeline refuses to touch unread
|
|
93
|
-
* skills). It is neither a validation reject nor an execution failure, so it
|
|
94
|
-
* has its own field; folding it into `rejectedOps` broke that field's stated
|
|
95
|
-
* contract and made the replay leaderboard penalize one refusal twice
|
|
96
|
-
* (rejectedOps weight AND the executionFailures dimension). */
|
|
97
|
-
skippedUnread?: number | undefined;
|
|
98
|
-
/** First execution-layer failure message (abort reason or op failure). */
|
|
99
|
-
executionError?: string | undefined;
|
|
100
|
-
/** Batch D (2026-09-27): ops whose ENTIRE evidence list cites bookkeeping frames
|
|
101
|
-
* (a turn/step boundary) — the report-only phase of the plan path's
|
|
102
|
-
* `EVIDENCE_CLASS` rule. Not a refusal and not a "not done" cause: the ops in
|
|
103
|
-
* this count executed. It rides the same payload as the other dimensions so the
|
|
104
|
-
* observation window has a durable record; the model's notice says nothing about
|
|
105
|
-
* it. */
|
|
106
|
-
evidenceClassReports?: number | undefined;
|
|
107
|
-
evidenceQuotes?: number | undefined;
|
|
108
|
-
estimatedInputChars?: number | undefined;
|
|
109
|
-
}
|
|
110
|
-
export interface EvolutionSkillMutatedEvent {
|
|
111
|
-
action: string;
|
|
112
|
-
name: string;
|
|
113
|
-
/** 0.3.16 (E-50): was `filePath` with mixed semantics — skill-directory ops
|
|
114
|
-
* carried the DIRECTORY while file ops (write_file/remove_file) carried the
|
|
115
|
-
* FILE path. Split into explicit fields so a subscriber can distinguish. */
|
|
116
|
-
skillDir?: string;
|
|
117
|
-
file?: string;
|
|
118
|
-
archivedPath?: string;
|
|
119
|
-
}
|
|
120
76
|
/** 0.3.18 (E-6): a turn-end review pipeline failure was caught (never an
|
|
121
77
|
* unhandled rejection); this event lets operators/observability see it. The
|
|
122
78
|
* reason is already logged by the emitter — the event is a timestamped signal. */
|
|
@@ -167,5 +123,4 @@ declare module '@deepseek-ai/cordis' {
|
|
|
167
123
|
'evolution/review-error'(event: EvolutionReviewErrorEvent): void;
|
|
168
124
|
}
|
|
169
125
|
}
|
|
170
|
-
export {};
|
|
171
126
|
//# sourceMappingURL=events.d.ts.map
|
package/lib/types/evidence.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Which session frames are EVIDENCE, and which are bookkeeping.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the window the plan was authored against". A boundary frame satisfies that while carrying
|
|
4
|
+
* The session's evidence index answers "does this seq carry content"; a bare range check used
|
|
5
|
+
* to accept any integer inside the authoring window. A boundary frame satisfies that while carrying
|
|
7
6
|
* nothing a claim can rest on: the `turn/start` seq is the frame a claim about that turn was
|
|
8
7
|
* most likely read out of, and citing it is indistinguishable from citing a real exchange. This
|
|
9
8
|
* module owns the ONE classification of a session frame by what it CARRIES, so the plan path can
|
|
@@ -33,8 +32,7 @@ export declare function isBookkeepingFrame(type: string): boolean;
|
|
|
33
32
|
*
|
|
34
33
|
* Structural on purpose — {@link evidenceKindIndex} materializes the dense set of content seqs,
|
|
35
34
|
* while the projection answers by complement over the sparse boundary seqs
|
|
36
|
-
* (`session-projection.ts`). Both satisfy this interface
|
|
37
|
-
* (`evolution-plan-validator/src/index.ts:164`).
|
|
35
|
+
* (`session-projection.ts`). Both satisfy this interface; `session-projection` is the reader.
|
|
38
36
|
*/
|
|
39
37
|
export interface EvidenceIndex {
|
|
40
38
|
/** @param seq - a cited evidence seq. @returns true when that frame carries content. */
|
package/lib/types/evidence.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Which session frames are EVIDENCE, and which are bookkeeping.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the window the plan was authored against". A boundary frame satisfies that while carrying
|
|
4
|
+
* The session's evidence index answers "does this seq carry content"; a bare range check used
|
|
5
|
+
* to accept any integer inside the authoring window. A boundary frame satisfies that while carrying
|
|
7
6
|
* nothing a claim can rest on: the `turn/start` seq is the frame a claim about that turn was
|
|
8
7
|
* most likely read out of, and citing it is indistinguishable from citing a real exchange. This
|
|
9
8
|
* module owns the ONE classification of a session frame by what it CARRIES, so the plan path can
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* B3 / G4 (0.3.78): the family's single-instance contract, made explicit.
|
|
3
3
|
*
|
|
4
4
|
* Every persisted sidecar is written under TWO assumptions: the IO backend's
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* transact serializes different processes when the provider guarantees it (the
|
|
6
|
+
* node backend is process-local only), and exactly ONE instance of each writer
|
|
7
|
+
* service exists per evolution home. The second half
|
|
7
8
|
* was implicit — `makeSerialQueue()` and the module-scope stores are
|
|
8
9
|
* per-instance, so two rows writing one home interleave inside one file (the
|
|
9
10
|
* "two instances, one file" class). This module makes that half enforceable: a
|
|
@@ -20,8 +21,9 @@
|
|
|
20
21
|
* `claims` below is a module-scope Map: two ROWS over one home in ONE process
|
|
21
22
|
* contend, while the SAME home in another process gets its own Map and is
|
|
22
23
|
* granted the key. That is by construction, not a gap to close here — the
|
|
23
|
-
* cross-process half of the contract is the IO backend's
|
|
24
|
-
* (`transactIo`, core/io.ts)
|
|
24
|
+
* cross-process half of the contract is the IO backend's transact
|
|
25
|
+
* (`transactIo`, core/io.ts) when the provider guarantees it; the node backend
|
|
26
|
+
* is process-local, so a shared home across processes is not protected by it alone.
|
|
25
27
|
* The FLOW2-1 finding was three call sites reading a GRANTED claim as "no other
|
|
26
28
|
* process can be doing this work", so the caller contract is stated here:
|
|
27
29
|
* - granted means "no other row OF THIS PROCESS owns the key";
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* B3 / G4 (0.3.78): the family's single-instance contract, made explicit.
|
|
3
3
|
*
|
|
4
4
|
* Every persisted sidecar is written under TWO assumptions: the IO backend's
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* transact serializes different processes when the provider guarantees it (the
|
|
6
|
+
* node backend is process-local only), and exactly ONE instance of each writer
|
|
7
|
+
* service exists per evolution home. The second half
|
|
7
8
|
* was implicit — `makeSerialQueue()` and the module-scope stores are
|
|
8
9
|
* per-instance, so two rows writing one home interleave inside one file (the
|
|
9
10
|
* "two instances, one file" class). This module makes that half enforceable: a
|
|
@@ -20,8 +21,9 @@
|
|
|
20
21
|
* `claims` below is a module-scope Map: two ROWS over one home in ONE process
|
|
21
22
|
* contend, while the SAME home in another process gets its own Map and is
|
|
22
23
|
* granted the key. That is by construction, not a gap to close here — the
|
|
23
|
-
* cross-process half of the contract is the IO backend's
|
|
24
|
-
* (`transactIo`, core/io.ts)
|
|
24
|
+
* cross-process half of the contract is the IO backend's transact
|
|
25
|
+
* (`transactIo`, core/io.ts) when the provider guarantees it; the node backend
|
|
26
|
+
* is process-local, so a shared home across processes is not protected by it alone.
|
|
25
27
|
* The FLOW2-1 finding was three call sites reading a GRANTED claim as "no other
|
|
26
28
|
* process can be doing this work", so the caller contract is stated here:
|
|
27
29
|
* - granted means "no other row OF THIS PROCESS owns the key";
|
package/lib/types/io.d.ts
CHANGED
|
@@ -6,6 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { open } from 'node:fs/promises';
|
|
8
8
|
export interface EvolutionIoLike {
|
|
9
|
+
/**
|
|
10
|
+
* The process scope this backend actually guarantees. `transact` is NOT proof:
|
|
11
|
+
* nodeEvolutionIo's transact serializes in-process only (G2 S4). Required for
|
|
12
|
+
* any backend that claims cross-process; omitted/`single-process` means the
|
|
13
|
+
* caller must keep its own chain and the family must report the weaker truth.
|
|
14
|
+
*/
|
|
15
|
+
readonly processScope?: 'single-process' | 'cross-process' | undefined;
|
|
9
16
|
readText(path: string): Promise<string | null>;
|
|
10
17
|
writeText(path: string, content: string): Promise<void>;
|
|
11
18
|
remove(path: string): Promise<void>;
|
package/lib/types/io.js
CHANGED
|
@@ -78,6 +78,7 @@ export function transactTaskGuard(what) {
|
|
|
78
78
|
/** Lazy adapter over an IO provider registry, shared by every evolution consumer. */
|
|
79
79
|
export function evolutionIoAdapter(provider) {
|
|
80
80
|
return {
|
|
81
|
+
get processScope() { return provider().processScope; },
|
|
81
82
|
readText: path => provider().readText(path),
|
|
82
83
|
writeText: (path, content) => provider().writeText(path, content),
|
|
83
84
|
remove: path => provider().remove(path),
|
|
@@ -382,6 +383,7 @@ export function nodeEvolutionIo() {
|
|
|
382
383
|
}
|
|
383
384
|
};
|
|
384
385
|
return {
|
|
386
|
+
processScope: 'single-process',
|
|
385
387
|
async readText(path) {
|
|
386
388
|
try {
|
|
387
389
|
return await readFile(path, 'utf8');
|
package/lib/types/params.js
CHANGED
|
@@ -178,7 +178,6 @@ export const PARAM_EXPOSURE = Object.freeze([
|
|
|
178
178
|
{ id: 'evolution-state.provider', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-state', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Registered state-store provider name.', why: 'identity' },
|
|
179
179
|
{ id: 'memory.provider', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'memory', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Registered memory provider name.', why: 'identity' },
|
|
180
180
|
{ id: 'memory-files.providerName', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'memory-files', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Name this package registers as the memory provider.', why: 'identity' },
|
|
181
|
-
{ id: 'maxOpsPerPlan', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-plan-validator', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Operation cap one staged plan may carry.', why: 'internal' },
|
|
182
181
|
{ id: 'substantiveMinToolCalls', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Tool calls that make a turn count as substantive.', why: 'internal' },
|
|
183
182
|
{ id: 'substantiveMinUserChars', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'User characters that make a turn count as substantive.', why: 'internal' },
|
|
184
183
|
{ id: 'substantiveMinAgentChars', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Assistant characters that make a turn count as substantive.', why: 'internal' },
|
|
@@ -11,15 +11,8 @@
|
|
|
11
11
|
* `client` probes run in the browser half, where the host has no view of the seats.
|
|
12
12
|
* @module @lmzhen/dsh-evolution-core
|
|
13
13
|
*/
|
|
14
|
-
|
|
15
|
-
export
|
|
16
|
-
/** The service key as `ctx.get` spells it. */
|
|
17
|
-
readonly service: string;
|
|
18
|
-
/** The family feature that silently degrades when the service is absent. */
|
|
19
|
-
readonly feature: string;
|
|
20
|
-
/** Where the probe runs. */
|
|
21
|
-
readonly side: 'host' | 'client';
|
|
22
|
-
}
|
|
14
|
+
import type { PlatformServiceProbe } from '@lmzhen/dsh-evolution-contract';
|
|
15
|
+
export type { PlatformServiceProbe } from '@lmzhen/dsh-evolution-contract';
|
|
23
16
|
/** The 30 probes, in service-name order (the guard checks this list against the tree). */
|
|
24
17
|
export declare const PLATFORM_SERVICE_PROBES: readonly PlatformServiceProbe[];
|
|
25
18
|
/**
|
|
@@ -29,6 +29,7 @@ export const PLATFORM_SERVICE_PROBES = Object.freeze([
|
|
|
29
29
|
{ service: 'evolutionPolicy', feature: 'the policy snapshot that shadows row knobs', side: 'host' },
|
|
30
30
|
{ service: 'evolutionReplay', feature: '/evolution replay', side: 'host' },
|
|
31
31
|
{ service: 'evolutionState', feature: 'the state facade behind activity and replay', side: 'host' },
|
|
32
|
+
{ service: 'evolutionStateStore', feature: 'generic durable state store for assignment queue and future collections', side: 'host' },
|
|
32
33
|
{ service: 'llm', feature: 'the curator one-shot review model call', side: 'host' },
|
|
33
34
|
{ service: 'memory', feature: 'the cross-session memory store (review and learning-graph reads)', side: 'host' },
|
|
34
35
|
{ service: 'pluginInventory', feature: 'the plugin inventory view', side: 'host' },
|
|
@@ -185,7 +185,8 @@ export function newRunRegistry(options) {
|
|
|
185
185
|
};
|
|
186
186
|
const persist = async () => {
|
|
187
187
|
try {
|
|
188
|
-
// Read-modify-write under
|
|
188
|
+
// Read-modify-write under io.transact when the backend provides it; the node
|
|
189
|
+
// backend serializes in-process only. The file is the
|
|
189
190
|
// BASE and only THIS process's rows are laid over it ("one writer per row"); the
|
|
190
191
|
// single write a non-owner may make is the orphan verdict for a row whose owner is
|
|
191
192
|
// gone. The row read inside this transaction IS the compare-and-swap: if its owner
|
package/lib/types/serial.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A process-local serial task queue: each task starts only after the previous
|
|
3
3
|
* one settles (success or failure), so read-modify-write sequences that share
|
|
4
|
-
* one file never interleave inside this process.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* one file never interleave inside this process. When the IO backend provides
|
|
5
|
+
* a cross-process transact lock, that is the first layer; the node backend does
|
|
6
|
+
* not, so this chain is its only serialization. (0.3.17 S2.8, T-1: the shape was
|
|
7
|
+
* duplicated in state-json and
|
|
7
8
|
* memory-files — one factory now).
|
|
8
9
|
*/
|
|
9
10
|
export declare function makeSerialQueue(): <T>(task: () => Promise<T>) => Promise<T>;
|
package/lib/types/serial.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A process-local serial task queue: each task starts only after the previous
|
|
3
3
|
* one settles (success or failure), so read-modify-write sequences that share
|
|
4
|
-
* one file never interleave inside this process.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* one file never interleave inside this process. When the IO backend provides
|
|
5
|
+
* a cross-process transact lock, that is the first layer; the node backend does
|
|
6
|
+
* not, so this chain is its only serialization. (0.3.17 S2.8, T-1: the shape was
|
|
7
|
+
* duplicated in state-json and
|
|
7
8
|
* memory-files — one factory now).
|
|
8
9
|
*/
|
|
9
10
|
export function makeSerialQueue() {
|
package/lib/types/tree-lock.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Tree write lock.
|
|
3
3
|
*
|
|
4
4
|
* The merge run holds this lock for its whole lifetime; curator's pass takes the same
|
|
5
|
-
* lock. The
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* lock. The record is created through `transactIo`, so exclusion is exactly as strong as
|
|
6
|
+
* the IO backend's `transact`: the platform `ctx.fs` provider is cross-process, while the
|
|
7
|
+
* standalone `nodeEvolutionIo` is explicitly single-process (G2 S4). This module builds no
|
|
8
|
+
* file lock or WAL of its own. A holder whose pid is gone is stale and may be taken over;
|
|
9
|
+
* a live pid is respected, even for a long run (a live long run is what the lock protects).
|
|
9
10
|
*
|
|
10
11
|
* `commitMerge` deliberately does NOT take this lock itself: the run shell owns it, so a
|
|
11
12
|
* run and its commit share one acquisition. Taking it inside the store would also
|
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.
|
|
4
|
+
"version": "0.32.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"yaml": "^2.4.2",
|
|
50
50
|
"zod": "^4.4.3",
|
|
51
|
-
"js-yaml": "^4.1.0"
|
|
51
|
+
"js-yaml": "^4.1.0",
|
|
52
|
+
"@lmzhen/dsh-evolution-contract": "^0.32.0"
|
|
52
53
|
},
|
|
53
54
|
"peerDependencies": {
|
|
54
55
|
"@deepseek-ai/cordis": "^4.0.5",
|
|
@@ -297,6 +297,15 @@
|
|
|
297
297
|
"marker": "transactIo(io, pairIndexPath(home)",
|
|
298
298
|
"state": [],
|
|
299
299
|
"note": "pairKey → result/runId/target index; RMW under the same IO lock so two merge runs cannot lose each other's entries."
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"id": "state-store-collections",
|
|
303
|
+
"path": "<evolutionHome>/state-store/<collection>.json",
|
|
304
|
+
"writer": "evolution-state-json/src/state-store.ts",
|
|
305
|
+
"serializedBy": "transact",
|
|
306
|
+
"marker": "transactIo(this.io, this.path(collection)",
|
|
307
|
+
"state": [],
|
|
308
|
+
"note": "Generic contract StateStore collections (one file per collection); provider serial queue plus transactIo. cross-process false on the node backend."
|
|
300
309
|
}
|
|
301
310
|
]
|
|
302
311
|
}
|