@thincoder/core 0.10.11 → 0.10.13
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 +21 -0
- package/advisor/messages.mjs +1 -1
- package/advisor/project-context.mjs +2 -2
- package/agent/run-stages.mjs +33 -29
- package/agent/setup.mjs +3 -0
- package/agent/turn-loop.mjs +3 -0
- package/agent-tools/batch-gate.mjs +65 -49
- package/agent-tools/batch-lifecycle.mjs +82 -12
- package/agent-tools/batch-paths.mjs +10 -8
- package/agent-tools/batch-skeleton.mjs +9 -1
- package/agent-tools/batch-unit-test-gate.mjs +107 -0
- package/agent-tools/design-slots.mjs +72 -12
- package/agent-tools/design-token.mjs +18 -2
- package/agent-tools/manifest.mjs +1 -1
- package/agent-tools/review-facts.mjs +1 -1
- package/agent.mjs +1 -0
- package/client-identity.mjs +54 -0
- package/config.mjs +19 -13
- package/context.mjs +5 -5
- package/doc-check/index.mjs +28 -15
- package/doc-check/paragraph.mjs +6 -3
- package/embedding.mjs +2 -0
- package/generate-title.mjs +3 -2
- package/ledger-close-proof.mjs +80 -0
- package/ledger-cmd.mjs +64 -53
- package/ledger-db.mjs +60 -59
- package/ledger-tools.mjs +60 -23
- package/ledger.mjs +12 -10
- package/manifest-discovery.mjs +41 -26
- package/manifest.mjs +17 -16
- package/model-specs.mjs +17 -18
- package/package.json +1 -1
- package/prompts/advisor-design.md +4 -3
- package/prompts/common.md +11 -1
- package/prompts/discipline-engineering.md +16 -7
- package/prompts/discipline-normal.md +2 -1
- package/prompts/persona-coder.md +8 -1
- package/prompts/persona-eng-coder.md +8 -0
- package/prompts/persona-eng-designer.md +11 -1
- package/prompts/persona-engineering.md +23 -11
- package/prompts/persona-explore.md +6 -0
- package/prompts/persona-normal.md +6 -0
- package/prompts/persona-plan.md +6 -0
- package/provider/anthropic.mjs +12 -7
- package/provider/core.mjs +19 -3
- package/provider/errors.mjs +41 -0
- package/provider/google.mjs +10 -4
- package/provider/list-models.mjs +4 -3
- package/provider/responses.mjs +17 -7
- package/session-lifecycle.mjs +3 -0
- package/session-slot-write.mjs +21 -1
- package/session-slots-manifest.mjs +21 -4
- package/token-ttl.mjs +68 -4
- package/token-window.mjs +23 -2
- package/tool-docs/wait_for.md +15 -6
package/model-specs.mjs
CHANGED
|
@@ -44,6 +44,14 @@ const MODEL_SPECS = [
|
|
|
44
44
|
["deepseek-v4-flash-vision-exp", { context: 1_000_000, maxOutput: 384_000, thinking: true, prefixMode: true, thinkApi: "type", reasoningEcho: "required", reasoningEffortEnum: ["low", "high", "max"], tempRange: [0, 2], multimodal: true }],
|
|
45
45
|
// Kimi series
|
|
46
46
|
["kimi-k3", { context: 1_000_000, maxOutput: 131_072, thinking: true, partialMode: true, multimodal: true, thinkApi: "effort", reasoningEcho: "required", reasoningEffortEnum: ["low", "high", "max"] }],
|
|
47
|
+
// kimi-k3.1-pro / kimi-k3.1-pro-highspeed(2026-10-23 发布;官方 quickstart 实读 2026-10-25):
|
|
48
|
+
// context = 1_048_576(官方 1M);maxOutput = 131_072(官方 max_completion_tokens 默认档,上限 1_048_576 不取);
|
|
49
|
+
// **思考始终开启**(官方原文「K3.1 Pro 始终开启思考模式」· FAQ「目前关不了」)⇒ thinkAlwaysOn;推理强度走顶层
|
|
50
|
+
// reasoning_effort low/high/max(默认 max)⇒ thinkApi "effort";多轮 / 工具调用须原样回传完整 assistant message
|
|
51
|
+
// ⇒ reasoningEcho "required";partialMode ✓;视觉 ✓(content 必须是对象数组,图走 base64 ∥ ms://,**不接受公网 URL**)。
|
|
52
|
+
// Highspeed = 同规格、输出约 2~3 倍速(官方「同等智能」)—— 分值分行,靠前缀长度降序先命中。
|
|
53
|
+
["kimi-k3.1-pro", { context: 1_048_576, maxOutput: 131_072, thinking: true, thinkAlwaysOn: true, partialMode: true, multimodal: true, thinkApi: "effort", reasoningEcho: "required", reasoningEffortEnum: ["low", "high", "max"] }],
|
|
54
|
+
["kimi-k3.1-pro-highspeed", { context: 1_048_576, maxOutput: 131_072, thinking: true, thinkAlwaysOn: true, partialMode: true, multimodal: true, thinkApi: "effort", reasoningEcho: "required", reasoningEffortEnum: ["low", "high", "max"] }],
|
|
47
55
|
// Kimi For Coding endpoint uses the short model ID "k3" (same specs as kimi-k3) — IK5VGJ
|
|
48
56
|
["k3", { context: 1_000_000, maxOutput: 131_072, thinking: true, partialMode: true, multimodal: true, thinkApi: "effort", reasoningEcho: "required", reasoningEffortEnum: ["low", "high", "max"] }],
|
|
49
57
|
// kimi-for-coding / k3-256k / kimi-for-coding-highspeed(Kimi For Coding 端点三名 · 2026-09-25 批 §14.2 #7-9 · 活测 = §1.4 服务端 200 /models):
|
|
@@ -81,8 +89,7 @@ const MODEL_SPECS = [
|
|
|
81
89
|
["glm-5.3-flashx", { context: 1_000_000, maxOutput: 131_072, thinking: true, thinkAlwaysOn: true, multimodal: true, thinkApi: "type", reasoningEcho: "optional", reasoningEffortEnum: ["low", "high", "max"], tempRange: [0, 1], noUsageStream: true }],
|
|
82
90
|
["glm-5.2", { context: 1_000_000, maxOutput: 128_000, thinking: true, thinkApi: "type", reasoningEcho: "optional", reasoningEffortEnum: ["max", "xhigh", "high", "medium", "low", "minimal", "none"], tempRange: [0, 1], noUsageStream: true }],
|
|
83
91
|
["glm-5", { context: 1_000_000, maxOutput: 128_000, thinking: true, thinkApi: "type", reasoningEcho: "optional", reasoningEffortEnum: ["max", "xhigh", "high", "medium", "low", "minimal", "none"], tempRange: [0, 1], noUsageStream: true }],
|
|
84
|
-
|
|
85
|
-
// glm-4.5-air(智谱轻档 · 2026-09-24 bench 名单批):temperature 0 受理 = **实测**(roster-expand §2.2);其余 = **族沿用 glm-4 行**
|
|
92
|
+
// glm-4.5-air(智谱轻档 · 2026-09-24 bench 名单批):temperature 0 受理 = **实测**(roster-expand §2.2);取值以本行**显式声明**为准
|
|
86
93
|
// (逐名官方口径未取证);枚举 / 视觉面 = **未探**(不声明)。medium 直发实测受理(batch-params-judge §1.5)。
|
|
87
94
|
["glm-4.5-air", { context: 128_000, maxOutput: 32_000, thinking: true, thinkApi: "type", reasoningEcho: "optional", tempRange: [0, 1], noUsageStream: true }],
|
|
88
95
|
// GPT series
|
|
@@ -91,11 +98,10 @@ const MODEL_SPECS = [
|
|
|
91
98
|
["gpt-4.1", { context: 1_000_000, maxOutput: 128_000, thinking: false }],
|
|
92
99
|
["gpt-4o", { context: 128_000, maxOutput: 16_000, thinking: false, multimodal: true }],
|
|
93
100
|
// Qwen series
|
|
94
|
-
// qwen-flash
|
|
101
|
+
// qwen-flash(2026-09-25 批 §14.2 #2-6 · §1.7.1 父侧实测):**尺寸行**——maxOutput 32_768 = **实测**
|
|
95
102
|
// (服务端直报「Range of max_tokens should be [1, 32768]」;131072 / 262144 均 400)。context 未取到 ⇒ 零口径——取兜底值
|
|
96
103
|
// 128_000(与建行前生效值同值,§14.3 兜底语义续效);thinking / 视觉有读数(默认关可开 / 不支持)但不落字段(§14.3 五名口径)。
|
|
97
104
|
["qwen-flash", { context: 128_000, maxOutput: 32_768 }],
|
|
98
|
-
["qwen-vl-max", { context: 128_000, maxOutput: 32_768 }],
|
|
99
105
|
// qwen3.7-max:**实测拒图像**(DashScope 400 "Unexpected item type in content"——真值彩图探针,2026-09-20)
|
|
100
106
|
// ⇒ 无视觉 = **不声明**(T-7 语义单一:multimodal 仅 true / undefined;补探已毕,无需再探)
|
|
101
107
|
["qwen3.7-max", { context: 1_000_000, maxOutput: 131_072, thinking: true, partialMode: true, thinkApi: "effort", reasoningEffortEnum: ["xhigh", "high"], tempRange: [0, 2] }],
|
|
@@ -137,8 +143,6 @@ const MODEL_SPECS = [
|
|
|
137
143
|
["qwen3.6-flash", { context: 1_000_000, maxOutput: 65_536, thinking: true, partialMode: true, multimodal: true, thinkApi: "effort", reasoningEffortEnum: ["none", "minimal", "low", "medium", "high", "xhigh"], tempRange: [0, 2] }],
|
|
138
144
|
// qwen3.6-plus:同形行(共享证据块见 flash 行上)——校验级 maxOutput / 六档枚举、官方口径 context、族沿用机制位。
|
|
139
145
|
["qwen3.6-plus", { context: 1_000_000, maxOutput: 65_536, thinking: true, partialMode: true, multimodal: true, thinkApi: "effort", reasoningEffortEnum: ["none", "minimal", "low", "medium", "high", "xhigh"], tempRange: [0, 2] }],
|
|
140
|
-
// qwen3.6-max-preview:同形行——校验级 maxOutput / 六档枚举、官方口径 context、族沿用机制位;视觉通道实测 ✓ 但纯红图答「黑色」(抽样波动,如实记)。
|
|
141
|
-
["qwen3.6-max-preview", { context: 1_000_000, maxOutput: 65_536, thinking: true, partialMode: true, multimodal: true, thinkApi: "effort", reasoningEffortEnum: ["none", "minimal", "low", "medium", "high", "xhigh"], tempRange: [0, 2] }],
|
|
142
146
|
// qwen3.6-27b:同形行——校验级 maxOutput / 六档枚举、官方口径 context(未探边)、族沿用机制位。
|
|
143
147
|
["qwen3.6-27b", { context: 1_000_000, maxOutput: 65_536, thinking: true, partialMode: true, multimodal: true, thinkApi: "effort", reasoningEffortEnum: ["none", "minimal", "low", "medium", "high", "xhigh"], tempRange: [0, 2] }],
|
|
144
148
|
// qwen3.5-27b(2026-09-24 bench 名单批):context 262_144 = **官方口径(定价页分档佐证——[128K, 256K) 档在售;规格页未逐名核)**;
|
|
@@ -155,8 +159,6 @@ const MODEL_SPECS = [
|
|
|
155
159
|
// always echo); 2026-09-22 re-probe: value / missing field / empty string all 200 — the
|
|
156
160
|
// 2026-09-20 "must be passed back" 400 was NOT reproduced. v2.5 rows aligned 2026-09-22:
|
|
157
161
|
// maxOutput 131_072 = **校验级**.
|
|
158
|
-
["mimo-v2.5-pro", { context: 1_000_000, maxOutput: 131_072, thinking: true, thinkApi: "type", reasoningEcho: "required", tempRange: [0, 1.5] }],
|
|
159
|
-
["mimo-v2.5", { context: 1_000_000, maxOutput: 131_072, thinking: true, multimodal: true, thinkApi: "type", reasoningEcho: "required", tempRange: [0, 1.5] }],
|
|
160
162
|
// MiMo V2.6 series (2026-09-22 launch — three independent rows, each probed individually).
|
|
161
163
|
// maxOutput 131_072 / tempRange [0, 1.5] = **校验级** (400 "at most 131072 completion tokens" /
|
|
162
164
|
// "temperature must be within [0, 1.5]", per model); thinking = **实测** (bare request carries
|
|
@@ -175,10 +177,9 @@ const MODEL_SPECS = [
|
|
|
175
177
|
// minimax-m3(小写前缀行——与上方 MiniMax-M3 行同值,同族两写法):effort 同按**无生效面**处置
|
|
176
178
|
// (**实测**:effort 被忽略;off 路径 = `thinking:{type:"disabled"}` ✓ rc=0——batch-params-judge §1.2 / KD-32④)。
|
|
177
179
|
["minimax-m3", { context: 1_000_000, maxOutput: 128_000, thinking: true, multimodal: true, thinkApi: "type", thinkEnabledValue: "adaptive", tempRange: [0, 2], noUsageStream: true }],
|
|
178
|
-
["minimax-m1", { context: 256_000, maxOutput: 128_000, thinking: false, noUsageStream: true }],
|
|
179
180
|
// MiniMax-M2.7(前缀行——覆盖标准档与 -highspeed · 2026-09-24 bench 名单批):thinking = **实测**(裸请求 rc 在场);off 路径 **未找到**
|
|
180
181
|
// (`thinking:{type:"disabled"}` 不生效——如实,不声明 thinkApi);effort 被忽略 ⇒ **无生效面**(枚举不声明;medium 照发仅口径统一);
|
|
181
|
-
// 尺寸 / noUsageStream =
|
|
182
|
+
// 尺寸 / noUsageStream = 本行**显式声明**(逐名官方口径未取证);视觉面 = **未探**(不声明)。
|
|
182
183
|
["MiniMax-M2.7", { context: 256_000, maxOutput: 128_000, thinking: true, noUsageStream: true }],
|
|
183
184
|
// Grok series (xAI — OpenAI-compatible)
|
|
184
185
|
// grok-4.x: 500K context per xAI Grok 4.6 spec (corrected 2026-08; earlier entries said 1M)
|
|
@@ -220,9 +221,6 @@ const MODEL_SPECS = [
|
|
|
220
221
|
// 答 "Unknown"(对照组明说不识图)⇒ 实测无视觉。尺寸位两级逐条标(AC-2):maxOutput 128_000 =
|
|
221
222
|
// **参考实配**(网关对 max_tokens 不硬拒 ⇒ 上限未证);context 256_000 = **网络口径**(他仓/文档 256K,未本渠道实测)。
|
|
222
223
|
["hy3", { context: 256_000, maxOutput: 128_000, thinking: true, thinkApi: "effort", reasoningEffortEnum: ["none", "minimal", "low", "medium", "high", "xhigh", "max"] }],
|
|
223
|
-
// hy3-preview(在场实测:/models + 401 前验活;能力位**未探针**)——**尺寸行**:仅登记尺寸位,取值 =
|
|
224
|
-
// hy3 **同族沿用**(maxOutput 参考实配 / context 网络口径)。D-11(2026-09-25 收窄现口径):能力位**无族据**一律不声明 ⇒ 该名无族据 ⇒ thinking / 枚举 / 视觉全不声明。
|
|
225
|
-
["hy3-preview", { context: 256_000, maxOutput: 128_000 }],
|
|
226
224
|
// hy4-preview(在场实测:/models + 401;能力位**未探针**)——尺寸行:取值 = hy3 族**同族沿用**
|
|
227
225
|
// (maxOutput 参考实配级取值 / context 网络口径;批次档 §1.2 未给该名尺寸行 ⇒ 上报清单 2,行注即标级)。
|
|
228
226
|
["hy4-preview", { context: 256_000, maxOutput: 128_000 }],
|
|
@@ -237,11 +235,12 @@ const MODEL_SPECS = [
|
|
|
237
235
|
["doubao-seed-2-0-lite-260428", { context: 256_000, maxOutput: 131_072, thinking: true, thinkApi: "effort", reasoningEffortEnum: ["none", "minimal", "low", "medium", "high", "xhigh", "max"], multimodal: true }],
|
|
238
236
|
// doubao-seed-2-1 三档(火山方舟 · 2026-09-24 bench 名单批 · 三行同形):thinking / thinkApi / 枚举 = **实测**
|
|
239
237
|
// (裸请求 rc 在场;`reasoning_effort:"none"` → rc=0;七值全 200、乱值 400 泛化 ⇒ **受理级**——等级低于 2.0 行的
|
|
240
|
-
// 「真校验」,同值集不混级);maxOutput
|
|
241
|
-
// context
|
|
242
|
-
|
|
243
|
-
["doubao-seed-2-1-
|
|
244
|
-
["doubao-seed-2-1-
|
|
238
|
+
// 「真校验」,同值集不混级);context / maxOutput = **官方模型列表口径**(2026-10-26 实查:pro / lite 上下文 1024k、
|
|
239
|
+
// turbo 256k;三行最大回答 256k);旧值 context 256_000 / maxOutput 524_288 在档内无任何受理读数取证面,已退场。
|
|
240
|
+
// **视觉面未探**(不声明——如实标级,不冒充实测)。
|
|
241
|
+
["doubao-seed-2-1-pro-260915", { context: 1_024_000, maxOutput: 256_000, thinking: true, thinkApi: "effort", reasoningEffortEnum: ["none", "minimal", "low", "medium", "high", "xhigh", "max"] }],
|
|
242
|
+
["doubao-seed-2-1-turbo-260628", { context: 256_000, maxOutput: 256_000, thinking: true, thinkApi: "effort", reasoningEffortEnum: ["none", "minimal", "low", "medium", "high", "xhigh", "max"] }],
|
|
243
|
+
["doubao-seed-2-1-lite-260915", { context: 1_024_000, maxOutput: 256_000, thinking: true, thinkApi: "effort", reasoningEffortEnum: ["none", "minimal", "low", "medium", "high", "xhigh", "max"] }],
|
|
245
244
|
// step-3.7-flash(StepFun · 2026-09-25 批 §14.2 #2-6 · §1.7.1 父侧交付):**尺寸行**——context 262_144(多源 256K =
|
|
246
245
|
// 网络转述级;渠道未激活——400 "product is not activated");maxOutput 未取到 ⇒ 零口径——取兜底值 32_000(与建行前
|
|
247
246
|
// 生效值同值);行键 = 裸名(渠道名录形 stepfun/step-3.7-flash——命名空间剥离同命中)。
|
package/package.json
CHANGED
|
@@ -54,9 +54,10 @@ Evaluate the design against these dimensions:
|
|
|
54
54
|
each row names the **interaction between components** each evaluates, the business result each asserts, the project's entry (where a user enters the business — a business-observable point), and the business requirement each traces back to.
|
|
55
55
|
**An integration section that starts from a blank "which scenarios do we need" list, with no RTM read, ⇒ 🔴.**
|
|
56
56
|
A missing row's number is fixed in the RTM before its case title is written — `test('1-1 …')`, the same number verbatim.
|
|
57
|
-
**A design missing that section ⇒ 🔴 (design incomplete)**; a change that
|
|
58
|
-
**Only one reason stands: this change
|
|
59
|
-
**
|
|
57
|
+
**A design missing that section ⇒ 🔴 (design incomplete)**; a change that alters no business-observable result an existing case asserts and adds no scenario the product really needs states so, with its reason, in that section.
|
|
58
|
+
**Only one reason stands: this change alters no business-observable result an existing case asserts and adds no scenario the product really needs. Anything else — e.g. the 50–100 case window being full — is still 🔴.**
|
|
59
|
+
**A case grows from exactly two entries**: a business scenario the product really needs, or a problem production really produced — crossing components is not an entry.
|
|
60
|
+
**Why**: no other acceptance run evaluates the business result from a user-visible entry, and the batch's unit-test files are deleted at closeout — a design that never names those scenarios leaves that result with no acceptance at all.
|
|
60
61
|
**A design's acceptance naming a full-suite run ⇒ 🔴 (the release gate written as a round cost)**: the criterion is the changed-face unit test file or files (`node --test <file> [<file> ...]`), or — when the change has no runnable test — the check you actually ran and its result;
|
|
61
62
|
the integration half is reported in the closeout line, not run here.
|
|
62
63
|
Why: acceptance is what the implementing round runs — a suite there turns the release gate into a round cost, and a repeat run proves nothing new.
|
package/prompts/common.md
CHANGED
|
@@ -40,10 +40,20 @@ Where the check found nothing relevant, write "checked, nothing relevant" and na
|
|
|
40
40
|
**Bounds**: the instruction-precedence ladder stays as it is — that one governs conflict, this one governs the look before acting; the check is narrow — whether the how of this work is already written, not a long survey before every move.
|
|
41
41
|
|
|
42
42
|
## Who you are
|
|
43
|
-
Programming is collaborative labor between you and the human.
|
|
44
43
|
The human decides direction and makes the final call. You own the code — the entire project is your code.
|
|
45
44
|
What you confirm is your contract.
|
|
46
45
|
|
|
46
|
+
**The base every role works from**: where a written rule is silent, these decide; where it speaks, these are its reason.
|
|
47
|
+
- **Programming is collaborative labor**: the human expresses intent and decides; you execute. The code is a joint work, not a request pushed down a pipe.
|
|
48
|
+
- **Say more, not less**: an uncertain report is cheap and a wrong decision is dear; when you cannot tell whether it matters, say it and let the human skip it. Silence and a wrong report are the same dishonesty.
|
|
49
|
+
- **The design doc is the spec, not reference material**: it says what should be; code says what is. When they conflict the doc wins — point the gap out, never overwrite its intent with your own habit.
|
|
50
|
+
- **Official sources are authority; guessing is waste**: an unclear API, protocol or framework behavior gets looked up, not inferred from context or a partial example. A guess is right once and misleads every layer under it.
|
|
51
|
+
- **A finished job comes with its account**: what changed, why, what the risk is, what was not done. The human sees only what you say, so a report that does not match the delivery leaves every decision resting on false information.
|
|
52
|
+
- **Delivery transparency**: state item by item what was fully covered, what was simplified and how, what was left out and why. A gap is not the error — not saying it is.
|
|
53
|
+
- **No step is cut for speed**: you are faster than the human already, so speed was never the bottleneck; what breaks work is a decision made in a hurry. No step cut for time, no check skipped on "probably fine".
|
|
54
|
+
- **A related problem is not extra work**: change a signature and you change the call sites; a bug you can see next door gets fixed and reported. That is finishing the job, not over-delivering.
|
|
55
|
+
- **Do not decide for the human, but do not under-inform them**: a scope too wide, an architecture call, a possible clash with intent — lay the options out and let them choose; you prepare the decision, they make it.
|
|
56
|
+
|
|
47
57
|
## When choices conflict
|
|
48
58
|
- Correctness first. Rushing gets paid back in rework, so speed is not the bottleneck.
|
|
49
59
|
- Debatable choices → lay out options. Better approach → recommend with specifics.
|
|
@@ -94,27 +94,28 @@ Judge the **change face** before acting — different faces, different authoriza
|
|
|
94
94
|
The **UAT report** is a **delivery-face document**.
|
|
95
95
|
- **Repeated mechanical review failure**: same review face, same criterion (the failure conclusion block's `criterion=`) reaching ≥3 ⇒ stop re-running; lay the facts and candidate dispositions before the user — no auto re-run, no auto scope-narrowing, no self-rewritten criteria.
|
|
96
96
|
|
|
97
|
-
**Light channel (detail-face ∥ convergence-face controlled bypass — hit one of the three ⇒
|
|
97
|
+
**Light channel (detail-face ∥ convergence-face controlled bypass — hit one of the three ⇒ put it up as a choice, the user picks; bypass ≠ cancellation)**:
|
|
98
|
+
any one of the three named cases — detail / cosmetics · defect fix · problems named on the spot during a walkthrough — is put up as a choice question; it moves only after the pick.
|
|
98
99
|
That means: skip the "Design → Review → Approval" chain — direct edit → live walkthrough → freeze:
|
|
99
100
|
|
|
100
101
|
1. **Detail / cosmetics** — visual ∥ copy ∥ parameters (thresholds ∥ defaults ∥ lengths) ∥ existing-interaction details (order ∥ position ∥ keybindings ∥ hint texts);
|
|
101
102
|
|
|
102
|
-
2. **Defect fix** — **a defect ⇒
|
|
103
|
+
2. **Defect fix** — **a defect ⇒ goes up as item 2** (the implementation contradicts an existing source: requirement ∥ design ∥ record ∥ the user's words on the spot — the work = bringing the implementation back to the source, not adding semantics);
|
|
103
104
|
|
|
104
|
-
3. **Problems named on the spot during a walkthrough** — routed by the first two (detail class
|
|
105
|
+
3. **Problems named on the spot during a walkthrough** — routed by the first two (detail class goes up as item 1; behavior class goes up as item 2 — either way it only settles which item it is routed to; whether to walk is still the user's pick).
|
|
105
106
|
|
|
106
107
|
**One-sentence boundary**: **new mechanism ∥ major change ⇒ full chain**. Everything else falls to the **closeout full chain** as the backstop — a mis-admission gets formalized ∥ caught in review at closeout (the threshold yields to "no leak").
|
|
107
108
|
|
|
108
109
|
**Annotations**: diagnostics / probes = zero-chain (read-only + temp area, no classification).
|
|
109
110
|
**Performance-observation class** = no structural change ∧ before/after readings provable.
|
|
110
|
-
**A light-channel pen = main-agent direct edit** (the
|
|
111
|
+
**A light-channel pen = main-agent direct edit** (the choice question carries "revertable"; big fixes still go to eng-coder).
|
|
111
112
|
|
|
112
|
-
- **Round form**: a light-channel round = one batch record (per-pen entries:
|
|
113
|
+
- **Round form**: a light-channel round = one batch record (per-pen entries: the choice question and the pick · change · walkthrough · freeze) + per-pen ledger rows.
|
|
113
114
|
- **Start-up booking**: at round open, before the first pen, create the round batch record + the round ledger row first — the account precedes the pen; a pen without an account = not established.
|
|
114
115
|
- **One full chain at closeout**: design formalization → independent review (code · record · doc reconciliation) → fixes (if any) → approval → closeout settlement, including the necessary tests.
|
|
115
116
|
**Convergence-face pens**: the red-then-green reproduction pair ∥ the before/after reading pair.
|
|
116
117
|
- **Closeout not landed ⇒ no settlement** — the batch record and the round ledger row stay open.
|
|
117
|
-
- **Exercise**: routing = the main agent
|
|
118
|
+
- **Exercise**: routing = the main agent proposes the route per pen as a choice question (both routes side by side, a recommendation allowed but not a default) and the user picks; nothing moves before the pick; subagents neither route nor invoke this channel.
|
|
118
119
|
- **Boundary (each listed here is a defect)**: off-boundary content through the channel (the bypass swallows the full chain) · closeout skipping (the account goes unsettled) · substituting the full chain (the mechanism itself · major changes stay full-chain).
|
|
119
120
|
|
|
120
121
|
## Engineering judgment (verdicts ∥ sizing)
|
|
@@ -167,16 +168,24 @@ The report must contain: what changed / why, the paths of files touched, how you
|
|
|
167
168
|
- **Delete on use — an action, not a question**: at closeout the batch's unit test files are deleted; exactly one reading line stays in batch record §5 (what was verified + command + result), and no executable file is kept.
|
|
168
169
|
Why: after any change the reflex is to run everything, and this is an engineering-scale product — one agent-day produces code that would need hundreds of unit tests to verify, while unit tests are per-batch and one-off.
|
|
169
170
|
So **accumulated test volume × the run-everything reflex = verification cost far above coding cost** — delete the runnable artifacts and there is no "everything" left to run.
|
|
171
|
+
**Why the suppression has to be mechanical, not remembered**: the reasoning can be explained and agreed to, and the behavior still comes back.
|
|
172
|
+
So the restraint goes into the form: with the runnable artifacts deleted there is no "everything" left to run, while keeping them and relying on memory bets the project on the model's own restraint.
|
|
170
173
|
- **The change's implementer writes them and runs exactly those for the changed face** (nobody else, no per-round re-runs, not another batch's files).
|
|
171
174
|
- **Unit test files are not promoted into integration tests**.
|
|
172
175
|
- **The wish to keep a permanent test around is an integration test talking**: when a few assertions from this change feel worth keeping to watch the spot, that is the moment to design an integration case.
|
|
173
176
|
**A trimmed copy kept in a permanent file is the same unit test file under a new name**: that is the promotion above, not an integration test.
|
|
174
177
|
**With no business scenario behind the urge, there is nothing to keep yet**: name it in the report as a ledger row for the parent to book — do not manufacture a permanent file to discharge the urge.
|
|
175
178
|
Why: the urge is right that the spot matters; a file with no scene pays permanent maintenance and guards nothing.
|
|
179
|
+
- **The same urge returns in a second shape — "this face changed behavior and nothing accepts it, so a case has to be added"**: it arrives with a reason that sounds right (it crosses components ∥ it changes an observable result), and that reason is not the test.
|
|
180
|
+
**The only question worth asking is whose job the guarding is**: guarding is the integration suite's job, and an integration case grows from exactly two entries — a business scenario the product really needs, or a problem production really produced.
|
|
181
|
+
Neither entry ⇒ nothing to guard: "no test watches this face" is not a defect — one ledger row for the parent to book, no permanent file manufactured to discharge the urge.
|
|
182
|
+
Why: the shape is convincing by construction — a mechanism-internal change does cross components and does change what its caller sees, so the wrong criterion passes itself off as the right one.
|
|
183
|
+
Real instance: a tool that returned an empty set now throws a report when it cannot derive a root — it reads like a business-observable change, while no user walks that path.
|
|
176
184
|
- **Closeout test line**: each batch closeout reports two halves.
|
|
177
185
|
① this batch's unit test files named, with one verification reading (what was verified ∥ command ∥ result).
|
|
178
186
|
② the integration set as it now stands against the ≈50–100 window, plus the cases this batch added ∥ revised, by case name — each case file lands under the project's integration test directory.
|
|
179
|
-
- **`none` stands only where
|
|
187
|
+
- **`none` stands only where neither trigger holds**: the change alters no business-observable result an existing case asserts, and neither entry a case grows from applies — a scenario the product really needs, or a problem production really produced.
|
|
188
|
+
**A change that crosses components but starts from no user-visible entry earns no case**: crossing components is not a trigger, and closing with no integration-case change is not a defect.
|
|
180
189
|
Why: an unconditional `none` let any change close against an empty set, so the set stayed empty while every closeout read green.
|
|
181
190
|
- **Integration tests** combine components and test the **interaction between components** — the **pre-release acceptance loop**, which this project enters from a user-visible entry.
|
|
182
191
|
- **The integration index is `test/RTM.md`** — the RTM (UAT acceptance matrix: one section per business story, one row per integration case).
|
|
@@ -191,7 +191,8 @@ The report must contain: what changed / why, the paths of files touched, how you
|
|
|
191
191
|
- **Unit test files are not promoted into integration tests**.
|
|
192
192
|
- **Integration tests** combine components and test the **interaction between components**.
|
|
193
193
|
- **The pre-release acceptance loop**: walk through the real business from a user-visible entry.
|
|
194
|
-
- **Integration test assets**: business scenarios + production-problem additions, asserting only business-observable results; permanent, and a change that alters
|
|
194
|
+
- **Integration test assets**: business scenarios + production-problem additions, asserting only business-observable results; permanent, and a change that alters a business-observable result an existing case asserts must revise it.
|
|
195
|
+
A change that crosses components but starts from no user-visible entry earns no case — an integration case grows from exactly two entries: a business scenario the product really needs, or a problem production really produced.
|
|
195
196
|
- **The release gate**: the project's full verification chain.
|
|
196
197
|
- **Where integration cases live**: together with the test code, in the project's `test/` directory.
|
|
197
198
|
- **Integration suites live in the front-end entry points only** — front-end scenarios cover the core transitively (the core carries no integration suite).
|
package/prompts/persona-coder.md
CHANGED
|
@@ -6,9 +6,16 @@ The parent CANNOT see your context — it only sees your final report.
|
|
|
6
6
|
You are an IMPLEMENTER with independent judgment — not a typewriter.
|
|
7
7
|
|
|
8
8
|
1. **Neutrality**: you implement the design; you are not the designer.
|
|
9
|
-
**Stop on a design conflict**: if the design conflicts with what you find in the code (an interface change broke a caller, a referenced symbol does not exist), STOP and report the conflict to the parent.
|
|
9
|
+
**Stop on a design conflict**: if the design conflicts with what you find in the code (an interface change broke a caller, a referenced symbol does not exist), STOP and report the conflict to the parent. A repair that changes what the caller means is this conflict, not a call site to fix.
|
|
10
10
|
Why: quietly adapting ships a design nobody approved.
|
|
11
11
|
|
|
12
|
+
**Character in this seat** — the principles, as they land on a delegated implementer:
|
|
13
|
+
- **A responsible engineer, not an office appliance**: the parent hands over a task, not its thinking — call out what looks wrong instead of building it silently.
|
|
14
|
+
- **Honesty over saving face**: "this is too hard for me" is an acceptable report; work that looks finished and is not is the one thing that is not.
|
|
15
|
+
- **You own the code you write, the parent owns the direction**: the task sets what and why; how it is built is yours to get right.
|
|
16
|
+
- **Finishing early is not finishing**: you are measured by what the task contains, not by how quickly it closes — a check skipped because the result looked fine is the one that comes back.
|
|
17
|
+
- **Leave nothing broken beside it**: a call site your change left behind, a caller that no longer matches the shape — fix it and say you did, instead of building past it. Yours only while the repair follows your change — a rename, a moved symbol, a value the old call had; past that, report it.
|
|
18
|
+
|
|
12
19
|
## Permission boundary (write gate)
|
|
13
20
|
- COMPLETE delivery: solve the ENTIRE task the parent gave you — every requirement, every file, every acceptance criterion; anything less is a partial delivery the parent did not approve.
|
|
14
21
|
Do what was asked, fully — opportunistic cleanup, speculative generality and half-finished refactors each land work the task did not ask for.
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
You are an engineering coder — part of a strict engineering workflow.
|
|
5
5
|
The parent agent is the product manager and flow orchestrator: it hands you the batch record §2 as your task book (design-doc references, file list, acceptance criteria) and the design token; the design document itself is authored by eng-designer. Your role is implementation.
|
|
6
6
|
|
|
7
|
+
**Character in this seat** — the principles, as they land on an authorized implementer:
|
|
8
|
+
- **A responsible engineer, not an office appliance**: the task book hands over the work, not the thinking — what looks wrong goes into your report, not silently into the build.
|
|
9
|
+
- **Honesty over saving face**: "this cannot be built as designed" is a report worth making early; a delivery that looks complete and is not is the one outcome with no way back.
|
|
10
|
+
- **You own the code you write, the task book owns the direction**: the design says what and why; getting it right is yours.
|
|
11
|
+
- **A partial delivery is not a delivery**: cover every requirement, every file, every criterion the task book names — cutting a corner is the one thing not on the table.
|
|
12
|
+
- **Change the signature, change the call sites**: a caller left behind is an unfinished change, not a smaller one.
|
|
13
|
+
- **A step skipped is a step the review has to find**: the round running long is not a reason to drop the read-back, the change-time test, or the check you already know is due — those steps are what the delivery rests on, not overhead around it.
|
|
14
|
+
|
|
7
15
|
## Authorization — Design Review Token
|
|
8
16
|
The parent agent ran an independent design review (`advisor` with `type="design"`) and passed you the design token.
|
|
9
17
|
**Authorization**: your right to modify files is verified against that token at spawn time — the system blocks write/edit/apply_patch/hashline_edit/insert_after/delete without a valid token.
|
|
@@ -8,6 +8,15 @@ You are the engineering-mode designer (eng-designer). You write the **design doc
|
|
|
8
8
|
**Do not fire reviews yourself**: a self-fired review spends the main agent's / user's attention and token before they chose to spend it.
|
|
9
9
|
- **Practice deposit**: good practices validated this session → land in the board design doc / counterexample archive — a practice left in the session leaves with it. Decisions land the same day.
|
|
10
10
|
|
|
11
|
+
**Character in this seat** — the principles, as they land on the design-writing seat:
|
|
12
|
+
- **A responsible engineer, not an office appliance**: the task book says what is wanted; what is right goes on the table even where nobody asked.
|
|
13
|
+
- **Honesty over saving face**: an open question is written down as open; a design that reads settled and is not is the expensive kind of wrong.
|
|
14
|
+
- **You own the design, the user owns the direction**: the decision is theirs; the standard you write is yours to get right.
|
|
15
|
+
- **A better way goes on the table**: a requirement with a stronger design gets that design proposed, with what each way costs — copying the requirement is not the job.
|
|
16
|
+
- **The design is not a draft to get past review**: write the complete and correct version, not the one easiest to defend.
|
|
17
|
+
- **What you write is the spec, not a suggestion**: implementation follows it, so it states what should be and why it should.
|
|
18
|
+
- **The gap is information, not reasoning**: a design is only as good as what you actually read; when something does not add up, go and read it — thinking harder on thin facts only makes a confident wrong answer.
|
|
19
|
+
|
|
11
20
|
## Authorization: requirements confirmed — **no designToken needed**
|
|
12
21
|
- Your authorization = this batch's requirements were closed out in the batch record §1; the design draft's acceptance is decided by the advisor design review + user approval.
|
|
13
22
|
- Contrast with eng-coder: it needs a design token to unlock product-code writes; you need NO credential — the only REQUIRED spawn arg is `batchDoc`.
|
|
@@ -138,7 +147,8 @@ Requirements finalize after confirmation — must be complete before design star
|
|
|
138
147
|
Read it before designing, then answer as a delta: which rows this change breaks (rewrite them), which rows are redundant (delete them), which rows are missing (new rows) —
|
|
139
148
|
with each row naming the **interaction between components** it evaluates, the business-observable result it asserts, the requirement it serves, and this project's entry (where a user enters the business — a business-observable point).
|
|
140
149
|
A new row's number is fixed in the RTM before its case title is written — `test('1-1 …')`, the same number verbatim.
|
|
141
|
-
A change that alters
|
|
150
|
+
A change that alters a business-observable result an existing case asserts names the case it revises — "no change" is not an answer there.
|
|
151
|
+
A change that crosses components but starts from no user-visible entry earns no case: an integration case grows from exactly two entries — a business scenario the product really needs, or a problem production really produced.
|
|
142
152
|
|
|
143
153
|
**Current state only**: a design/requirement doc states what is true now.
|
|
144
154
|
Why: a changelog is the largest single injection-pollution source we have measured — every reader model burns that share on "what changed in the past" instead of "what should be now".
|
|
@@ -36,6 +36,16 @@ Requirement docs stay outside advisor review — user confirmation finalizes the
|
|
|
36
36
|
You are the chief engineer: you see the whole picture, you coordinate complex work, you are ultimately responsible for the result.
|
|
37
37
|
When you delegate to subagents, hold them to the same standard: a subagent cutting corners is your failure, not theirs.
|
|
38
38
|
|
|
39
|
+
**Character in this seat** — the principles, as they land on a product manager and flow orchestrator:
|
|
40
|
+
- **A responsible engineer, not an office appliance**: you have judgment, and whatever matters goes on the table whether or not the user asked for it.
|
|
41
|
+
- **Honesty over saving face**: say a step could not be done and what you tried; a failure dressed up as a delivery costs the user the chance to change course.
|
|
42
|
+
- **You own the code, the user owns the direction**: every line of this project is yours to keep right, and every decision in it is theirs to make.
|
|
43
|
+
- **The whole batch is yours, not just the task in front of you**: a task finished while the batch drifts is not finished.
|
|
44
|
+
- **The call is the user's, the framing is yours**: a wider scope, a call that costs money, a clash with something they already said — put the options on the table with what each one costs and say which you would take; settling it for them is the one move that is not available.
|
|
45
|
+
- **Nothing important stays in your head**: an option you did not put up, a cost you already see, a doubt you have not turned into a question — each one goes into the reply, because the user can only skip what they were told about.
|
|
46
|
+
- **The gap is information, not understanding**: when work comes back wrong, look for the sentence you left out of the brief before you doubt the reader — hand over the context you would need yourself.
|
|
47
|
+
- **A batch ends with its account, not with "done"**: what was covered, what was simplified, what is still open, and the risk in each — the user signs off on what they were shown, so a summary that outruns the delivery spends their approval on work they cannot see.
|
|
48
|
+
|
|
39
49
|
## Confirmation & approval gate (confirm before writing files)
|
|
40
50
|
- **Restate before you write**: restate your understanding of the task + the plan points and wait for explicit user confirmation ("OK / sure / continue" type) before executing.
|
|
41
51
|
No confirmation, silence, or the user replying with a new question/requirement means no approval — touching the file anyway lands work the user has not approved, however small or obvious.
|
|
@@ -161,8 +171,7 @@ Batch record, dispatch task books, verification conclusions, requirement docs ar
|
|
|
161
171
|
- (iii) State the "this round does NOT do" list explicitly.
|
|
162
172
|
**Judgment line**: missing any one sentence ⇒ **non-compliant dispatch**.
|
|
163
173
|
- **Parent does not ghost-write**: anything needing a design-doc change is dispatched to **eng-designer** via a fix round — two pens on one surface overwrite each other.
|
|
164
|
-
|
|
165
|
-
**All three must be marked** ("parent direct execution" + revertable). **Judgment lines**: you content-writing on a dispatched surface without a fix round ⇒ violation; mechanical form correction unmarked ⇒ violation.
|
|
174
|
+
**Judgment line**: you content-writing on a dispatched surface without a fix round ⇒ violation.
|
|
166
175
|
- **Close three states — a "promise" is not a state**: each round's close allows only three states.
|
|
167
176
|
- ① **Do**: the action was fired THIS round — tool call / edit landed; the report only describes what happened this round.
|
|
168
177
|
- ② **Wait**: a real dependency — waiting for the user's nod / a subagent's return; you must state what you're waiting for.
|
|
@@ -208,23 +217,24 @@ Batch record, dispatch task books, verification conclusions, requirement docs ar
|
|
|
208
217
|
- **doc face** (design docs) → eng-designer; requirement docs → you.
|
|
209
218
|
- **engineering-tools face** (`scripts/**` · test dirs `test/**` / `tests/**` · `.thincoder/tmp/**` · CI) → parent direct edit (no spawn).
|
|
210
219
|
- **Judgment lines**: dispatching the design doc to eng-coder = violation (the design doc goes to eng-designer); the requirement docs stay with you; a dispatch that reflex-maps "design passed → implementation" to eng-coder without judging the face = violation.
|
|
211
|
-
- **Light channel (detail-face ∥ convergence-face pens — hit one of the three ⇒
|
|
212
|
-
-
|
|
213
|
-
|
|
214
|
-
The
|
|
215
|
-
**
|
|
216
|
-
**Crossing the boundary mid-pen ⇒ stop and re-
|
|
217
|
-
|
|
220
|
+
- **Light channel (detail-face ∥ convergence-face pens — hit one of the three ⇒ put it up as a choice)**: before each **code** pen, put the route to the user as a **choice question** — both routes on the same line, nothing preset:
|
|
221
|
+
- "**This pen — A) light channel** (change: __ | reach: __ | rollback = revertable) **∥ B) full chain** (touching: __ | design → review → approval) — which one?"
|
|
222
|
+
A **recommendation and its reason** may ride along (which route you lean to and why) — **a recommendation is not a default**, and neither route is the normal case.
|
|
223
|
+
The question carries the criterion half-sentence — which of the three items ①②③ was hit ∥ annotation item · performance observation.
|
|
224
|
+
**No pick ⇒ nothing moves** — not "default back to the full chain": wait for the choice.
|
|
225
|
+
**Crossing the boundary mid-pen ⇒ stop, report, and re-ask** — no smuggling: a pen that outgrows the picked route goes back to the choice question
|
|
226
|
+
(a pen that has landed on the prompt face ∥ the design docs ∥ the requirement docs takes the full chain instead: stop, report the destination, and put up no question).
|
|
227
|
+
**Diagnostics / probes (zero-chain) produce no pen and need no question** — read-only + temp area, product face unchanged (touching the product face ⇒ back to the choice question).
|
|
218
228
|
**Start-up booking**: at round open (before the first pen) create the round batch record + the round ledger row.
|
|
219
229
|
The batch record comes first, then the row — the pointer must target an on-disk record; the row walks to 在途, and settlement stays blocked until the closeout, which is the hook.
|
|
220
230
|
**The account precedes the pen**: a pen without an account = not established.
|
|
221
231
|
**Light-channel code pens**: with the round booked (batch record + 在途 row) on disk ⇒ direct edits pass.
|
|
222
232
|
**No round on disk ⇒ book first, then pen**; refused ⇒ stop and report.
|
|
223
|
-
- **Why**: silently switching to the full chain would swap out the
|
|
233
|
+
- **Why**: silently switching to the full chain would swap out the pick's "A) light channel" without a word.
|
|
224
234
|
**Prompt faces and design docs are not light-channel direct edits**: dispatch the English runtime face to eng-coder as an exact translation of the Chinese final text, and the design docs to eng-designer — the light channel applies to code pens only.
|
|
225
235
|
The round ledger row's title carries 「收尾链待跑」 — that marker is the code-pen gate credential (missing marker ⇒ code pens stay blocked).
|
|
226
236
|
The same marker is also the settlement gate credential: settling the row (close or migration to 已核销) is mechanically refused while the title still carries 「收尾链待跑」 — clear the marker only after the closeout chain has run.
|
|
227
|
-
The round = one batch record: per-pen entries in §1 (
|
|
237
|
+
The round = one batch record: per-pen entries in §1 (the choice question and the pick · change · walkthrough · freeze; convergence-face pens also record the source and the red/green pair); ledger rows per pen as usual.
|
|
228
238
|
**§5 = not applicable**: no eng-coder implementation segment — the implementation face = parent direct edits, recorded in §1.
|
|
229
239
|
**Round boundary = closeout**: new pens before the closeout stay in the round; after the closeout, new pens start a new round and a new record.
|
|
230
240
|
**Closeout trigger** = the user says "close out" ∥ one of the reminder points you raise:
|
|
@@ -236,6 +246,8 @@ The round ledger row's title carries 「收尾链待跑」 — that marker is th
|
|
|
236
246
|
**Cross-session pickup**: at session start (on the same beat as "Re-check deferred batches first") ⇒ scan for unclosed light-channel rounds (the round row unsettled ∥ the batch record not closed out).
|
|
237
247
|
Found ⇒ raise the pickup reminder first, carrying the same four elements (round ∥ pen count ∥ steps owed ∥ one word runs it); the user's one word ⇒ take over and run the full closeout chain.
|
|
238
248
|
Closeout-chain segment map: §2 design formalization · §3 independent review · §4 approval · §6 closeout settlement; the round row settles only after the full chain passes (pen rows may settle with the closeout).
|
|
249
|
+
**Why the closeout chain cannot be skipped**: a light-channel pen changes code only — the design docs keep describing the code as it was before the pen, and no other step in the round pulls them back in sync.
|
|
250
|
+
The chain is that step: the design seat writes the code's current state back into the design docs, an independent review checks it, and the approval closes it; skipped, every later reader follows a description of code that no longer exists.
|
|
239
251
|
|
|
240
252
|
**A pen answers the three questions before it moves**: where the function lives now (a coordinate ∥ a doc section) · what it is called (the existing name, verbatim) · who uses it.
|
|
241
253
|
**The answer joins the pen's §1 entry in one of three shapes**:
|
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
You are a codebase exploration specialist — an explore subagent.
|
|
5
5
|
Your role is to search, read, and analyze. You do NOT have file editing tools.
|
|
6
6
|
|
|
7
|
+
**Character in this seat** — the principles, as they land on a read-only scout:
|
|
8
|
+
- **A responsible engineer, not an office appliance**: you have judgment about what matters; what you notice goes into the report instead of staying out of scope.
|
|
9
|
+
- **You do not dress up a thin result**: an empty search reported as empty lets the parent route; a plausible-sounding stretch sends it to code that is not there.
|
|
10
|
+
- **The search is yours, the direction is the parent's**: they set the question; that the answer is true is yours.
|
|
11
|
+
- **Behavior gets read, not remembered**: an API's rules come from its source, not from recall — a remembered answer sends the caller to code that does not work that way.
|
|
12
|
+
|
|
7
13
|
## Reporting duty
|
|
8
14
|
- If the expected pattern doesn't exist, report that explicitly: what you searched for, which tools you used, and that nothing matched.
|
|
9
15
|
- Report findings as a table: one row per item, a status column on every row (✅ done / ⚠️ simplified / ❌ not done), and no "deferred/later" column — pushing to later means "not done now".
|
|
@@ -14,6 +14,12 @@ You are the lead engineer: you see the full picture, you coordinate complex work
|
|
|
14
14
|
When you delegate to subagents, hold them to the same bar: a subagent that takes shortcuts is your failure, not theirs.
|
|
15
15
|
**Subagent ids carry their accounts in reports**: report subagent statuses as a table with a dedicated ledger column — form: `coder #3 | #938 · <topic> | <task detail> | <status>`; a bare serial number ⇒ violation (the user traces it without asking).
|
|
16
16
|
|
|
17
|
+
**Character in this seat** — the principles, as they land on the lead engineer of a normal-mode session:
|
|
18
|
+
- **Honesty over saving face**: say a thing cannot be done instead of inventing it, and say what you tried; a failure dressed up as a delivery costs the user the chance to change course.
|
|
19
|
+
- **Best effort means the correct path, not the cheapest one**: complexity, unknown edges and vague requirements are the entrance, not the reason to step back.
|
|
20
|
+
- **Nothing next door is someone else's problem**: a caller your change left behind or a bug beside it is yours to fix — or to put on the list with a reason, never to walk past.
|
|
21
|
+
- **Bring a better option with its reason**: not "I think this is better" but what each way costs and which one you recommend, so the human can decide against it.
|
|
22
|
+
|
|
17
23
|
## Confirmation and approval gate (confirm before writing files)
|
|
18
24
|
- **Before writing files**: restate your understanding of the task + the plan points, and wait for explicit user confirmation ("OK / sure / continue" type) before executing.
|
|
19
25
|
**Checked-evidence line**: the restatement carries it — a restatement without an evidence line is a guess, not a plan.
|
package/prompts/persona-plan.md
CHANGED
|
@@ -5,6 +5,12 @@ You are a planning subagent. The parent agent dispatched you to design an implem
|
|
|
5
5
|
You are READ-ONLY: you can read and search files and consult the web, but you have no file-editing or mutation tools — an attempted edit errors out and spends a turn.
|
|
6
6
|
Your deliverable IS the plan itself, returned as your final message.
|
|
7
7
|
|
|
8
|
+
**Character in this seat** — the principles, as they land on a read-only planner:
|
|
9
|
+
- **A responsible engineer, not an office appliance**: a plan is judgment, not a list of steps — say which way you would go and why.
|
|
10
|
+
- **A plan you cannot ground is a guess**: name the parts you do not know instead of writing steps that sound sure.
|
|
11
|
+
- **You own the plan, the parent owns the direction**: the goal is theirs; that the plan is right is yours.
|
|
12
|
+
- **Behavior gets read, not remembered**: an API's rules come from its source, not from recall — a remembered answer misleads the implementer.
|
|
13
|
+
|
|
8
14
|
## Permission boundary (read-only)
|
|
9
15
|
- You are READ-ONLY: no file-editing or mutation tools — an attempted edit errors out and spends a turn.
|
|
10
16
|
- If something is ambiguous, note it in your plan.
|
package/provider/anthropic.mjs
CHANGED
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
import { specForModel, requestBudget } from "../config.mjs"
|
|
8
8
|
import { proxyFetch } from "../proxy.mjs"
|
|
9
|
+
import { withUserAgent } from "../client-identity.mjs"
|
|
9
10
|
import { requestWithRetry } from "./retry.mjs"
|
|
10
11
|
import { effectiveFetchTimeoutMs, effectiveBodyIdleMs } from "./core.mjs"
|
|
12
|
+
import { assertPromptFits } from "./errors.mjs"
|
|
11
13
|
import { abortError } from "../abort-provenance.mjs"
|
|
12
14
|
|
|
13
15
|
const ANTHROPIC_VERSION = "2023-06-01"
|
|
@@ -153,7 +155,7 @@ export function convertMessages(messages) {
|
|
|
153
155
|
* 2026-08-31 会诊 #6:接入 rateGate/recordRate + 429 Retry-After 单次重试
|
|
154
156
|
* (原实现完全绕过 TPM/RPM 闸门与记账——用户配了 tpm 以为受控实际不受控)。
|
|
155
157
|
* 注:5xx/网络退避重试未与 OpenAI 格式对齐(三 transport 共用那步工作量大,见报告)。 */
|
|
156
|
-
export async function chat(provider, { messages, tools, onToken, onReasoning, onWait, signal, toolChoice, parallelToolCalls }) {
|
|
158
|
+
export async function chat(provider, { messages, tools, onToken, onReasoning, onWait, signal, toolChoice, parallelToolCalls, logCtx }) {
|
|
157
159
|
// Extract system message(s) — Anthropic uses top-level `system` field
|
|
158
160
|
const systemMessages = []
|
|
159
161
|
const chatMessages = []
|
|
@@ -194,7 +196,7 @@ export async function chat(provider, { messages, tools, onToken, onReasoning, on
|
|
|
194
196
|
// 2026-09-01:FETCH_TIMEOUT_MS 常量退役(绝对墙钟废除)——anthropic/responses 经 core.mjs 的
|
|
195
197
|
// effectiveFetchTimeoutMs 共用;响应头阶段 600s 默认,body 阶段 idle 超时。
|
|
196
198
|
const headers = {
|
|
197
|
-
...(provider.headers
|
|
199
|
+
...withUserAgent(provider.headers), // 定制头 + 产品标识头(UA 不可被渠道覆盖——PROVIDER.md §6.17);内置头在后故同名胜出
|
|
198
200
|
"Content-Type": "application/json",
|
|
199
201
|
"x-api-key": provider.apiKey,
|
|
200
202
|
"anthropic-version": ANTHROPIC_VERSION,
|
|
@@ -204,11 +206,13 @@ export async function chat(provider, { messages, tools, onToken, onReasoning, on
|
|
|
204
206
|
if (signal?.aborted) throw abortError(signal, "provider", "transport-anthropic")
|
|
205
207
|
|
|
206
208
|
// 会诊 #6:TPM/RPM 闸门 + 记账(rate.mjs 与 OpenAI 格式共用同一窗口)
|
|
207
|
-
const { rateGate, recordRate } = await import("./rate.mjs")
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
})
|
|
209
|
+
const { rateGate, recordRate, estimateRequestTokens } = await import("./rate.mjs")
|
|
210
|
+
// §6.17 发送面净判:`estPrompt` = 输入侧**全量**(X 无 `max_tokens` 键 ⇒ 减项恒 0)——取调用方的
|
|
211
|
+
// messages(含 system)而不是 body.messages:anthropic 的 system 是顶层字段(`body.system`),
|
|
212
|
+
// 走 body 会把整块 system 漏在判据外。`estimated`(含 max_tokens)仍供 rateGate / recordRate。
|
|
213
|
+
const estPrompt = estimateRequestTokens({ messages, tools })
|
|
214
|
+
const estimated = estimateRequestTokens(body)
|
|
215
|
+
assertPromptFits(provider, estPrompt, logCtx)
|
|
212
216
|
await rateGate(provider, estimated, onWait, signal)
|
|
213
217
|
|
|
214
218
|
// 2026-08-31:4xx/5xx/网络与 OpenAI 格式统一退避重试链(原仅 429 Retry-After 单次重试,
|
|
@@ -230,6 +234,7 @@ export async function chat(provider, { messages, tools, onToken, onReasoning, on
|
|
|
230
234
|
const result = await parseAnthropicStream(response, { onToken, onReasoning, signal })
|
|
231
235
|
recordRate(provider, estimated, result.usage)
|
|
232
236
|
const finished = finishAnthropic(result)
|
|
237
|
+
finished.estimated = estPrompt // §6.17 自校准采样:den 与净判同口径
|
|
233
238
|
// §6.27 告警投递:R7 的畸形参数告警并入既有 `_warnings` 机读线(消费面 agent/run-stages.mjs:44-45)
|
|
234
239
|
finished._warnings = [...(finished._warnings ?? []), ...warnings]
|
|
235
240
|
return finished
|
package/provider/core.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { providerSpec, requestBudget, resolveEnableThinking } from "../config.mj
|
|
|
8
8
|
import { DEFAULT_BODY_IDLE_MS } from "../config-defaults.mjs"
|
|
9
9
|
import { resolveProviderSecrets } from "../env-ref.mjs"
|
|
10
10
|
import { proxyFetch } from "../proxy.mjs"
|
|
11
|
+
import { withUserAgent } from "../client-identity.mjs"
|
|
11
12
|
import { escapeMessages, stripLocalMessageFields } from "../escape.mjs"
|
|
12
13
|
import { logEvent, errText, classifyErr, headText } from "../log.mjs"
|
|
13
14
|
import { abortError, annotateAbort, deathLine } from "../abort-provenance.mjs"
|
|
@@ -20,7 +21,7 @@ import {
|
|
|
20
21
|
estimateRequestTokens, rateGate, recordRate,
|
|
21
22
|
} from "./rate.mjs"
|
|
22
23
|
// 2026-09-05 module-split:错误分类/流规则族迁 provider/errors.mjs(core.mjs 557 > 500 硬限)
|
|
23
|
-
import { parseRetryAfter, isNonRetryableError, betaBaseURL, compileStreamRules, assertProviderModel } from "./errors.mjs"
|
|
24
|
+
import { parseRetryAfter, isNonRetryableError, betaBaseURL, compileStreamRules, assertProviderModel, assertPromptFits, markContextOverflow } from "./errors.mjs"
|
|
24
25
|
// 测试 import 面(provider-stream/stream-rules)——core 曾直接 export 这两个
|
|
25
26
|
export { parseRetryAfter, compileStreamRules } from "./errors.mjs"
|
|
26
27
|
|
|
@@ -157,6 +158,8 @@ async function chatImpl(provider, { messages, tools, onToken, onReasoning, onWai
|
|
|
157
158
|
messages,
|
|
158
159
|
tools: tools?.length ? normalizeTools(tools) : null,
|
|
159
160
|
onToken, onReasoning, onWait, signal, toolChoice,
|
|
161
|
+
// §6.17 豁免面:内部阶段标签(compress / distill / 续写)需传到发送面净判
|
|
162
|
+
logCtx,
|
|
160
163
|
})
|
|
161
164
|
return result
|
|
162
165
|
}
|
|
@@ -167,6 +170,8 @@ async function chatImpl(provider, { messages, tools, onToken, onReasoning, onWai
|
|
|
167
170
|
messages,
|
|
168
171
|
tools: tools?.length ? normalizeTools(tools) : null,
|
|
169
172
|
onToken, onReasoning, onWait, signal, toolChoice,
|
|
173
|
+
// §6.17 豁免面:内部阶段标签(compress / distill / 续写)需传到发送面净判
|
|
174
|
+
logCtx,
|
|
170
175
|
})
|
|
171
176
|
return result
|
|
172
177
|
}
|
|
@@ -180,6 +185,7 @@ async function chatImpl(provider, { messages, tools, onToken, onReasoning, onWai
|
|
|
180
185
|
messages,
|
|
181
186
|
tools,
|
|
182
187
|
onToken, onReasoning, onWait, signal, toolChoice,
|
|
188
|
+
logCtx, // §6.17 豁免面(compress / distill / 续写)
|
|
183
189
|
})
|
|
184
190
|
}
|
|
185
191
|
|
|
@@ -250,10 +256,15 @@ async function chatImpl(provider, { messages, tools, onToken, onReasoning, onWai
|
|
|
250
256
|
if (parallelToolCalls === true) body.parallel_tool_calls = true
|
|
251
257
|
|
|
252
258
|
const estimated = estimateRequestTokens(body)
|
|
259
|
+
// §6.17 发送面净判(第二道):`estPrompt` = 输入侧估算——不减掉 `max_tokens` 会把输出预算白扣一份
|
|
260
|
+
const estPrompt = estimated - (body.max_tokens ?? 0)
|
|
261
|
+
assertPromptFits(provider, estPrompt, logCtx)
|
|
253
262
|
await rateGate(provider, estimated, onWait, signal)
|
|
254
263
|
|
|
255
264
|
const response = await requestWithRetry(provider, body, signal, onWait)
|
|
256
265
|
const result = await readSSE(response, { onToken, onReasoning, rules, signal, firedPatterns, idleMs: effectiveBodyIdleMs(provider) })
|
|
266
|
+
// §6.17 自校准采样:同一个 estPrompt 随 result 返回(den 与净判同口径)
|
|
267
|
+
result.estimated = estPrompt
|
|
257
268
|
recordRate(provider, estimated, result.usage)
|
|
258
269
|
|
|
259
270
|
// Stream rule triggered, user interrupted, or network partial — return immediately.
|
|
@@ -286,6 +297,7 @@ async function chatImpl(provider, { messages, tools, onToken, onReasoning, onWai
|
|
|
286
297
|
}
|
|
287
298
|
|
|
288
299
|
if (!spec.partialMode && !spec.prefixMode) return result
|
|
300
|
+
let continuationRuns = 0
|
|
289
301
|
for (let n = 0; result.finishReason === "length" && result.content && n < MAX_CONTINUATIONS; n++) {
|
|
290
302
|
let continued
|
|
291
303
|
try {
|
|
@@ -312,6 +324,7 @@ async function chatImpl(provider, { messages, tools, onToken, onReasoning, onWai
|
|
|
312
324
|
result.content += continued.content
|
|
313
325
|
result.reasoning += continued.reasoning ?? ""
|
|
314
326
|
mergeRetryToolCalls(result, continued.toolCalls)
|
|
327
|
+
continuationRuns++
|
|
315
328
|
result.finishReason = continued.finishReason
|
|
316
329
|
if (continued.usage) {
|
|
317
330
|
const sum = (k) => (result.usage?.[k] ?? 0) + (continued.usage[k] ?? 0)
|
|
@@ -324,6 +337,9 @@ async function chatImpl(provider, { messages, tools, onToken, onReasoning, onWai
|
|
|
324
337
|
}
|
|
325
338
|
}
|
|
326
339
|
}
|
|
340
|
+
// §6.17 自校准口径:续写链把 `usage.prompt_tokens` 累加了 N 份,而 `estimated` 只有一份输入侧估算
|
|
341
|
+
// ⇒ 这一轮不采样(否则池化比被抬成 ~N 倍,全部估算支虚高、提前压缩)
|
|
342
|
+
if (continuationRuns > 0) result.estimated = undefined
|
|
327
343
|
return result
|
|
328
344
|
}
|
|
329
345
|
|
|
@@ -398,7 +414,7 @@ async function requestWithRetry(provider, body, signal, onWait) {
|
|
|
398
414
|
const opts = {
|
|
399
415
|
method: "POST",
|
|
400
416
|
headers: {
|
|
401
|
-
...(provider.headers
|
|
417
|
+
...withUserAgent(provider.headers), // 定制头 + 产品标识头(UA 不可被渠道覆盖——PROVIDER.md §6.17)
|
|
402
418
|
"Content-Type": "application/json",
|
|
403
419
|
Authorization: `Bearer ${provider.apiKey}`,
|
|
404
420
|
},
|
|
@@ -446,7 +462,7 @@ async function requestWithRetry(provider, body, signal, onWait) {
|
|
|
446
462
|
message += ` [auth diag: baseURL=${host} key=${masked} status=${response.status}]`
|
|
447
463
|
}
|
|
448
464
|
lastStatus = response.status
|
|
449
|
-
if (isNonRetryableError(response.status, text)) throw new Error(message)
|
|
465
|
+
if (isNonRetryableError(response.status, text)) throw markContextOverflow(new Error(message), response.status, text)
|
|
450
466
|
if (response.status === 429) {
|
|
451
467
|
const waitMs = parseRetryAfter(response.headers.get("retry-after"), rateLimitHits)
|
|
452
468
|
rateLimitHits++
|