@lmzhen/dsh-evolution-core 0.3.34 → 0.3.36
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 +68 -15
- package/lib/types/curator.d.ts +8 -0
- package/lib/types/threats.d.ts +8 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { basename, dirname, join } from "node:path";
|
|
2
|
-
import { cp, lstat, mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { cp, lstat, mkdir, open, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { load } from "js-yaml";
|
|
@@ -149,11 +149,20 @@ function nodeEvolutionIo() {
|
|
|
149
149
|
const lock = `${path}.lock`;
|
|
150
150
|
let myClaim = "";
|
|
151
151
|
for (let attempt = 0; attempt < 40; attempt += 1) {
|
|
152
|
+
let lockHandle = null;
|
|
152
153
|
try {
|
|
153
154
|
myClaim = `${process.pid}:${randomBytes(4).toString("hex")}`;
|
|
154
|
-
await
|
|
155
|
+
lockHandle = await open(lock, "wx");
|
|
156
|
+
await lockHandle.writeFile(myClaim);
|
|
157
|
+
await lockHandle.close();
|
|
158
|
+
lockHandle = null;
|
|
155
159
|
} catch (error) {
|
|
156
160
|
const code = error?.code;
|
|
161
|
+
if (lockHandle) {
|
|
162
|
+
await lockHandle.close().catch(() => {});
|
|
163
|
+
await rm(lock, { force: true }).catch(() => {});
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
157
166
|
if (code !== "EEXIST" && code !== "EPERM") throw error;
|
|
158
167
|
try {
|
|
159
168
|
const st = await stat(lock);
|
|
@@ -169,13 +178,16 @@ function nodeEvolutionIo() {
|
|
|
169
178
|
}
|
|
170
179
|
continue;
|
|
171
180
|
}
|
|
172
|
-
|
|
181
|
+
const staleDead = Number.isInteger(holder) && holder > 0 && Date.now() - st.mtimeMs > 1e3 && !holderAlive;
|
|
182
|
+
const staleEmpty = holderContent === "" && Date.now() - st.mtimeMs > 1e3;
|
|
183
|
+
if (staleDead || staleEmpty) {
|
|
173
184
|
if (await readFile(lock, "utf8").catch(() => "") === holderContent) {
|
|
174
185
|
const ticket = `${lock}.next`;
|
|
175
186
|
try {
|
|
176
187
|
const ticketBody = await readFile(ticket, "utf8").catch(() => "");
|
|
188
|
+
const ticketMtime = await stat(ticket).then((s) => s.mtimeMs, () => 0);
|
|
177
189
|
const ticketHolder = Number(ticketBody.split(":")[0] ?? "");
|
|
178
|
-
if ((!Number.isInteger(ticketHolder) || ticketHolder <= 0 || !isAlive(ticketHolder) || Date.now() -
|
|
190
|
+
if ((!Number.isInteger(ticketHolder) || ticketHolder <= 0 || !isAlive(ticketHolder) || Date.now() - ticketMtime > 1e3) && (ticketBody !== "" || Date.now() - ticketMtime > 1e3)) await rm(ticket, { force: true }).catch(() => {});
|
|
179
191
|
} catch {}
|
|
180
192
|
try {
|
|
181
193
|
await writeFile(ticket, `${process.pid}:${randomBytes(4).toString("hex")}`, { flag: "wx" });
|
|
@@ -217,8 +229,24 @@ function nodeEvolutionIo() {
|
|
|
217
229
|
return;
|
|
218
230
|
}
|
|
219
231
|
const prefix = `${base}.`;
|
|
232
|
+
const lockName = `${base}.lock`;
|
|
233
|
+
const ticketName = `${lockName}.next`;
|
|
220
234
|
for (const name of entries) {
|
|
221
|
-
if (!name.startsWith(prefix) ||
|
|
235
|
+
if (!name.startsWith(prefix) || name === lockName) continue;
|
|
236
|
+
if (!name.endsWith(".tmp")) {
|
|
237
|
+
if (name === ticketName) {
|
|
238
|
+
const ticketPath = join(dir, name);
|
|
239
|
+
try {
|
|
240
|
+
const body = await readFile(ticketPath, "utf8").catch(() => "");
|
|
241
|
+
const holder = Number(body.split(":")[0] ?? "");
|
|
242
|
+
const st = await stat(ticketPath);
|
|
243
|
+
const dead = !Number.isInteger(holder) || holder <= 0 || !isAlive(holder);
|
|
244
|
+
const old = Date.now() - st.mtimeMs > 1e3;
|
|
245
|
+
if (dead || old) await rm(ticketPath, { force: true });
|
|
246
|
+
} catch {}
|
|
247
|
+
}
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
222
250
|
const tmpPath = join(dir, name);
|
|
223
251
|
const holder = Number(name.slice(prefix.length, name.length - 4).split(".")[0] ?? "");
|
|
224
252
|
try {
|
|
@@ -718,7 +746,8 @@ function buildCuratorRunReport(input) {
|
|
|
718
746
|
failed: [...input.failed],
|
|
719
747
|
...input.consolidated === void 0 ? {} : { consolidated: [...input.consolidated] },
|
|
720
748
|
...input.snapshotPath === void 0 ? {} : { snapshotPath: input.snapshotPath },
|
|
721
|
-
...input.llmReviewEnabled === void 0 ? {} : { llmReviewEnabled: input.llmReviewEnabled }
|
|
749
|
+
...input.llmReviewEnabled === void 0 ? {} : { llmReviewEnabled: input.llmReviewEnabled },
|
|
750
|
+
...input.nominationsWarnings === void 0 ? {} : { nominationsWarnings: [...input.nominationsWarnings] }
|
|
722
751
|
};
|
|
723
752
|
}
|
|
724
753
|
/**
|
|
@@ -737,7 +766,8 @@ function renderCuratorReportMarkdown(report) {
|
|
|
737
766
|
`- **Archived**: ${report.archived.length}`,
|
|
738
767
|
`- **Failed**: ${report.failed.length}`,
|
|
739
768
|
...report.snapshotPath === void 0 ? [] : [`- **Snapshot**: ${report.snapshotPath}`],
|
|
740
|
-
...report.llmReviewEnabled === void 0 ? [] : [`- **llmReview**: ${report.llmReviewEnabled}`]
|
|
769
|
+
...report.llmReviewEnabled === void 0 ? [] : [`- **llmReview**: ${report.llmReviewEnabled}`],
|
|
770
|
+
...report.nominationsWarnings === void 0 || report.nominationsWarnings.length === 0 ? [] : [`- **Nomination warnings**: ${report.nominationsWarnings.join("; ")}`]
|
|
741
771
|
];
|
|
742
772
|
const section = (title, items) => items.length === 0 ? [] : [
|
|
743
773
|
"",
|
|
@@ -763,10 +793,16 @@ const NOMINATION_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
|
763
793
|
function parseCuratorNominations(text) {
|
|
764
794
|
const prunings = [];
|
|
765
795
|
const consolidations = [];
|
|
796
|
+
const warnings = [];
|
|
766
797
|
let section = null;
|
|
767
798
|
let currentFrom = "";
|
|
768
799
|
let currentMode;
|
|
769
800
|
for (const line of text.split("\n")) {
|
|
801
|
+
const header = /^\s*(consolidations|prunings)\s*:\s*$/.exec(line);
|
|
802
|
+
if (header) {
|
|
803
|
+
section = header[1] === "consolidations" ? "consolidations" : "prunings";
|
|
804
|
+
continue;
|
|
805
|
+
}
|
|
770
806
|
const consolidated = /^\s*-\s*from:\s*([a-z0-9][a-z0-9-]*)\s*$/.exec(line);
|
|
771
807
|
if (consolidated) {
|
|
772
808
|
section = "consolidations";
|
|
@@ -777,6 +813,7 @@ function parseCuratorNominations(text) {
|
|
|
777
813
|
const mode = /^\s*mode:\s*(append|reference)\s*$/.exec(line);
|
|
778
814
|
if (mode) {
|
|
779
815
|
if (currentFrom !== "") currentMode = mode[1] === "reference" ? "reference" : "append";
|
|
816
|
+
else warnings.push(`mode: ${mode[1]} ignored — no preceding "- from:" entry (the consolidation falls back to append)`);
|
|
780
817
|
continue;
|
|
781
818
|
}
|
|
782
819
|
const into = /^\s*into:\s*([a-z0-9][a-z0-9-]*)\s*$/.exec(line);
|
|
@@ -793,6 +830,7 @@ function parseCuratorNominations(text) {
|
|
|
793
830
|
}
|
|
794
831
|
const pruned = /^\s*-\s*name:\s*([a-z0-9][a-z0-9-]*)\s*$/.exec(line);
|
|
795
832
|
if (pruned) {
|
|
833
|
+
if (section === "consolidations") warnings.push("\"- name:\" inside the consolidations section flips the parse to prunings");
|
|
796
834
|
section = "prunings";
|
|
797
835
|
const name = pruned[1];
|
|
798
836
|
if (name) prunings.push(name);
|
|
@@ -801,7 +839,8 @@ function parseCuratorNominations(text) {
|
|
|
801
839
|
const valid = (name) => NOMINATION_NAME_RE.test(name);
|
|
802
840
|
return {
|
|
803
841
|
prunings: prunings.filter(valid),
|
|
804
|
-
consolidations: consolidations.filter((item) => valid(item.from) && valid(item.into))
|
|
842
|
+
consolidations: consolidations.filter((item) => valid(item.from) && valid(item.into)),
|
|
843
|
+
warnings
|
|
805
844
|
};
|
|
806
845
|
}
|
|
807
846
|
/**
|
|
@@ -836,7 +875,8 @@ function computeScopeView(usage, config, protectedNames, gates) {
|
|
|
836
875
|
}
|
|
837
876
|
const bundled = config.bundledNames?.has(name) === true;
|
|
838
877
|
const suppressed = gateSet.suppressed.has(name);
|
|
839
|
-
|
|
878
|
+
const isBuiltin = PROTECTED_BUILTIN_SKILLS.has(name);
|
|
879
|
+
if (record.pinned || bundled || suppressed || protectedNames?.has(name) === true || isBuiltin) protectedSet.add(name);
|
|
840
880
|
if (lifecycleCandidate(name, record, config, bundled, gateSet)) {
|
|
841
881
|
managed.push(name);
|
|
842
882
|
if (record.state === "stale" || record.quality_warn === true) watched.push(name);
|
|
@@ -1779,9 +1819,13 @@ const SCOPE_ORDER = {
|
|
|
1779
1819
|
strict: 3
|
|
1780
1820
|
};
|
|
1781
1821
|
const NO_SCAN_OPTIONS = {};
|
|
1782
|
-
/**
|
|
1783
|
-
*
|
|
1784
|
-
* window
|
|
1822
|
+
/** Minimum window size for the full-coverage scan (V6-05, 0.3.35). With the
|
|
1823
|
+
* proportional half-window step below, the overlap is `ceil(w/2)` — only a
|
|
1824
|
+
* window at or above this floor keeps the overlap above the longest pattern
|
|
1825
|
+
* span (~530 chars: `curl [^\n]{0,512} ...`), so a match straddling a window
|
|
1826
|
+
* boundary is fully inside at least one window (E-12, 0.3.16). The clamp
|
|
1827
|
+
* falls back to the default for a smaller caller value instead of risking a
|
|
1828
|
+
* blind zone. */
|
|
1785
1829
|
const PATTERN_OVERLAP = 4096;
|
|
1786
1830
|
/**
|
|
1787
1831
|
* Scan text at `scope`. Patterns are cumulative: `strict` includes all scopes.
|
|
@@ -1791,7 +1835,7 @@ const PATTERN_OVERLAP = 4096;
|
|
|
1791
1835
|
* characters (skill files may run to 100,000) is no longer a blind zone.
|
|
1792
1836
|
*/
|
|
1793
1837
|
function scanThreats(text, scope = "strict", maxScanChars = 65536, options = NO_SCAN_OPTIONS) {
|
|
1794
|
-
const windowSize = clampedNumber(maxScanChars, 65536, { min:
|
|
1838
|
+
const windowSize = clampedNumber(maxScanChars, 65536, { min: 4097 });
|
|
1795
1839
|
const findings = [];
|
|
1796
1840
|
if (ZERO_WIDTH_CHARS.test(text)) findings.push({
|
|
1797
1841
|
label: "unicode_zero_width",
|
|
@@ -1807,7 +1851,7 @@ function scanThreats(text, scope = "strict", maxScanChars = 65536, options = NO_
|
|
|
1807
1851
|
const windows = [];
|
|
1808
1852
|
if (normalized.length <= windowSize) windows.push(normalized);
|
|
1809
1853
|
else {
|
|
1810
|
-
const step = Math.max(
|
|
1854
|
+
const step = Math.max(Math.floor(windowSize / 2), 1);
|
|
1811
1855
|
for (let start = 0; start < normalized.length; start += step) windows.push(normalized.slice(start, start + windowSize));
|
|
1812
1856
|
}
|
|
1813
1857
|
const excluded = new Set(options.excludeLabels ?? []);
|
|
@@ -4470,6 +4514,15 @@ var SkillLibrary = class {
|
|
|
4470
4514
|
};
|
|
4471
4515
|
const target = join(dir, ...filePath.replace(/\\/g, "/").split("/").filter(Boolean));
|
|
4472
4516
|
return await this.runSingleWrite(target, (current) => {
|
|
4517
|
+
if (current !== null && content.trimEnd() === current.trimEnd()) return {
|
|
4518
|
+
result: {
|
|
4519
|
+
ok: true,
|
|
4520
|
+
message: `Support file "${filePath}" unchanged: the supplied content already matches the current file; nothing written.`,
|
|
4521
|
+
noop: true,
|
|
4522
|
+
path: target
|
|
4523
|
+
},
|
|
4524
|
+
write: null
|
|
4525
|
+
};
|
|
4473
4526
|
return {
|
|
4474
4527
|
result: {
|
|
4475
4528
|
ok: true,
|
|
@@ -4738,4 +4791,4 @@ function evolutionHome(env = process.env) {
|
|
|
4738
4791
|
return join(evolutionRoot(env), "evolution");
|
|
4739
4792
|
}
|
|
4740
4793
|
//#endregion
|
|
4741
|
-
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_HEALTH_THRESHOLDS, 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, 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_WRITE_TOOLS, EvolutionGateSet, FORBIDDEN_CONTROL_KEYS, HEALTH_STAMP_RE, LOW_QUALITY_THRESHOLD, MAINTAIN_PROMPT, MAX_DESCRIPTION_LENGTH, MAX_RESTRUCTURE_MOVES, MAX_SKILL_CONTENT_CHARS, MAX_SKILL_FILE_BYTES, MAX_SKILL_NAME_LENGTH, MEMORY_REVIEW_PROMPT, MIN_STAMP_BODY_CHARS, MUTATIONS_FILE_VERSION, MemoryStore, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, PROMPT_BUNDLE_VERSION, PROTECTED_BUILTIN_SKILLS, QUALITY_WEIGHTS, RESTRUCTURE_TARGET_RE, 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, applyCuratorLifecycleFields, applyCuratorMetaFields, assessStructureHealth, authoringFeedback, buildCuratorRunReport, buildLearnPrompt, bumpPatch, bumpUse, bumpView, clampedNumber, composePresetComposition, computeDedupGroups, computeDriftSignals, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, createGateSet, duplicateHeadings, emptyRecord, evaluateThreat, eventsFile, evolutionHome, evolutionIoAdapter, evolutionRoot, findDriftSignal, foldCuratorFields, foldTurn, frontmatterBlock, frontmatterYamlUnsafeValues, getRecord, latestActivityAt, lifecycleCandidate, listEventArchives, loadMutations, loadSuppressedNames, loadUsage, makeSerialQueue, markAgentCreated, markerEntryName, memoryRoot, missingSupportPointers, mutateUsage, mutationsFile, narrowNameMatches, nodeEvolutionIo, normalizeFrontmatter, normalizeUsageRecord, observeEvent, overlongLines, parseCuratorNominations, parseEvolutionEvents, parseFrontmatter, pendingSelfCleanup, readEvolutionEvents, readEvolutionTimeline, recordMutation, redactSecrets, relatedSkillNames, renameWithRetry, renderCuratorReportMarkdown, resolveOrigins, resolveSkillsRoot, retainEventArchives, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, transactIo, updateSuppressedNames, usageFile, usageObserved, validateFrontmatter, verifyPromptBundle, yamlPlainScalarNeedsQuotes };
|
|
4794
|
+
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_HEALTH_THRESHOLDS, 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, 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_WRITE_TOOLS, EvolutionGateSet, FORBIDDEN_CONTROL_KEYS, HEALTH_STAMP_RE, LOW_QUALITY_THRESHOLD, MAINTAIN_PROMPT, MAX_DESCRIPTION_LENGTH, MAX_RESTRUCTURE_MOVES, MAX_SKILL_CONTENT_CHARS, MAX_SKILL_FILE_BYTES, MAX_SKILL_NAME_LENGTH, MEMORY_REVIEW_PROMPT, MIN_STAMP_BODY_CHARS, MUTATIONS_FILE_VERSION, MemoryStore, PATTERN_OVERLAP, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, PROMPT_BUNDLE_VERSION, PROTECTED_BUILTIN_SKILLS, QUALITY_WEIGHTS, RESTRUCTURE_TARGET_RE, 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, applyCuratorLifecycleFields, applyCuratorMetaFields, assessStructureHealth, authoringFeedback, buildCuratorRunReport, buildLearnPrompt, bumpPatch, bumpUse, bumpView, clampedNumber, composePresetComposition, computeDedupGroups, computeDriftSignals, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, createGateSet, duplicateHeadings, emptyRecord, evaluateThreat, eventsFile, evolutionHome, evolutionIoAdapter, evolutionRoot, findDriftSignal, foldCuratorFields, foldTurn, frontmatterBlock, frontmatterYamlUnsafeValues, getRecord, latestActivityAt, lifecycleCandidate, listEventArchives, loadMutations, loadSuppressedNames, loadUsage, makeSerialQueue, markAgentCreated, markerEntryName, memoryRoot, missingSupportPointers, mutateUsage, mutationsFile, narrowNameMatches, nodeEvolutionIo, normalizeFrontmatter, normalizeUsageRecord, observeEvent, overlongLines, parseCuratorNominations, parseEvolutionEvents, parseFrontmatter, pendingSelfCleanup, readEvolutionEvents, readEvolutionTimeline, recordMutation, redactSecrets, relatedSkillNames, renameWithRetry, renderCuratorReportMarkdown, resolveOrigins, resolveSkillsRoot, retainEventArchives, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, transactIo, updateSuppressedNames, usageFile, usageObserved, validateFrontmatter, verifyPromptBundle, yamlPlainScalarNeedsQuotes };
|
package/lib/types/curator.d.ts
CHANGED
|
@@ -63,6 +63,8 @@ export interface CuratorRunReport {
|
|
|
63
63
|
snapshotPath?: string;
|
|
64
64
|
/** Whether the LLM nomination pass was enabled for this run (decision visibility). */
|
|
65
65
|
llmReviewEnabled?: boolean;
|
|
66
|
+
/** V6-35 (0.3.36): lenient-parse shape notes from the LLM nomination block. */
|
|
67
|
+
nominationsWarnings?: string[];
|
|
66
68
|
}
|
|
67
69
|
export interface CuratorReportInput {
|
|
68
70
|
runId: string;
|
|
@@ -76,6 +78,7 @@ export interface CuratorReportInput {
|
|
|
76
78
|
consolidated?: readonly CuratorConsolidation[];
|
|
77
79
|
snapshotPath?: string;
|
|
78
80
|
llmReviewEnabled?: boolean;
|
|
81
|
+
nominationsWarnings?: readonly string[];
|
|
79
82
|
}
|
|
80
83
|
export declare function buildCuratorRunReport(input: CuratorReportInput): CuratorRunReport;
|
|
81
84
|
/**
|
|
@@ -97,6 +100,11 @@ export interface CuratorConsolidation {
|
|
|
97
100
|
export interface CuratorNominations {
|
|
98
101
|
prunings: string[];
|
|
99
102
|
consolidations: CuratorConsolidation[];
|
|
103
|
+
/** V6-35 (0.3.36): lenient-parse shape notes (an entry the lenient logic
|
|
104
|
+
* silently dropped or re-routed). Parsing stays lenient — these are advisory
|
|
105
|
+
* and flow into the run report so the operator sees why a mode or a pruning
|
|
106
|
+
* went somewhere unexpected. */
|
|
107
|
+
warnings: string[];
|
|
100
108
|
}
|
|
101
109
|
/**
|
|
102
110
|
* Parse the curator LLM's YAML nomination block (consolidations + prunings).
|
package/lib/types/threats.d.ts
CHANGED
|
@@ -23,6 +23,14 @@ export interface ScanOptions {
|
|
|
23
23
|
/** Pattern labels to skip during this scan. */
|
|
24
24
|
excludeLabels?: readonly string[];
|
|
25
25
|
}
|
|
26
|
+
/** Minimum window size for the full-coverage scan (V6-05, 0.3.35). With the
|
|
27
|
+
* proportional half-window step below, the overlap is `ceil(w/2)` — only a
|
|
28
|
+
* window at or above this floor keeps the overlap above the longest pattern
|
|
29
|
+
* span (~530 chars: `curl [^\n]{0,512} ...`), so a match straddling a window
|
|
30
|
+
* boundary is fully inside at least one window (E-12, 0.3.16). The clamp
|
|
31
|
+
* falls back to the default for a smaller caller value instead of risking a
|
|
32
|
+
* blind zone. */
|
|
33
|
+
export declare const PATTERN_OVERLAP = 4096;
|
|
26
34
|
/**
|
|
27
35
|
* Scan text at `scope`. Patterns are cumulative: `strict` includes all scopes.
|
|
28
36
|
* `options.excludeLabels` removes matching patterns without changing `scope`.
|
package/package.json
CHANGED