@yangdcm/dsh-expert-team 1.2.2 → 1.2.3
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/CHANGELOG.md +12 -0
- package/README.en.md +4 -0
- package/README.md +4 -0
- package/lib/command.js +36 -1
- package/lib/settings.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
本包遵循[语义化版本](https://semver.org/lang/zh-CN/)。dsh 宿主版本线的对应关系写在
|
|
4
4
|
`package.json` 的 `engines.dsh` 与 `dsh.compatibility` 里,插件市场按它判断"这个插件跟你的宿主兼不兼容"。
|
|
5
5
|
|
|
6
|
+
## 1.2.3
|
|
7
|
+
|
|
8
|
+
**给 lead 工具面收窄加开关**(因为 1.2.2 让一个从未生效的行为突然生效了)
|
|
9
|
+
|
|
10
|
+
- 背景:A 线"把执行类工具从 lead 手上拿走"此前因取错作用域**从未真正生效**,1.2.2 修好后它会
|
|
11
|
+
立刻改变日常形态 —— expert-team 会话的 lead 不再持有 `bash/write/edit/grep/glob`。
|
|
12
|
+
这是设计意图,但**没有开关的行为变更不该只留一个"忍着或回退版本"的选项**。
|
|
13
|
+
- 新增开关 `gates.leadToolFace`(`on`/`off`,默认 `on`):优先级与档位门一致
|
|
14
|
+
**`config.leadToolFace` > `DSH_EXPERT_TEAM_LEAD_TOOLFACE` > 设置(官方面板/浮层) > 默认 on**;
|
|
15
|
+
非法值一律回默认 on(不猜、不报错 —— 与档位门同一条纪律)。
|
|
16
|
+
- 关掉时**出声一次**(`[expert-team] lead 工具面收窄已关闭…`):否则"我明明关了"与
|
|
17
|
+
"开关没生效"看起来一模一样。
|
|
6
18
|
## 1.2.2
|
|
7
19
|
|
|
8
20
|
**修掉"lead 工具面收窄静默失效"**(拿真机启动日志换来的)
|
package/README.en.md
CHANGED
|
@@ -91,6 +91,10 @@ pnpm install && dsh web
|
|
|
91
91
|
> on the official page — its value type cannot be expressed reliably in the host schema, so it stays with
|
|
92
92
|
> the overlay's settings tab and `$DSH_HOME/expert-team/settings.json`. On a host with no settings service
|
|
93
93
|
> every setting falls back to that file.
|
|
94
|
+
>
|
|
95
|
+
> **The A-line switch**: the "narrow the lead's tool face" gate (`gates.leadToolFace`, default `on`)
|
|
96
|
+
> decides whether execution tools (`bash/write/edit/grep/glob`) are taken away from the lead and given
|
|
97
|
+
> to the role subagents. Turn it off with `config.leadToolFace` or `DSH_EXPERT_TEAM_LEAD_TOOLFACE=off`.
|
|
94
98
|
|
|
95
99
|
## Quick start
|
|
96
100
|
|
package/README.md
CHANGED
|
@@ -84,6 +84,10 @@ pnpm install && dsh web
|
|
|
84
84
|
> 并且随插件市场的**备份与恢复**一起走。**诚实边界**:`默认班底`(角色 id 数组)不在官方页面里
|
|
85
85
|
> —— 它的取值类型在宿主 schema 里表达不可靠,继续由浮层设置页签与
|
|
86
86
|
> `$DSH_HOME/expert-team/settings.json` 负责;宿主没有 settings 服务时,全部设置退回该文件。
|
|
87
|
+
>
|
|
88
|
+
> **A 线开关**:设置里的「门禁 → 收窄 lead 工具面」(`gates.leadToolFace`,默认 `on`)决定
|
|
89
|
+
> 是否把执行类工具(`bash/write/edit/grep/glob`)从 lead 手上拿走、交给角色子代理。
|
|
90
|
+
> 也可用 `config.leadToolFace` 或环境变量 `DSH_EXPERT_TEAM_LEAD_TOOLFACE=off` 关闭。
|
|
87
91
|
|
|
88
92
|
## 快速上手
|
|
89
93
|
|
package/lib/command.js
CHANGED
|
@@ -565,6 +565,7 @@ function reapplySettingsDerived() {
|
|
|
565
565
|
resolveLimits(PLUGIN_CONFIG, limitsBaseFromSettings(s));
|
|
566
566
|
resolveRoundLimits(PLUGIN_CONFIG, roundLimitsBaseFromSettings(s));
|
|
567
567
|
resolveTierGate(PLUGIN_CONFIG, s.gates);
|
|
568
|
+
resolveLeadToolFace(PLUGIN_CONFIG, s.gates);
|
|
568
569
|
return true;
|
|
569
570
|
} catch (e) {
|
|
570
571
|
console.warn('[expert-team] 重算设置派生值失败(保持上一次生效值):' + String(e && e.message ? e.message : e));
|
|
@@ -1611,6 +1612,28 @@ const TIER_GATE_VALUES = ['soft', 'hard'];
|
|
|
1611
1612
|
const TIER_GATE_ENV = 'DSH_EXPERT_TEAM_TIER_GATE';
|
|
1612
1613
|
let TIER_GATE = DEFAULT_TIER_GATE;
|
|
1613
1614
|
|
|
1615
|
+
// ── lead 工具面收窄的开关(2026-09-14 加)──────────────────────────────────────
|
|
1616
|
+
// 为什么需要它:A 线的"把执行类工具从 lead 手上拿走"此前因一个 bug **从未真正生效**
|
|
1617
|
+
// (清单取错作用域,见 lib/lead-toolface.js)。修好之后它会立刻改变日常使用形态 ——
|
|
1618
|
+
// lead(含正在跟你对话的那个)不再持有 bash/write/edit/grep/glob,执行全部落到角色子代理。
|
|
1619
|
+
// 这是设计意图,但**没有开关的行为变更不该只留给用户一个"忍着或回退版本"**。
|
|
1620
|
+
// 优先级与档位门完全一致:**config > env > 设置控制台 > 内置默认(on)**。
|
|
1621
|
+
const DEFAULT_LEAD_TOOLFACE = 'on';
|
|
1622
|
+
const LEAD_TOOLFACE_VALUES = ['on', 'off'];
|
|
1623
|
+
const LEAD_TOOLFACE_ENV = 'DSH_EXPERT_TEAM_LEAD_TOOLFACE';
|
|
1624
|
+
let LEAD_TOOLFACE = DEFAULT_LEAD_TOOLFACE;
|
|
1625
|
+
|
|
1626
|
+
/** 解析 lead 工具面收窄开关(非法值一律回默认 on —— 与档位门同理,不猜不报错)。 */
|
|
1627
|
+
function resolveLeadToolFace(config, base) {
|
|
1628
|
+
const cfgRaw = String((config && typeof config === 'object' && config.leadToolFace) || '').trim().toLowerCase();
|
|
1629
|
+
const envRaw = String(((typeof process !== 'undefined' && process.env) || {})[LEAD_TOOLFACE_ENV] || '').trim().toLowerCase();
|
|
1630
|
+
const baseRaw = String((base && typeof base === 'object' ? base.leadToolFace : base) || '').trim().toLowerCase();
|
|
1631
|
+
LEAD_TOOLFACE = LEAD_TOOLFACE_VALUES.includes(cfgRaw) ? cfgRaw
|
|
1632
|
+
: (LEAD_TOOLFACE_VALUES.includes(envRaw) ? envRaw
|
|
1633
|
+
: (LEAD_TOOLFACE_VALUES.includes(baseRaw) ? baseRaw : DEFAULT_LEAD_TOOLFACE));
|
|
1634
|
+
return LEAD_TOOLFACE;
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1614
1637
|
/**
|
|
1615
1638
|
* 解析档位门是软还是硬。**非法值一律回默认(soft)**,不猜也不报错 ——
|
|
1616
1639
|
* 一个拼错的开关值把流程卡死(hard)比静默放行更糟,而"卡死"正是最贵的失败模式。
|
|
@@ -4416,12 +4439,13 @@ const WRITE_TRACER = createWriteTracer();
|
|
|
4416
4439
|
* 去重只影响**重复次数**,不影响"第一次一定喊",也不合并不同 status(两种零仍然分得清)。
|
|
4417
4440
|
*/
|
|
4418
4441
|
const LEAD_TOOLFACE_WARNED = new Set();
|
|
4442
|
+
let LEAD_TOOLFACE_OFF_LOGGED = false;
|
|
4419
4443
|
function warnLeadToolFaceOnce(status, detail) {
|
|
4420
4444
|
if (LEAD_TOOLFACE_WARNED.has(status)) return;
|
|
4421
4445
|
LEAD_TOOLFACE_WARNED.add(status);
|
|
4422
4446
|
console.warn(`[expert-team] lead 工具面**未**收窄(${status}):${detail}`);
|
|
4423
4447
|
}
|
|
4424
|
-
export const _live = { pushActivity, phaseAccountingViolations, loggedPhases, authorityViolations, WRITE_TRACER, createWriteTracer, formatConflict, summarizeTool, parseLogLine, roleOfSub, mapRoleToSub, membersFromState, buildRoleSubMap, resolveSubRoles, childSessionTiming, SUB_HEADER_CACHE, workflowEventIndex, workflowChildLabels, workflowChildMeta, workflowRuns, WF_EVENT_CACHE, rememberSessionRun, sessionRunFor, runOwnerSession, SESSION_RUNS, parseTeamCommand, deriveMemberEntries, schemaViolations, runHealth, RUN_STALL_MS, scaffoldFingerprint, SCAFFOLD_REQUIRED, strandedTasks, settleStranded, IN_FLIGHT_STATUSES, normalizeCoverage, SCHEMA_WARN_SEEN, pushActivityEvent, DEFAULT_LIMITS, LIMITS, resolveLimits, capacityViolations, DEFAULT_ROUND_LIMITS, ROUND_LIMITS, ROUND_LIMIT_ENV, resolveRoundLimits, ROUND_LIMIT_OF_KIND, roundOf, isQualityTask, normTitle, roundLimitViolations, reworkLoopWriteGuard, mutateTasks, readStandingRules, appendStandingRule, rulesRun, scopeOverlapWarnings, applyTaskStatus, waitRun, eventFamily, verdictFromToken, normalizeRoleName, truncateCodepoints, filterRunScopedSubs, runCreatedAtMs, runLogTail, liveFiles, LIVE_FILES_CACHE, DEFAULT_ROLES, resolveTierGate, TIER_GATE_ENV, snapshotRun, settingsPath, loadSettingsSync, currentSettings, limitsBaseFromSettings, roundLimitsBaseFromSettings, effectiveTierGate: () => TIER_GATE, ensureSkillInstalled, ensurePresetInstalled, uninstallInstalled, buildSkillRegistration, parseSkillMarkdown, PLUGIN_VERSION, INSTALL_STAMP, runtimeSkillRegistered: () => RUNTIME_SKILL_REGISTERED, agentScopedToolNames, warnLeadToolFaceOnce, installHostSettings, hostValues, hostScope, hostSettingsNote, updateHostSettings, pickFileOnly, pickHostExpressible, buildHostSchema, hostBase, hostSchemaPaths, reapplySettingsDerived, currentSettings, mergeSettings };
|
|
4448
|
+
export const _live = { pushActivity, phaseAccountingViolations, loggedPhases, authorityViolations, WRITE_TRACER, createWriteTracer, formatConflict, summarizeTool, parseLogLine, roleOfSub, mapRoleToSub, membersFromState, buildRoleSubMap, resolveSubRoles, childSessionTiming, SUB_HEADER_CACHE, workflowEventIndex, workflowChildLabels, workflowChildMeta, workflowRuns, WF_EVENT_CACHE, rememberSessionRun, sessionRunFor, runOwnerSession, SESSION_RUNS, parseTeamCommand, deriveMemberEntries, schemaViolations, runHealth, RUN_STALL_MS, scaffoldFingerprint, SCAFFOLD_REQUIRED, strandedTasks, settleStranded, IN_FLIGHT_STATUSES, normalizeCoverage, SCHEMA_WARN_SEEN, pushActivityEvent, DEFAULT_LIMITS, LIMITS, resolveLimits, capacityViolations, DEFAULT_ROUND_LIMITS, ROUND_LIMITS, ROUND_LIMIT_ENV, resolveRoundLimits, ROUND_LIMIT_OF_KIND, roundOf, isQualityTask, normTitle, roundLimitViolations, reworkLoopWriteGuard, mutateTasks, readStandingRules, appendStandingRule, rulesRun, scopeOverlapWarnings, applyTaskStatus, waitRun, eventFamily, verdictFromToken, normalizeRoleName, truncateCodepoints, filterRunScopedSubs, runCreatedAtMs, runLogTail, liveFiles, LIVE_FILES_CACHE, DEFAULT_ROLES, resolveTierGate, TIER_GATE_ENV, snapshotRun, settingsPath, loadSettingsSync, currentSettings, limitsBaseFromSettings, roundLimitsBaseFromSettings, effectiveTierGate: () => TIER_GATE, ensureSkillInstalled, ensurePresetInstalled, uninstallInstalled, buildSkillRegistration, parseSkillMarkdown, PLUGIN_VERSION, INSTALL_STAMP, runtimeSkillRegistered: () => RUNTIME_SKILL_REGISTERED, agentScopedToolNames, warnLeadToolFaceOnce, resolveLeadToolFace, LEAD_TOOLFACE_ENV, effectiveLeadToolFace: () => LEAD_TOOLFACE, installHostSettings, hostValues, hostScope, hostSettingsNote, updateHostSettings, pickFileOnly, pickHostExpressible, buildHostSchema, hostBase, hostSchemaPaths, reapplySettingsDerived, currentSettings, mergeSettings };
|
|
4425
4449
|
|
|
4426
4450
|
export function apply(ctx, config) {
|
|
4427
4451
|
// 留一份 config:设置在运行时改变(官方面板 / 浮层)时要**用同一份 config** 重算上限与档位门,
|
|
@@ -4439,6 +4463,8 @@ export function apply(ctx, config) {
|
|
|
4439
4463
|
resolveRoundLimits(config, roundLimitsBaseFromSettings());
|
|
4440
4464
|
// G 线:档位门软/硬(config.tierGate > DSH_EXPERT_TEAM_TIER_GATE > 设置 > soft)。
|
|
4441
4465
|
resolveTierGate(config, currentSettings().gates);
|
|
4466
|
+
// A 线开关:config > env > 设置 > 默认(on)。关掉即 lead 保留全部工具。
|
|
4467
|
+
resolveLeadToolFace(config, currentSettings().gates);
|
|
4442
4468
|
// 批 2-1:宿主若提供 ctx.fs,就让它接管工件写入(真实版本栅栏);否则保持同语义的回退实现。
|
|
4443
4469
|
// 机会式探测而非 inject —— 见 ARTIFACT 声明处的说明(inject 缺失服务会让整条命令挂不上)。
|
|
4444
4470
|
const hostFsAdopted = adoptHostFs(ctx);
|
|
@@ -4611,6 +4637,15 @@ export function apply(ctx, config) {
|
|
|
4611
4637
|
const isRoot = agents?.roots?.().includes(agent) === true;
|
|
4612
4638
|
if (!shouldNarrowLeadToolFace({ presetId, isRoot }).apply) return; // 无关 agent:静默返回,不是失败
|
|
4613
4639
|
|
|
4640
|
+
if (LEAD_TOOLFACE === 'off') {
|
|
4641
|
+
// 关掉时**出声一次**:否则"我明明关了"与"开关没生效"看起来一模一样(两种零纪律)。
|
|
4642
|
+
if (!LEAD_TOOLFACE_OFF_LOGGED) {
|
|
4643
|
+
LEAD_TOOLFACE_OFF_LOGGED = true;
|
|
4644
|
+
console.log(`[expert-team] lead 工具面收窄已关闭(${LEAD_TOOLFACE_ENV}=off 或设置 gates.leadToolFace=off)⇒ lead 保留全部工具`);
|
|
4645
|
+
}
|
|
4646
|
+
return;
|
|
4647
|
+
}
|
|
4648
|
+
|
|
4614
4649
|
// ③ **必须取 agent 作用域**的名字清单:`view()` 不传 scope = 全局视图,而模型可见工具
|
|
4615
4650
|
// 在 0.1.5 起由 preset 注册在 agent 平面 ⇒ 全局视图非空但缺那几个名字,收窄会静默失效
|
|
4616
4651
|
// 且给出"宿主里没有这些工具"的错误结论(拿真机日志换来的教训,详见 lead-toolface.js)。
|
package/lib/settings.js
CHANGED
|
@@ -57,6 +57,7 @@ export const SETTINGS_SPEC = {
|
|
|
57
57
|
boundarySpec: { type: 'bool', default: true, label: '规格边界章节(SPEC.md)', hint: '边界没填就不让进 implement' },
|
|
58
58
|
loopGuard: { type: 'bool', default: true, label: '振荡检测(A→B→A→B)', hint: '宿主那份只管同工具重复,这份管来回振荡' },
|
|
59
59
|
tierGate: { type: 'enum', values: ['soft', 'hard'], default: 'soft', label: '档位选择门', hint: 'soft = 建议先生效;hard = 不选不开工' },
|
|
60
|
+
leadToolFace: { type: 'enum', values: ['on', 'off'], default: 'on', label: '收窄 lead 工具面', hint: 'on = 执行类工具(bash/write/edit/grep/glob)从 lead 手上拿走,交给角色子代理(省 token);off = lead 保留全部工具' },
|
|
60
61
|
maxReviewRounds: { type: 'int', min: 1, max: 20, default: 3, label: '评审轮次上限', hint: '到顶的正确动作是升级用户,不是再来一轮' },
|
|
61
62
|
maxTestRounds: { type: 'int', min: 1, max: 20, default: 3, label: '测试轮次上限', hint: '同上' },
|
|
62
63
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yangdcm/dsh-expert-team",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "dsh「专家团」bundle:一句自然语言自动组建/持久化一支 12 角色多智能体团队,共享工作区协议 + 阶段门控编排 + 结构化交接 + 质量门禁/自动调度,实现者直接改代码并产出持久工件;带 live 团队浮层(质量门禁/覆盖率/工件预览)。 · Role-based multi-agent expert team for DeepSeek Harness: one sentence in, a staged and gated team delivery out.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|