@thincoder/core 0.10.6 → 0.10.8
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 +24 -0
- package/advisor/compaction.mjs +1 -1
- package/advisor/run.mjs +1 -1
- package/agent/chat-call.mjs +40 -27
- package/agent/child-marks.mjs +1 -1
- package/agent/dispatch-gates.mjs +7 -4
- package/agent/dispatch-run.mjs +1 -0
- package/agent/family-tools.mjs +11 -6
- package/agent/helpers.mjs +6 -4
- package/agent/image-heal.mjs +65 -0
- package/agent/light-round.mjs +4 -4
- package/agent/live-beat.mjs +4 -4
- package/agent/record-results.mjs +9 -1
- package/agent/run-stages.mjs +2 -1
- package/agent/setup-reminders.mjs +14 -13
- package/agent/setup.mjs +62 -46
- package/agent/spawn-child.mjs +1 -1
- package/agent/subagent-event.mjs +1 -1
- package/agent/suspension.mjs +2 -1
- package/agent/timers.mjs +8 -8
- package/agent/turn-loop.mjs +1 -1
- package/agent-tools/advisor.mjs +1 -1
- package/agent-tools/async-discard.mjs +40 -5
- package/agent-tools/async-settle.mjs +3 -1
- package/agent-tools/audit-block.mjs +1 -1
- package/agent-tools/batch-paths.mjs +20 -20
- package/agent-tools/checkpoint.mjs +1 -1
- package/agent-tools/design-slots.mjs +44 -5
- package/agent-tools/doc-check.mjs +37 -0
- package/agent-tools/eng.mjs +5 -3
- package/agent-tools/manifest.mjs +25 -18
- package/agent-tools/parent-channel.mjs +3 -3
- package/agent-tools/review-facts.mjs +2 -2
- package/agent-tools/settings.mjs +1 -1
- package/agent-tools/spawn-gates.mjs +8 -6
- package/agent-tools/ssh-session.mjs +439 -0
- package/agent-tools/ssh-transport.mjs +311 -0
- package/agent-tools/subagent-scheduler.mjs +6 -5
- package/agent-tools/subagent.mjs +7 -5
- package/agent-tools/task.mjs +1 -1
- package/agent-tools/timer.mjs +6 -0
- package/agent-tools/zero-write-watch.mjs +2 -2
- package/agent-tools.mjs +3 -2
- package/attachments.mjs +4 -4
- package/browser/cdp.mjs +2 -2
- package/browser/launch.mjs +50 -4
- package/browser/snapshot.mjs +1 -1
- package/config-io.mjs +7 -2
- package/config-watch.mjs +2 -2
- package/config.mjs +7 -0
- package/conventions.mjs +1 -1
- package/declaration.mjs +157 -13
- package/doc-check/anchors.mjs +100 -0
- package/doc-check/index.mjs +61 -0
- package/doc-check/width.mjs +131 -0
- package/file-refs.mjs +6 -6
- package/generate-title.mjs +1 -1
- package/hooks.mjs +1 -1
- package/i18n.mjs +11 -1
- package/ledger-cmd.mjs +4 -5
- package/ledger-db.mjs +100 -21
- package/ledger-migrate.mjs +3 -3
- package/ledger-read.mjs +6 -7
- package/ledger-tools.mjs +24 -9
- package/ledger.mjs +23 -54
- package/log.mjs +17 -3
- package/manifest-discovery.mjs +21 -18
- package/manifest-schema.mjs +2 -13
- package/manifest.mjs +37 -22
- package/mcp/transport-stdio.mjs +1 -1
- package/mcp.mjs +2 -2
- package/memory/code-search.mjs +21 -4
- package/memory/code-sync.mjs +7 -4
- package/memory/core.mjs +1 -1
- package/memory/docs.mjs +23 -6
- package/memory/file-list.mjs +13 -7
- package/memory/file-walk.mjs +9 -4
- package/memory/scan.mjs +1 -1
- package/memory/sweep.mjs +1 -1
- package/memory/sync-tail.mjs +11 -7
- package/model-specs.mjs +7 -7
- package/notify-policy.mjs +6 -6
- package/package.json +2 -1
- package/permission.mjs +14 -0
- package/prompts/advisor-design.md +43 -13
- package/prompts/advisor-round1.md +25 -5
- package/prompts/advisor-round2.md +17 -4
- package/prompts/advisor-round3.md +17 -4
- package/prompts/common.md +60 -6
- package/prompts/consult-base.md +8 -2
- package/prompts/discipline-engineering.md +11 -10
- package/prompts/discipline-normal.md +22 -14
- package/prompts/persona-coder.md +1 -1
- package/prompts/persona-eng-designer.md +8 -3
- package/prompts/persona-engineering.md +21 -5
- package/prompts/persona-normal.md +4 -1
- package/provider/errors.mjs +8 -0
- package/provider/google.mjs +3 -0
- package/provider/normalize.mjs +42 -12
- package/provider/responses-request.mjs +1 -1
- package/provider/responses.mjs +2 -2
- package/provider/wait-status.mjs +1 -1
- package/provider-flows.mjs +1 -1
- package/queued.mjs +2 -2
- package/rules.mjs +4 -4
- package/session-gc.mjs +1 -1
- package/session-lifecycle.mjs +1 -1
- package/session-slot-write.mjs +2 -2
- package/session-slots-manifest.mjs +1 -1
- package/session.mjs +1 -1
- package/shell-candidates.mjs +2 -2
- package/shell-identity.mjs +1 -1
- package/team.mjs +61 -4
- package/think-off.mjs +3 -3
- package/token-ttl.mjs +1 -1
- package/tool-docs/bash.md +1 -1
- package/tool-docs/browser.md +1 -1
- package/tool-docs/doc_check.md +31 -0
- package/tool-docs/manifest.md +14 -2
- package/tool-docs/ssh.md +34 -0
- package/tool-docs/subagent.md +2 -0
- package/tool-docs/timer.md +2 -1
- package/tools/browser.mjs +1 -1
- package/tools/execute.mjs +1 -1
- package/tools/git-run.mjs +2 -2
- package/tools/git.mjs +8 -8
- package/tools/index.mjs +3 -0
- package/tools/ops.mjs +1 -1
- package/tools/process-tree.mjs +2 -2
- package/tools/ssh-askpass.mjs +35 -0
- package/tools/ssh.mjs +92 -0
- package/vision-reader.mjs +4 -4
package/agent-tools/eng.mjs
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* (subagent-spawn.mjs). See docs/design/ENG-TOKEN-BINDING-TUNING.md §5/§5.1 (F-R16).
|
|
13
13
|
* #41(2026-09-18):enter 分支改「先判后翻」——判据 = 入口决策树单源
|
|
14
14
|
* `resolveEngineeringManifest`(docs/core/design/MANIFEST.md §2.8 F2 / KD-M1-20/21);
|
|
15
|
+
* **可拒面 = 仅「档非法」一格**(工作区 `workspace` 放行——零附着,模式照开);
|
|
15
16
|
* 拒翻 ⇒ 返回原因串 + **零副作用**(模式保持 OFF)。OFF 方向与幂等 enter 零改。
|
|
16
17
|
*/
|
|
17
18
|
import { ENG_ON_REMINDER, ENG_OFF_REMINDER } from "../agent.mjs"
|
|
@@ -74,15 +75,16 @@ export const engTool = {
|
|
|
74
75
|
return "Engineering mode already active. Existing design tokens stay valid."
|
|
75
76
|
}
|
|
76
77
|
// #41 先判后翻(MANIFEST.md §2.8 F2 / KD-M1-21):判据 = 入口决策树**单源**
|
|
77
|
-
// (resolveEngineeringManifest——KD-M1-20
|
|
78
|
+
// (resolveEngineeringManifest——KD-M1-20),判据通过才写态。**可拒面 = 仅「档非法」格**
|
|
79
|
+
// (工作区 `workspace` ⇒ 放行——**零附着**:无项目档可附,模式照开);拒翻 ⇒ 返回原因串 +
|
|
78
80
|
// **零副作用**(不清 token / 不重置 _advisorRuns / 不入列 ENG_ON_REMINDER /
|
|
79
81
|
// 不动 _lastEngState / 不触镜像缝);准 ⇒ 缺档格就地建档(writer:'main')+
|
|
80
82
|
// agent.manifest ← 结果(翻转面唯一赋值点——相位行当回合起活,§2.8 F2 放行行)。
|
|
81
83
|
const r = resolveEngineeringManifest(ctx.agent.cwd ?? ctx.cwd ?? process.cwd(), { writer: "main" })
|
|
82
|
-
if (!r.ok) {
|
|
84
|
+
if (!r.ok && r.code !== "workspace") {
|
|
83
85
|
return `Error: cannot enter engineering mode — ${r.message} (mode unchanged)`
|
|
84
86
|
}
|
|
85
|
-
ctx.agent.manifest = r.manifest
|
|
87
|
+
ctx.agent.manifest = r.ok ? r.manifest : null // 工作区放行 ⇒ 零附着(显式置 null——§2.8 F2 放行行)
|
|
86
88
|
ctx.agent.config.agent.engineering = true
|
|
87
89
|
// FR31 ③ / KD10(翻转点①):工程模式 ⇒ planMode 恒 false——中途开模式时清残留
|
|
88
90
|
//(planMode 位 + reminder 计数 + 未注入的 plan 提示语),半状态(工程纪律 × plan 只读)不产生。
|
package/agent-tools/manifest.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* agent 侧读写出口(2026-10-08 · 台账 #1098;权威设计 = `docs/core/design/MANIFEST.md` §2.10)。
|
|
4
4
|
*
|
|
5
5
|
* 三动作(KD-M1-38):
|
|
6
|
-
* - `read` ⇒ `projectView(target)` 五态报明(稳定锚 `state=ok|missing|invalid|
|
|
6
|
+
* - `read` ⇒ `projectView(target)` 五态报明(稳定锚 `state=ok|missing|invalid|workspace|no-project`);
|
|
7
7
|
* `ok` 态再 `readManifest(view.root)` 取细节面(`projectView` 面不含 `missingKeys` /
|
|
8
8
|
* `unknownKeys`)——**不抛**(缺档报明,非拒)。
|
|
9
9
|
* - `init` ⇒ 缺档建默认档(`initManifest`——内容 = `DEFAULT_MANIFEST`);**已带档 ⇒ 拒**
|
|
@@ -15,30 +15,35 @@
|
|
|
15
15
|
* (`version` / `phase` / `promptsLanding` / `codePaths` 整键)+ `nestedKeys` 子键
|
|
16
16
|
* (`docRoot.*` / `checkConfig.*` / `index.*`(含 `publicRepos`)/ `advisor.*`);**四族整键写
|
|
17
17
|
* (传整个对象)⇒ 拒**;白名单外 ⇒ 拒(拼写保护——未知键写盘 = 静默死键,KD-M1-36 问题本体)。
|
|
18
|
-
* `value` 解析 = 同款口径 `settings.mjs
|
|
18
|
+
* `value` 解析 = 同款口径 `settings.mjs` 的 `parseValue`(先 `JSON.parse`,失败取字面串;`"null"` ⇒ `null`
|
|
19
19
|
* ——`docRoot.*` 的「本面无」,KD-M1-37)。
|
|
20
20
|
*
|
|
21
21
|
* 目标面(KD-M1-39——判据复用零新解析器):`read` = `projectView`;`init` / `write` =
|
|
22
|
-
* `projectRootView
|
|
23
|
-
* ⇒ 写 / 建两动作**不得**直用。
|
|
22
|
+
* `projectRootView`(工作区 ⇒ 拒 + 下辖项目全列 + 显式 `target` 指引);`resolveProjectRoot` 对
|
|
23
|
+
* 工作区塌缩 `null` 再回落 cwd ⇒ 写 / 建两动作**不得**直用。
|
|
24
24
|
*
|
|
25
25
|
* 写路径复用(零新写路径):落盘恒经 `writeManifest` / `initManifest`——`writer` 恒显式 `'main'`
|
|
26
26
|
* (缺省 `'subagent'` = 写门 fail-closed 缺省,KD-M1-3 / AC-M1-5 零改)。
|
|
27
27
|
*
|
|
28
28
|
* 报告面随动(KD-M1-40):本工具**不写** `agent.manifest`(第二值源否——工具目标可为非锚项目)——
|
|
29
29
|
* 写盘 = 盘面变化,情境行经既有 ③b mtime 门控于下回合采纳(`agent/setup-reminders.mjs`)。
|
|
30
|
+
*
|
|
31
|
+
* 缓存失效(#1367 面⑦):写档成功(init ∥ write——全部成功路径)⇒ `clearDeclarationCache()`——
|
|
32
|
+
* 「补档即回归」进程内即时(声明 ∥ 范围缓存同清);失败路径不清(盘零变 ⇒ 缓存照旧);
|
|
33
|
+
* 手工改档 ⇒ 重启生效(零文件侦听)。
|
|
30
34
|
*/
|
|
31
35
|
import { existsSync } from "node:fs"
|
|
32
36
|
import { join, resolve } from "node:path"
|
|
33
37
|
import { MANIFEST_REL, MANIFEST_SCHEMA, initManifest, projectRootView, projectView, readManifest, writeManifest } from "../manifest.mjs"
|
|
34
38
|
import { DESC } from "../tools/shared.mjs"
|
|
39
|
+
import { clearDeclarationCache } from "../conventions.mjs" // #1367 面⑦:写档成功 ⇒ 缓存失效(fix 轮接线)
|
|
35
40
|
|
|
36
41
|
/** 拒面统一前缀(设计 §2.10:`manifest <action>: refused — …`)——盘零变类拒绝一律经此抛错。 */
|
|
37
42
|
function refuse(action, reason) {
|
|
38
43
|
return new Error(`manifest ${action}: refused — ${reason}`)
|
|
39
44
|
}
|
|
40
45
|
|
|
41
|
-
/** `target` 解析(先例 `eng.mjs
|
|
46
|
+
/** `target` 解析(先例 `eng.mjs` 的 `resolveEngineeringManifest` 缺省会话锚 ∥ `git.mjs` 的 `resolveBaseDir` 相对形归一):缺省 = 会话锚
|
|
42
47
|
* (`ctx.agent.cwd ?? ctx.cwd ?? process.cwd()`);显式相对形按会话锚归一(绝对形原样)。 */
|
|
43
48
|
function resolveTarget(args, ctx) {
|
|
44
49
|
const base = ctx?.agent?.cwd ?? ctx?.cwd ?? process.cwd()
|
|
@@ -60,7 +65,7 @@ function isWritableKey(key) {
|
|
|
60
65
|
return false
|
|
61
66
|
}
|
|
62
67
|
|
|
63
|
-
/** `value` 解析(同款口径 = `settings.mjs
|
|
68
|
+
/** `value` 解析(同款口径 = `settings.mjs` 的 `parseValue`):先 `JSON.parse`(`"null"` ⇒ `null`;数值 /
|
|
64
69
|
* 布尔 / 数组皆 JSON 形),失败取字面串(裸串如 `docs/design`)。 */
|
|
65
70
|
function parseValue(raw) {
|
|
66
71
|
const s = String(raw)
|
|
@@ -78,14 +83,14 @@ function setKeyPath(obj, path, value) {
|
|
|
78
83
|
cur[segs[segs.length - 1]] = value
|
|
79
84
|
}
|
|
80
85
|
|
|
81
|
-
/**
|
|
82
|
-
function
|
|
83
|
-
return
|
|
86
|
+
/** 工作区拒文案(下辖项目全列 + 显式 `target` 下一步——init / write 共用;事实行,非二义框定)。 */
|
|
87
|
+
function workspaceReason(target, candidates) {
|
|
88
|
+
return `${target} is a workspace holding ${candidates.length} projects — pass the project root explicitly via target:\n` +
|
|
84
89
|
candidates.map((c) => `- ${c}`).join("\n")
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
/** read 动作(五态报明——**不抛**):`state=` 稳定锚 + 各态附行(ok 细节面 / missing 引导 /
|
|
88
|
-
*
|
|
93
|
+
* workspace 下辖项目全列 / invalid 错误行)。 */
|
|
89
94
|
function readAction(target) {
|
|
90
95
|
const view = projectView(target)
|
|
91
96
|
const lines = [`state=${view.state}`]
|
|
@@ -100,10 +105,10 @@ function readAction(target) {
|
|
|
100
105
|
lines.push(`hint: run manifest action=init to create the default manifest here`)
|
|
101
106
|
} else if (view.state === "no-project") {
|
|
102
107
|
lines.push(`hint: no project on the ancestor chain and none below — manifest action=init can create one at the target`)
|
|
103
|
-
} else if (view.state === "
|
|
104
|
-
lines.push(`
|
|
108
|
+
} else if (view.state === "workspace") {
|
|
109
|
+
lines.push(`projects (${(view.candidates ?? []).length}):`)
|
|
105
110
|
for (const c of view.candidates ?? []) lines.push(`- ${c}`)
|
|
106
|
-
lines.push(`hint: pass target explicitly — the
|
|
111
|
+
lines.push(`hint: pass target explicitly — the target must be one of the projects above`)
|
|
107
112
|
} else if (view.state === "invalid") {
|
|
108
113
|
if (view.errors?.length) lines.push(`errors=${view.errors.join(";")}`)
|
|
109
114
|
}
|
|
@@ -117,13 +122,13 @@ export const manifestTool = {
|
|
|
117
122
|
type: "object",
|
|
118
123
|
properties: {
|
|
119
124
|
action: { type: "string", enum: ["read", "init", "write"], description: "read — current manifest + validation state (five-state anchor, never throws); init — create the default manifest when missing (refused when one already exists); write — point-edit one node (key + value) of an existing manifest" },
|
|
120
|
-
target: { type: "string", description: "Explicit target directory — defaults to the session anchor; relative paths resolve against it.
|
|
125
|
+
target: { type: "string", description: "Explicit target directory — defaults to the session anchor; relative paths resolve against it. A workspace target (several projects below it) is refused with the full project list — pass the project root you mean." },
|
|
121
126
|
key: { type: "string", description: "(write) Dot path of the node to set — version / phase / promptsLanding / codePaths, or a sub-key of docRoot / checkConfig / index / advisor (e.g. docRoot.design / index.publicRepos / advisor.docMap); whole-object writes of those four families are refused", },
|
|
122
127
|
value: { type: "string", description: "(write) New value — parsed as JSON first (null / true / 5 / [\"a\"]), otherwise kept as a literal string; \"null\" is the explicit no-such-face for docRoot.<key>" },
|
|
123
128
|
},
|
|
124
129
|
required: ["action"],
|
|
125
130
|
},
|
|
126
|
-
readonly: false, // 动作级分类(dispatch-gates `
|
|
131
|
+
readonly: false, // 动作级分类(dispatch-gates `isReadonlyAction`):read = 只读类;init / write 保持侧效门
|
|
127
132
|
async execute(args, ctx) {
|
|
128
133
|
const action = args?.action
|
|
129
134
|
if (!["read", "init", "write"].includes(action)) {
|
|
@@ -133,10 +138,10 @@ export const manifestTool = {
|
|
|
133
138
|
|
|
134
139
|
if (action === "read") return readAction(target)
|
|
135
140
|
|
|
136
|
-
// init / write:目标面 = `projectRootView
|
|
141
|
+
// init / write:目标面 = `projectRootView`(直读形——工作区不成目标;KD-M1-39)
|
|
137
142
|
const rootView = projectRootView(target)
|
|
138
|
-
if (rootView.state === "
|
|
139
|
-
throw refuse(action,
|
|
143
|
+
if (rootView.state === "workspace") {
|
|
144
|
+
throw refuse(action, workspaceReason(target, rootView.candidates))
|
|
140
145
|
}
|
|
141
146
|
|
|
142
147
|
if (action === "init") {
|
|
@@ -150,6 +155,7 @@ export const manifestTool = {
|
|
|
150
155
|
} catch (e) {
|
|
151
156
|
throw refuse("init", `could not write the default manifest at ${file} — ${e?.message ?? String(e)}`)
|
|
152
157
|
}
|
|
158
|
+
clearDeclarationCache() // 写成功:补档 ⇒ 范围即回归(进程内——失败路径不清)
|
|
153
159
|
return `manifest init: created default manifest (DEFAULT_MANIFEST)\npath=${file}`
|
|
154
160
|
}
|
|
155
161
|
|
|
@@ -188,6 +194,7 @@ export const manifestTool = {
|
|
|
188
194
|
} catch (e) {
|
|
189
195
|
throw refuse("write", `the edited manifest fails the pre-write validation (disk unchanged) — ${e?.message ?? String(e)}`)
|
|
190
196
|
}
|
|
197
|
+
clearDeclarationCache() // 写成功:声明 ∥ 范围逐字随动(进程内——失败路径不清)
|
|
191
198
|
return `manifest write: set ${key} = ${JSON.stringify(value)}\npath=${file}`
|
|
192
199
|
},
|
|
193
200
|
}
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* 两端共用的提示行携参(队首 ask 的 `from` + 单行归一截断的 `message`);两端各持一份 = 漂移源(D2)。
|
|
35
35
|
*
|
|
36
36
|
* 模块图:静态 import 核单点 `async-settle.mjs`(`carrierField` / `getAsyncPool` /
|
|
37
|
-
* `tombstoneOf` / `wakeAsyncWaiters`——同层既有导出,同 `async-discard.mjs
|
|
37
|
+
* `tombstoneOf` / `wakeAsyncWaiters`——同层既有导出,同 `async-discard.mjs` 的 `async-settle.mjs` 静态导入先例;唤醒走
|
|
38
38
|
* 既有静态边,零新增)+ `../context.mjs`(`pushReal`)
|
|
39
39
|
* / `../agent/helpers.mjs`(`escapeXml`)/ `../log.mjs`(`logEvent`);单向、叶子向、无环。
|
|
40
40
|
* 登记册导出(`agent-tools.mjs`)→ 家族矩阵装配(`agent/family-tools.mjs` depth>0 段)。
|
|
@@ -55,7 +55,7 @@ export const UPSTREAM_ASK_MAX_INFLIGHT = 1
|
|
|
55
55
|
|
|
56
56
|
/** 工具返回注(异步形——sync: false;答复按普通指令在下回合边界到达)。 */
|
|
57
57
|
const ASYNC_NOTE =
|
|
58
|
-
"delivered to your parent's queue — consumed at the parent's next
|
|
58
|
+
"delivered to your parent's queue — consumed at the parent's next delivery round (idle wake or suspension window; not during a user turn), non-blocking. " +
|
|
59
59
|
"Keep working on the unaffected parts; a reply arrives as an ordinary instruction at your next turn boundary. " +
|
|
60
60
|
"If your run ends first, report the unanswered part as not done."
|
|
61
61
|
|
|
@@ -73,7 +73,7 @@ const refused = (error) => JSON.stringify({ status: "error", error })
|
|
|
73
73
|
* ① 父字段在场 ⇒ 父对象(CLI 形主容器——写侧不变);
|
|
74
74
|
* ② 缺 ⇒ `carrierField` 回退 `history` 命中 ⇒ **借用同一容器**(不另建分叉);
|
|
75
75
|
* ③ 两者皆无 ⇒ 建在父字段 + **载体别名**(`parent.history._childUpstream = parent._childUpstream`
|
|
76
|
-
* ——同 `writeTombstone` 借用规则扩张句的既有形态,`agent-tools/async-settle.mjs
|
|
76
|
+
* ——同 `writeTombstone` 借用规则扩张句的既有形态,`agent-tools/async-settle.mjs` 的 `writeTombstone`)。
|
|
77
77
|
*/
|
|
78
78
|
function upstreamHolder(parent) {
|
|
79
79
|
if (!Array.isArray(parent._childUpstream)) {
|
|
@@ -142,11 +142,11 @@ export function noteReviewDelivered(agent, run) {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
/** 分支③候选底座(`MANIFEST.md` §2.5「路径归一增量」族第四笔 · 2026-10-05 · #945):现行
|
|
145
|
-
* `projectRootView(cwd)` 集(ok → [root];
|
|
145
|
+
* `projectRootView(cwd)` 集(ok → [root];workspace → candidates 按名序;none → 空集)+
|
|
146
146
|
* cwd 祖先链全量目录(自父目录起至盘根、最近→远、去重、现行集在前)——容器相对形在子仓锚下
|
|
147
147
|
* 可解析;受理判据(目标解析位最近 manifest 声明面)∥ 围栏 ∥ 可读唯一化 ∥ fail-closed 歧义零改。 */
|
|
148
148
|
function candidateRoots(view, cwd) {
|
|
149
|
-
const current = view.state === "ok" ? [view.root] : view.state === "
|
|
149
|
+
const current = view.state === "ok" ? [view.root] : view.state === "workspace" ? view.candidates : []
|
|
150
150
|
const ancestors = []
|
|
151
151
|
for (let d = dirname(resolve(cwd)); ; ) {
|
|
152
152
|
ancestors.push(d)
|
package/agent-tools/settings.mjs
CHANGED
|
@@ -127,7 +127,7 @@ function _checkShape(path, spec, value) {
|
|
|
127
127
|
}
|
|
128
128
|
return
|
|
129
129
|
}
|
|
130
|
-
// nonEmptyString —— defaultModel 另加 provider:model 形态面(与 model-ref.mjs
|
|
130
|
+
// nonEmptyString —— defaultModel 另加 provider:model 形态面(与 model-ref.mjs 的 `parseModelRef` 同判据;
|
|
131
131
|
// 存在性面不查——D-S2.5)
|
|
132
132
|
if (typeof value !== "string" || !value.trim()) throw _expectsError(path, spec.expects, value)
|
|
133
133
|
if (spec.providerModel) {
|
|
@@ -87,18 +87,20 @@ const MANIFEST_BASENAME = "project-manifest.json"
|
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
89
|
* F6 files 声明面拦截谓词(ENGINEERING-MODE-V2-MODULE-DELEGATION §2.2):
|
|
90
|
-
* scripts
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
90
|
+
* scripts/*(工程工具面不入域——**层级锚定:仅仓根与直接子层**——目录名在深层不携带
|
|
91
|
+
* face 信息(2026-10-14 收正:#1449——`deployment/<x>/scripts/*` 类交付物放行)——内容
|
|
92
|
+
* 产物 only)与过程档(父侧职责)→ 收集全部违规后抛合并错误(fail-closed——错误即工具
|
|
93
|
+
* 结果 JSON——无排队残留)。目录声明不在本谓词(normalizeFileList 循环内先行拒——错误
|
|
94
|
+
* 序不变)。调用点 = normalizeFileList(subagent-scheduler.mjs——本谓词在循环后跑——
|
|
95
|
+
* 目录错误先于过程档错误)。
|
|
94
96
|
*/
|
|
95
97
|
export function rejectEngineeringFilePaths(files) {
|
|
96
98
|
const violations = []
|
|
97
99
|
for (const f of Array.isArray(files) ? files : []) {
|
|
98
100
|
const segs = String(f).replace(/\\/g, "/").split("/").filter((s) => s)
|
|
99
101
|
const base = (segs[segs.length - 1] ?? "").toLowerCase()
|
|
100
|
-
if (segs.some((s) => s.toLowerCase() === "scripts")) {
|
|
101
|
-
violations.push(`engineering-tools face path ${f} must not be listed in files — scripts
|
|
102
|
+
if (segs.slice(0, 2).some((s) => s.toLowerCase() === "scripts")) {
|
|
103
|
+
violations.push(`engineering-tools face path ${f} must not be listed in files — scripts/* at the repo root or a direct child package is the engineering-tools face, not a content product (applies to every session, not engineering-mode-scoped; files carries source/test/design-doc paths only)`)
|
|
102
104
|
} else if (PROCESS_BASENAMES.has(base)) {
|
|
103
105
|
violations.push(`Parent-side maintained file ${f} must not be listed in files — reconciliation is the parent's duty; use the design-doc path if you need to edit a design doc`)
|
|
104
106
|
} else if (base === MANIFEST_BASENAME) {
|