Merge origin/main and preserve approved teacher Agent consensus
This commit is contained in:
commit
10da39341e
29 files changed
+666
-24
No files matched your search
@@ -2,31 +2,31 @@
|
||||
|
||||
## One-line Positioning
|
||||
|
||||
This project is {one-line project positioning}.
|
||||
Makelore 是面向学生和创作者的 AI 创作客户端,承载编程、视觉创作、机器人和个人智能体/项目咨询;社区课程与机构教学分别留在 WS 和 LMS。
|
||||
|
||||
## Primary Goal
|
||||
|
||||
The project exists to {primary project goal}.
|
||||
帮助用户围绕自己的项目创作、修改和提交作品,并在清晰的账号/付款边界下使用 AI 工具与咨询能力。
|
||||
|
||||
## Target Users / Consumers
|
||||
|
||||
- {primary user or consumer}
|
||||
- 学生、创作者、代孩子操作充值的家长,以及个人智能体使用者。
|
||||
|
||||
## Non-goals
|
||||
|
||||
This project does not aim to {non-goal or boundary}.
|
||||
客户端不体现课程,不增加课程目录、课次/任务上下文、learningOrigins、课程深链接或课次恢复。不承担机构排课、正式学情、课程观看授权或钱包账本权威。
|
||||
|
||||
## Core Constraints
|
||||
|
||||
- {core constraint}
|
||||
- Main 持有认证、项目与固定服务端交互;Renderer 显示当前账号和服务端资格。家长登录孩子号充值,作品发布仍受 WS 审核和交付规则约束。
|
||||
|
||||
## Quality Bar
|
||||
|
||||
A good solution should {quality bar}.
|
||||
保持普通创作与发布独立,明确充值对象、失败恢复和账号切换边界;区分本地验证与真实安装版/支付/模型验收。
|
||||
|
||||
## Last Reviewed
|
||||
|
||||
{YYYY-MM-DD}
|
||||
2026-10-09(社区协作、无课程客户端及当前账号充值;老师 Agent 定义保留)
|
||||
|
||||
## 老师 Agent 的产品定位
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Project Success
|
||||
|
||||
- {observable project-level success condition}
|
||||
- 用户能完成普通创作/发布,按服务端资格给当前账号充值并清楚看到对象;切换账号不显示旧结果。课程流程留在社区/LMS,不新增客户端课程入口或隐含上下文。
|
||||
|
||||
## Task Completion Standard
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Memory Index
|
||||
|
||||
## Community Collaboration · 2026-10-09
|
||||
|
||||
先读[社区协作与充值边界](../20-architecture/community-collaboration.md):麦洛不体现课程;D01 当前账号充值及正式设计已合入本地 main,家长登录孩子号。任务证据、真实支付和安装版留项分别记录,不恢复旧客户端课程待办。
|
||||
|
||||
Use this as the high-density entry point after the Concurrent Task Gate establishes task identity and worktree ownership.
|
||||
|
||||
## Startup Set
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
|
||||
- 2026-10-08 确认、后续平等身份澄清同步至[用户理解与执行表达](../00-brief/project-positioning.md#用户理解与执行表达):用户采纳老师 Agent 建议后,须自己理解并向操作 Agent 表述目标与要求,老师 Agent 或系统不直接交接建议触发执行;保留用户表达作为观察理解的依据,具体观察方法待讨论,不预设教学或评分身份。
|
||||
|
||||
## Community Collaboration · 2026-10-09
|
||||
|
||||
2026-10-09 已确认并实现[社区协作与充值边界](../20-architecture/community-collaboration.md):当前账号充值并显示对象;家长登录孩子号;麦洛不体现课程,D05 关联改在社区。后续决定取代原 parent-only 永久充值及客户端课程提案,其他家庭/付款/咨询规则保持。
|
||||
|
||||
- [老师思考与回答流式展示](ADR-2026-09-22-coding-teacher.md):2026-09-29 已合并;主线程思考独立保存与折叠展示,正文逐步投影并由最终回复确认,快捷回复仅完成后显示;思考不进入后续模型上下文、工具活动或带回草稿。
|
||||
|
||||
- [老师可配置快捷提示](ADR-2026-09-22-coding-teacher.md):2026-09-29 已合并;Yuxi 有序展示文案/实际提示词,显式发布冻结,WS 版本化下发,客户端普通提问;空列表隐藏入口,历史缺字段保持旧入口。
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# 麦洛与社区、LMS 的协作边界
|
||||
|
||||
日期:2026-10-09。状态:用户已确认,D01 代码及正式设计已合入本地 main;未推送、更新安装版或部署服务。
|
||||
|
||||
## 产品职责
|
||||
|
||||
麦洛是创作和 AI 工具入口,支持普通项目、作品提交、视觉创作、机器人及智能体/项目咨询。社区 WS 承载课程原版、视频自学、任务作品关联、公开作品、活动和点数;机构 LMS 承载可选的课程采用和正式教学。
|
||||
|
||||
**麦洛客户端不体现课程。** 不增加课程目录、课次页面、课程任务上下文、learningOrigins、课程深链接、返回课次按钮或课程任务恢复。原详细设计中的这些客户端条款由后续用户指令取代,不是将来等待后端接口补齐的任务。
|
||||
|
||||
合作机构是否使用 LMS 不影响孩子使用麦洛。教培智念和恩野按普通合作机构规则参与;客户端不因此呈现机构身份或获得教学数据。
|
||||
|
||||
## 创作与成果
|
||||
|
||||
1. 孩子在社区或机构了解学习任务,然后在麦洛普通创作。
|
||||
2. 已有作品上传/提交保持原构建、版本、重试、审核与公开交付规则。
|
||||
3. 孩子回到社区网页,从本人已上传的固定编程版本中选择课程任务作品;关联失败只在社区恢复,不要求客户端再次构建或上传。
|
||||
4. 是否公开由孩子另行发起。LMS 可引用当前公开的确切成果,提交由后端复核;麦洛不保存课程来源或替 LMS 确认作业完成。
|
||||
|
||||
普通项目、社区任务关联、作品公开和 LMS 作业提交是不同记录。课程关联不扩大私人内容访问,不证明能力掌握,也不把版本自动变成公开状态。
|
||||
|
||||
## 永久点数充值
|
||||
|
||||
家长为孩子购买点数时登录孩子账号。Sidebar 把当前认证账号的昵称/用户名传给 PointWallet,钱包明确显示充值对象。充值通过既有 Renderer → Main 固定 Host API → WS 账务接口,只提交产品及稳定请求身份,不提交另一个孩子 ID、价格或凭据。
|
||||
|
||||
是否允许充值由 WS 返回;旧服务端拒绝仍须显示不可充值。当前账号规则不改变家庭角色、共享钱包选择、另一付款方的隐私、云智能体创建者付款或 Plugin 个人付款。
|
||||
|
||||
订单冻结当前账号、金额和点数。结果不明先恢复原请求/订单,已有待支付或人工核对订单不能另建替代;服务端确认前不显示到账。账号切换后原响应不得回写新账号界面。
|
||||
|
||||
机构资助由 WS 运营按孩子人工发永久点数;客户端不维护机构额度、第二个钱包、周期重置或家长资金转移。充值也不授予课程观看资格。
|
||||
|
||||
## 工程落点与验证
|
||||
|
||||
| 落点 | 本次变化 |
|
||||
| --- | --- |
|
||||
| src/components/layout/Sidebar.tsx | 传当前认证账号的显示名 |
|
||||
| src/components/account/PointWallet.tsx | 收款对象、家长登录孩子账号提示,保留资格及旧单恢复 |
|
||||
| electron/api/routes/works-billing.ts | 拒绝提示不再要求切换为家长身份 |
|
||||
| 既有 works-billing 服务/DTO | 认证和付款权威继续在 Main/WS;不增加课程或跨账号充值协议 |
|
||||
|
||||
源 281e6dc / 0d442ce 的 41 项定向单测、类型检查、相关 lint、Renderer/Main/preload 构建和 1 项 Electron 流程已通过;详见[实施任务](../30-worklog/tasks/20261009-makelore-product-implementation-eaa0ffa5.md)。本次只整合正式文档,应用和测试文件与源保持相同,不把文档检查算成重新运行这些测试。
|
||||
|
||||
先更新 WS 的当前账号充值资格,再发布配套客户端。实际支付提供方对孩子账号令牌的接受、真实到账及正式安装版仍需验收。代码与设计已完成本地主分支合并;没有付费请求、打包、安装、推送或部署。
|
||||
|
||||
## 配套权威
|
||||
|
||||
总体架构只在 WS 的 .project-docs/20-architecture/ecosystem-overview.md 维护;课程关联以 WS 的 community-product-design.md 和已确认 D05 修订为准;LMS 在自身 community-integration-design.md 维护采用、学生访问和公开成果契约。三仓分别维护本地职责,不复制整套课程状态或钱包。
|
||||
|
||||
旧 Learning 已退役;历史本地课程数据仍不读取、不迁移、不自动删除。现有老师 Agent 能力定义、普通创作和平台服务调用不因无课程边界被删除或改写。
|
||||
@@ -14,6 +14,8 @@ Renderer 自由输入/空输入框上方已发布快捷提示(历史缺字
|
||||
|
||||
## Permanent wallet and recharge
|
||||
|
||||
家长登录孩子账号 → Sidebar 将当前账号显示名传给 PointWallet → 核对收款对象后按服务端资格充值。课程观看和任务作品关联只在社区网页完成,不向客户端传课程上下文;参见[协作边界](community-collaboration.md)。
|
||||
|
||||
账号菜单 / PointWallet → `src/lib/works-billing.ts` → Main 固定 `/api/works/billing/*` 路由 → Works Square 账务 API。Main 持有认证与账号绑定,通过 `shared/works-billing.ts` 的公开 DTO 投影余额、产品、订单及流水;充值沿用 Renderer capability,Renderer 不传付款人、价格、Token 或任意上游地址。账号切换后 Main 与账号绑定的 UI 丢弃迟到结果,打开菜单和窗口 focus 刷新当前账号。
|
||||
|
||||
本人点数与 AI 编程已选付款来源分开呈现。`shared_available` 为布尔值时只向 Renderer 提供另一付款方的可用性,精确余额置空;为 `null` 时保留本人规范字符串余额,即使 `family_shared=true` 且来源为 `self` / `shared_group`。充值资格来自服务端,不能用旧会员管理权限或共享标记推算。云智能体创建者付款与 Plugin 个人付款不受 AI 编程来源选择改变。
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Module Map
|
||||
|
||||
## Community Collaboration · 2026-10-09
|
||||
|
||||
社区协作只调整 src/components/account/PointWallet.tsx、Sidebar.tsx 的当前账号展示与 electron/api/routes/works-billing.ts 的拒绝提示,沿用原账务传输;不新增课程模块。具体设计见[协作边界](community-collaboration.md)。
|
||||
|
||||
## Source Layout
|
||||
|
||||
| Path | Responsibility | Owner Notes |
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# System Overview
|
||||
|
||||
## Community Collaboration · 2026-10-09
|
||||
|
||||
当前跨产品职责见[社区协作与充值边界](community-collaboration.md):本地 D01 已实现当前登录账号充值和收款对象展示;家长使用孩子账号。课程目录、任务与进度留在 WS/LMS,麦洛不新增课程 UI、上下文、learningOrigins 或深链接。普通创作、发布、Main 认证和既有云端咨询保持。
|
||||
|
||||
老师咨询沿用 Main-owned Yuxi 事件与项目聊天 SSE。`cloud-runner` 分离主线程 `reasoning_content`(兼容已保留的 `additional_reasoning_content`)增量和当前消息的回答原文预览;service 用 `previewTeacherReply` 从未完成结构化回复投影正文,最终仍由完整解析确认。新消息/工具续接替换正文预览,问题级独立 `reasoning` 字段继续累积,终态初次读取也消费保留事件。Renderer 分开展示思考和 Markdown 正文,运行时展开思考、终态收起,快捷回复只在完成后可见。取消/失败保留片段与原文;思考随轮保存但不进入模型上下文或带回正文,子线程只推进游标。无新增服务端协议或模型配置,未返回思考的模型仍正常输出正文。
|
||||
|
||||
咨询输入区从当前老师发布定义的 `shortcuts` 按序渲染展示文案,并通过已有普通提问路径发送实际提示词;不附加旧 suggestions 意图。明确的空列表隐藏入口,缺字段/null 保留旧入口。多项长文案在限定高度内滚动,正在回答时不可点击;目录更新不替换项目聊天或草稿,同一未确认提问重试保留请求身份。详见[老师决定](../10-decisions/ADR-2026-09-22-coding-teacher.md)。
|
||||
|
||||
@@ -4,6 +4,16 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
|
||||
|
||||
## Integrated Through
|
||||
|
||||
- 2026-10-11:用户授权回滚与主目录交接,已在本地 main 合入源 658bf7d 和正式文档整合 9949328,合并提交 5ae6ffd204e4d5e0f8546544fa8fc8cc3e1c51f1。恢复旧 Works Square 登录/刷新/注销路径;产品与已验证源一致。原有三份任务文档保持未提交,未推送、部署或删除工作区。见[主分支记录](tasks/20261011-integrate-makelore-rollback-b8f41a62.md)。
|
||||
|
||||
- 2026-10-11:按用户明确要求,将 Makelore 平台 SSO 回滚源 `e28beff`(原平台 OIDC 实现 `7236def` 的逆提交)合入本地集成分支,客户端恢复 Works Square 传统密码/手机登录、刷新与注销边界。回滚验证沿用源任务的 60 项聚焦测试、typecheck、scoped lint、Renderer-only Vite build 与 `git diff --check`;正常 D: 构建仍因磁盘空间不足未完成。本次未推送、部署、迁移真实账号、改 LMS 或支付;主目录 3 份外来未跟踪文档原样保留且未纳入提交。此前 2026-10-10 的 OIDC 条目和来源任务继续保留为历史证据,当前运行时以本条及 ADR-004 为准。见[回滚源任务](tasks/20261011-rollback-makelore-platform-auth-7c4e9a2b.md)和[本次集成](tasks/20261011-integrate-rollback-makelore-c9d8e7f6.md)。
|
||||
|
||||
- 2026-10-10:按用户确认,将 Makelore 平台 SSO 源 `7236def07d6a9a5cfde70c3239c6ac53764bcd7d` 无冲突快进合入本地 `main`,并修正来源登记提交 `86216b8458db9a2c58850a6835fd1a76cee5a846`。Electron Main 通过系统浏览器使用平台 OIDC Authorization Code + PKCE,校验 state/nonce/S256、精确 `niancode://auth/callback`,并在 Main 内持有 access/refresh token;平台身份按 issuer + `sub=platform:<UUID>` 使用,传统 Works Square 密码/手机登录路径保留。该条记录的是已回滚的历史迭代,不代表当前客户端状态。源验证沿用 65 项聚焦测试、typecheck 与变更文件 lint;本次未推送、部署、迁移真实账号、改 LMS 或支付。已有 3 份外来未跟踪文档原样保留且未纳入提交。见[源任务](tasks/20261010-makelore-platform-sso-a1b2.md)和[本次集成](tasks/20261010-integrate-makelore-platform-sso-9c2d.md)。
|
||||
|
||||
- 2026-10-09:按用户要求,将集成源 `35e2a9149aed7d918176f00369cee6528505cdb8` 从 `fe1a3775` 无冲突快进合入本地 `main`。应用、测试、配置与已验证源保持相同,本次仅补充主分支交付记录。原有 3 份外来文档原样保留且未纳入提交;全部源分支和工作区按用户要求保留。未推送、部署、迁移生产数据或发布安装包;真实机构、OSS/网络、支付和设备验收仍待执行。见[本次合并](tasks/20261009-merge-product-dd0461f9.md)。本条更新下方独立分支阶段的未合主分支状态,历史来源记录不改写。
|
||||
|
||||
- 2026-10-09:本独立 integration 分支以实施源 `0d442ce576430880355ca35382b844d2cec14d64` 为基线,整合原创作和永久点数决定及后续用户决定。D01 当前账号充值、可见收款对象及无课程客户端边界已有本地实现;家长登录孩子账号充值、麦洛不体现课程替代旧充值待定/客户端课程提案。应用和测试保持源版本,源记录原样保留。当前正式设计尚未推广到主分支;未部署、支付或删除工作区。本批无客户端迁移。真实机构、OSS/网络、支付或移动验收仍按各项目留项。见[正式设计](../20-architecture/community-collaboration.md)、[实施证据](tasks/20261009-makelore-product-implementation-eaa0ffa5.md)、[本次集成](tasks/20261009-makelore-product-integration-29d647c5.md)。下方日期条目为历史阶段,不以早期未实现/待定描述覆盖本条。
|
||||
|
||||
- 2026-10-09:续接用户授权的老师 Agent 共识记录,确认[八方面内在映射框架](../00-brief/project-positioning.md#内在映射的八个方面),[首版目标](../00-brief/project-positioning.md#首版内在映射目标)只重点覆盖前五方面:价值、动机与优先顺序,注意与问题构造,对世界的理解,经验与实践能力,证据标准与自我修正。身份与生命叙事、关系与社会处境、情绪与自我调节留待后续迭代,不另把第七方面列为首版要求;判断证据仍保留必要的事实背景。同步此前用户的平等身份澄清,“老师”是名称,具体真人与用户的交流不预设教师/学生关系;用户自己理解并向操作 Agent 表达执行要求的边界保留。基于既有共识提交 `00db469`、`07f009c` 更新产品定位、README、老师 ADR、决策索引及同一集成记录。下一步讨论 Codex 等工具痕迹能提供哪些证据及需要补充什么;本次只记录已确认方向,未读取个人历史或实现蒸馏,既有运行和发布边界保持。见[集成记录](tasks/20261008-teacher-consensus-integration-a9c2d7e1.md)。
|
||||
|
||||
- 2026-10-08 补充(后续身份澄清见上条):用户明确纠正老师建议进入执行的方式。老师建议后,学生须自己理解、决定是否采纳并向操作 Agent 表述目标与执行要求;不通过老师/系统直接转发、自动下发或一键采纳执行替代学生表达。随后查看作品结果,老师再基于可获得的事实继续判断。学生表达为观察理解提供依据,不等于自动证明理解;具体观察方法待讨论。本次基于共识提交 `00db469` 同步[产品定位](../00-brief/project-positioning.md#用户理解与执行表达)、README、老师 ADR 和决策索引,替换原先将老师建议与操作 Agent 交接留待设计的表述;仅更新文档,未改动运行代码、配置或发布。见[同一集成记录](tasks/20261008-teacher-consensus-integration-a9c2d7e1.md)。
|
||||
@@ -1236,4 +1246,4 @@ Robot 绑定设备默认先显示“引导配网 / 已有激活码”路径选
|
||||
|
||||
## Last Updated
|
||||
|
||||
2026-09-29
|
||||
2026-10-11
|
||||
@@ -0,0 +1,73 @@
|
||||
# Task: Implement approved product detailed design
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20261009-makelore-product-implementation-eaa0ffa5
|
||||
- Mode: Feature
|
||||
- Branch: codex/20261009-makelore-product-implementation-eaa0ffa5-product-implementation
|
||||
- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20261009-makelore-product-implementation-eaa0ffa5
|
||||
- Base commit: fe1a3775c5f785adaa6372bd7ea3102c79331656
|
||||
- Owner: codex
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Cross-project continuation: correct this task's obsolete course follow-up to the user's explicit no-course-client boundary; prepare the recharge rollout and canonical promotion handoff. No client course implementation or production actions.
|
||||
|
||||
- Implement the first complete D01 slice from approved detailed design 28ac43ba: current-account personal-wallet recharge, parent-operates-child-account guidance, visible recipient, and existing payment/order recovery. Own PointWallet/caller, Main billing messages, README and focused unit/Electron tests.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- Cross-project continuation: official same-task Concurrent/Planning Gates Passed; read required context and all 146 unchanged peer scopes, with matching task/mode/worktree/branch/base. The user's later no-client-course decision controls over the original D05 plan. Only this owned task record changes. Formal integration start is Blocked by 20260929-merge-teacher-stream-1e4177fe; preserve its worktree, branch and all untracked/modified files. No subagents, canonical writes, client course code, merge/push, deployment or payment.
|
||||
|
||||
- Concurrent and Planning Gates Passed in this isolated feature worktree; current owner/reservation matches. Preserve all foreign work and canonical documents. User explicitly approved child-account recharge; old parent-only guidance is superseded for permanent point recharge only. Do not change legacy membership, identity, shared funding choice, provider callbacks or frozen order owner. No subagents, live payment, push, merge or deployment.
|
||||
- Plan: implement backend qualification and both UI projections; test actual child/parent own-wallet orders, shared payer privacy, idempotency/recovery and account switching; run relevant backend/frontend and required client checks; commit each complete slice with evidence. D02–D08 remain subsequent implementation packages, not completion claims of this first slice.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Cross-project handoff corrected obsolete future client-course work and promotion status. D01 remains the implemented client change; community/LMS own subsequent course and teaching flows. WS prepared the overall integration/rollout guide and task-owned canonical candidate. No application code, dependency or test changes this continuation.
|
||||
|
||||
- D01 implemented in this worktree. Sidebar passes the authenticated account nickname/username into PointWallet; the wallet explicitly displays the recipient and asks parents to log into the child's account before paying.
|
||||
- Recharge uses the existing authenticated Main/Host API flow and still submits only product plus request ID. It does not submit a target child, change platform identity, transfer points or alter the selected funding source.
|
||||
- Server-denied recharge copy no longer tells users to switch to a separate parent identity. Existing pending-order recovery, frozen pricing, payment status confirmation and unknown-outcome behavior remain in place.
|
||||
- README records the approved current-account rule and WS rollout dependency. Existing captured server fixture remains a pre-D01 fixture; its false capability is still honored rather than fabricated.
|
||||
- Companion WS implementation: task 20261009-community-product-implementation-b001b1db, branch codex/20261009-community-product-implementation-b001b1db-product-implementation; it updates account/billing capability and order eligibility, community UI and focused tests. LMS has no D01 code change.
|
||||
- Work remains isolated; no primary checkout edits, subagents, merge, push, deployment or live payment.
|
||||
|
||||
## Verification
|
||||
|
||||
- This continuation's Task Documentation Gate: inspected committed scope since the recorded base and current changes; git diff --check and official task-aware document drift check passed. Only owned task records/supporting proposal and ordinary delivery/configuration files changed. Ready for Integration; canonical ownership handoff remains pending.
|
||||
|
||||
- Reviewed base fe1a3775-to-HEAD 281e6dc file scope (10 files) and the current task-record diff; git merge-base --is-ancestor main HEAD succeeded at this checkpoint. No code change, so prior 41 unit tests, typecheck/build and Electron E2E remain the relevant evidence; did not repeat them for a task-record correction. Exact integration owner confirmed by failed official start; no ownership mutated.
|
||||
|
||||
- PASS: `pnpm exec vitest run tests/unit/point-wallet.test.tsx tests/unit/sidebar-token-points.test.tsx tests/unit/works-billing-routes.test.ts tests/unit/works-billing-client.test.ts tests/unit/works-billing-server-contract.test.ts --maxWorkers=2`: five files, 41 tests passed.
|
||||
- Focused assertions cover actual Sidebar recipient props; child account recharge submits no extra recipient; shared funding is not automatically changed; safe denial copy; old server capability remains authoritative.
|
||||
- PASS: `pnpm run typecheck`.
|
||||
- PASS: scoped `pnpm exec eslint` on all changed TS/TSX implementation and test files.
|
||||
- PASS: `pnpm run build:vite` for Renderer, Main, preload and utility.
|
||||
- PASS: `pnpm exec playwright test tests/e2e/permanent-point-wallet.spec.ts --workers=1`: one Electron E2E. Verified child recipient/guidance, pending-order reopen, frozen price, one order POST and credit only after server-confirmed success.
|
||||
- Exact pinned pnpm 10.33.4 used; `pnpm install --frozen-lockfile --offline` used cached dependencies and respected approved scripts. No dependency or lockfile change.
|
||||
- Companion WS checks passed: 68 backend tests, 138 web tests, web build and rendered-browser payment/account-switch scenarios with synthetic responses.
|
||||
- Existing build warnings concern chunk size, mixed static/dynamic imports and Browserslist data. Tests use isolated fixtures/synthetic payments; real provider acceptance and real money settlement remain unverified.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Integrate with WS D01 and deploy backend eligibility before expecting child-account recharge in this client. Existing 0094 permanent-points storage suffices; this slice adds no migration.
|
||||
- Validate child-account token acceptance with the actual payment provider before production rollout.
|
||||
- The user's subsequent instruction “makelore客户端不体现课程” supersedes the original client course plan. Do not implement course UI, course context, learningOrigins, course deep links or course-task recovery. D02–D08 now live in WS/LMS; WS implements course-work association in its own community page. Ordinary creation/publication and D01 recharge remain the client scope. The WS task-owned makelore-creation-boundary proposal records the amended D05 contract.
|
||||
- Retain the worktree/branch for review and integration.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- Target: .project-docs/40-domain/business-rules.md and .project-docs/20-architecture/system-overview.md.
|
||||
Proposal: active current-account recharge uses the child's authenticated session when a parent pays for that child; recipient must be visible; account identity and selected shared funding remain unchanged.
|
||||
Evidence: explicit user decision “家长登录孩子的号进行充值”, approved detailed design 28ac43ba, 41 focused unit tests, Electron E2E and companion WS tests.
|
||||
Future impact: prevent reintroducing separate parent-wallet recharge guidance or client-side eligibility guesses.
|
||||
Semantic conflict: supersedes old parent-only permanent-point recharge language; parent-only family administration and other legacy rules remain separate.
|
||||
Human confirmation: already supplied by the user; canonical promotion still requires Integration Gate.
|
||||
- Target: .project-docs/30-worklog/current-state.md.
|
||||
Proposal: after integration, record D01's client implementation and WS rollout dependency. Remove the superseded client course follow-up; WS through 3e39a8f4 and LMS through 4a84132 contain the D02–D08 implementation within their scopes. Preserve unverified production/provider/mobile acceptance as rollout work, not missing client course features.
|
||||
Evidence: this task and companion 20261009-community-product-implementation-b001b1db.
|
||||
Future impact: keeps implementation and deployed/integrated state distinct.
|
||||
Semantic conflict: no canonical changes permitted from this feature task.
|
||||
Human confirmation: no additional product decision needed.
|
||||
@@ -0,0 +1,54 @@
|
||||
# Task: Integrate implemented community product boundaries
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20261009-makelore-product-integration-29d647c5
|
||||
- Mode: Integration
|
||||
- Branch: codex/20261009-makelore-product-integration-29d647c5-product-integration
|
||||
- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20261009-makelore-product-integration-29d647c5
|
||||
- Base commit: 0d442ce576430880355ca35382b844d2cec14d64
|
||||
- Owner: codex
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Integrate the approved product design and implemented source into this isolated integration branch; update canonical architecture, rules, current state, evidence and remaining rollout work. Preserve all source task records and original worktrees.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- User explicitly authorized transfer of WS 20261008-integrate-product-design-50fdab23, LMS 20261008-integrate-product-design-b23c91e7 and Makelore 20260929-merge-teacher-stream-1e4177fe. Official release --force changed only those registrations/locks; old directories, branches, files and uncommitted contents retained.
|
||||
- Concurrent/Planning/Integration Gates Passed: bundled check/start/status matched this task, integration mode, absolute worktree, branch and recorded source base. Required entry, positioning, architecture/domain, accepted decisions, success/evidence/reflection/commitment context and source outcomes/candidates loaded. WS 277/LMS 26/Makelore 146 peer records read; none changed since preceding continuation. Historical Gateway record lacks Intent And Constraints, without a concrete dependency.
|
||||
- Project goal: community supplies courses/tools/support and public learning/works; institutions independently manage teaching with optional LMS; Makelore is a creation tool without courses. Current focus: unite separate approved design and implementation histories, amend only later explicitly confirmed behavior, and separate local evidence from deployment. Preserve existing wallet/family/tenant/publication boundaries. No subagents, primary-checkout adoption, main-branch changes, push, deployment, payment or worktree deletion.
|
||||
- Decisions: parents recharge while logged into the child's account; permanent manual per-child points; child-initiated publication; no institution labels in ordinary community; no client course UI/context/deep links/learningOrigins. These user decisions supersede the old design's pending recharge choice and client task entry; no new product decision needed. Source verification remains applicable because application code will remain unchanged.
|
||||
- Implementation plan after gates: merge the retained WS/LMS design commits into the new integration branches, reconcile canonical text with actual feature contracts, verify source-code equality and unchanged imported task records, check edited links and documentation boundaries, then commit and complete the integration records. Makelore needs only canonical creation/recharge boundaries and status.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Promoted implemented D01 and the explicitly confirmed creation-only client boundary from source 0d442ce into community-collaboration, positioning, architecture/module/data-flow, permanent-point rules, success criteria, indexes, evidence and current state. Removed obsolete parent-only recharge and client course assumptions. Preserved teachers/agents and retired Learning data rules; no application change.
|
||||
- All code, tests, deployment configuration and dependencies match the verified implementation source. This is a local isolated integration branch, not a main-branch promotion, deployment or client release. Shared state records exact Integrated Through source commits and keeps real-world acceptance gaps explicit. All original worktrees, branches and uncommitted files retained.
|
||||
|
||||
## Verification
|
||||
|
||||
- PASS: git diff from the recorded source base excluding Markdown is empty; untracked files are Markdown only. This proves application/configuration/test equality with the source and avoids repeating unaffected application tests.
|
||||
- PASS: 12 added local document links resolve; no missing targets. 0 imported source task/proposal records compare unchanged to the retained design commit. git diff --check (working/staged) and check_project_docs.py passed; canonical text no longer presents implemented collaboration or client courses as pending design.
|
||||
- PASS: official check_doc_drift.py after integration commit 12af6aed5d076bd0168d23469cfa2675ff639594 validates canonical ownership and unchanged source imports through shared ancestry. The pre-commit WS check could not yet prove the five staged imports; after recording the real merge parents it passes without adoption, source edits or bypass. All three check_project_docs.py/drift gates passed. Original WS/LMS design checkouts retain their exact HEAD/branch and clean state; original Makelore main retains its HEAD and same three untracked documents.
|
||||
- Task Documentation Gate complete: reviewed source-base-to-integrated changes, recorded actual outcomes/verification/remaining rollout work and exact sources, retained all directories/branches, and prepared this final Ready for Integration record. No main-branch merge occurred, so no cleanup action or new cleanup permission is needed.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Promote the completed integration branches to the main branches in a separately coordinated step; preserve the foreign changes already present in the original WS/Makelore checkouts and the LMS feature owner. No main worktree was claimed or switched here.
|
||||
- Real institution/course pilot, production OSS/long-video/network, actual payment provider/settlement, native devices and WeChat tool pages remain acceptance work. Automatic adoption receipts are unimplemented; Operations records actual delivery manually. Do not revive cancelled Makelore course features or repeat completed D06/D07 work.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- Promoted the user-confirmed community/institution/client boundaries and implemented contracts into canonical documents. Exact feature and retained design sources are in current-state Integrated Through. Old historical records stay read-only; current-account recharge and no-course-client policy derive from explicit user decisions, not inferred timestamps. No further product decision or ownership handoff is required for this integration.
|
||||
|
||||
## Remaining-work review · 2026-10-09
|
||||
|
||||
- Same-task follow-up requested by the user: compare the approved detailed design and later scope decisions with current code, branch delivery and acceptance evidence. Official start/status and Planning Gate passed; peer records are unchanged since integration. Status audit only; no application edits, merge, deployment, real payment or workspace deletion. Findings follow after source inspection.
|
||||
|
||||
- Findings: Confirmed D01 source 281e6dc remains implemented and formally documented. No further course work is pending: user's explicit instruction cancelled it. main remains fe1a3775; current-account recharge code and canonical documentation are on the retained integration branch. Matching installed build, actual payment provider and child-account credit acceptance remain unverified.
|
||||
- Cross-project follow-ups: main-branch delivery, coordinated migrations/API/clients, real OSS/media/package/network, institution/course pilot, actual payment and selected native/WeChat/installed-client acceptance. Real course, institution, support/commercial terms and public-display/promotion-use authorization remain business inputs; no new scope inferred from historical pending bullets.
|
||||
- Verification for this status review: inspected original approved design, current canonical/ordinary docs, relevant source/configuration, main branch refs and source-to-integrated application equality. Application code unchanged; existing phase-specific test evidence retained rather than rerun. Only own task records and WS task-owned evidence are updated; no main merge, push, deployment, payment, subagent or cleanup.
|
||||
|
||||
- PASS: source-to-integrated non-Markdown diff is empty; current edits remain task-owned documentation only. Official project-docs structure and task drift gates passed for all three repositories; six evidence-report links resolve. Task Documentation Gate completed for this status follow-up.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Task: Merge approved product integration into main branch
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20261009-merge-product-dd0461f9
|
||||
- Mode: Integration
|
||||
- Branch: main
|
||||
- Worktree: D:\Datas\OthersProjects\makelore
|
||||
- Base commit: fe1a3775c5f785adaa6372bd7ea3102c79331656
|
||||
- Owner: codex
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Fast-forward approved integration source 35e2a9149aed7d918176f00369cee6528505cdb8 into local main; update current canonical delivery status and preserve all source records, branches and worktrees.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- User explicitly requested main-branch merge. WS/Makelore adoption of the five named foreign documents was separately confirmed; they remain unchanged and excluded from commits. LMS primary checkout was clean; released this conversation's completed implementation/source integration ownership normally before claiming main.
|
||||
- Official check/start/status and Concurrent/Planning/Integration Gates Passed. Exact task, integration mode, branch, absolute worktree and base match. Entry, own record, required current memory and source outcome/candidates loaded; source decisions already approved. WS 277/LMS 25/Makelore 146 peer records unchanged. Historical WS Gateway missing Intent has no relevant dependency.
|
||||
- Community owns courses/self-study/works/points/support; institutions own teaching with optional LMS; Makelore stays course-free. Retain permanent manual per-child points and current-child-account recharge. No new product scope, subagents, remote push, deployment, payments or deletion.
|
||||
- Plan: fast-forward the fixed reviewed source, verify source ancestry/application equality and original foreign bytes, reconcile only current main-branch status, run task-aware documentation checks, commit the integration record and complete. Keep all worktrees by existing user instruction; do not ask again for cleanup.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Fast-forwarded fe1a3775c5f785adaa6372bd7ea3102c79331656 to approved source 35e2a9149aed7d918176f00369cee6528505cdb8 on local main, without conflicts. Application, tests, configuration and dependencies are unchanged from the verified source. Updated current canonical status and main delivery pointers; imported source records remain unchanged.
|
||||
- 3 original foreign documents remain byte-for-byte unchanged and excluded from this commit. All source worktrees and branches retained as explicitly requested; no cleanup question repeated. No push, deployment, production migration, payment, packaging or installation.
|
||||
|
||||
## Verification
|
||||
|
||||
- PASS: source clean; main base is an ancestor of the exact source; fast-forward succeeded. Source-to-main non-Markdown diff is empty, including working changes. Existing source phase-specific test evidence remains applicable; no unaffected business suite was rerun.
|
||||
- PASS: original foreign document bytes unchanged; their paths do not overlap this merge. Source task/proposal imports preserved through real ancestry. Official check_project_docs.py and task-aware check_doc_drift.py passed for all three repositories.
|
||||
- Reviewed base-to-integrated changes and the current status-only edits; current task record records actual scope, outcome, verification and follow-ups. Task Documentation Gate complete; Ready for Integration retains the primary checkout for future same-task work.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Real institution/course, OSS/media/network, payment and selected native/WeChat/installed-client acceptance remain separate. Course-package default limits still need real-pilot configuration; no optional receipt/mobile/multi-media expansion is included.
|
||||
- Retain all worktrees and branches by user instruction, including ignored output and dependencies; do not delete.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- Promoted exact source under Integrated Through and updated current pending-main wording in canonical designs, memory/evidence/commitment entry points and applicable root documents. Dated source records and historical entries remain read-only. No business decision changed.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Task: Integrate Makelore platform SSO
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20261010-integrate-makelore-platform-sso-9c2d
|
||||
- Mode: Integration
|
||||
- Branch: main
|
||||
- Worktree: D:\Datas\OthersProjects\makelore
|
||||
- Base commit: 87d3f03d751b93b607e56d3667c3655f2a03a792
|
||||
- Owner: codex-client-integrations
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Integrate source task `20261010-makelore-platform-sso-a1b2` at `7236def07d6a9a5cfde70c3239c6ac53764bcd7d` into local `main`; the source registration correction is `86216b8458db9a2c58850a6835fd1a76cee5a846`.
|
||||
- Reconcile the platform OIDC client boundary across the Makelore system overview, data flow, ADR-004, decision index, and current state. Preserve the existing Works Square password/mobile facade and the unchanged LMS/payment boundary.
|
||||
- Preserve the three adopted untracked documents byte-for-byte and exclude them from this integration commit: `30-worklog/tasks/20260901-package-122-c5e8.md`, `30-worklog/tasks/20260901-package-123-d7f3.md`, and `30-worklog/tasks/20260902-client-hang-diagnosis-a47c9e2b.md`.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- Electron Main owns the system-browser OIDC Authorization Code + PKCE flow, token exchange, refresh, and logout projection; require state, nonce, PKCE S256, and exact `niancode://auth/callback`.
|
||||
- Use the configured platform issuer and stable identity `issuer + sub=platform:<UUID>`; do not rebind by username, email, or legacy `auth_user_id`. Makelore's registered audience remains `works-square-api`.
|
||||
- Keep confidential OAuth secrets out of the Renderer and packaged public client. Do not call the custom one-feel identity service directly from the client. Do not deploy, push, migrate real accounts, or alter LMS/payment behavior.
|
||||
- Integration mode owns canonical project-memory reconciliation; the imported source task record remains source evidence and is not rewritten from this task.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Source implementation and its corrected Ready for Integration registration are fast-forwarded into `main`.
|
||||
- Canonical architecture and decision records now describe platform OIDC PKCE alongside the retained Works Square legacy authentication facade.
|
||||
- The three adopted foreign documents remain unchanged and untracked; none is staged by this task.
|
||||
|
||||
## Verification
|
||||
|
||||
- `check_project_docs.py` passed before planning; Concurrent Task Gate and Planning Gate passed for this integration task.
|
||||
- Source evidence reused: 65 focused Makelore tests, `pnpm run typecheck`, and scoped lint passed at source `7236def`; no duplicate full suite or package build was needed for this documentation-only reconciliation.
|
||||
- Fast-forward merge and source task drift passed; final integration runs `git diff --check` and `check_doc_drift.py --task-id 20261010-integrate-makelore-platform-sso-9c2d`.
|
||||
- No deployment, provider/real-account validation, push, package release, LMS change, payment change, or real-data migration was performed.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Deployment must provide `PLATFORM_AUTH_ISSUER`, the registered Makelore public client, exact `niancode://auth/callback` redirect, and the configured `works-square-api` audience before packaged platform login is released.
|
||||
- Cleanup completed after the authorized official retire attempt: `D:\Datas\OthersProjects\.codex-worktrees\makelore\20261010-makelore-platform-sso-a1b2` was removed, its Git branch `codex/20261010-makelore-platform-sso-a1b2-20261010-makelore-platform-sso-a1b2` and source commit `86216b8458db9a2c58850a6835fd1a76cee5a846` were preserved, and the stale ownership record was cleared with the official `release-missing --force` recovery after Windows left ignored dependency residue. No production migration is implied.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- None pending; the OIDC boundary is recorded in ADR-004, `system-overview.md`, `data-flow.md`, and `current-state.md`.
|
||||
@@ -0,0 +1,53 @@
|
||||
# Task: Makelore platform SSO client integration
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20261010-makelore-platform-sso-a1b2
|
||||
- Mode: Feature
|
||||
- Branch: codex/20261010-makelore-platform-sso-a1b2-20261010-makelore-platform-sso-a1b2
|
||||
- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20261010-makelore-platform-sso-a1b2
|
||||
- Base commit: 87d3f03d751b93b607e56d3667c3655f2a03a792
|
||||
- Owner: codex-client-integrations
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Replace the Makelore client’s direct one-feel password/mobile proxy as the primary sign-in path with a platform OIDC Authorization Code flow using PKCE S256.
|
||||
- Keep the flow in Electron Main: generate state and verifier, open the system browser, accept only an authorization code on `niancode://auth/callback`, exchange it against the platform token endpoint, and keep refresh credentials in Main’s existing secure session store.
|
||||
- Project the platform identity (`sub=platform:<UUID>`, `user_id=<platform UUID>`, issuer/audience) into the existing Renderer auth state without copying browser refresh credentials or changing LMS, payment, or server migration behavior.
|
||||
- Add focused Main/deep-link/session tests and update the owning product documentation for the new login boundary.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- The parent platform contract is authoritative: issuer comes from `platform_auth_issuer`; discovery, JWKS, authorize, token, userinfo, and revoke use the standard `/api/auth/oauth/*` paths; Makelore audience defaults to `works-square-api`.
|
||||
- The desktop client uses the system browser and PKCE S256. Client secrets, if the registered desktop client requires one, remain Main-owned and are read from OS-protected configuration; Renderer never receives them.
|
||||
- A callback carries `code` and `state` only. Access/refresh tokens in a deep-link are rejected. State is single-use and bound to the generated verifier and redirect URI.
|
||||
- Existing Main session refresh, account partitioning, logout, and Renderer capability projection remain the owners of local session behavior.
|
||||
- Do not infer identity by username, email, or legacy `auth_user_id`; preserve any legacy identifiers only as opaque migration metadata. Do not deploy, migrate real data, or modify the LMS.
|
||||
- Other active Makelore tasks concern marketplace, fullscreen, teacher concurrency, WeChat diagnosis, or review-only work; none owns auth routes, deep-link parsing, or session storage. Gate result: Passed.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Added a Main-owned platform OIDC Authorization Code + PKCE flow. Main discovers the platform authorization and token endpoints, generates one-time state/nonce/verifier values, opens the system browser through the renderer-safe Host API route, accepts the registered `niancode://auth/callback` code/state redirect, cleans the previous local runtime, and persists the returned Works Square session. The callback correlates by state because the platform redirect does not append the legacy desktop `request_id`; legacy request-id-only links remain accepted for compatibility.
|
||||
- Added explicit `/api/auth/platform/start` Host API routing, a platform login action on the native login page, and renderer account rehydration from `/api/auth/me` after Main commits the callback session. Access/refresh credentials remain Main-owned.
|
||||
- Updated the product README and added focused tests for callback parsing, discovery/PKCE/replay, route projection, and login-page browser launch.
|
||||
|
||||
## Verification
|
||||
|
||||
- Planning gate passed after reading the project positioning, current state, decision index, system overview, data flow, module map, business rules, stale-items, commitments, and peer task records.
|
||||
- `pnpm exec vitest run tests/unit/app-deep-link.test.ts tests/unit/platform-auth.test.ts tests/unit/auth-routes.test.ts tests/unit/login-page.test.tsx --maxWorkers=1` (65 tests passed).
|
||||
- `pnpm run typecheck` passed.
|
||||
- `pnpm run lint:check -- electron/main/app-deep-link.ts electron/services/platform-auth.ts electron/api/routes/auth.ts electron/main/index.ts src/App.tsx src/pages/Login/index.tsx tests/unit/app-deep-link.test.ts tests/unit/platform-auth.test.ts tests/unit/auth-routes.test.ts tests/unit/login-page.test.tsx` passed with eight pre-existing warnings outside the changed files and no errors.
|
||||
- Production deployment, real-account migration, and LMS changes were not performed.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- The platform issuer/client configuration must be supplied in the packaged deployment (`PLATFORM_AUTH_ISSUER`, with optional `PLATFORM_AUTH_CLIENT_ID`/`PLATFORM_AUTH_SCOPE`); this local task intentionally does not deploy or register clients.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- None. The product README documents the implemented client behavior; shared architecture promotion remains owned by the parent integration task.
|
||||
|
||||
## Status
|
||||
|
||||
Ready for Integration
|
||||
@@ -0,0 +1,42 @@
|
||||
# Task: Integrate Makelore identity rollback
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20261011-integrate-makelore-rollback-b8f41a62
|
||||
- Mode: Integration
|
||||
- Branch: main
|
||||
- Worktree: D:\Datas\OthersProjects\makelore
|
||||
- Base commit: f2a0eefc9ec5dfc2a09c15745b4786bc61682968
|
||||
- Owner: Codex
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Merge rollback source 658bf7d and prepared canonical integration 9949328 into local main, preserving the three known foreign task documents.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- User explicitly approved rollback and main ownership handoff with preserved dirty documents. The prior worker released the old main owner and prepared an isolated integration; its completed clean lock was normally released without deleting that checkout. Official start --mode integration --adopt-existing and status established this exact primary owner.
|
||||
- Project Context Loaded / Planning Gate Passed: entry, own task, memory, positioning, current state, decisions, architecture, evidence/reflection/commitments and both ready source records read; reuse unchanged peer assessment from this same rollback. User request resolves the OIDC direction conflict. Historical source records are read-only; no push, deployment or real provider operation.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Fast-forwarded main to 658bf7d, then merged prepared canonical integration 9949328 as 5ae6ffd204e4d5e0f8546544fa8fc8cc3e1c51f1. Product/test/README bytes equal the verified rollback source. Both source records remain unchanged; current canonical authentication again uses Electron Main and the Works Square one-feel facade.
|
||||
- All three preexisting untracked task records remain untracked and unchanged. No dependency or build files are staged.
|
||||
|
||||
## Verification
|
||||
|
||||
- Cleanup continuation: resumed the same primary integration with matching official ownership and preserved approved foreign content; reused unchanged project/peer context, re-read entry and task/source scope, and passed Planning Gate. Rechecked the exact resolved source path, clean managed ready state, committed ready record and latest-source ancestry before retire. Product tests are not repeated for checkout cleanup and task-record-only changes.
|
||||
|
||||
- Source evidence: 60 focused tests, typecheck and scoped lint passed; renderer-only Vite output to C: passed after the standard D: build ran out of disk space. Reused these results because integration changes only documentation.
|
||||
- Verified non-document equality to 658bf7d, merge/source ancestry, unchanged source records, adopted foreign states, whitespace and task-aware documentation boundaries.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Match the platform rollback release before deploying this client; production login/payment and packaged callbacks are not tested here.
|
||||
- User approved source-worktree cleanup on 2026-10-11. Official retire passed eligibility but Git removal failed with Directory not empty. Git unregistered the linked checkout and removed its .git file; residual directory D:\Datas\OthersProjects\.codex-worktrees\makelore\20261011-rollback-makelore-platform-auth-7c4e9a2b and its task ownership remain. A command to inspect and finish removal of only this approved residue, then use official release-missing, was rejected by automatic approval with blocked by policy before execution. Cleanup remains incomplete; no bypass was attempted. Branch codex/20261011-rollback-makelore-platform-auth-7c4e9a2b-rollback-makelore-platform-auth and commit 658bf7d remain preserved.
|
||||
- The released preparation checkout C:\Users\7brot\.codex-worktrees\makelore\20261011-integrate-rollback-makelore-c9d8e7f6 remains on disk and is not an automatic retire candidate.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- Accepted the prepared canonical rollback in 9949328 under the explicit user instruction; no new product decision or unresolved promotion remains.
|
||||
@@ -0,0 +1,98 @@
|
||||
# Task: Integrate Makelore platform SSO rollback
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20261011-integrate-rollback-makelore-c9d8e7f6
|
||||
- Mode: Integration
|
||||
- Branch: codex/20261011-integrate-rollback-makelore-c9d8e7f6-integrate-makelore-rollback-c9d8e7f6
|
||||
- Worktree: C:\Users\7brot\.codex-worktrees\makelore\20261011-integrate-rollback-makelore-c9d8e7f6
|
||||
- Base commit: f2a0eefc9ec5dfc2a09c15745b4786bc61682968
|
||||
- Owner: codex
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Integrate the completed Makelore rollback commit `e28beff` from
|
||||
`20261011-rollback-makelore-platform-auth-7c4e9a2b` onto the local `main`
|
||||
baseline `f2a0eefc9ec5dfc2a09c15745b4786bc61682968`.
|
||||
- Reconcile the canonical OIDC claims in ADR-004, the decision index, data
|
||||
flow, system overview, and current state so they describe the restored
|
||||
Works Square legacy login boundary after this rollback.
|
||||
- Preserve the original SSO source and former integration task records as
|
||||
historical evidence. The three known primary-checkout task documents are
|
||||
outside this worktree and must remain byte-for-byte unchanged and excluded
|
||||
from the integration commit.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- The user explicitly authorized the account-iteration rollback and local
|
||||
integration. This task changes only the Makelore client rollback and its
|
||||
canonical project-memory reconciliation; it does not touch one-feel,
|
||||
Yuxi, LMS, payment behavior, real accounts, deployment, or remotes.
|
||||
- Source task records and peer worktrees are read-only. Do not reset, delete
|
||||
branches, clean unknown files, or alter the Makelore primary checkout.
|
||||
- Keep the existing Works Square password/mobile facade, refresh, logout, and
|
||||
remembered-password boundary as the current desktop authentication contract.
|
||||
|
||||
## Project Context Loaded
|
||||
|
||||
- Concurrent Task Gate: Passed. `check_project_docs.py` passed; this task
|
||||
owns the isolated managed worktree and the integration lock.
|
||||
- Planning Gate: Passed after reading `read-before-planning.md`,
|
||||
`memory-index.md`, this task record, project positioning, current state,
|
||||
decision index, system overview, and the completed rollback source record.
|
||||
- Relevant peer scope: the rollback source is ready for integration and its
|
||||
only canonical conflict is the now-stale platform OIDC description. Other
|
||||
active Makelore tasks concern unrelated product areas and do not overlap
|
||||
these authentication or canonical-memory paths.
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
1. Cherry-pick the completed rollback commit and confirm only the documented
|
||||
client, test, and README paths are reversed.
|
||||
2. Restore the canonical authentication description to the pre-OIDC
|
||||
Works Square boundary, then add a current-state entry for this rollback
|
||||
with source, verification, and the unresolved future SSO decision.
|
||||
3. Run whitespace, project-document drift, and focused regression checks that
|
||||
distinguish restored legacy authentication from removed platform OIDC.
|
||||
4. Record the integration outcome, verification, preserved primary contents,
|
||||
and follow-ups in this task record; complete the integration registration.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Cherry-picked rollback commit `e28beff` as `45198ae`; the Makelore client
|
||||
application, focused tests, and README now match the pre-SSO code baseline.
|
||||
- Reconciled ADR-004, the decision index, data flow, system overview, and
|
||||
current state to make the Works Square legacy password/mobile login,
|
||||
refresh, and logout boundary current again. The prior OIDC records remain
|
||||
historical source evidence and are explicitly marked as superseded in the
|
||||
current-state entry.
|
||||
- The Makelore primary checkout was not edited by this task. Its three known
|
||||
untracked project task documents remain preserved and excluded from this
|
||||
integration.
|
||||
|
||||
## Verification
|
||||
|
||||
- Concurrent and Planning Gates passed.
|
||||
- Source verification is recorded in
|
||||
`20261011-rollback-makelore-platform-auth-7c4e9a2b`: 60 focused tests,
|
||||
typecheck, scoped lint, `git diff --check`, and a renderer-only Vite build
|
||||
passed; the normal D: output build was blocked by `ENOSPC`.
|
||||
- Integration verification passed: `git diff --name-status
|
||||
87d3f03d751b93b607e56d3667c3655f2a03a792 HEAD -- .` excluding
|
||||
`.project-docs/**` returned no paths, `git diff --check` passed, and
|
||||
`check_doc_drift.py --task-id 20261011-integrate-rollback-makelore-c9d8e7f6`
|
||||
passed. The isolated integration worktree has no dependency installation,
|
||||
so the source test evidence was reused rather than rerunning the same suite.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- A future platform SSO implementation requires a new explicit design and
|
||||
integration decision; this rollback leaves the client on the legacy path.
|
||||
- Re-run a normal Vite output build when D: has sufficient free space.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- None pending; the accepted rollback reconciliation is recorded in the
|
||||
canonical documents above. The historical OIDC source and prior integration
|
||||
task remain read-only evidence.
|
||||
@@ -0,0 +1,121 @@
|
||||
# Task: Rollback Makelore platform SSO integration
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20261011-rollback-makelore-platform-auth-7c4e9a2b
|
||||
- Mode: Feature
|
||||
- Branch: codex/20261011-rollback-makelore-platform-auth-7c4e9a2b-rollback-makelore-platform-auth
|
||||
- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20261011-rollback-makelore-platform-auth-7c4e9a2b
|
||||
- Base commit: f2a0eefc9ec5dfc2a09c15745b4786bc61682968
|
||||
- Owner: Codex
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Roll back the Makelore platform OIDC/SSO implementation introduced by
|
||||
source commit `7236def` while leaving the main checkout and unrelated
|
||||
product work untouched.
|
||||
- Reverse only the application code, tests, and README changes from that
|
||||
source commit. Preserve all `.project-docs` source and integration history,
|
||||
including the records for the original SSO work.
|
||||
- Keep the existing legacy Makelore login boundary and its current payment,
|
||||
LMS, and local session behavior.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- Work only in this isolated feature worktree based on `f2a0eef`; do not
|
||||
reset, delete branches, push, deploy, or modify the Makelore primary
|
||||
checkout.
|
||||
- The rollback must not discard subsequent unrelated product changes or any
|
||||
pre-existing primary-checkout content.
|
||||
- The canonical `.project-docs` files are shared project memory and remain
|
||||
read-only in this feature task. Any semantic reconciliation after removing
|
||||
the runtime implementation is a follow-up for an authorized integration
|
||||
task.
|
||||
|
||||
## Project Context Loaded
|
||||
|
||||
Read:
|
||||
- `.project-docs/05-agent-entry/read-before-planning.md`
|
||||
- `.project-docs/05-agent-entry/memory-index.md`
|
||||
- `.project-docs/00-brief/project-positioning.md`
|
||||
- `.project-docs/30-worklog/current-state.md`
|
||||
- `.project-docs/10-decisions/decision-index.md`
|
||||
- `.project-docs/20-architecture/system-overview.md`
|
||||
- Relevant peer records `20261010-makelore-platform-sso-a1b2` and
|
||||
`20261010-integrate-makelore-platform-sso-9c2d`
|
||||
- Repository `AGENTS.md`
|
||||
|
||||
Relevant understanding:
|
||||
- `7236def` is the only source commit adding the Makelore platform OIDC
|
||||
runtime, focused tests, and README behavior; `86216b8`, `afaefdc`, and
|
||||
`f2a0eef` are project-memory records.
|
||||
- The rollback overlaps the prior SSO task by design, but no peer owns this
|
||||
isolated worktree. Other active Makelore tasks concern unrelated product
|
||||
areas.
|
||||
|
||||
Gate result:
|
||||
- Passed
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
1. Compare the source and current commit ranges and identify the exact
|
||||
non-`.project-docs` paths introduced by `7236def`.
|
||||
2. Reverse those runtime, test, and README changes while retaining
|
||||
`.project-docs` from the current base.
|
||||
3. Run focused legacy authentication tests, type checking, linting, and
|
||||
whitespace/document drift checks.
|
||||
4. Record the committed rollback and leave the isolated branch ready for the
|
||||
parent integration task.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Created rollback commit `e28beff` by reversing the runtime, renderer,
|
||||
deep-link, focused-test, and README changes from `7236def`.
|
||||
- Preserved the original SSO source task, integration task, and all other
|
||||
`.project-docs` content from the current base. The non-`.project-docs`
|
||||
tree now matches the pre-SSO baseline `87d3f03`.
|
||||
- No primary checkout, branch, remote, deployment, account, or provider state
|
||||
was changed.
|
||||
|
||||
## Verification
|
||||
|
||||
- `git diff --name-status 87d3f03 HEAD -- . ':(exclude).project-docs/**'`
|
||||
returned no paths, confirming the application/test/README rollback matches
|
||||
the pre-SSO code baseline.
|
||||
- `git diff --check` passed.
|
||||
- Focused Vitest: 3 files / 60 tests passed.
|
||||
- `pnpm run typecheck` passed.
|
||||
- Scoped ESLint for the restored authentication paths passed.
|
||||
- `pnpm run build:vite` reached module transformation but failed while
|
||||
writing ignored build output because D: had no free space (`ENOSPC`).
|
||||
- A renderer-only Vite build then passed with
|
||||
`NIANCODE_RENDERER_ONLY=1 pnpm exec vite build --outDir
|
||||
C:\Users\7brot\AppData\Local\Temp\codex-makelore-vite-rollback-20261011`.
|
||||
It emitted 131 files (about 6.96 MB); only the existing dynamic-import and
|
||||
large-chunk warnings were reported.
|
||||
- Read-only primary-worktree snapshot: the owner is integration task
|
||||
`20261010-integrate-makelore-platform-sso-9c2d`, mode `integration`,
|
||||
status `ready_for_integration`, on `main`. The primary has no staged or
|
||||
modified tracked files and has exactly three pre-existing untracked task
|
||||
records under `.project-docs/30-worklog/tasks/`.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Reconcile the canonical `.project-docs` OIDC claims in a separately
|
||||
authorized integration task before presenting the rollback as the current
|
||||
product architecture.
|
||||
- Re-run the Vite build after dependency/build-output space is available.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- Target: canonical SSO architecture and current-state records.
|
||||
Proposal: mark the platform OIDC client rollback and restore the legacy
|
||||
Makelore login boundary.
|
||||
Evidence: rollback commit `e28beff` and the exact no-diff comparison to
|
||||
`87d3f03`.
|
||||
Future impact: packaged clients continue using the legacy login route until
|
||||
a replacement SSO implementation is explicitly approved.
|
||||
Semantic conflict: current canonical project memory still records the
|
||||
integrated OIDC design; an integration task must resolve that conflict.
|
||||
Human confirmation: required before changing canonical project memory.
|
||||
@@ -28,7 +28,7 @@
|
||||
## Permanent Token Points
|
||||
|
||||
- 账号不再具有会员或订阅等级、周额度或重置卡。真实新注册一次赠送 100 点;旧账号不补送、不折算,存量旧权益直接取消。充值 1 元人民币兑换 50 点,点数永不过期。所有资格、价格、余额、赠送和入账以 Works Square 为权威,客户端不以首次登录推测新注册或自行补点。
|
||||
- 家长只给本人钱包充值。青少年可以看本人精确余额;另一付款方的共享钱包只展示可用性,不展示金额、点数或其账本。付款资格与余额可见性分别来自服务端,不再依赖旧会员管理权限。
|
||||
- 家长给孩子购买点数时登录孩子的号;充值进入当前登录账号,界面明确显示收款对象,不传另一个孩子 ID、不转移家长资金、不改变已选付款来源。青少年可以看本人精确余额;另一付款方的共享钱包只展示可用性,不展示金额、点数或其账本。付款资格与余额可见性分别来自服务端,不再依赖旧会员管理权限。
|
||||
- `family_shared=true` 不足以判定是否隐藏余额:付款方自己的钱包也可能带此标记。`shared_available` 为布尔值时投影另一付款方的粗粒度余额;为 `null` 时保留本人精确余额,包括 `entitlement_source=self` 或 `shared_group` 的本人家庭钱包。
|
||||
- AI 编程明确选择付款来源,余额不足时不静默切换。云智能体仍由创建者付费,Plugin 仍用个人付款;共享付款不授予其他账号内容、订单或流水权限。
|
||||
- 充值必须由用户明确发起,Renderer 不传付款人、价格或认证凭据。一次意图复用原请求身份;结果不明时只允许同身份重试,待支付或人工核对订单先恢复原订单。订单创建时冻结金额和点数,商品改价不改变旧单,服务端确认前不展示到账。
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Evidence Index
|
||||
|
||||
## Community Product Integration · 2026-10-09
|
||||
|
||||
源 `0d442ce576430880355ca35382b844d2cec14d64` 的D01 当前账号充值、可见收款对象及无课程客户端边界已与正式设计对齐并合入本地 main。合并源 `35e2a914`,见[主分支交付记录](../30-worklog/tasks/20261009-merge-product-dd0461f9.md)。各阶段测试仍以[实施任务](../30-worklog/tasks/20261009-makelore-product-implementation-eaa0ffa5.md)为证据;本次只核对代码/测试/配置一致性、源记录保留、文档链接和门禁,结果见[集成任务](../30-worklog/tasks/20261009-makelore-product-integration-29d647c5.md)。未重新运行未受影响的全套应用测试,也不把本地验证等同真实环境验收。
|
||||
|
||||
2026-09-28 [项目会话隔离修复](../30-worklog/tasks/20260928-agent-project-chat-6644c06d.md) `4b41c23` 已合入本地main:382项相关测试、标准typecheck、变更文件lint、Vite构建及3项Electron场景通过。覆盖同一智能体双项目历史/草稿切换与重载、旧全局轮项目归属/已读迁移/部分写入恢复、新云端checkpoint、独立运行与取消边界、迟到响应排除和目录刷新。产品/测试与源一致,合并沿用其验证;扩展Main仍有66项既有诊断。真实模型、安装版和主动观察组合验收未执行。
|
||||
|
||||
2026-09-28 [单会话源任务](../30-worklog/tasks/20260928-agent-single-chat-27da516b.md) `7aa81da` 已合入本地main:365项相关单测、Renderer typecheck、变更文件lint、Vite构建与1项真实Electron夹具交互通过,覆盖存储恢复、分页/事件合并、旧记录归属、每轮范围/版本、历史原文读取、草稿与已读。集成产品/测试与源一致,沿用其证据;扩展Main仍有相同66项基线诊断。未验证线上付费模型、跨设备同步或独立主动观察与单聊天的组合交付。
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Commitments
|
||||
|
||||
## Community Product Rollout · 2026-10-09
|
||||
|
||||
本地实现与正式设计已合入本地 main;发布与真实环境验收待安排。按[当前设计](../20-architecture/community-collaboration.md)协调 WS API/迁移、LMS API 与资料客户端、麦洛当前账号充值资格;真实机构/课程、OSS/长视频、支付、真机和微信工具页面分别验收。机构采用回执尚未自动回写社区,先人工登记实际交付。不要恢复已取消的麦洛课程任务或重复已实现的 D06/D07。保留全部工作区/分支,未部署或删除。
|
||||
|
||||
Track future-facing memory: promised follow-ups, unfinished loops, timed checks, and restart points.
|
||||
|
||||
| Date | Commitment | Trigger / Due | Owner | Status | Next Action |
|
||||
|
||||
@@ -33,7 +33,7 @@ Makelore 是一个面向软件、视觉创作、智能机器人与个人云智
|
||||
- AI 编程核心对话运行时:Electron Main 按需启动一个长驻 Pi Agent Server,同一进程内为每条 Conversation 建立独立的 Runtime、Session、凭证视图、扩展上下文和 JSONL 通道,同时复用 Pi 模块与进程启动成本;Server 异常退出时所有旧通道统一失效,下一次恢复只重启一个 Server。正式包中的 Agent Server 从明确传入的 `resources/pi-runtime` 根定位依赖清单与包入口,不从脚本所在目录或应用 `node_modules` 猜测解析。Renderer 不直接启动或调用 Pi,也不读取其 wire 类型。项目与 Conversation 元数据先从本地读取,选中对话后才按需准备对应逻辑线程;输入框不等待运行时准备完成。同一助手工具批次中,会取得项目写租约的 `bash`、`edit`、`write` 与动态产品工具按顺序执行,避免批次在命令启动前自锁;纯只读工具仍可并行。子 Agent 仍使用独立的短生命周期进程,以保留并发配额、故障和写入边界;macOS 上两类后台进程都使用 Electron 自带的 Helper,不在 Dock 中创建额外应用图标。
|
||||
- AI 编程默认入口:进入 Code 后保持在 `/chat`。顶部返回箭头与侧栏收起图标同排,与右侧项目/会话名称对齐;折叠时保留返回和展开入口。macOS 为原生窗口按钮保留安全空间,窄侧栏仍可使用。下方麦洛品牌与“操作对话/作品”标签行对齐;更浅底色的“作品广场”与“新建项目”采用相同高度、圆角、边框与阴影,并位于品牌和新建项目之间,上下各留 10px;“我的项目”和项目列表紧接新建项目;项目配置及其资源子页不再重复显示此侧栏入口,保留配置页自身的返回操作。尚未选择本地项目时,页面以麦洛 M 标识和居中引导语建立焦点,下方提供独立的“新增项目”主操作以及可横向浏览、直接进入的已有项目卡片;项目创建和进入仍复用侧栏现有流程。已有项目的新 Conversation 在可编辑 Composer 上方沿用同一品牌引导,第一条消息出现后切换为正常时间线。
|
||||
- AI 编程历史与配额反馈:Pi 上下文压缩不删除用户可见的 active-branch 历史,压缩摘要保持 Main-private;Renderer 首次渲染最近 120 个节点,向上滚动时按 100 个节点追加更早内容并保持阅读位置。Main 精确识别 `token_point_balance_exhausted` / `词元点数余额不足`,只向 Renderer 投影不可重试的稳定配额错误和安全中文提示,重开会话后仍可见且不暴露上游原始错误或 request id。
|
||||
- 账号词元点数:左下角账户菜单显示本人永久余额和预占,提供充值、充值订单与分页收支记录。真正新注册赠送 100 点,1 元充值 50 点,永久有效;旧账户不补送,旧会员/订阅/周额度/重置卡入口已移除。家长充值始终进入自己的钱包,青少年可查看自己的精确余额;使用他人共享钱包时仅显示可用状态,不显示付款人的余额或记录。Main 持有凭据并转发充值请求;付款结果未知时沿用原请求并核查原订单,只有服务端确认才显示到账。扫码信息缺失时可到网页账户页继续原订单,付款来源也由网页账户页管理。需配套部署 Works Square 永久点数 API 与 0094 迁移;本地模拟验收不代表真实支付通过。
|
||||
- 账号词元点数:左下角账户菜单显示本人永久余额和预占,提供充值、充值订单与分页收支记录。真正新注册赠送 100 点,1 元充值 50 点,永久有效;旧账户不补送,旧会员/订阅/周额度/重置卡入口已移除。家长为孩子充值时登录孩子的账号,页面显示当前昵称和账号,点数进入该账号自己的钱包;无需将孩子身份改为家长。当前有效账号可给本人充值,青少年可查看自己的精确余额;使用他人共享钱包时仅显示可用状态,不显示付款人的余额或记录。Main 持有凭据并转发充值请求;付款结果未知时沿用原请求并核查原订单,只有服务端确认才显示到账。扫码信息缺失时可到网页账户页继续原订单,付款来源也由网页账户页管理,充值不会自动切换共享/个人来源。需配套部署 Works Square 当前账号充值资格更新(本次无需新迁移,原永久点数基础为 0094);本地模拟验收不代表真实支付通过。
|
||||
- 桌面性能策略:应用窗口使用不透明浅色表面并默认保留硬件合成;仅在显式安全模式或短时间内重复 GPU 进程崩溃时启用软件渲染,并把故障原因保存在用户数据目录。启动关键路径只创建本地应用壳,认证、代理、同步、更新和遥测在首帧后延迟初始化;开发版可通过 `app:performance` 快照观察 GPU、进程、WebContents、事件循环与 Renderer Long Task 聚合指标。
|
||||
- 后台生命周期:Main 统一维护模块活动状态与任务租约。隐藏窗口、离开模块和关闭开发浏览器会释放非必要连接;生成、Code 执行、下载与发布构建持有租约并在完成后释放。已写入 Pi 的 prompt 或上下文整理即使确认超过 10 秒,也会继续持有运行所有权与后台租约,直到迟到响应、权威事件、明确失败或用户清理使其收敛;此时同一 Conversation 不接受重叠 mutation,其他 Conversation 不受影响。各模块的后台连接、轮询和子进程必须通过同一生命周期入口登记。
|
||||
- 共享开发浏览器:AI 编程右侧提供项目级浏览器,用户与 Agent 查看并调试同一实时页面、Console 和 Network,支持本地与公网开发地址。
|
||||
|
||||
@@ -178,7 +178,7 @@ export async function handleWorksBillingRoutes(req: IncomingMessage, res: Server
|
||||
if (!response.ok) {
|
||||
const detail = record(payload).detail;
|
||||
const rejection = detail && typeof detail === 'object' && record(detail).outcome === 'definitive_rejection';
|
||||
const messages: Record<number, string> = { 401: '登录已失效,请重新登录。', 403: '当前账户不能充值,请联系家长。', 404: '充值档位或订单已不可用,请刷新。', 409: '请先完成或核查已有充值订单;计费服务也可能正在切换。', 410: '账户服务版本不匹配,请更新客户端和服务端。' };
|
||||
const messages: Record<number, string> = { 401: '登录已失效,请重新登录。', 403: '当前账号暂不能充值,请在社区账户页查看原因或联系支持。', 404: '充值档位或订单已不可用,请刷新。', 409: '请先完成或核查已有充值订单;计费服务也可能正在切换。', 410: '账户服务版本不匹配,请更新客户端和服务端。' };
|
||||
sendJson(res, response.status >= 400 && response.status < 500 ? response.status : 502, {
|
||||
success: false, error: rejection ? '支付服务拒绝了本次请求,请稍后重试。' : messages[response.status] ?? '支付结果尚未确认,请刷新订单或联系运营核查,勿重复付款。',
|
||||
commandOutcome: rejection || [401, 403, 404, 422].includes(response.status) ? 'definitive_failure' : 'unknown',
|
||||
|
||||
@@ -21,7 +21,7 @@ const money = (cents: number) => `¥${(cents / 100).toFixed(2)}`;
|
||||
const time = (value: string) => new Date(value).toLocaleString('zh-CN');
|
||||
const unresolved = (order: WorksRechargeOrder) => order.status === 'pending' || order.status === 'manual_review';
|
||||
|
||||
export function PointWallet({ active = true }: { active?: boolean }) {
|
||||
export function PointWallet({ active = true, accountName = '当前登录账号', accountUsername }: { active?: boolean; accountName?: string; accountUsername?: string }) {
|
||||
const [summary, setSummary] = useState<WorksBillingSummary | null>(null);
|
||||
const [summaryError, setSummaryError] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
@@ -166,7 +166,7 @@ export function PointWallet({ active = true }: { active?: boolean }) {
|
||||
{own && <p className="mt-1 text-[11px] text-muted-foreground">永久有效 · 预占 {points(own.reserved)} 点</p>}
|
||||
{usingShared && <p className="mt-1 text-[11px] text-muted-foreground">AI 编程使用共享点数:{selected?.shared_available ? '可用' : '已用尽,请联系付款人'}</p>}
|
||||
{summary?.funding_error && <p className="mt-1 text-[11px] text-muted-foreground">{summary.funding_error}</p>}
|
||||
{isWorksTokenPointBalanceExhausted(own) && !usingShared && <p className="mt-1 text-[11px] text-muted-foreground">{summary?.can_recharge ? '点数已用尽,充值后可继续使用。' : '点数已用尽,请联系家长。'}</p>}
|
||||
{isWorksTokenPointBalanceExhausted(own) && !usingShared && <p className="mt-1 text-[11px] text-muted-foreground">{summary?.can_recharge ? '点数已用尽,请由家长完成当前账号充值。' : '点数已用尽,当前账号暂不能充值,请联系支持。'}</p>}
|
||||
{summaryError && <button className="mt-1 underline" onClick={() => void refreshSummary()}>重试余额</button>}
|
||||
</div>
|
||||
<button type="button" role="menuitem" data-testid="sidebar-point-wallet-open" className="flex min-h-10 w-full items-center gap-2 rounded-md px-1 text-left text-sm hover:bg-surface-subtle" onClick={() => { setOpen(true); setTab('recharge'); setOffset(0); }}><Coins className="h-4 w-4" />词元点数与充值</button>
|
||||
@@ -192,6 +192,8 @@ export function PointWallet({ active = true }: { active?: boolean }) {
|
||||
</div>
|
||||
<Button variant="outline" size="sm" disabled={loading || busy} onClick={() => { setError(''); void refreshSummary(); void refreshPage(); }}><RefreshCw className="mr-1 h-3.5 w-3.5" />刷新</Button>
|
||||
</div>
|
||||
<p className="text-sm" data-testid="point-recharge-recipient">充值到:{accountName}{accountUsername && accountUsername !== accountName ? `(${accountUsername})` : ''}</p>
|
||||
<p className="text-sm text-muted-foreground">为孩子充值时,请由家长登录孩子的账号完成付款。点数仅进入当前账号的钱包。</p>
|
||||
{summary?.funding_error && <p className="text-sm text-muted-foreground">{summary.funding_error}</p>}
|
||||
{usingShared && <p className="text-sm text-muted-foreground">AI 编程使用共享点数({selected?.shared_available ? '可用' : '已用尽'})。下方余额、充值与记录均属于你自己的钱包;充值不会自动切换付款来源。</p>}
|
||||
<div className="flex gap-2" role="tablist" aria-label="词元点数记录">{(['recharge', 'orders', 'history'] as const).map((value) => <Button key={value} role="tab" aria-selected={tab === value} variant={tab === value ? 'default' : 'outline'} onClick={() => { setTab(value); setOffset(0); }}>{value === 'recharge' ? '充值' : value === 'orders' ? '充值订单' : '收支记录'}</Button>)}</div>
|
||||
@@ -199,7 +201,7 @@ export function PointWallet({ active = true }: { active?: boolean }) {
|
||||
{error && <p role="alert" className="text-sm text-destructive">{error}</p>}
|
||||
{loading && <p role="status" className="text-sm text-muted-foreground">正在读取记录…</p>}
|
||||
{tab === 'recharge' && <div className="grid gap-3">
|
||||
{summary && !summary.can_recharge && <p className="text-sm text-muted-foreground">仅家长身份可以充值,请联系家长。你仍可查看自己的余额和收支。</p>}
|
||||
{summary && !summary.can_recharge && <p className="text-sm text-muted-foreground">当前账号暂不能充值,请在社区账户页查看原因或联系支持。你仍可查看自己的余额和收支。</p>}
|
||||
{summary?.can_recharge && !summary.payment_configured && <p className="text-sm text-muted-foreground">充值暂未开放,请稍后再试。</p>}
|
||||
{pending && checkout?.id !== pending.id && <div className="rounded-lg border p-3 text-sm"><p>已有{labels[pending.status]}订单:{money(pending.amount_cents)} / {points(pending.point_amount)} 点。请先完成或联系运营核查。</p><Button variant="outline" className="mt-2" onClick={() => setCheckout(pending)}>查看原订单</Button></div>}
|
||||
{(!checkout || !unresolved(checkout)) && <div className="grid grid-cols-1 gap-2 sm:grid-cols-3">{summary?.recharge_products.map((product) => <Button key={product.id} className="h-auto flex-col gap-1 py-4" variant="outline" disabled={!loaded || busy || Boolean(pending) || !summary.can_recharge || !summary.payment_configured || Boolean(unknownProduct)} onClick={() => void purchase(product.id)}><span className="text-lg font-semibold">{points(product.point_amount)} 点</span><span>{money(product.amount_cents)}</span></Button>)}</div>}
|
||||
|
||||
@@ -872,7 +872,7 @@ export function Sidebar({
|
||||
</div>
|
||||
|
||||
<div className="mt-1 grid gap-0.5">
|
||||
{authUser && <PointWallet key={authUser.userId ?? authUser.username} active={accountMenuOpen} />}
|
||||
{authUser && <PointWallet key={authUser.userId ?? authUser.username} active={accountMenuOpen} accountName={accountName} accountUsername={authUser.username} />}
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
|
||||
@@ -4,7 +4,7 @@ type WalletFixture = { requests: string[]; paid: boolean; created: boolean };
|
||||
type FixtureGlobal = typeof globalThis & { __pointWalletE2E: WalletFixture };
|
||||
|
||||
test.describe('Permanent point wallet', () => {
|
||||
test('reopens an unpaid order, keeps its frozen amount, and refreshes only after confirmed credit', async ({ launchElectronApp }, testInfo) => {
|
||||
test('shows the child recipient, reopens its frozen unpaid order, and refreshes only after confirmed credit', async ({ launchElectronApp }, testInfo) => {
|
||||
const app = await launchElectronApp({ skipSetup: true });
|
||||
try {
|
||||
const page = await getStableWindow(app);
|
||||
@@ -40,12 +40,12 @@ test.describe('Permanent point wallet', () => {
|
||||
});
|
||||
if (path === '/api/auth/me') return result({
|
||||
success: true,
|
||||
user: { username: 'point-wallet', userId: 'point-wallet-user', tenantId: null, deptId: null, authorities: [] },
|
||||
user: { username: 'child-wallet', userId: 'child-wallet-user', tenantId: null, deptId: null, authorities: [] },
|
||||
moduleAccess: { programming: true, design: true, robot: true },
|
||||
});
|
||||
if (path === '/api/works/user/agent-profile') return result({
|
||||
success: true, profile: {
|
||||
display_name: '词元点数用户', age: null, gender: null, avatar_url: null,
|
||||
display_name: '小麦', age: null, gender: null, avatar_url: null,
|
||||
share_age_with_agents: false, share_gender_with_agents: false, analysis_enabled: true,
|
||||
completed: true, version: 1, updated_at: '2026-09-22T00:00:00Z',
|
||||
},
|
||||
@@ -78,13 +78,15 @@ test.describe('Permanent point wallet', () => {
|
||||
await page.goto(applicationUrl, { waitUntil: 'domcontentloaded' });
|
||||
await page.getByTestId('ai-module-option-programming').click();
|
||||
await expect(page.getByTestId('main-layout')).toBeVisible();
|
||||
await expect(page.getByTestId('sidebar-member-menu-trigger')).toContainText('词元点数用户');
|
||||
await expect(page.getByTestId('sidebar-member-menu-trigger')).toContainText('小麦');
|
||||
await page.getByTestId('sidebar-member-menu-trigger').click();
|
||||
await expect(page.getByTestId('sidebar-total-token-points')).toHaveText('0 点');
|
||||
await expect(page.getByText('点数已用尽,充值后可继续使用。')).toBeVisible();
|
||||
await expect(page.getByText('点数已用尽,请由家长完成当前账号充值。')).toBeVisible();
|
||||
await page.getByTestId('sidebar-point-wallet-open').click();
|
||||
const wallet = page.getByTestId('point-wallet-dialog');
|
||||
await expect(wallet).toContainText('1 元充值 50 点');
|
||||
await expect(wallet.getByTestId('point-recharge-recipient')).toHaveText('充值到:小麦(child-wallet)');
|
||||
await expect(wallet).toContainText('请由家长登录孩子的账号完成付款');
|
||||
await expect(wallet).not.toContainText('重置卡');
|
||||
await wallet.getByRole('button', { name: /500 点\s*¥10.00/ }).click();
|
||||
await expect(wallet.getByAltText('充值支付二维码')).toBeVisible();
|
||||
|
||||
@@ -27,14 +27,31 @@ describe('permanent point wallet', () => {
|
||||
expect(dialog).toHaveTextContent('永久有效');
|
||||
expect(screen.queryByText(/重置卡|升级订阅|本周剩余/)).not.toBeInTheDocument();
|
||||
});
|
||||
it('shows youth own precision and shared availability without enabling recharge', async () => {
|
||||
it('honors unavailable recharge without asking the user to change account identity', async () => {
|
||||
api.summary.mockResolvedValue(billingSummary({ can_recharge: false, payment_configured: false, own_points: permanentBalance({ can_recharge: false }), points: permanentBalance({ total: null, used: null, reserved: null, total_remaining: null, family_shared: true, entitlement_source: 'family_owner', shared_available: false, can_recharge: false }) }));
|
||||
render(<PointWallet />); await screen.findByText('75 点');
|
||||
expect(screen.getByText(/AI 编程使用共享点数/)).toHaveTextContent('已用尽');
|
||||
fireEvent.click(screen.getByTestId('sidebar-point-wallet-open'));
|
||||
await screen.findByText(/仅家长身份可以充值/);
|
||||
await screen.findByText(/当前账号暂不能充值,请在社区账户页查看原因或联系支持/);
|
||||
expect(screen.queryByText(/仅家长身份可以充值/)).not.toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /500 点\s*¥10.00/ })).toBeDisabled();
|
||||
});
|
||||
it('recharges the displayed child account while leaving shared funding selected', async () => {
|
||||
api.summary.mockResolvedValue(billingSummary({ points: permanentBalance({ total: null, used: null, reserved: null, total_remaining: null, family_shared: true, entitlement_source: 'shared_group', shared_available: true, can_recharge: false }) }));
|
||||
render(<PointWallet accountName="小麦" accountUsername="child-account" />);
|
||||
await screen.findByText('75 点');
|
||||
fireEvent.click(screen.getByTestId('sidebar-point-wallet-open'));
|
||||
const dialog = screen.getByTestId('point-wallet-dialog');
|
||||
expect(screen.getByTestId('point-recharge-recipient')).toHaveTextContent('充值到:小麦(child-account)');
|
||||
expect(dialog).toHaveTextContent('请由家长登录孩子的账号完成付款');
|
||||
expect(dialog).toHaveTextContent('充值不会自动切换付款来源');
|
||||
const buy = within(dialog).getByRole('button', { name: /500 点\s*¥10.00/ });
|
||||
await waitFor(() => expect(buy).toBeEnabled());
|
||||
fireEvent.click(buy);
|
||||
await screen.findByTestId('point-recharge-checkout');
|
||||
expect(api.create).toHaveBeenCalledWith('recharge-10', expect.any(String));
|
||||
expect(api.external).not.toHaveBeenCalled();
|
||||
});
|
||||
it('does not mistake the family payer’s own shared wallet for an exhausted external wallet', async () => {
|
||||
api.summary.mockResolvedValue(billingSummary({ points: permanentBalance({ family_shared: true, entitlement_source: 'shared_group' }) }));
|
||||
await openWallet();
|
||||
|
||||
@@ -91,6 +91,7 @@ describe('Sidebar permanent point wallet', () => {
|
||||
expect(screen.queryByText(/重置卡|升级订阅|会员等级|本周剩余/)).not.toBeInTheDocument();
|
||||
fireEvent.click(screen.getByTestId('sidebar-point-wallet-open'));
|
||||
expect(screen.getByTestId('point-wallet-dialog')).toHaveTextContent('1 元充值 50 点');
|
||||
expect(screen.getByTestId('point-recharge-recipient')).toHaveTextContent('测试用户(member@example.com)');
|
||||
});
|
||||
it('shows a retryable failure without inventing a zero balance', async () => {
|
||||
fetchBillingSummaryMock.mockRejectedValue(new Error('offline'));
|
||||
|
||||
@@ -101,6 +101,12 @@ describe('permanent points Main contract', () => {
|
||||
const result = await call('/me');
|
||||
expect(result.status).toBe(409); expect(result.body.data).toBeUndefined();
|
||||
});
|
||||
it('does not translate an unavailable current-account recharge into a parent-identity requirement', async () => {
|
||||
reply({ detail: '当前账号暂不能充值词元点数' }, 403);
|
||||
const result = await call('/recharge/orders', 'POST', { productId: 'p', requestId: 'r' });
|
||||
expect(result.body).toMatchObject({ commandOutcome: 'definitive_failure', error: '当前账号暂不能充值,请在社区账户页查看原因或联系支持。' });
|
||||
expect(result.body.error).not.toContain('联系家长');
|
||||
});
|
||||
it.each(['/plans', '/reset-cards', '/subscriptions', '/reset-card-orders'])('retires %s without contacting payment services', async (path) => {
|
||||
expect((await call(path)).status).toBe(410); expect(net).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import server from '../fixtures/permanent-points-server.json';
|
||||
// an isolated SQLite database and a fake payment provider. All identities are synthetic.
|
||||
// Covers the real API's serialized decimals, timestamps, optional fields and order envelopes.
|
||||
describe('Works Square permanent-points API compatibility', () => {
|
||||
it('projects old accounts at zero and genuinely registered youth at 100, without a client gift', () => {
|
||||
it('projects balance and recharge permission from the captured pre-D01 server response without a client gift', () => {
|
||||
expect(projectBillingSummary(server.before).own_points.total_remaining).toBe('0.00');
|
||||
const youth = projectBillingSummary(server.youth);
|
||||
expect(youth.own_points.total_remaining).toBe('100.00');
|
||||
|
||||
Reference in new issue
Block a user