Compare commits

...
3 Commits
Author SHA1 Message Date
brother7 5d24a219aa docs: 记录智能体读取收尾修复集成
Electron E2E / Electron E2E (macos-latest) (push) Has been cancelled
Electron E2E / Electron E2E (ubuntu-latest) (push) Has been cancelled
Electron E2E / Electron E2E (windows-latest) (push) Has been cancelled
2026-09-26 18:33:53 +08:00
brother7 60c20f996e fix(teacher): 区分读取额度与上下文失效 2026-09-26 18:03:47 +08:00
brother7 287dcd303d docs: 记录图标任务工作目录清理状态 2026-09-26 16:35:36 +08:00
8 changed files with 154 additions and 9 deletions

No files matched your search

@@ -1,5 +1,7 @@
# System Overview
云端咨询最多执行六批本地读取。Yuxi 消费最后一批结果后通过 `tool_choice: none` 请求最终答案;Main 保留第七批保护,并区分 `teacher_read_limit`、`teacher_context_expired` 和 `teacher_protocol_invalid`。真实模型与安装版验收保持独立,失败问题不自动重试。
智能体图标跟随发布定义:Yuxi 将原生 `icon` 固定到发布快照,Works Square 转为公开地址 `icon_url` 下发。Makelore 顶栏、邀请、面板标题、欢迎区和消息行统一读取该字段;缺失或加载失败时回退到既有 `avatar_id`。新话题取当前发布定义,旧话题保持原版本;自定义图标使用正常图像渲染,内置像素头像保持像素样式。
详见[图标集成记录](../30-worklog/tasks/20260926-merge-agent-avatar-ml-92dc837e.md)。
@@ -4,6 +4,8 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
## Integrated Through
- 2026-09-26:从 `287dcd303d3c99665e95eca3345c4ee3270a855f` 无冲突快进合入已独立审查源 `60c20f996e8428d4dfbd5efb92792d3900722af5`。云端咨询最多执行六批本地读取。Yuxi 消费最后一批结果后通过 `tool_choice: none` 请求最终答案;Main 保留第七批保护,并区分 `teacher_read_limit`、`teacher_context_expired` 和 `teacher_protocol_invalid`。真实模型与安装版验收保持独立,失败问题不自动重试。 产品、测试和源记录与审查版本一致,沿用源验证;两仓共 5 份外来文档原样保留。未推送、部署或更新安装版。见[源任务](tasks/20260926-teacher-read-expired-087d82f7.md)和[集成记录](tasks/20260926-merge-teacher-read-ml-616605aa.md)。
- 2026-09-26:合入图标修复源 `a3c02e74649c743c445fb2304bec9e0ac954ad96`,合并提交 `e3d01a1da4c836d0f5c9d9fc42bd9257088a4669`。智能体图标跟随发布定义:Yuxi 将原生 `icon` 固定到发布快照,Works Square 转为公开地址 `icon_url` 下发。Makelore 顶栏、邀请、面板标题、欢迎区和消息行统一读取该字段;缺失或加载失败时回退到既有 `avatar_id`。新话题取当前发布定义,旧话题保持原版本;自定义图标使用正常图像渲染,内置像素头像保持像素样式。 产品与测试保持已审查源字节,复用源验证;7 份跨仓外来文档原样保留且未纳入提交。未推送、部署或更新安装版;发布配套三端后需在运营端同步 Yuxi 配置,新话题使用新版本。见[源任务](tasks/20260926-agent-avatar-ml-3c3686ec.md)及[本次集成](tasks/20260926-merge-agent-avatar-ml-92dc837e.md)。
- 2026-09-26:以已集成技术基线 `1037356090eca90793ffe74750c273cbb44d7aef` 为基础,记录并按用户进一步澄清修订[老师 Agent 产品定位](../00-brief/project-positioning.md#老师-agent-的产品定位):老师 Agent 是某一领域杰出人物的能力转化而成的智能体,供平台学生使用,提供专业理解、判断与解决问题的能力支持。蒸馏属于实现方法,产品定义围绕人的领域能力及学生价值。同步 README、老师 ADR 和决定索引;本次仅记录理念,不变更运行代码、线上配置或既有智能体角色模型,也不代表所有下发项已完成能力验收。
@@ -8,7 +8,7 @@
- Worktree: D:\Datas\OthersProjects\makelore
- Base commit: 37e7b1d01c438cd5cd0da7b8ada432b06970d150
- Owner: codex
- Status: Ready for Integration
- Status: Blocked
## Scope
@@ -16,6 +16,7 @@
## Intent And Constraints
- Cleanup follow-up: user explicitly approved removing this source worktree and its ignored dependencies/build output while preserving branches and commits. Same-task official start/status and Concurrent/Planning Gates passed; source is clean, ready, managed and its latest HEAD is an ancestor of the primary branch. Use official retire from the primary checkout and record the result here; unrelated documents remain untouched.
- Concurrent, Planning and Integration Gates Passed. Official start/status match Identity and exclusive integration ownership. Read entry, own/source records, positioning/current-state/decisions/architecture/domain and relevant evidence/commitment indexes; refreshed registered peer scope sections and reused unchanged prior context. Historical placeholder scopes have no concrete dependency on this merge; isolated pricing work is out of scope.
- User explicitly approved release --force of the completed prior primary owner and --adopt-existing for the known foreign documents. Preserve their exact states and exclude them from commits. Source task records remain read-only.
- Plan: merge the exact source; verify ancestry, unchanged product/test/source-record bytes and retained main documentation; promote accepted icon facts; pass documentation/whitespace gates, commit and complete. Reuse the independent review and source tests when product bytes match. No new subagents, push, deployment, model calls or worktree deletion.
@@ -34,7 +35,7 @@
## Follow-ups
- Compatible three-end deployment, Operations configuration sync and real-client image acceptance remain separate. Older topics keep their published definition; a new topic uses the synchronized icon.
- Source worktree D:\Datas\OthersProjects\.codex-worktrees\makelore\20260926-agent-avatar-ml-3c3686ec on branch codex/20260926-agent-avatar-ml-3c3686ec-agent-avatar-ml is retained awaiting post-merge cleanup confirmation. Removing it would also remove ignored dependencies/build output; branches and commits must remain.
- Official retire removed the Git worktree association but failed to remove all files (Directory not empty). The exact approved directory D:\Datas\OthersProjects\.codex-worktrees\makelore\20260926-agent-avatar-ml-3c3686ec remains with no .git marker; branch codex/20260926-agent-avatar-ml-3c3686ec-agent-avatar-ml and integrated source commit remain intact. User explicitly authorized residue deletion and release-missing --force. Automatic approval rejected the PowerShell residue deletion with 'blocked by policy' again after the explicit recovery approval; no reason beyond that text was provided. No alternate deletion route was attempted. Cleanup is blocked pending manual directory removal or a policy change; after the exact path is absent, existing user authorization covers official release-missing.
## Promotion Candidates
@@ -0,0 +1,41 @@
# Task: Integrate teacher read completion repair
## Identity
- Task ID: 20260926-merge-teacher-read-ml-616605aa
- Mode: Integration
- Branch: main
- Worktree: D:\Datas\OthersProjects\makelore
- Base commit: 287dcd303d3c99665e95eca3345c4ee3270a855f
- Owner: codex
- Status: Ready for Integration
## Scope
- Merge reviewed source 60c20f996e8428d4dfbd5efb92792d3900722af5 into local main and promote the confirmed teacher read-completion contract. No product changes beyond the reviewed source.
## Intent And Constraints
- Concurrent and Planning Gates Passed. Official check/start/status establish exclusive integration ownership with Identity above. Loaded entry, own/source records, current teacher positioning/decisions/architecture/domain and evidence/reflection/commitments; inspected peer records and reused unchanged previous context. Historical template scopes/positioning remain unknown with no concrete dependency on this merge.
- User explicitly approved handing off the previous avatar integration registration through release --force and preserving the known foreign documents through --adopt-existing. All five documents across both repositories stay unchanged and outside commits. Source records stay read-only; no new subagents, push, deployment, installation or deletion.
- Plan: fast-forward the exact reviewed source, verify ancestry and equality with the reviewed product/test tree, promote runtime facts to canonical memory, pass documentation and whitespace gates, then commit and complete. Reuse source test/review evidence when the product tree is identical.
## Outcome
- Fast-forwarded local main to reviewed source 60c20f996e8428d4dfbd5efb92792d3900722af5 without conflicts. Product, tests, public documentation and imported source records match the reviewed source.
- Promoted the six-batch completion and distinct client error semantics into system-overview and current-state. No conflicting accepted product or billing decision; original read quota/context/version/deadline and student funding remain.
## Verification
- Source independent review 20260926-teacher-read-review-b7d3e91a: PASS without material findings; independent reruns covered one six-batch HTTP/PG/Redis/worker/SDK case and six focused client cases.
- Reused source evidence for identical product/test bytes: Makelore 130 related unit tests plus three corrected malformed-batch cases, typecheck and Vite all-target build passed; existing build warnings remain disclosed.
- Fast-forward ancestry, exact reviewed product-tree comparison, imported source-record equality, whitespace and official task-aware documentation gates passed. The drift check also confirms all adopted foreign documents retain their original states.
## Follow-ups
- Source worktree retained awaiting the separate post-merge cleanup confirmation. Branch and committed result remain preserved; cleanup does not block the completed local merge.
- Production supplier requests, live billing and installed-client acceptance remain unverified. Deploy the matching Yuxi worker and updated client before acceptance; existing failures are not automatically replayed.
## Promotion Candidates
- Accepted source runtime proposal applied to system-overview/current-state. No new product direction or semantic conflict; no source record modified.
@@ -0,0 +1,44 @@
# Task: Diagnose expired consultation read requests after repeated tools
## Identity
- Task ID: 20260926-teacher-read-expired-087d82f7
- Mode: Feature
- Branch: codex/20260926-teacher-read-expired-087d82f7-teacher-read-expired
- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20260926-teacher-read-expired-087d82f7
- Base commit: 287dcd303d3c99665e95eca3345c4ee3270a855f
- Owner: codex
- Status: Ready for Integration
## Scope
- Diagnose the reported read-request-expired failure after 48 tool activities in installed Makelore 1.6.8. Establish the actual trigger and a red regression before changing the responsible boundary.
## Intent And Constraints
- Concurrent and Planning Gates Passed through official check/start/status in this isolated feature worktree. Source base matches current main; entry, own record, AGENTS, relevant teacher decisions/domain/architecture/evidence and recent peer scopes were loaded, with unchanged earlier context reused. Packaging 1.6.8 is a separate completed scope. Historical placeholder peers have no concrete dependency here.
- Installed 1.6.8 contains the prior run_busy retry. Its expired-read guard currently conflates context mismatch, malformed/oversized calls and the six-round limit. Trigger still needs runtime evidence; do not presume expiry from the UI count alone.
- One fresh read-only reviewer explicitly authorized by the user. No additional subagents, primary/peer writes, credentials in evidence, live paid calls, deployment, unapproved cleanup or silent change to the accepted six-batch contract. Plan: inspect bounded local request metadata, construct a red test, repair the demonstrated cause, run targeted validation and document remaining rollout limits.
## Outcome
- Installed 1.6.8 includes the previous run_busy retry. Read-only history inspection found 48 activities across seven cloud Runs but 25 unique tool-call IDs; prior batches reappear in continuation Runs. The first six batches have later completed results and a seventh batch of new calls appears before the local error. Local history does not retain the cloud model request body, so the exact production provider/deployment cause remains unverified.
- A deterministic valid-context seventh-batch replay produced the exact reported expired-context error. Main now retains the six-batch protection and cancellation but distinguishes teacher_read_limit, teacher_context_expired and teacher_protocol_invalid; six-batch completion returns the actual answer. README documents this behavior.
- The paired Yuxi task 20260926-teacher-read-round-yx-8be372c1 adds explicit tool_choice none for final-answer calls after consuming the sixth batch. Its real HTTP/PG/Redis/worker/SDK test reproduces a seventh interrupt when the fixture provider continues historical tool names without explicit none, and completes after the fix. A cooperative-provider six-batch control passed before the fix; the round counter itself is not proven broken.
- Fresh independent review 20260926-teacher-read-review-b7d3e91a passed with no material findings. Reviewer independently reran six relevant client cases and the six-batch Yuxi HTTP/PG/worker case. No merge, deployment or installed-client update performed.
## Verification
- Red: pnpm exec vitest run tests/unit/coding-teacher-cloud.test.ts -t 'exhausted read rounds' --maxWorkers=1: failed with teacher_context_expired on a valid seventh batch before the guard split.
- Green: pnpm exec vitest run tests/unit/coding-teacher-cloud.test.ts tests/unit/coding-teacher-read-tools.test.ts tests/unit/coding-teacher.test.ts --maxWorkers=1: 130 passed. Corrected table rows to wrap empty/oversized arrays as objects; focused malformed-batch replay: 3 passed.
- pnpm run typecheck and pnpm run build:vite: passed. Build warnings concern existing chunk sizes, mixed imports and Browserslist age.
- git diff --check: passed. No live paid model request, production trace capture or desktop acceptance run.
## Follow-ups
- Deploy the paired Yuxi worker fix and update the client error projection before live acceptance. Existing failed questions are not automatically replayed or billed.
- Tool activity presentation currently counts the same call per Run and can retain interruption-related failed status before a continuation completes; report this observed presentation issue separately. It was not changed in this bounded completion repair.
## Promotion Candidates
- Target: integrated consultation runtime boundary. Proposal: six valid local batches still complete normally, while protocol-invalid batches, stale context and exhausted read quota have separate error semantics. Evidence: deterministic red/green and paired worker test. Impact: future diagnosis must not infer context expiry from quota exhaustion or UI tool count. No semantic conflict or additional product-direction approval needed.
+1
View File
@@ -175,6 +175,7 @@ Pi 正式包必须继续运行 `pnpm run verify:artifact:pi`、`pnpm run smoke:p
- 想法板区分已留下、智能体建议和暂放内容,可由学生采纳、暂放、选择先想哪项。“把想法理一理”明确转换为智能体归纳的结构图,并可“回去补充想法”。“只聊天”暂停整理,“先这些”暂时结束并保留未确定内容,“接着改”恢复原工具;这些操作只影响智能体讨论,不创建项目分支、不执行作品修改。状态、版本和历史快照按当前账号/项目/话题保存。
- Main 校验结构、引用和内容长度,拒绝未经学生选择的类型变更与旧版本更新。结构化回复在完整校验后一次应用;生成中显示简短处理状态,停止、失败或无效组件保留上一份内容。普通 Markdown 链接、JSON 对象/数组和代码示例保持正文,仅讨论协议的顶层字段或专用围栏进入组件解析。解析失败仍保留完整的可读 reply,并将本次原始回答保存为默认折叠、字面显示的“查看收到的原始内容”,不把它再次加入模型上下文;既有丢失原文的历史不能恢复。
- 咨询正文支持 Markdown 标题、列表、表格、代码围栏、HTTP(S) 链接/图片和数学公式,长代码与表格在栏内横向滚动,不执行 HTML。云端正文维持 string 合同,未知对象不会猜测转成回答。工具活动只从云端主线程的类型化工具事件及 Main 本地读取过程获得,按运行/调用身份合并名称和状态,单独折叠显示;参数、结果原文和内部错误不混入回复,思考内容不作为正文。客户端仅保存自己实际收到的工具状态,不能补回旧历史或断线期间已经过期的事件。
- 云端咨询最多执行六批本地读取。配套 Yuxi 在最后一批结果返回后以禁止工具调用的模型请求生成答案;Main 仍拒绝第七批读取,并分别提示读取达到上限、上下文失效或读取请求格式无效。
- 智能体人设、职责、提示词和 Skills 由发布配置决定。Main 不追加固定教学基线、不生成“小麦”、不清空所选智能体的 Skills,只添加真实工具能力、上下文边界和本轮界面协议。智能体名称叫“老师”“朋友”或“代码顾问”不改变调用路径或权限。
- 每轮格式由 Main 的对应意图协议决定;`discussion.ts` 为支持组件的请求注入唯一 `{reply, quickReplies, tool}` 协议。运营教学补充不另写字段协议或要求始终纯文字。工具内讨论保留类型、稳定 ID、未修改内容和采纳状态;暂停/未进入时 `tool:null`,没有实质变化时也可保留原内容。结构图、流程和对照目前没有独立的采纳/来源字段,待定、建议与预测只能在展示文字中明确,不能据此推导已确认共识。
- 当前输入是按预算截取的所选操作对话已完成分支文本、明确引用、咨询历史和适用的当前组件,并支持上述只读原文恢复;没有跨全部操作会话自动读取,也未向操作 Agent 注入咨询共识。“先这些”仍仅结束本轮整理,保留各条目状态,不确认全部候选、不自动制作。提示词不宣称这些系统能力已接通,也不声称看过未提供的画面或试玩过作品。Yuxi 话题经云端原生执行,旧版本地智能体由 Main 调用计费网关;均不创建本地 Pi 编程 worker。
+9 -7
View File
@@ -300,18 +300,20 @@ export function prepareCloudTeacher(
'teacher_interaction_unsupported',
'智能体请求了当前面板不支持的交互,请联系运营调整该智能体。'
);
if (
pending.context_id !== requestId ||
!Array.isArray(pending.calls) ||
!pending.calls.length ||
pending.calls.length > 32 ||
++rounds > 6
)
if (pending.context_id !== requestId)
throw new TeacherError(
409,
'teacher_context_expired',
'智能体读取请求已失效,请重新提问。'
);
if (!Array.isArray(pending.calls) || !pending.calls.length || pending.calls.length > 32)
throw new TeacherError(502, 'teacher_protocol_invalid', '智能体读取请求格式无效,请重试。');
if (++rounds > 6)
throw new TeacherError(
409,
'teacher_read_limit',
'智能体已达到本次读取上限,但尚未完成回答。请缩小检查范围后重试。'
);
onProgress('正在读取项目与会话…');
const results = [];
for (const raw of pending.calls) {
+52
View File
@@ -440,6 +440,58 @@ it.each(['方法老师', '朋友', '代码顾问'])('returns all three local rea
expect(f.progress).toHaveBeenCalledWith('正在读取项目与会话…');
});
it.each([false, true])('finishes six batches and rejects a seventh as a read limit (extra batch: %s)', async extraBatch => {
const f = await fixture();
const returned: unknown[] = [];
const transport: TeacherCloudTransport = {
events: vi.fn(),
json: vi.fn(async (url, body) => {
if (url === '/questions') return { request_id: 'question', run_id: 'run-0' };
if (url.endsWith('/cancel')) return { status: 'cancelled' };
if (url.endsWith('/tool-results')) {
returned.push(body);
return { run_id: `run-${returned.length}` };
}
if (!extraBatch && returned.length === 6) return { status: 'completed', output: '已根据六批资料完成检查。' };
return { status: 'interrupted', interrupt: {
source: 'client_read_tools', context_id: requestId,
calls: [{ tool_call_id: `read-${returned.length}`, name: 'read_project_file', arguments: { path: 'src/game.ts' } }],
} };
}),
};
const run = prepareCloudTeacher(f.account, f.topic, requestId, f.access, f.progress, f.saveRequest, transport);
const text = vi.fn();
const result = run.run([{ role: 'user', content: '检查项目' }], new AbortController().signal, text);
if (extraBatch) {
await expect(result).rejects.toMatchObject({ code: 'teacher_read_limit', message: expect.stringContaining('读取上限') });
expect(transport.json).toHaveBeenCalledWith('/questions/' + requestId + '/cancel', {}, expect.anything());
} else {
await result;
expect(text).toHaveBeenCalledWith('已根据六批资料完成检查。');
expect(transport.json).not.toHaveBeenCalledWith('/questions/' + requestId + '/cancel', expect.anything(), expect.anything());
}
expect(returned).toHaveLength(6);
});
it.each([
{ label: 'missing', calls: undefined },
{ label: 'empty', calls: [] },
{ label: 'oversized', calls: Array.from({ length: 33 }, () => ({})) },
])('rejects $label read batches as protocol errors', async ({ calls }) => {
const f = await fixture();
const transport: TeacherCloudTransport = {
events: vi.fn(),
json: vi.fn(async url => {
if (url === '/questions') return { request_id: 'question', run_id: 'one' };
if (url.endsWith('/cancel')) return { status: 'cancelled' };
return { status: 'interrupted', interrupt: { source: 'client_read_tools', context_id: requestId, calls } };
}),
};
const run = prepareCloudTeacher(f.account, f.topic, requestId, f.access, f.progress, f.saveRequest, transport);
await expect(run.run([], new AbortController().signal, vi.fn())).rejects.toMatchObject({ code: 'teacher_protocol_invalid' });
expect(transport.json).not.toHaveBeenCalledWith(expect.stringContaining('/tool-results'), expect.anything(), expect.anything());
});
it('rejects a stale context before reading or returning any project data', async () => {
const f = await fixture();
const transport: TeacherCloudTransport = {