@lmzhen/dsh-evolution-core 0.26.26 → 0.27.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/README.md +16 -1
- package/lib/composition/index.js +3 -0
- package/lib/composition-D8Y3-ROd.js +604 -0
- package/lib/ensure-MEYMj9jn.js +222 -0
- package/lib/errors-Br2-uUSK.js +57 -0
- package/lib/http-routes-BP-S3KV-.js +149 -0
- package/lib/http-routes.js +2 -0
- package/lib/index.js +66 -850
- package/lib/restrictor.js +37 -0
- package/lib/subagent/index.js +186 -0
- package/lib/types/citations.js +192 -0
- package/lib/types/{preset-composition.d.ts → composition/composer.d.ts} +1 -1
- package/lib/types/composition/composer.js +681 -0
- package/lib/types/composition/ensure.d.ts +10 -0
- package/lib/types/composition/ensure.js +95 -0
- package/lib/types/composition/index.d.ts +5 -0
- package/lib/types/composition/index.js +7 -0
- package/lib/types/composition/preset-ids.d.ts +17 -0
- package/lib/types/composition/preset-ids.js +21 -0
- package/lib/types/composition/restricted-preset.d.ts +36 -0
- package/lib/types/composition/restricted-preset.js +42 -0
- package/lib/types/constants.js +223 -0
- package/lib/types/cost.js +67 -0
- package/lib/types/curator.js +346 -0
- package/lib/types/diagnostics.d.ts +26 -0
- package/lib/types/diagnostics.js +23 -0
- package/lib/types/document-body.js +91 -0
- package/lib/types/drift-signals.js +319 -0
- package/lib/types/env.js +25 -0
- package/lib/types/errors.d.ts +4 -1
- package/lib/types/errors.js +59 -0
- package/lib/types/events.js +16 -0
- package/lib/types/evidence.js +65 -0
- package/lib/types/evolution-events.js +479 -0
- package/lib/types/fold-untrusted.js +44 -0
- package/lib/types/frontmatter.js +623 -0
- package/lib/types/fuzzy-match.js +135 -0
- package/lib/types/gates.js +51 -0
- package/lib/types/guards.js +27 -0
- package/lib/types/health-baseline.js +63 -0
- package/lib/types/http-routes.d.ts +67 -35
- package/lib/types/http-routes.js +135 -0
- package/lib/types/index.d.ts +7 -2
- package/lib/types/index.js +101 -0
- package/lib/types/instance-scope.js +69 -0
- package/lib/types/io.js +675 -0
- package/lib/types/learn-prompt.js +42 -0
- package/lib/types/limits.js +63 -0
- package/lib/types/live.js +107 -0
- package/lib/types/long-runs.js +96 -0
- package/lib/types/memory-store.d.ts +0 -16
- package/lib/types/memory-store.js +606 -0
- package/lib/types/mutations.js +95 -0
- package/lib/types/namespace-migration.js +156 -0
- package/lib/types/numeric.js +47 -0
- package/lib/types/opt-in.js +101 -0
- package/lib/types/package-identity.js +47 -0
- package/lib/types/params.js +328 -0
- package/lib/types/payload.js +36 -0
- package/lib/types/platform-line.generated.d.ts +10 -0
- package/lib/types/platform-line.generated.js +12 -0
- package/lib/types/platform-services.d.ts +2 -2
- package/lib/types/platform-services.js +52 -0
- package/lib/types/probe.js +122 -0
- package/lib/types/prompts.js +409 -0
- package/lib/types/quality.js +308 -0
- package/lib/types/reachability.js +122 -0
- package/lib/types/redact.js +257 -0
- package/lib/types/reference-rewrite.js +144 -0
- package/lib/types/reports.js +110 -0
- package/lib/types/restrictor.d.ts +11 -0
- package/lib/types/restrictor.js +48 -0
- package/lib/types/review-channel.js +59 -0
- package/lib/types/run-registry.js +345 -0
- package/lib/types/scope.js +7 -0
- package/lib/types/serial.js +17 -0
- package/lib/types/session-fold.d.ts +15 -0
- package/lib/types/session-fold.js +28 -0
- package/lib/types/session-projection.js +295 -0
- package/lib/types/signals.js +209 -0
- package/lib/types/skill-discovery.js +66 -0
- package/lib/types/skill-health.js +134 -0
- package/lib/types/skill-history.js +745 -0
- package/lib/types/skill-lint.js +112 -0
- package/lib/types/skill-reads.js +67 -0
- package/lib/types/skill-row-cells.js +123 -0
- package/lib/types/skill-store.js +3528 -0
- package/lib/types/state-store.js +60 -0
- package/lib/types/store-ledger.js +117 -0
- package/lib/types/subagent/channel.d.ts +4 -0
- package/lib/types/subagent/channel.js +131 -0
- package/lib/types/subagent/index.d.ts +4 -0
- package/lib/types/subagent/index.js +5 -0
- package/lib/types/subagent/readiness.d.ts +6 -0
- package/lib/types/subagent/readiness.js +35 -0
- package/lib/types/subagent/types.d.ts +58 -0
- package/lib/types/subagent/types.js +2 -0
- package/lib/types/threats.js +338 -0
- package/lib/types/tool-dispatch.d.ts +5 -0
- package/lib/types/tool-dispatch.js +535 -0
- package/lib/types/tree-write.js +40 -0
- package/lib/types/unit-members.js +121 -0
- package/lib/types/usage.js +474 -0
- package/lib/types/write-authority.js +23 -0
- package/lib/types/write-gates.js +344 -0
- package/lib/types/write-inventory.js +158 -0
- package/package.json +39 -11
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter id consolidation (G0/S0.2): one semantic gets ONE id.
|
|
3
|
+
*
|
|
4
|
+
* Nine places in this family carry the same value under two carriers: three use
|
|
5
|
+
* the SAME name in two carriers (reviewMode, staleAfterDays, archiveAfterDays —
|
|
6
|
+
* resolved by the existing policy-shadows-row rule) and six use DIFFERENT names.
|
|
7
|
+
* This module owns the six: the policy/snapshot name is the canonical id, the
|
|
8
|
+
* plugin-row name is a deprecated alias kept readable since 0.6.x. Removal was
|
|
9
|
+
* planned for 0.7.0 and is deferred: the aliases still ship, so no later version
|
|
10
|
+
* is claimed here.
|
|
11
|
+
*
|
|
12
|
+
* Reading stays compatible (a carrier still spelling the legacy name resolves),
|
|
13
|
+
* writing is strict (the write path accepts canonical ids only, so no new
|
|
14
|
+
* document is created under a deprecated name).
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
/** Deprecated alias (plugin-row name) -> canonical id (policy/snapshot name). */
|
|
18
|
+
export const PARAM_ALIASES = Object.freeze({
|
|
19
|
+
memoryInterval: 'reviewMemoryInterval',
|
|
20
|
+
skillInterval: 'reviewSkillInterval',
|
|
21
|
+
intervalHours: 'curatorIntervalHours',
|
|
22
|
+
maxSkillContentChars: 'skillContentChars',
|
|
23
|
+
memoryCharLimit: 'memoryChars',
|
|
24
|
+
userCharLimit: 'userChars',
|
|
25
|
+
});
|
|
26
|
+
/** Canonical ids that have at least one deprecated alias, for read fallback. */
|
|
27
|
+
const ALIASES_BY_CANONICAL = (() => {
|
|
28
|
+
const index = {};
|
|
29
|
+
for (const [alias, canonical] of Object.entries(PARAM_ALIASES)) {
|
|
30
|
+
;
|
|
31
|
+
(index[canonical] ??= []).push(alias);
|
|
32
|
+
}
|
|
33
|
+
return index;
|
|
34
|
+
})();
|
|
35
|
+
/**
|
|
36
|
+
* Resolve any parameter id to its canonical form.
|
|
37
|
+
* @param id - canonical id or deprecated alias.
|
|
38
|
+
* @returns the canonical id; ids without an alias pass through unchanged.
|
|
39
|
+
*/
|
|
40
|
+
export function resolveParamId(id) {
|
|
41
|
+
return PARAM_ALIASES[id] ?? id;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Whether an id is a deprecated alias.
|
|
45
|
+
* @param id - parameter id to test.
|
|
46
|
+
* @returns true when the id must be migrated to its canonical form.
|
|
47
|
+
*/
|
|
48
|
+
export function isDeprecatedParamId(id) {
|
|
49
|
+
return PARAM_ALIASES[id] !== undefined;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Guard for the write path: only canonical ids may be written.
|
|
53
|
+
* @param id - parameter id a caller intends to write.
|
|
54
|
+
* @returns the canonical id.
|
|
55
|
+
* @throws {Error} when the id is a deprecated alias; the message names both ids.
|
|
56
|
+
*/
|
|
57
|
+
export function canonicalWriteId(id) {
|
|
58
|
+
const canonical = PARAM_ALIASES[id];
|
|
59
|
+
if (canonical === undefined)
|
|
60
|
+
return id;
|
|
61
|
+
throw new Error(`parameter id \`${id}\` is deprecated; write \`${canonical}\` instead`);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Read a parameter from a carrier that may still spell the legacy name.
|
|
65
|
+
* @param carrier - config/snapshot object to read from, or undefined.
|
|
66
|
+
* @param id - canonical id (a deprecated alias is accepted and resolved first).
|
|
67
|
+
* @returns the canonical value when present, else the alias value, else undefined.
|
|
68
|
+
*/
|
|
69
|
+
export function readParam(carrier, id) {
|
|
70
|
+
if (carrier === undefined)
|
|
71
|
+
return undefined;
|
|
72
|
+
const record = carrier;
|
|
73
|
+
const canonical = resolveParamId(id);
|
|
74
|
+
if (record[canonical] !== undefined)
|
|
75
|
+
return record[canonical];
|
|
76
|
+
for (const alias of ALIASES_BY_CANONICAL[canonical] ?? []) {
|
|
77
|
+
if (record[alias] !== undefined)
|
|
78
|
+
return record[alias];
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Chinese display name per group, one entry per line (the scripts read this block
|
|
84
|
+
* by text, the same way they read PARAM_NAMESPACES). The raw group id is what
|
|
85
|
+
* `--group` accepts and what the JSON face reports; this only names it on screen.
|
|
86
|
+
*/
|
|
87
|
+
export const PARAM_GROUP_LABELS = Object.freeze({
|
|
88
|
+
library: '技能库',
|
|
89
|
+
'write-caps': '写入上限',
|
|
90
|
+
review: '会话回顾',
|
|
91
|
+
memory: '记忆',
|
|
92
|
+
curator: '技能整理',
|
|
93
|
+
deployment: '安装配置',
|
|
94
|
+
internal: '内部',
|
|
95
|
+
});
|
|
96
|
+
/**
|
|
97
|
+
* The parameter registry. G1/S1.1 seeds it with the review group (G-C); the
|
|
98
|
+
* remaining groups land in S2.1. E3 = behaviour preference the user may change
|
|
99
|
+
* (live); E2 = resource or identity knob that stays with the deployment.
|
|
100
|
+
*/
|
|
101
|
+
export const PARAM_EXPOSURE = Object.freeze([
|
|
102
|
+
{ id: 'reviewSkillInterval', group: 'review', tier: 'E3', authority: 'cordis', owner: 'evolution-review', applies: 'live', docAnchor: 'PARAMETERS.md#review', summary: 'Tool calls between skill-review injections: a turn advances by its tool-call count (a turn with none counts as one), or by 1 when the turn itself used a skill.', label: '技能检查间隔', hint: '每累计多少次工具调用检查一次技能:一轮按该轮工具调用数累加(一轮没有工具调用也算 1 次),本轮本身用到技能则只算 1 次。', control: 'number', unit: '次', values: '', card: 'evolution-review' },
|
|
103
|
+
{ id: 'reviewMemoryInterval', group: 'review', tier: 'E3', authority: 'cordis', owner: 'evolution-review', applies: 'live', docAnchor: 'PARAMETERS.md#review', summary: 'Tool calls between memory-review injections: a turn advances by its tool-call count (a turn with none counts as one), or by 1 when the turn itself touched memory.', label: '记忆检查间隔', hint: '每累计多少次工具调用检查一次记忆:一轮按该轮工具调用数累加(一轮没有工具调用也算 1 次),本轮本身用到记忆则只算 1 次。', control: 'number', unit: '次', values: '', card: 'evolution-review' },
|
|
104
|
+
{ id: 'skillReviewTrigger', group: 'review', tier: 'E3', authority: 'cordis', owner: 'evolution-review', applies: 'live', docAnchor: 'PARAMETERS.md#review', summary: 'Which channel may inject a skill review (cadence, completion, both).', label: '技能检查时机', hint: '什么时候检查技能:按间隔/按任务完成/两者。', control: 'select', unit: '', values: 'cadence|completion|both', valueLabels: '按间隔|按任务完成|两者', card: 'evolution-review' },
|
|
105
|
+
{ id: 'skillReviewCompletionMinToolCalls', group: 'review', tier: 'E3', authority: 'cordis', owner: 'evolution-review', applies: 'live', docAnchor: 'PARAMETERS.md#review', summary: 'Tool calls a task needs before the completion channel injects.', label: '完成时的最少工具调用', hint: '选「按任务完成」时,任务至少用了几次工具才检查。', control: 'number', unit: '次', values: '', card: 'evolution-review' },
|
|
106
|
+
{ id: 'reviewEnabled', group: 'review', tier: 'E3', authority: 'cordis', owner: 'evolution-review', applies: 'live', docAnchor: 'PARAMETERS.md#review', summary: 'Master switch for the review plugin.', label: '启用自动检查', hint: '关闭后不再自动回顾会话。', control: 'switch', unit: '', values: '', card: 'evolution-review' },
|
|
107
|
+
{ id: 'reviewMode', group: 'review', tier: 'E3', authority: 'cordis', owner: 'evolution-review', applies: 'live', docAnchor: 'PARAMETERS.md#review', summary: 'Run the review in the parent session (inject) or on a subagent.', label: '运行位置', hint: '在哪里运行检查:在当前会话里/交给子代理。', control: 'select', unit: '', values: 'subagent|inject', valueLabels: '交给子代理|在当前会话里', card: 'evolution-review' },
|
|
108
|
+
{ id: 'reviewWakeInject', group: 'review', tier: 'E3', authority: 'cordis', owner: 'evolution-review', applies: 'live', docAnchor: 'PARAMETERS.md#review', summary: 'Deliver the deferred review as a waking follow-up message.', label: '延后结果发提醒', hint: '会话空闲时,把延后的检查结果作为一条提醒发给你。', control: 'switch', unit: '', values: '', card: 'evolution-review' },
|
|
109
|
+
{ id: 'reviewProvider', group: 'review', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#review', summary: 'LLM provider for review subagents (deployment identity).', why: 'identity' },
|
|
110
|
+
{ id: 'reviewTimeoutMs', group: 'review', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#review', summary: 'Bound on one review subagent run and its write leg.', why: 'internal' },
|
|
111
|
+
{ id: 'reviewContextMessages', group: 'review', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#review', summary: 'Messages of context handed to a review subagent.', why: 'internal' },
|
|
112
|
+
{ id: 'reviewMessageChars', group: 'review', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#review', summary: 'Per-message character budget of the review context.', why: 'internal' },
|
|
113
|
+
{ id: 'reviewMaxDepth', group: 'review', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#review', summary: 'Absolute delegation-depth cap of the review subagent.', why: 'internal' },
|
|
114
|
+
{ id: 'reviewToolAllow', group: 'review', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#review', summary: 'Tools the review subagent may use (safety surface).', why: 'security' },
|
|
115
|
+
{ id: 'skillContentChars', group: 'write-caps', tier: 'E3', authority: 'cordis', owner: 'tool-skill-manage', applies: 'live', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Character cap on a SKILL.md body (tighten-only).', label: '技能文件正文上限', hint: '技能 Markdown 正文最多多少字符(只能调小)。', control: 'number', unit: '字符', values: '', card: 'tool-skill-manage' },
|
|
116
|
+
{ id: 'maxSkillFileBytes', group: 'write-caps', tier: 'E3', authority: 'cordis', owner: 'tool-skill-manage', applies: 'live', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Byte cap on one support file (tighten-only).', label: '附带文件大小上限', hint: '技能附带文件单个最大多少字节(只能调小)。', control: 'number', unit: '字节', values: '', card: 'tool-skill-manage' },
|
|
117
|
+
{ id: 'maxSkillNameLength', group: 'write-caps', tier: 'E3', authority: 'cordis', owner: 'tool-skill-manage', applies: 'live', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Character cap on a skill name (tighten-only).', label: '技能名长度上限', hint: '技能名最多多少字符(只能调小)。', control: 'number', unit: '字符', values: '', card: 'tool-skill-manage' },
|
|
118
|
+
{ id: 'maxDescriptionLength', group: 'write-caps', tier: 'E3', authority: 'cordis', owner: 'tool-skill-manage', applies: 'live', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Character cap on a skill description (tighten-only).', label: '技能描述长度上限', hint: '技能描述最多多少字符(只能调小)。', control: 'number', unit: '字符', values: '', card: 'tool-skill-manage' },
|
|
119
|
+
{ id: 'descriptionStrict', group: 'write-caps', tier: 'E3', authority: 'cordis', owner: 'tool-skill-manage', applies: 'live', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Refuse a description over the authoring bar instead of advising.', label: '描述不合规即拒绝', hint: '描述不符合要求时直接拒绝写入(默认只提醒)。', control: 'switch', unit: '', values: '', card: 'tool-skill-manage' },
|
|
120
|
+
{ id: 'strictCrossSource', group: 'write-caps', tier: 'E3', authority: 'cordis', owner: 'tool-skill-manage', applies: 'live', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Refuse writes whose catalog entry resolves outside the family.', label: '引用外部内容即拒绝', hint: '技能引用了本插件之外的文件时拒绝写入。', control: 'switch', unit: '', values: '', card: 'tool-skill-manage' },
|
|
121
|
+
{ id: 'citationPolicy', group: 'write-caps', tier: 'E3', authority: 'cordis', owner: 'tool-skill-manage', applies: 'live', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Refuse a move that would leave a dangling reference, or verify it.', label: '引用检查方式', hint: '移动或合并技能时怎么处理引用:先检查/直接拒绝。', control: 'select', unit: '', values: 'verify|refuse', valueLabels: '先检查|直接拒绝', card: 'tool-skill-manage' },
|
|
122
|
+
{ id: 'referenceRewrite', group: 'write-caps', tier: 'E2', authority: 'cordis', owner: 'tool-skill-manage', applies: 'none', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Re-home support files and rewrite references during a merge (plan or apply).', why: 'internal' },
|
|
123
|
+
{ id: 'archiveRetention', group: 'write-caps', tier: 'E2', authority: 'cordis', owner: 'tool-skill-manage', applies: 'none', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Report expired archives, or prune them.', why: 'internal' },
|
|
124
|
+
{ id: 'skillVersionKeep', group: 'write-caps', tier: 'E2', authority: 'cordis', owner: 'tool-skill-manage', applies: 'none', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Content versions retained per skill; older ones leave the index. Their stored blobs stay on disk — no automatic sweep exists yet, so a long-lived library grows by the distinct bodies it has written.', why: 'internal' },
|
|
125
|
+
{ id: 'supportFileCharPolicy', group: 'write-caps', tier: 'E3', authority: 'cordis', owner: 'tool-skill-manage', applies: 'live', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Warn about an oversize support file, or refuse the write.', label: '附带文件超限时', hint: '附带文件超出上限时:只提醒/拒绝写入。', control: 'select', unit: '', values: 'report|enforce', valueLabels: '只提醒|拒绝写入', card: 'tool-skill-manage' },
|
|
126
|
+
{ id: 'skillWriteConfirm', group: 'write-caps', tier: 'E3', authority: 'cordis', owner: 'tool-skill-manage', applies: 'live', docAnchor: 'PARAMETERS.md#write-caps', summary: 'What the one confirmation before a create or a bare delete does: write straight through, wait for an answer, or cancel the write when nobody answers within the timeout.', label: '写入前是否确认', hint: '新建或删除技能前要不要问你:直接写入/一直等你回答/超时未答就取消这次写入。', control: 'select', unit: '', values: 'auto|ask|timeout', valueLabels: '不弹窗直接写入|一直等待回答|超时自动取消', card: 'tool-skill-manage' },
|
|
127
|
+
{ id: 'skillWriteConfirmTimeoutSeconds', group: 'write-caps', tier: 'E3', authority: 'cordis', owner: 'tool-skill-manage', applies: 'live', docAnchor: 'PARAMETERS.md#write-caps', summary: 'Seconds the confirmation waits for an answer in timeout mode before the write is cancelled.', label: '确认等待秒数', hint: '选「超时自动取消」时,等多少秒没人回答就取消这次写入。', control: 'number', unit: '秒', values: '', card: 'tool-skill-manage' },
|
|
128
|
+
{ id: 'memoryChars', group: 'memory', tier: 'E3', authority: 'cordis', owner: 'memory-files', applies: 'live', docAnchor: 'PARAMETERS.md#memory', summary: 'Character budget the memory store enforces for MEMORY.md.', label: '记忆库上限', hint: '长期记忆文件(MEMORY.md)最多多少字符。', control: 'number', unit: '字符', values: '', card: 'memory-files' },
|
|
129
|
+
{ id: 'userChars', group: 'memory', tier: 'E3', authority: 'cordis', owner: 'memory-files', applies: 'live', docAnchor: 'PARAMETERS.md#memory', summary: 'Character budget the memory store enforces for USER.md.', label: '用户画像上限', hint: '用户画像文件(USER.md)最多多少字符。', control: 'number', unit: '字符', values: '', card: 'memory-files' },
|
|
130
|
+
{ id: 'memoryEnabled', group: 'memory', tier: 'E2', authority: 'cordis', owner: 'tool-memory', applies: 'none', docAnchor: 'PARAMETERS.md#memory', summary: 'Register the memory tool and its prompt section at all (deployment switch).', why: 'deployment' },
|
|
131
|
+
{ id: 'entryPreviewChars', group: 'memory', tier: 'E3', authority: 'cordis', owner: 'tool-memory', applies: 'live', docAnchor: 'PARAMETERS.md#memory', summary: 'Characters of one memory entry shown in a tool result preview.', label: '记忆预览长度', hint: '列表里每条记忆最多显示多少字符。', control: 'number', unit: '字符', values: '', card: 'tool-memory' },
|
|
132
|
+
{ id: 'addDatePrefix', group: 'memory', tier: 'E3', authority: 'cordis', owner: 'memory-files', applies: 'live', docAnchor: 'PARAMETERS.md#memory', summary: 'Prefix stored memory entries with their date heading.', label: '记忆条目加日期', hint: '写入时在条目开头加上日期。', control: 'switch', unit: '', values: '', card: 'memory-files' },
|
|
133
|
+
{ id: 'maxConsolidationFailures', group: 'memory', tier: 'E3', authority: 'cordis', owner: 'memory-files', applies: 'live', docAnchor: 'PARAMETERS.md#memory', summary: 'Consolidation failures one turn tolerates before the tool gives up.', label: '合并失败重试', hint: '合并记忆连续失败多少次后停止。', control: 'number', unit: '次', values: '', card: 'memory-files' },
|
|
134
|
+
{ id: 'curatorIntervalHours', group: 'curator', tier: 'E3', authority: 'cordis', owner: 'evolution-curator', applies: 'live', docAnchor: 'PARAMETERS.md#curator', summary: 'Minimum hours between deterministic curation passes.', label: '自动整理间隔', hint: '两次自动整理之间至少间隔多少小时。', control: 'number', unit: '小时', values: '', card: 'evolution-curator' },
|
|
135
|
+
{ id: 'staleAfterDays', group: 'curator', tier: 'E3', authority: 'cordis', owner: 'evolution-curator', applies: 'live', docAnchor: 'PARAMETERS.md#curator', summary: 'Inactive days before a skill counts as stale.', label: '多久没用算过时', hint: '技能连续多少天没被用到就算过时。', control: 'number', unit: '天', values: '', card: 'evolution-curator' },
|
|
136
|
+
{ id: 'archiveAfterDays', group: 'curator', tier: 'E3', authority: 'cordis', owner: 'evolution-curator', applies: 'live', docAnchor: 'PARAMETERS.md#curator', summary: 'Inactive days before a stale skill is archived (must be >= staleAfterDays).', label: '过时后归档', hint: '过时技能再过多少天移入归档(不能小于上一项)。', control: 'number', unit: '天', values: '', relation: { atLeast: 'staleAfterDays' }, card: 'evolution-curator' },
|
|
137
|
+
{ id: 'qualityWarnStaleAfterDays', group: 'curator', tier: 'E2', authority: 'cordis', owner: 'evolution-curator', applies: 'none', docAnchor: 'PARAMETERS.md#curator', summary: 'Age at which a low quality score starts warning (the pair of evolution-feedback.qualityWarnThreshold; both live on the deployment face so one bar is not half user-set).', why: 'internal' },
|
|
138
|
+
{ id: 'minIdleHours', group: 'curator', tier: 'E3', authority: 'cordis', owner: 'evolution-curator', applies: 'live', docAnchor: 'PARAMETERS.md#curator', summary: 'Idle hours required before an automatic curation pass runs.', label: '最少空闲时长', hint: '你至少多少小时没用,才运行自动整理。', control: 'number', unit: '小时', values: '', card: 'evolution-curator' },
|
|
139
|
+
{ id: 'minIdleFailOpen', group: 'curator', tier: 'E3', authority: 'cordis', owner: 'evolution-curator', applies: 'live', docAnchor: 'PARAMETERS.md#curator', summary: 'Let the idle gate open when the activity probe is unavailable.', label: '检测不到活动也运行', hint: '无法判断你是否空闲时,仍然运行自动整理。', control: 'switch', unit: '', values: '', card: 'evolution-curator' },
|
|
140
|
+
{ id: 'llmReview', group: 'curator', tier: 'E3', authority: 'cordis', owner: 'evolution-curator', applies: 'live', docAnchor: 'PARAMETERS.md#curator', summary: 'Enable the LLM nomination pass on top of the deterministic lifecycle.', label: '用模型挑选', hint: '在固定规则之外,再用模型挑一遍候选项。', control: 'switch', unit: '', values: '', card: 'evolution-curator' },
|
|
141
|
+
{ id: 'curatorReviewMaxTokens', group: 'curator', tier: 'E3', authority: 'cordis', owner: 'evolution-curator', applies: 'live', docAnchor: 'PARAMETERS.md#curator', summary: 'Token budget of the curator LLM review.', label: '模型处理上限', hint: '每次用模型挑选时最多消耗多少 token。', control: 'number', unit: 'token', values: '', card: 'evolution-curator' },
|
|
142
|
+
{ id: 'curatorReviewTimeoutMs', group: 'curator', tier: 'E3', authority: 'cordis', owner: 'evolution-curator', applies: 'live', docAnchor: 'PARAMETERS.md#curator', summary: 'Wall-clock bound of the curator LLM review.', label: '模型处理超时', hint: '一次模型挑选最长允许运行多久。', control: 'number', unit: '毫秒', values: '', card: 'evolution-curator' },
|
|
143
|
+
{ id: 'healthSoftBodyChars', group: 'curator', tier: 'E3', authority: 'cordis', owner: 'evolution-curator', applies: 'live', docAnchor: 'PARAMETERS.md#curator', summary: 'Body character line the health view judges against.', label: '正文长度参考值', hint: '技能正文超过多少字符算偏长(只用于健康提示)。', control: 'number', unit: '字符', values: '', card: 'evolution-curator' },
|
|
144
|
+
{ id: 'healthStampDensityPerKb', group: 'curator', tier: 'E3', authority: 'cordis', owner: 'evolution-curator', applies: 'live', docAnchor: 'PARAMETERS.md#curator', summary: 'Stamp density per KB that flags log-like content in a body.', label: '日志化判定阈值', hint: '每 KB 出现多少个时间标记,就判为「像日志」。', control: 'number', unit: '处/KB', values: '', card: 'evolution-curator' },
|
|
145
|
+
{ id: 'healthChurnMinPatches', group: 'curator', tier: 'E3', authority: 'cordis', owner: 'evolution-curator', applies: 'live', docAnchor: 'PARAMETERS.md#curator', summary: 'Patches without a read that flag a write-ghost skill.', label: '只写不读判定次数', hint: '连续多少次改动都没有被读取,就判为「只写不读」。', control: 'number', unit: '处', values: '', card: 'evolution-curator' },
|
|
146
|
+
{ id: 'evolution-curator.enabled', group: 'curator', tier: 'E2', authority: 'cordis', owner: 'evolution-curator', applies: 'none', docAnchor: 'PARAMETERS.md#curator', summary: 'Mount the curator plugin at all.', why: 'deployment' },
|
|
147
|
+
{ id: 'autoStart', group: 'curator', tier: 'E2', authority: 'cordis', owner: 'evolution-curator', applies: 'none', docAnchor: 'PARAMETERS.md#curator', summary: 'Arm the hourly due-ness tick with the plugin — the STARTUP default only; at runtime /evolution curator pause or resume overrides it (the override is persisted in curation state and wins until cleared). Off keeps curation manual.', why: 'deployment' },
|
|
148
|
+
{ id: 'bootGraceSeconds', group: 'curator', tier: 'E2', authority: 'cordis', owner: 'evolution-curator', applies: 'none', docAnchor: 'PARAMETERS.md#curator', summary: 'Grace period before the first automatic pass after a restart.', why: 'internal' },
|
|
149
|
+
{ id: 'curatorProvider', group: 'curator', tier: 'E2', authority: 'cordis', owner: 'evolution-curator', applies: 'none', docAnchor: 'PARAMETERS.md#curator', summary: 'LLM provider for curator reviews (deployment identity).', why: 'identity' },
|
|
150
|
+
{ id: 'curatorModel', group: 'curator', tier: 'E2', authority: 'cordis', owner: 'evolution-curator', applies: 'none', docAnchor: 'PARAMETERS.md#curator', summary: 'Model for curator reviews (deployment identity).', why: 'identity' },
|
|
151
|
+
{ id: 'protectedSkillNames', group: 'library', tier: 'E2', authority: 'cordis', owner: 'evolution-curator', applies: 'none', docAnchor: 'PARAMETERS.md#library', summary: 'Skills the lifecycle never archives or rewrites.', why: 'deployment' },
|
|
152
|
+
{ id: 'manageUnmanaged', group: 'library', tier: 'E2', authority: 'cordis', owner: 'evolution-curator', applies: 'none', docAnchor: 'PARAMETERS.md#library', summary: 'Let curation touch skills with no family metadata.', why: 'deployment' },
|
|
153
|
+
{ id: 'pruneBuiltins', group: 'library', tier: 'E2', authority: 'cordis', owner: 'evolution-curator', applies: 'none', docAnchor: 'PARAMETERS.md#library', summary: 'Let curation nominate bundled skills for pruning.', why: 'deployment' },
|
|
154
|
+
{ id: 'referencedSkillNames', group: 'library', tier: 'E2', authority: 'cordis', owner: 'evolution-curator', applies: 'none', docAnchor: 'PARAMETERS.md#library', summary: 'Names treated as referenced by external docs (never retired).', why: 'deployment' },
|
|
155
|
+
{ id: 'includeSkillNames', group: 'library', tier: 'E2', authority: 'cordis', owner: 'evolution-skill-catalog', applies: 'none', docAnchor: 'PARAMETERS.md#library', summary: 'Allow-list of skills the catalog exposes.', why: 'deployment' },
|
|
156
|
+
{ id: 'skill-catalog.excludeSkillNames', group: 'library', tier: 'E2', authority: 'cordis', owner: 'evolution-skill-catalog', applies: 'none', docAnchor: 'PARAMETERS.md#library', summary: 'Deny-list of skills the catalog hides (row-local name; see the collision note).', why: 'deployment' },
|
|
157
|
+
{ id: 'modelInvocable', group: 'library', tier: 'E2', authority: 'cordis', owner: 'evolution-skill-catalog', applies: 'none', docAnchor: 'PARAMETERS.md#library', summary: 'Default for whether the model may invoke a catalog skill.', why: 'deployment' },
|
|
158
|
+
{ id: 'userInvocable', group: 'library', tier: 'E2', authority: 'cordis', owner: 'evolution-skill-catalog', applies: 'none', docAnchor: 'PARAMETERS.md#library', summary: 'Default for whether the user may invoke a catalog skill.', why: 'deployment' },
|
|
159
|
+
{ id: 'maxItems', group: 'library', tier: 'E2', authority: 'cordis', owner: 'evolution-activity', applies: 'none', docAnchor: 'PARAMETERS.md#library', summary: 'Entries kept in the activity sidecar window.', why: 'internal' },
|
|
160
|
+
{ id: 'sessionScoped', group: 'library', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#library', summary: 'Act only on sessions carrying the family model tools.', why: 'deployment' },
|
|
161
|
+
{ id: 'skill-usage.sessionScoped', group: 'library', tier: 'E2', authority: 'cordis', owner: 'skill-usage', applies: 'none', docAnchor: 'PARAMETERS.md#library', summary: 'Keep the usage sidecar scoped per session (row-local name).', why: 'deployment' },
|
|
162
|
+
{ id: 'evolution-review.root', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Skill-tree root for review-created skills (empty = shared default).', why: 'path' },
|
|
163
|
+
{ id: 'evolution-review.skillsRoot', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Retired alias of root; a value here fails the load (V27 G2.4).', why: 'path' },
|
|
164
|
+
{ id: 'evolution-curator.root', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-curator', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Skill-tree root for curator scope, snapshot and archive.', why: 'path' },
|
|
165
|
+
{ id: 'evolution-commands.root', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-commands', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Skill-tree root the command surface writes through.', why: 'path' },
|
|
166
|
+
{ id: 'evolution-commands.skillsRoot', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-commands', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Retired alias of the commands root; a value here fails the load.', why: 'path' },
|
|
167
|
+
{ id: 'evolution-maintenance.root', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-maintenance', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Skill-tree root the maintenance probe scans.', why: 'path' },
|
|
168
|
+
{ id: 'evolution-maintenance.skillsRoot', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-maintenance', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Accepted skill-root spelling for the maintenance row.', why: 'path' },
|
|
169
|
+
{ id: 'evolution-skill-catalog.root', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-skill-catalog', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Skill-tree root the catalog lists.', why: 'path' },
|
|
170
|
+
{ id: 'evolution-learning-graph.root', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-learning-graph', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Skill-tree root the learning graph reads.', why: 'path' },
|
|
171
|
+
{ id: 'skill-usage.root', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'skill-usage', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Skill-tree root the usage store observes.', why: 'path' },
|
|
172
|
+
{ id: 'skill-usage.eventsHome', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'skill-usage', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Directory holding the family event log the usage store reads.', why: 'path' },
|
|
173
|
+
{ id: 'evolution-state-json.root', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-state-json', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Directory holding the JSON state store.', why: 'path' },
|
|
174
|
+
{ id: 'memory-files.root', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'memory-files', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Directory holding MEMORY.md and USER.md (empty = $DSH_HOME/memories).', why: 'path' },
|
|
175
|
+
{ id: 'evolution-feedback.path', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-feedback', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Event log the feedback scorer reads (empty = family events file).', why: 'path' },
|
|
176
|
+
{ 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' },
|
|
177
|
+
{ id: 'memory.provider', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'memory', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Registered memory provider name.', why: 'identity' },
|
|
178
|
+
{ 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' },
|
|
179
|
+
{ id: 'memoryReviewModel', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Model for the memory review channel (deployment identity).', why: 'identity' },
|
|
180
|
+
{ id: 'skillReviewModel', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-review', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Model for the skill review channel (deployment identity).', 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
|
+
{ 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
|
+
{ 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
|
+
{ 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' },
|
|
185
|
+
{ id: 'threatExemptLabels', group: 'deployment', tier: 'E1', authority: 'cordis', owner: 'evolution-threat', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Threat labels the deployment declares benign (safety surface, never user-writable).', why: 'security' },
|
|
186
|
+
{ id: 'evolution-threat.enabled', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-threat', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Mount the write-time threat guard at all.', why: 'security' },
|
|
187
|
+
{ id: 'evolution-threat.maxScanChars', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-threat', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Scan window size of the threat guard.', why: 'security' },
|
|
188
|
+
{ id: 'evolution-approval.enabled', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-approval', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Require approval before a staged write executes.', why: 'security' },
|
|
189
|
+
{ id: 'evolution-approval.stageForeground', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-approval', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Stage foreground agent writes for approval too.', why: 'security' },
|
|
190
|
+
{ id: 'evolution-approval.pendingTtlMs', group: 'deployment', tier: 'E3', authority: 'cordis', owner: 'evolution-approval', applies: 'live', docAnchor: 'PARAMETERS.md#deployment', summary: 'How long a staged write may wait before it expires: expired writes are closed as rejected and are NEVER executed; 0 (the default) means the window never expires.', label: '待批过期时间', hint: '一条待批写入最多等多久:超时就按「拒绝」关掉(不会执行,写效果不会落地);0 = 永不过期(默认)。', control: 'number', unit: '毫秒', values: '', card: 'evolution-approval' },
|
|
191
|
+
{ id: 'approvalConfirm', group: 'write-caps', tier: 'E3', authority: 'cordis', owner: 'evolution-approval', applies: 'live', docAnchor: 'PARAMETERS.md#write-caps', summary: 'What the confirmation before an APPROVE does: write straight through, ask first, or treat an unanswered prompt as a cancel. The same three words skillWriteConfirm uses for a skill write.', label: '批准前先确认', hint: '点「批准」时要不要再确认一次:直接执行 / 先确认 / 等待超时即取消。默认直接执行(不打断批量批准)。', control: 'select', unit: '', values: 'auto|ask|timeout', valueLabels: '直接执行|先确认|等待超时即取消', card: 'evolution-approval' },
|
|
192
|
+
{ id: 'qualityWarnThreshold', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-feedback', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Feedback score below which a skill carries a warning.', why: 'internal' },
|
|
193
|
+
{ id: 'replay.maxPlans', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-replay', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Plans compared in one replay report.', why: 'internal' },
|
|
194
|
+
{ id: 'replay.weights', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-replay', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Scoring weights of the replay comparison.', why: 'internal' },
|
|
195
|
+
{ id: 'evolution-commands.maintainCooldownMs', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-commands', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Cooldown between maintenance runs from the command surface.', why: 'internal' },
|
|
196
|
+
{ id: 'evolution-commands.maintainHandoffOnSettle', group: 'deployment', tier: 'E3', authority: 'cordis', owner: 'evolution-commands', applies: 'live', docAnchor: 'PARAMETERS.md#deployment', summary: 'Hand the maintenance report to the model automatically once a scan settles successfully (the same injection as maintain handoff); off by default — enabling it costs one extra model call per successful run.', label: '扫描完成后自动交接', hint: '维护扫描成功结束后,自动把报告交给模型(等同 maintain handoff);默认关闭,每次成功扫描会多花一次模型调用。', control: 'switch', unit: '', values: '', card: 'evolution-commands' },
|
|
197
|
+
{ id: 'evolution-commands.maintainTimeoutMs', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-commands', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Timeout of one maintenance run started from the command surface.', why: 'internal' },
|
|
198
|
+
{ id: 'evolution-maintenance.probeTimeoutMs', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'evolution-maintenance', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Model-facing budget of one maintenance_probe call — a hang guard, not a latency budget.', why: 'internal' },
|
|
199
|
+
{ id: 'skill-usage.supportReadToolNames', group: 'deployment', tier: 'E2', authority: 'cordis', owner: 'skill-usage', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Tool names whose file reads are attributed to support files.', why: 'internal' },
|
|
200
|
+
{ id: 'install.mode', group: 'deployment', tier: 'E4', authority: 'install', owner: 'scripts', applies: 'restart', docAnchor: 'PARAMETERS.md#deployment', summary: 'Install target plane (values host / agent / layered / oneclick; the `layered` form uses the generated preset, the others mount the bundle at profile root).', why: 'install' },
|
|
201
|
+
{ id: 'install.basePreset', group: 'deployment', tier: 'E4', authority: 'install', owner: 'scripts', applies: 'restart', docAnchor: 'PARAMETERS.md#deployment', summary: 'Agent-preset base the layered install composes from (--base).', why: 'install' },
|
|
202
|
+
{ id: 'install.home', group: 'deployment', tier: 'E4', authority: 'install', owner: 'scripts', applies: 'restart', docAnchor: 'PARAMETERS.md#deployment', summary: 'Harness home the installer writes into (--home).', why: 'install' },
|
|
203
|
+
{ id: 'install.presetRowOverrides', group: 'deployment', tier: 'E4', authority: 'install', owner: 'scripts', applies: 'restart', docAnchor: 'PARAMETERS.md#deployment', summary: 'Preset row overrides the installer injects (row-overrides.json).', why: 'install' },
|
|
204
|
+
{ id: 'timeout.gateDefault', group: 'deployment', tier: 'E2', authority: 'install', owner: 'scripts', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Gate budget: the vitest --testTimeout the gate table and the CI step carry (the number lives in testing-policy.timeouts).', why: 'internal' },
|
|
205
|
+
{ id: 'timeout.specDefault', group: 'deployment', tier: 'E2', authority: 'install', owner: 'scripts', applies: 'none', docAnchor: 'PARAMETERS.md#deployment', summary: 'Local spec budget: the vitest testTimeout the family config generates per leaf tier (the number lives in testing-policy.timeouts).', why: 'internal' },
|
|
206
|
+
]);
|
|
207
|
+
/** The settings namespace each OWNER PACKAGE registers (design §7.2).
|
|
208
|
+
*
|
|
209
|
+
* Keyed by owner rather than by group because a namespace has exactly one
|
|
210
|
+
* registrant (the platform refuses a second registration of the same name),
|
|
211
|
+
* while a group may span packages — group 'memory' is served by memory-files and
|
|
212
|
+
* tool-memory, each owning its own section. A package without an entry has no
|
|
213
|
+
* user layer (its knobs stay deployment-only). */
|
|
214
|
+
export const PARAM_NAMESPACES = Object.freeze({
|
|
215
|
+
'evolution-review': 'evolution-review',
|
|
216
|
+
'memory-files': 'evolution-memory',
|
|
217
|
+
'tool-memory': 'evolution-tool-memory',
|
|
218
|
+
'evolution-curator': 'evolution-curator',
|
|
219
|
+
'tool-skill-manage': 'evolution-skills',
|
|
220
|
+
// 0.21.0 (G1): the approval row's `pendingTtlMs` is E3, so its owner must publish a user layer —
|
|
221
|
+
// without this entry the row's card could not exist and `/evolution policy set` answered E-315.
|
|
222
|
+
'evolution-approval': 'evolution-approval',
|
|
223
|
+
// 0.21.0 (G3): the commands row's handoff switch is E3 — same reason as the entry above: the card
|
|
224
|
+
// and `/evolution params set` both resolve their settings namespace through this map.
|
|
225
|
+
'evolution-commands': 'evolution-commands',
|
|
226
|
+
});
|
|
227
|
+
/**
|
|
228
|
+
* The rows whose settings namespace CHANGED with the platform-line move (G3): the
|
|
229
|
+
* platform keys a settings section by the Loader entry id now, while 0.1.x let each
|
|
230
|
+
* plugin register a free-form namespace — this table is the difference, DERIVED from
|
|
231
|
+
* {@link PARAM_NAMESPACES} so freezing a row id renames it in one place.
|
|
232
|
+
*
|
|
233
|
+
* It is the migration's TARGET (`rowId`) and its SOURCE (`namespace`, the section a
|
|
234
|
+
* stored value sits in). Rows whose two names already agree are absent: there is
|
|
235
|
+
* nothing to move for them.
|
|
236
|
+
*/
|
|
237
|
+
export const NAMESPACE_MIGRATIONS = Object.freeze(Object.entries(PARAM_NAMESPACES)
|
|
238
|
+
.filter(([owner, namespace]) => namespace !== owner)
|
|
239
|
+
.map(([owner, namespace]) => Object.freeze({ namespace, rowId: owner })));
|
|
240
|
+
/**
|
|
241
|
+
* The LEGACY settings namespace one owner package used to register through the family's
|
|
242
|
+
* own seam (0.1.x). It is no longer what the platform calls the section: the platform
|
|
243
|
+
* derives a settings namespace from the Loader entry id, and this registry's `owner` field
|
|
244
|
+
* IS that row id, so a live lookup uses {@link paramRowId}. What remains here is the
|
|
245
|
+
* migration SOURCE (G3 moves a user layer out of this string and into the row id).
|
|
246
|
+
* @param owner - owner package directory name (the map's key).
|
|
247
|
+
* @returns the legacy namespace that owner registered.
|
|
248
|
+
* @throws when the owner has no entry in {@link PARAM_NAMESPACES}.
|
|
249
|
+
*/
|
|
250
|
+
export function paramNamespace(owner) {
|
|
251
|
+
const namespace = PARAM_NAMESPACES[owner];
|
|
252
|
+
if (namespace === undefined)
|
|
253
|
+
throw new Error('no settings namespace registered for owner `' + owner + '` (add it to PARAM_NAMESPACES)');
|
|
254
|
+
return namespace;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* The settings id one row's user layer lives under, or undefined when the owner publishes
|
|
258
|
+
* no user layer at all (a deployment-only row: its knobs are E2 and never reach a settings
|
|
259
|
+
* section). The platform derives a settings namespace from the Loader entry id and reports
|
|
260
|
+
* it in `settings.describe()` / `configForms.get(entryId)`, and an owner package's row id is
|
|
261
|
+
* its own name — spelled the same in every bundle patch.
|
|
262
|
+
*
|
|
263
|
+
* This is the id to LOOK UP with; {@link paramNamespace} keeps the legacy string the 0.1.x
|
|
264
|
+
* seam registered, which is the G3 migration source and never a live lookup key.
|
|
265
|
+
* @param owner - owner package directory name (the row id).
|
|
266
|
+
* @returns the entry id the platform reports for that row, or undefined for a row without
|
|
267
|
+
* a user layer.
|
|
268
|
+
*/
|
|
269
|
+
export function paramSettingsId(owner) {
|
|
270
|
+
return PARAM_NAMESPACES[owner] === undefined ? undefined : owner;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* The settings id of a row that MUST have a user layer (an owner reading its own section).
|
|
274
|
+
* @param owner - owner package directory name (the row id).
|
|
275
|
+
* @returns the entry id the platform reports for that row.
|
|
276
|
+
* @throws when the owner publishes no user layer.
|
|
277
|
+
*/
|
|
278
|
+
/** The keys the USER set in one row's settings namespace (G1 §8.4-A).
|
|
279
|
+
*
|
|
280
|
+
* The settings user layer is read in exactly ONE place, and it reads KEY NAMES, never values: the
|
|
281
|
+
* platform resolves the user layer into the row's live fields, so a value always comes from the
|
|
282
|
+
* row. The precedence rule (user > policy) needs to know WHICH keys the user set, or a deployment
|
|
283
|
+
* policy would silently override the user. S2.9 (T3-10): review and curator each had their own
|
|
284
|
+
* reader, so one key could be resolved two ways.
|
|
285
|
+
* @param ctx - the plugin context (a `get(name)` view is enough).
|
|
286
|
+
* @param rowId - the row's registry namespace (`paramRowId(<package>)`).
|
|
287
|
+
* @returns the keys present in that row's user layer.
|
|
288
|
+
*/
|
|
289
|
+
export function userSetKeys(ctx, rowId) {
|
|
290
|
+
// platform-declaration anchor: the platform’s `settings` service (optional; undefined ⇒ the source column reports “unknown”)
|
|
291
|
+
const settings = ctx.get('settings');
|
|
292
|
+
const entry = settings?.describe?.({ redactSecrets: false }).find(item => item.ns === rowId);
|
|
293
|
+
return new Set(Object.keys(entry?.user ?? {}));
|
|
294
|
+
}
|
|
295
|
+
/** ONE key's effective value, in the design's precedence (G1 §8.4-A): the user layer (whose value
|
|
296
|
+
* already arrived through the row's live field) → the deployment policy snapshot → the row itself.
|
|
297
|
+
* S2.9 (T3-10): both readers of the policy row resolve through this, so a new key cannot get one
|
|
298
|
+
* answer on the review side and another on the curator side.
|
|
299
|
+
* @param userSet - the keys the user set (see {@link userSetKeys}).
|
|
300
|
+
* @param row - the row's live fields.
|
|
301
|
+
* @param snapshot - the deployment policy snapshot, when a policy row is mounted.
|
|
302
|
+
* @param key - the key being resolved.
|
|
303
|
+
* @returns the effective value.
|
|
304
|
+
*/
|
|
305
|
+
export function pickWithPolicy(userSet, row, snapshot, key) {
|
|
306
|
+
if (userSet.has(key))
|
|
307
|
+
return row[key];
|
|
308
|
+
return snapshot?.[key] ?? row[key];
|
|
309
|
+
}
|
|
310
|
+
export function paramRowId(owner) {
|
|
311
|
+
const id = paramSettingsId(owner);
|
|
312
|
+
if (id === undefined)
|
|
313
|
+
throw new Error('no settings namespace registered for owner `' + owner + '` (add it to PARAM_NAMESPACES)');
|
|
314
|
+
return id;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Number-typed read over {@link readParam}: the family's tunables are numbers,
|
|
318
|
+
* and a value of another type reads as absent so the caller's default applies
|
|
319
|
+
* (the same outcome the numeric clamps produce for a malformed value).
|
|
320
|
+
* @param carrier - config/snapshot object to read from, or undefined.
|
|
321
|
+
* @param id - canonical id (a deprecated alias is accepted and resolved first).
|
|
322
|
+
* @returns the resolved number, or undefined when absent or not a number.
|
|
323
|
+
*/
|
|
324
|
+
export function readNumberParam(carrier, id) {
|
|
325
|
+
const value = readParam(carrier, id);
|
|
326
|
+
return typeof value === 'number' ? value : undefined;
|
|
327
|
+
}
|
|
328
|
+
//# sourceMappingURL=params.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The memory op's payload field, resolved in ONE place (T3-06/A34).
|
|
3
|
+
*
|
|
4
|
+
* A memory op carries its body under two names — `facts` (the original) and
|
|
5
|
+
* `content` (the schema alias) — and every reader used to resolve the pair with
|
|
6
|
+
* `op.facts ?? op.content`. `??` only skips null/undefined, so
|
|
7
|
+
* `{ facts: '', content: '正文' }` counted as "has facts": the plan validator
|
|
8
|
+
* refused the op as empty (a FALSE refusal of a payload that is right there),
|
|
9
|
+
* and the writers that normalized the pair dropped the body to `''`.
|
|
10
|
+
*
|
|
11
|
+
* The payload is the first field whose TRIMMED value is non-empty — a blank
|
|
12
|
+
* string carries no payload, so it yields to its alias. Both blank (or absent)
|
|
13
|
+
* ⇒ `''`, the one shape every caller already reads as "no payload".
|
|
14
|
+
*
|
|
15
|
+
* Non-string values are SKIPPED, never trimmed: a truthy non-string `facts`
|
|
16
|
+
* used to reach `.trim()` and throw a TypeError out of callers that promise to
|
|
17
|
+
* be deterministic (the E-60 / P2-1 class). The field-type gates reject such an
|
|
18
|
+
* op on their own; this helper must not be the one that throws.
|
|
19
|
+
*
|
|
20
|
+
* The union posture matches evolution-threat's E-28a scan (BOTH fields are
|
|
21
|
+
* scanned, not only the first truthy one); the two agree on what counts as
|
|
22
|
+
* provided.
|
|
23
|
+
* @module @lmzhen/dsh-evolution-core
|
|
24
|
+
*/
|
|
25
|
+
/** The op's payload text: the first of `facts`/`content` whose trim is non-empty, trimmed; `''` when neither carries one. */
|
|
26
|
+
export function payloadText(op) {
|
|
27
|
+
for (const value of [op?.facts, op?.content]) {
|
|
28
|
+
if (typeof value !== 'string')
|
|
29
|
+
continue;
|
|
30
|
+
const text = value.trim();
|
|
31
|
+
if (text !== '')
|
|
32
|
+
return text;
|
|
33
|
+
}
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=payload.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** The frozen platform line this release targets (peers/engines/anchors derived from version+floor). */
|
|
2
|
+
export declare const PLATFORM_LINE: {
|
|
3
|
+
readonly version: "0.2.1-rc.2";
|
|
4
|
+
readonly floor: "0.2.1-rc.1";
|
|
5
|
+
readonly previousAnchor: "0.2.0-rc.2";
|
|
6
|
+
readonly peersRange: "^0.2.1-rc.1";
|
|
7
|
+
readonly enginesRange: ">=0.2.1-rc.1 <0.2.2-0";
|
|
8
|
+
readonly upstreamRef: "dsh-v0.2.1-rc.2";
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=platform-line.generated.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// GENERATED FILE — do not edit. Source: platform-line.json (repository root) (generator: packages/scripts/gen-platform-line.mjs).
|
|
2
|
+
// Regenerate with: node packages/scripts/gen-platform-line.mjs
|
|
3
|
+
/** The frozen platform line this release targets (peers/engines/anchors derived from version+floor). */
|
|
4
|
+
export const PLATFORM_LINE = {
|
|
5
|
+
version: '0.2.1-rc.2',
|
|
6
|
+
floor: '0.2.1-rc.1',
|
|
7
|
+
previousAnchor: '0.2.0-rc.2',
|
|
8
|
+
peersRange: '^0.2.1-rc.1',
|
|
9
|
+
enginesRange: '>=0.2.1-rc.1 <0.2.2-0',
|
|
10
|
+
upstreamRef: 'dsh-v0.2.1-rc.2',
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=platform-line.generated.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Every platform service the family reaches for with `ctx.get`, and what degrades without it.
|
|
3
3
|
*
|
|
4
|
-
* O-2 (v46 audit): the family probes
|
|
4
|
+
* O-2 (v46 audit): the family probes 25 platform services optionally — the platform has no
|
|
5
5
|
* formalized "optional dependency", so an ABSENT service is a silent downgrade and the diagnostic
|
|
6
6
|
* surface is the only place a reader can learn about it. `/evolution doctor` used to judge six of
|
|
7
7
|
* them; this table is the single source it judges the rest from, and the arch guard cross-checks it
|
|
@@ -20,7 +20,7 @@ export interface PlatformServiceProbe {
|
|
|
20
20
|
/** Where the probe runs. */
|
|
21
21
|
readonly side: 'host' | 'client';
|
|
22
22
|
}
|
|
23
|
-
/** The
|
|
23
|
+
/** The 25 probes, in service-name order (the guard checks this list against the tree). */
|
|
24
24
|
export declare const PLATFORM_SERVICE_PROBES: readonly PlatformServiceProbe[];
|
|
25
25
|
/**
|
|
26
26
|
* The HOST-side probes that do not resolve in this runtime — what `/evolution doctor` prints as
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every platform service the family reaches for with `ctx.get`, and what degrades without it.
|
|
3
|
+
*
|
|
4
|
+
* O-2 (v46 audit): the family probes 25 platform services optionally — the platform has no
|
|
5
|
+
* formalized "optional dependency", so an ABSENT service is a silent downgrade and the diagnostic
|
|
6
|
+
* surface is the only place a reader can learn about it. `/evolution doctor` used to judge six of
|
|
7
|
+
* them; this table is the single source it judges the rest from, and the arch guard cross-checks it
|
|
8
|
+
* against the actual probe sites so a new `ctx.get` cannot stay undeclared.
|
|
9
|
+
*
|
|
10
|
+
* `side` decides who can judge it: `host` probes run in the plugin process (doctor judges those),
|
|
11
|
+
* `client` probes run in the browser half, where the host has no view of the seats.
|
|
12
|
+
* @module @lmzhen/dsh-evolution-core
|
|
13
|
+
*/
|
|
14
|
+
/** The 25 probes, in service-name order (the guard checks this list against the tree). */
|
|
15
|
+
export const PLATFORM_SERVICE_PROBES = Object.freeze([
|
|
16
|
+
{ service: 'agents', feature: 'review and curator subagent wake-ups', side: 'host' },
|
|
17
|
+
{ service: 'approval', feature: 'the platform approval policy the approval row shadows', side: 'host' },
|
|
18
|
+
{ service: 'configEditor', feature: 'the params view inherited-vs-override column', side: 'host' },
|
|
19
|
+
{ service: 'configForms', feature: 'the settings card seat (its section renders read-only without it)', side: 'client' },
|
|
20
|
+
{ service: 'evolutionApproval', feature: 'pending writes: list, approve and reject from the command surface', side: 'host' },
|
|
21
|
+
{ service: 'evolutionCurator', feature: '/evolution curator subcommands, skill undo and history', side: 'host' },
|
|
22
|
+
{ service: 'evolutionIo', feature: 'every durable read and write (the IO seam)', side: 'host' },
|
|
23
|
+
{ service: 'hmr', feature: 'the preset install read-merge-write commit (the platform HMR lock serializes it)', side: 'host' },
|
|
24
|
+
{ service: 'evolutionMemoryBudget', feature: 'the memory-budget divergence section of this report', side: 'host' },
|
|
25
|
+
{ service: 'evolutionPolicy', feature: 'the policy snapshot that shadows row knobs', side: 'host' },
|
|
26
|
+
{ service: 'evolutionReplay', feature: '/evolution replay', side: 'host' },
|
|
27
|
+
{ service: 'evolutionState', feature: 'the state facade behind activity and replay', side: 'host' },
|
|
28
|
+
{ service: 'llm', feature: 'the curator one-shot review model call', side: 'host' },
|
|
29
|
+
{ service: 'memory', feature: 'the cross-session memory store (review and learning-graph reads)', side: 'host' },
|
|
30
|
+
{ service: 'pluginInventory', feature: 'the plugin inventory view', side: 'host' },
|
|
31
|
+
{ service: 'pluginManager', feature: 'the platform plugin and preset surfaces this report reads', side: 'host' },
|
|
32
|
+
{ service: 'profileContext', feature: 'writing the agent-preset row into a profile patch', side: 'host' },
|
|
33
|
+
{ service: 'sessionProjections', feature: 'the domain-owned session units', side: 'host' },
|
|
34
|
+
{ service: 'sessionQuery', feature: 'the session corpus behind /evolution sessions', side: 'host' },
|
|
35
|
+
{ service: 'settings', feature: 'the settings user layer and the params view', side: 'host' },
|
|
36
|
+
{ service: 'skillUsage', feature: 'usage counters feeding the curator and the review planner', side: 'host' },
|
|
37
|
+
{ service: 'skills', feature: 'the platform skill catalog the skill tool writes through', side: 'host' },
|
|
38
|
+
{ service: 'storageDomain', feature: 'the storage-domain state provider', side: 'host' },
|
|
39
|
+
{ service: 'systemPrompt', feature: 'the protected-skills prompt variable', side: 'host' },
|
|
40
|
+
{ service: 'tools', feature: 'tool registration and the guard seam', side: 'host' },
|
|
41
|
+
]);
|
|
42
|
+
/**
|
|
43
|
+
* The HOST-side probes that do not resolve in this runtime — what `/evolution doctor` prints as
|
|
44
|
+
* "capability absence". Empty is the normal, healthy answer: every capability the family can use
|
|
45
|
+
* is mounted, and the section stays away.
|
|
46
|
+
* @param has - a `ctx.get(name) !== undefined` probe of the running context.
|
|
47
|
+
* @returns the absent host-side probes, in declaration order.
|
|
48
|
+
*/
|
|
49
|
+
export function absentHostServices(has) {
|
|
50
|
+
return PLATFORM_SERVICE_PROBES.filter(entry => entry.side === 'host' && !has(entry.service));
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=platform-services.js.map
|