|
20253
|
8
|
5
|
10
|
22
|
0
|
0
|
refs/heads/app-260818
|
0
|
{"Commits":[{"Sha1":"e059d5058 {"Commits":[{"Sha1":"e059d505828c22f149039cf2c94e8b4669b8c655","Message":"1\n","AuthorEmail":"yangruilin888@gmail.com","AuthorName":"linyangrui","CommitterEmail":"yangruilin888@gmail.com","CommitterName":"linyangrui","Timestamp":"2026-07-31T16:31:17+08:00"}],"HeadCommit":{"Sha1":"e059d505828c22f149039cf2c94e8b4669b8c655","Message":"1\n","AuthorEmail":"yangruilin888@gmail.com","AuthorName":"linyangrui","CommitterEmail":"yangruilin888@gmail.com","CommitterName":"linyangrui","Timestamp":"2026-07-31T16:31:17+08:00"},"CompareURL":"vodtest/app/compare/14505c18ce48a5255345983ef2919bad362a951b...e059d505828c22f149039cf2c94e8b4669b8c655","Len":1}...
|
1785486684
|
Edit
Delete
|
|
20254
|
11
|
5
|
10
|
22
|
0
|
0
|
refs/heads/app-260818
|
0
|
{"Commits":[{"Sha1":"e059d5058 {"Commits":[{"Sha1":"e059d505828c22f149039cf2c94e8b4669b8c655","Message":"1\n","AuthorEmail":"yangruilin888@gmail.com","AuthorName":"linyangrui","CommitterEmail":"yangruilin888@gmail.com","CommitterName":"linyangrui","Timestamp":"2026-07-31T16:31:17+08:00"}],"HeadCommit":{"Sha1":"e059d505828c22f149039cf2c94e8b4669b8c655","Message":"1\n","AuthorEmail":"yangruilin888@gmail.com","AuthorName":"linyangrui","CommitterEmail":"yangruilin888@gmail.com","CommitterName":"linyangrui","Timestamp":"2026-07-31T16:31:17+08:00"},"CompareURL":"vodtest/app/compare/14505c18ce48a5255345983ef2919bad362a951b...e059d505828c22f149039cf2c94e8b4669b8c655","Len":1}...
|
1785486684
|
Edit
Delete
|
|
20255
|
1
|
5
|
1
|
32
|
0
|
0
|
refs/heads/master
|
1
|
{"Commits":[{"Sha1":"fe71ee60f {"Commits":[{"Sha1":"fe71ee60f35a3818ccc6b78d4af0f61c760d639a","Message":"补丁\n","AuthorEmail":"121158035@qq.com","AuthorName":"zhangjunnan","CommitterEmail":"121158035@qq.com","CommitterName":"zhangjunnan","Timestamp":"2026-07-31T16:36:52+08:00"}],"HeadCommit":{"Sha1":"fe71ee60f35a3818ccc6b78d4af0f61c760d639a","Message":"补丁\n","AuthorEmail":"121158035@qq.com","AuthorName":"zhangjunnan","CommitterEmail":"121158035@qq.com","CommitterName":"zhangjunnan","Timestamp":"2026-07-31T16:36:52+08:00"},"CompareURL":"zhangjunnan/zhouhui/compare/813c20b815c210ce7cb9ac5b6b530a3d6027e2cc...fe71ee60f35a3818ccc6b78d4af0f61c760d639a","Len":1}...
|
1785487028
|
Edit
Delete
|
|
20256
|
1
|
5
|
1
|
32
|
0
|
0
|
refs/heads/master
|
1
|
{"Commits":[{"Sha1":"2aad82522 {"Commits":[{"Sha1":"2aad82522978e608519a2acba78e43a6b6806f16","Message":"补丁\n","AuthorEmail":"121158035@qq.com","AuthorName":"zhangjunnan","CommitterEmail":"121158035@qq.com","CommitterName":"zhangjunnan","Timestamp":"2026-07-31T16:54:55+08:00"}],"HeadCommit":{"Sha1":"2aad82522978e608519a2acba78e43a6b6806f16","Message":"补丁\n","AuthorEmail":"121158035@qq.com","AuthorName":"zhangjunnan","CommitterEmail":"121158035@qq.com","CommitterName":"zhangjunnan","Timestamp":"2026-07-31T16:54:55+08:00"},"CompareURL":"zhangjunnan/zhouhui/compare/fe71ee60f35a3818ccc6b78d4af0f61c760d639a...2aad82522978e608519a2acba78e43a6b6806f16","Len":1}...
|
1785488111
|
Edit
Delete
|
|
20257
|
8
|
5
|
8
|
51
|
0
|
0
|
refs/heads/main
|
0
|
{"Commits":[{"Sha1":"d230fd6df {"Commits":[{"Sha1":"d230fd6dfb8fdba731ca1356263d1ec584d734be","Message":"接入阿里模型\n","AuthorEmail":"developer.jeff.c@gmail.com","AuthorName":"chenjunfeng","CommitterEmail":"developer.jeff.c@gmail.com","CommitterName":"chenjunfeng","Timestamp":"2026-07-31T17:31:49+08:00"}],"HeadCommit":{"Sha1":"d230fd6dfb8fdba731ca1356263d1ec584d734be","Message":"接入阿里模型\n","AuthorEmail":"developer.jeff.c@gmail.com","AuthorName":"chenjunfeng","CommitterEmail":"developer.jeff.c@gmail.com","CommitterName":"chenjunfeng","Timestamp":"2026-07-31T17:31:49+08:00"},"CompareURL":"luoanwu/yggdrasil-local-life-tools/compare/ead57a81e98d7f55797e6963b61e4847d9d9a96d...d230fd6dfb8fdba731ca1356263d1ec584d734be","Len":1}...
|
1785490315
|
Edit
Delete
|
|
20258
|
5
|
5
|
8
|
51
|
0
|
0
|
refs/heads/main
|
0
|
{"Commits":[{"Sha1":"d230fd6df {"Commits":[{"Sha1":"d230fd6dfb8fdba731ca1356263d1ec584d734be","Message":"接入阿里模型\n","AuthorEmail":"developer.jeff.c@gmail.com","AuthorName":"chenjunfeng","CommitterEmail":"developer.jeff.c@gmail.com","CommitterName":"chenjunfeng","Timestamp":"2026-07-31T17:31:49+08:00"}],"HeadCommit":{"Sha1":"d230fd6dfb8fdba731ca1356263d1ec584d734be","Message":"接入阿里模型\n","AuthorEmail":"developer.jeff.c@gmail.com","AuthorName":"chenjunfeng","CommitterEmail":"developer.jeff.c@gmail.com","CommitterName":"chenjunfeng","Timestamp":"2026-07-31T17:31:49+08:00"},"CompareURL":"luoanwu/yggdrasil-local-life-tools/compare/ead57a81e98d7f55797e6963b61e4847d9d9a96d...d230fd6dfb8fdba731ca1356263d1ec584d734be","Len":1}...
|
1785490315
|
Edit
Delete
|
|
20259
|
17
|
5
|
17
|
69
|
0
|
0
|
refs/heads/chanpin-20260818
|
0
|
{"Commits":[{"Sha1":"0315b2b68 {"Commits":[{"Sha1":"0315b2b689d430da7d4f3360bde84c4225f2630e","Message":"更新加盟分账原型标注\n","AuthorEmail":"linmingzhang@g-hi.com","AuthorName":"linmingzhang","CommitterEmail":"linmingzhang@g-hi.com","CommitterName":"linmingzhang","Timestamp":"2026-07-31T17:52:04+08:00"}],"HeadCommit":{"Sha1":"0315b2b689d430da7d4f3360bde84c4225f2630e","Message":"更新加盟分账原型标注\n","AuthorEmail":"linmingzhang@g-hi.com","AuthorName":"linmingzhang","CommitterEmail":"linmingzhang@g-hi.com","CommitterName":"linmingzhang","Timestamp":"2026-07-31T17:52:04+08:00"},"CompareURL":"linmingzhang/ktv-booking-prototype/compare/c78bd61a40ff40bf3fd92b4ad9866b7cd19e4c40...0315b2b689d430da7d4f3360bde84c4225f2630e","Len":1}...
|
1785491553
|
Edit
Delete
|
|
20260
|
18
|
5
|
17
|
69
|
0
|
0
|
refs/heads/chanpin-20260818
|
0
|
{"Commits":[{"Sha1":"0315b2b68 {"Commits":[{"Sha1":"0315b2b689d430da7d4f3360bde84c4225f2630e","Message":"更新加盟分账原型标注\n","AuthorEmail":"linmingzhang@g-hi.com","AuthorName":"linmingzhang","CommitterEmail":"linmingzhang@g-hi.com","CommitterName":"linmingzhang","Timestamp":"2026-07-31T17:52:04+08:00"}],"HeadCommit":{"Sha1":"0315b2b689d430da7d4f3360bde84c4225f2630e","Message":"更新加盟分账原型标注\n","AuthorEmail":"linmingzhang@g-hi.com","AuthorName":"linmingzhang","CommitterEmail":"linmingzhang@g-hi.com","CommitterName":"linmingzhang","Timestamp":"2026-07-31T17:52:04+08:00"},"CompareURL":"linmingzhang/ktv-booking-prototype/compare/c78bd61a40ff40bf3fd92b4ad9866b7cd19e4c40...0315b2b689d430da7d4f3360bde84c4225f2630e","Len":1}...
|
1785491553
|
Edit
Delete
|
|
20261
|
8
|
5
|
8
|
51
|
0
|
0
|
refs/heads/main
|
0
|
{"Commits":[{"Sha1":"88fb2aa68 {"Commits":[{"Sha1":"88fb2aa68377d24865992a812dc9dfb5f200569c","Message":"接入阿里模型\n","AuthorEmail":"developer.jeff.c@gmail.com","AuthorName":"chenjunfeng","CommitterEmail":"developer.jeff.c@gmail.com","CommitterName":"chenjunfeng","Timestamp":"2026-07-31T17:58:13+08:00"}],"HeadCommit":{"Sha1":"88fb2aa68377d24865992a812dc9dfb5f200569c","Message":"接入阿里模型\n","AuthorEmail":"developer.jeff.c@gmail.com","AuthorName":"chenjunfeng","CommitterEmail":"developer.jeff.c@gmail.com","CommitterName":"chenjunfeng","Timestamp":"2026-07-31T17:58:13+08:00"},"CompareURL":"luoanwu/yggdrasil-local-life-tools/compare/d230fd6dfb8fdba731ca1356263d1ec584d734be...88fb2aa68377d24865992a812dc9dfb5f200569c","Len":1}...
|
1785491898
|
Edit
Delete
|
|
20262
|
5
|
5
|
8
|
51
|
0
|
0
|
refs/heads/main
|
0
|
{"Commits":[{"Sha1":"88fb2aa68 {"Commits":[{"Sha1":"88fb2aa68377d24865992a812dc9dfb5f200569c","Message":"接入阿里模型\n","AuthorEmail":"developer.jeff.c@gmail.com","AuthorName":"chenjunfeng","CommitterEmail":"developer.jeff.c@gmail.com","CommitterName":"chenjunfeng","Timestamp":"2026-07-31T17:58:13+08:00"}],"HeadCommit":{"Sha1":"88fb2aa68377d24865992a812dc9dfb5f200569c","Message":"接入阿里模型\n","AuthorEmail":"developer.jeff.c@gmail.com","AuthorName":"chenjunfeng","CommitterEmail":"developer.jeff.c@gmail.com","CommitterName":"chenjunfeng","Timestamp":"2026-07-31T17:58:13+08:00"},"CompareURL":"luoanwu/yggdrasil-local-life-tools/compare/d230fd6dfb8fdba731ca1356263d1ec584d734be...88fb2aa68377d24865992a812dc9dfb5f200569c","Len":1}...
|
1785491898
|
Edit
Delete
|
|
20263
|
1
|
5
|
1
|
32
|
0
|
0
|
refs/heads/master
|
1
|
{"Commits":[{"Sha1":"48cb56881 {"Commits":[{"Sha1":"48cb56881d1f51ba03dab011f4cf9682f27b8556","Message":"游戏\n","AuthorEmail":"121158035@qq.com","AuthorName":"zhangjunnan","CommitterEmail":"121158035@qq.com","CommitterName":"zhangjunnan","Timestamp":"2026-07-31T18:39:56+08:00"}],"HeadCommit":{"Sha1":"48cb56881d1f51ba03dab011f4cf9682f27b8556","Message":"游戏\n","AuthorEmail":"121158035@qq.com","AuthorName":"zhangjunnan","CommitterEmail":"121158035@qq.com","CommitterName":"zhangjunnan","Timestamp":"2026-07-31T18:39:56+08:00"},"CompareURL":"zhangjunnan/zhouhui/compare/2aad82522978e608519a2acba78e43a6b6806f16...48cb56881d1f51ba03dab011f4cf9682f27b8556","Len":1}...
|
1785494412
|
Edit
Delete
|
|
20264
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/fix/contracts-build-chain-and-review-pa refs/heads/fix/contracts-build-chain-and-review-panel...
|
0
|
|
1785504180
|
Edit
Delete
|
|
20265
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/fix/contracts-build-chain-and-review-pa refs/heads/fix/contracts-build-chain-and-review-panel...
|
0
|
{"Commits":[{"Sha1":"67849d6aa {"Commits":[{"Sha1":"67849d6aad796878e6fd40b2e54307780b01442f","Message":"chore: 重跑三级门禁并绑定干净工作区证据\n\n上一提交的报告生成于 dirty 工作区(gitSha 指向父提交 7638e94、\nworktreeDirty=true),只能支撑「本地工作区通过」。此处在 a015400 的\n干净检出上重跑三级门禁,让三份 latest 报告的 provenance 统一绑定\n该提交且 worktreeDirty=false——可支撑「提交 a015400 在本机干净工作区\n通过三级门禁」。\n\npnpm check ✅ 5/5\npnpm check:runtime ✅ 83 用例 / 0 失败(PG:55432/juhai_quotation_runtime_20260731d + Redis:6382)\npnpm check:ui ✅ 8 用例 / 0 失败(PG:55432/juhai_quotation_ui_20260731d + Redis:6382)\n\n仍不得外推为远端已发布或 CI 已通过:本分支未推送,无远端 run 证据(G14)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:16:25-07:00"},{"Sha1":"a015400b8aa901246315eb213d20354d6ded3133","Message":"fix: 打通契约构建链并补齐方案复核依据\n\n本提交包含两批改动。工作区里它们已交织到同一行/同一 hunk\n(package.json 的 check 串、next.config.ts 的 output),无法拆开单独提交。\n\n── 批次 A:本轮定位并修复(Claude 作业)────────────────────────────\n\n契约包 src/dist 漂移(C23)——P1「运行时到底读哪一份」的隐藏变体:\ntypecheck 与 contracts 单测读 src,两后端运行时经 package main 读 dist。\n`pnpm --filter` 不走 turbo 的 dependsOn ^build,dist 又被 gitignore,\n于是门禁全绿而运行时按旧契约行为。实测症状:dist 缺 versionNo →\nZod 静默 strip → 技术复核恒返 409 STALE_VERSION。\n负向验证:移走 dist 后 typecheck 立刻 TS2307,证明全新 clone/CI 上必红。\n- package.json: check 前置 build:contracts\n- scripts/check-{runtime,ui}-acceptance.mjs: 各加 contracts 构建步骤\n- .claude/launch.json: 四个配置均前置 contracts 构建\n- packages/contracts/package.json: 补 prepare;clean 补删 tsconfig.tsbuildinfo\n (composite 下留着 buildinfo 会让 clean+build 空 emit)\n\n方案表单默认路径不可用(C24):\n「使用客户主联系人」value 为空串,contactId 契约是 uuid().optional(),\n空串不过校验,导致默认状态下表单永不可提交,错误还被汇总成一句\n指不到联系人的话。register 处归一为 undefined。\n\n客户方案复核依据面板:\n技术复核/经理批准需在同一屏看到客户需求、空间与工区、平面图、逐档配置清单。\n清单只渲染规格字段,刻意不展开 product 以免带出 standardPriceCents\n(角色权限单源里技术角色不继承报价域敏感读取)。缺图纸显式标注但不阻断。\n补填资料入口接上此前零消费者的 useUpdateSolution + PATCH /solutions/:id,\n仅在 DRAFT/NEEDS_INFORMATION/REVISION_REQUIRED 开放——修复「目标客群留空\n的方案走到 APPROVED 后永远发布不了且无处补填」的死路。\n\n契约类型补齐:SolutionProduct 增补 product/surveySpace 嵌套(服务端一直下发,\n此前类型比载荷窄)。\n\nE2E 回归锁:新增专打默认联系人路径的用例,兼测复核依据面板与价格红线。\n负向验证:撤回 contactId 修复 → check:ui 报红;还原 → 8 用例全绿。\n\n附带:next.config.ts 的 output 重复定义(TS2783,本轮之前即存在,\n导致 pnpm check 红)改为三元计算,行为等价;check-vm-deploy 的 standalone\n绊网相应收窄为「字面量或该正确三元」,不放宽成 /output:.*standalone/\n(负向验证:三元写反即红)。\n\n── 批次 B:进入本轮前工作区已有的未提交改动(非本轮作业)──────────\n\nVM 部署强化(Dockerfile/compose/vm-deploy.sh/check-vm-deploy.mjs、restore/\ndrill/rollback)、移动端导航 MobileNav、客户方案域后端与验收测试、\n角色权限与模块对接门禁、方案蓝图与验收记录等。这批未经逐项复核,\n如需单独审阅可 `git reset --soft HEAD~1` 后重新拆分。\n\n── 证据(本地工作区,2026-07-31,工作区 dirty)──────────────────\npnpm check ✅ 5/5\npnpm check:runtime ✅ 83 用例 / 0 失败(地板 79→83)\npnpm check:ui ✅ 8 用例 / 0 失败(地板 7→8)\nownTestCases 地板 90→91。未推送、无远端 CI 运行证据(G14 仍 OPEN)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:13:59-07:00"}],"HeadCommit":{"Sha1":"67849d6aad796878e6fd40b2e54307780b01442f","Message":"chore: 重跑三级门禁并绑定干净工作区证据\n\n上一提交的报告生成于 dirty 工作区(gitSha 指向父提交 7638e94、\nworktreeDirty=true),只能支撑「本地工作区通过」。此处在 a015400 的\n干净检出上重跑三级门禁,让三份 latest 报告的 provenance 统一绑定\n该提交且 worktreeDirty=false——可支撑「提交 a015400 在本机干净工作区\n通过三级门禁」。\n\npnpm check ✅ 5/5\npnpm check:runtime ✅ 83 用例 / 0 失败(PG:55432/juhai_quotation_runtime_20260731d + Redis:6382)\npnpm check:ui ✅ 8 用例 / 0 失败(PG:55432/juhai_quotation_ui_20260731d + Redis:6382)\n\n仍不得外推为远端已发布或 CI 已通过:本分支未推送,无远端 run 证据(G14)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:16:25-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/7638e946e8817308b94a23c028a18ac465c342c6...67849d6aad796878e6fd40b2e54307780b01442f","Len":2}...
|
1785504181
|
Edit
Delete
|
|
20266
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/fix/contracts-build-chain-and-review-pa refs/heads/fix/contracts-build-chain-and-review-panel...
|
0
|
{"Commits":[{"Sha1":"0d85a3de6 {"Commits":[{"Sha1":"0d85a3de6efbf4ca42ba1345bfbc66f9d1f9ac0d","Message":"docs: 按真实 CI 证据更正 C23 与 G14\n\n上一提交把一个未经正确验证的结论写进了治理真源,此处更正。\n\nC23 原文断言「全新 clone/CI 上 pnpm check 必红(contracts dist 不存在)」。\n该结论来自 `pnpm --filter \u003capp\u003e typecheck` 的负向测试,而它绕过 turbo;\nCI 实际走 `pnpm typecheck` → `turbo run typecheck`,而 turbo.json 的\ntypecheck/lint/test 均带 dependsOn ^build,contracts 会被自动构建。\nGitHub run 30603461723 的 static job 实际通过,证伪原结论。\nC23 仍然成立的部分:绕过 turbo 的调用路径(.claude/launch.json 直接\npnpm dev、check:ui 的 pnpm --filter build)确实会吃到陈旧 dist——本轮\n409 STALE_VERSION 即由此而来;clean 不删 tsconfig.tsbuildinfo 导致\nclean \u0026\u0026 build 空 emit 是独立真 bug。修复本身保留。\n\nG14 原记「尚无远端 CI 运行证据」已过时。实际已有 run 30603461723\n(push main fdf7b59,2026-07-31T04:10Z):static ✅、runtime ❌\n`tests-floor: expected \u003e= 74, got 0`,整步仅 24s,真实 DB 测试没跑起来。\n地板断言拦住了这次「0 tests 假绿」,但根因未定位,需专项排查 CI 上\nturbo run test --force 为何产不出 vitest 报告。基线表 ci-gate 行同步\n改为「已有远端证据但为红盘」,仍 OPEN。\n\n另记:两个远端 main 不同步(origin 7638e94 / github fdf7b59),\nCI 只挂 github 侧,且只在 pull_request 或 push main 触发。\n\npnpm check ✅ 绿(含 check:governance-docs / check:docs-truth)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:30:18-07:00"}],"HeadCommit":{"Sha1":"0d85a3de6efbf4ca42ba1345bfbc66f9d1f9ac0d","Message":"docs: 按真实 CI 证据更正 C23 与 G14\n\n上一提交把一个未经正确验证的结论写进了治理真源,此处更正。\n\nC23 原文断言「全新 clone/CI 上 pnpm check 必红(contracts dist 不存在)」。\n该结论来自 `pnpm --filter \u003capp\u003e typecheck` 的负向测试,而它绕过 turbo;\nCI 实际走 `pnpm typecheck` → `turbo run typecheck`,而 turbo.json 的\ntypecheck/lint/test 均带 dependsOn ^build,contracts 会被自动构建。\nGitHub run 30603461723 的 static job 实际通过,证伪原结论。\nC23 仍然成立的部分:绕过 turbo 的调用路径(.claude/launch.json 直接\npnpm dev、check:ui 的 pnpm --filter build)确实会吃到陈旧 dist——本轮\n409 STALE_VERSION 即由此而来;clean 不删 tsconfig.tsbuildinfo 导致\nclean \u0026\u0026 build 空 emit 是独立真 bug。修复本身保留。\n\nG14 原记「尚无远端 CI 运行证据」已过时。实际已有 run 30603461723\n(push main fdf7b59,2026-07-31T04:10Z):static ✅、runtime ❌\n`tests-floor: expected \u003e= 74, got 0`,整步仅 24s,真实 DB 测试没跑起来。\n地板断言拦住了这次「0 tests 假绿」,但根因未定位,需专项排查 CI 上\nturbo run test --force 为何产不出 vitest 报告。基线表 ci-gate 行同步\n改为「已有远端证据但为红盘」,仍 OPEN。\n\n另记:两个远端 main 不同步(origin 7638e94 / github fdf7b59),\nCI 只挂 github 侧,且只在 pull_request 或 push main 触发。\n\npnpm check ✅ 绿(含 check:governance-docs / check:docs-truth)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:30:18-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/67849d6aad796878e6fd40b2e54307780b01442f...0d85a3de6efbf4ca42ba1345bfbc66f9d1f9ac0d","Len":1}...
|
1785504640
|
Edit
Delete
|
|
20267
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/fix/contracts-build-chain-and-review-pa refs/heads/fix/contracts-build-chain-and-review-panel...
|
0
|
{"Commits":[{"Sha1":"de7d09aee {"Commits":[{"Sha1":"de7d09aee2a89208f006bc3ca829f289619a64b7","Message":"docs: 记录首份远端 CI 绿盘证据(PR #1 / run 30634897066)\n\nGitHub run 30634897066(PR #1,head 0d85a3d)两 job 全绿:\nstatic ✅;runtime 83 用例(contracts 31 / nestjs 26 / fastify 26)、\nUI 8 用例,与本地逐项一致,耗时 3m21s。这是本仓第一份远端绿盘证据。\n\n对照上一次 run 30603461723(push main fdf7b59):runtime 失败于\ntests-floor「expected \u003e= 74, got 0」,整步仅 24s。\n\n刻意不把这次转绿归因到本轮任何一个提交:PR #1 含 7 个提交,除本轮 3 个外\n还有 4 个存量提交(283f1bf…7638e94),其中任一都可能是真正修好它的那个,\n且 7638e94 从未单独在 CI 上跑过。要归因需另构造对照 run。\n\nG14 仍 OPEN:绿盘只覆盖该 PR 分支,github main 最近一次 run 仍红;\n尚未用受控失败 PR 证明违规真被阻断,分支保护 / required checks 也未定位。\nci-gate 行同步改写,明确「不得宣称 PR 已被机器拦截」。\n\npnpm check ✅ 绿。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:39:36-07:00"}],"HeadCommit":{"Sha1":"de7d09aee2a89208f006bc3ca829f289619a64b7","Message":"docs: 记录首份远端 CI 绿盘证据(PR #1 / run 30634897066)\n\nGitHub run 30634897066(PR #1,head 0d85a3d)两 job 全绿:\nstatic ✅;runtime 83 用例(contracts 31 / nestjs 26 / fastify 26)、\nUI 8 用例,与本地逐项一致,耗时 3m21s。这是本仓第一份远端绿盘证据。\n\n对照上一次 run 30603461723(push main fdf7b59):runtime 失败于\ntests-floor「expected \u003e= 74, got 0」,整步仅 24s。\n\n刻意不把这次转绿归因到本轮任何一个提交:PR #1 含 7 个提交,除本轮 3 个外\n还有 4 个存量提交(283f1bf…7638e94),其中任一都可能是真正修好它的那个,\n且 7638e94 从未单独在 CI 上跑过。要归因需另构造对照 run。\n\nG14 仍 OPEN:绿盘只覆盖该 PR 分支,github main 最近一次 run 仍红;\n尚未用受控失败 PR 证明违规真被阻断,分支保护 / required checks 也未定位。\nci-gate 行同步改写,明确「不得宣称 PR 已被机器拦截」。\n\npnpm check ✅ 绿。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:39:36-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/0d85a3de6efbf4ca42ba1345bfbc66f9d1f9ac0d...de7d09aee2a89208f006bc3ca829f289619a64b7","Len":1}...
|
1785505181
|
Edit
Delete
|
|
20268
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/main
|
0
|
{"Commits":[{"Sha1":"9618d78da {"Commits":[{"Sha1":"9618d78da3e668f14e3c1611d7090f45eef0c085","Message":"Merge pull request #1: 打通契约构建链、补齐方案复核依据,并按真实 CI 证据更正治理记录\n\nfix: 打通契约构建链、补齐方案复核依据,并按真实 CI 证据更正治理记录","AuthorEmail":"158980461+laoluojuhai@users.noreply.github.com","AuthorName":"laoluojuhai","CommitterEmail":"noreply@github.com","CommitterName":"GitHub","Timestamp":"2026-07-31T06:46:17-07:00"},{"Sha1":"de7d09aee2a89208f006bc3ca829f289619a64b7","Message":"docs: 记录首份远端 CI 绿盘证据(PR #1 / run 30634897066)\n\nGitHub run 30634897066(PR #1,head 0d85a3d)两 job 全绿:\nstatic ✅;runtime 83 用例(contracts 31 / nestjs 26 / fastify 26)、\nUI 8 用例,与本地逐项一致,耗时 3m21s。这是本仓第一份远端绿盘证据。\n\n对照上一次 run 30603461723(push main fdf7b59):runtime 失败于\ntests-floor「expected \u003e= 74, got 0」,整步仅 24s。\n\n刻意不把这次转绿归因到本轮任何一个提交:PR #1 含 7 个提交,除本轮 3 个外\n还有 4 个存量提交(283f1bf…7638e94),其中任一都可能是真正修好它的那个,\n且 7638e94 从未单独在 CI 上跑过。要归因需另构造对照 run。\n\nG14 仍 OPEN:绿盘只覆盖该 PR 分支,github main 最近一次 run 仍红;\n尚未用受控失败 PR 证明违规真被阻断,分支保护 / required checks 也未定位。\nci-gate 行同步改写,明确「不得宣称 PR 已被机器拦截」。\n\npnpm check ✅ 绿。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:39:36-07:00"},{"Sha1":"0d85a3de6efbf4ca42ba1345bfbc66f9d1f9ac0d","Message":"docs: 按真实 CI 证据更正 C23 与 G14\n\n上一提交把一个未经正确验证的结论写进了治理真源,此处更正。\n\nC23 原文断言「全新 clone/CI 上 pnpm check 必红(contracts dist 不存在)」。\n该结论来自 `pnpm --filter \u003capp\u003e typecheck` 的负向测试,而它绕过 turbo;\nCI 实际走 `pnpm typecheck` → `turbo run typecheck`,而 turbo.json 的\ntypecheck/lint/test 均带 dependsOn ^build,contracts 会被自动构建。\nGitHub run 30603461723 的 static job 实际通过,证伪原结论。\nC23 仍然成立的部分:绕过 turbo 的调用路径(.claude/launch.json 直接\npnpm dev、check:ui 的 pnpm --filter build)确实会吃到陈旧 dist——本轮\n409 STALE_VERSION 即由此而来;clean 不删 tsconfig.tsbuildinfo 导致\nclean \u0026\u0026 build 空 emit 是独立真 bug。修复本身保留。\n\nG14 原记「尚无远端 CI 运行证据」已过时。实际已有 run 30603461723\n(push main fdf7b59,2026-07-31T04:10Z):static ✅、runtime ❌\n`tests-floor: expected \u003e= 74, got 0`,整步仅 24s,真实 DB 测试没跑起来。\n地板断言拦住了这次「0 tests 假绿」,但根因未定位,需专项排查 CI 上\nturbo run test --force 为何产不出 vitest 报告。基线表 ci-gate 行同步\n改为「已有远端证据但为红盘」,仍 OPEN。\n\n另记:两个远端 main 不同步(origin 7638e94 / github fdf7b59),\nCI 只挂 github 侧,且只在 pull_request 或 push main 触发。\n\npnpm check ✅ 绿(含 check:governance-docs / check:docs-truth)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:30:18-07:00"},{"Sha1":"67849d6aad796878e6fd40b2e54307780b01442f","Message":"chore: 重跑三级门禁并绑定干净工作区证据\n\n上一提交的报告生成于 dirty 工作区(gitSha 指向父提交 7638e94、\nworktreeDirty=true),只能支撑「本地工作区通过」。此处在 a015400 的\n干净检出上重跑三级门禁,让三份 latest 报告的 provenance 统一绑定\n该提交且 worktreeDirty=false——可支撑「提交 a015400 在本机干净工作区\n通过三级门禁」。\n\npnpm check ✅ 5/5\npnpm check:runtime ✅ 83 用例 / 0 失败(PG:55432/juhai_quotation_runtime_20260731d + Redis:6382)\npnpm check:ui ✅ 8 用例 / 0 失败(PG:55432/juhai_quotation_ui_20260731d + Redis:6382)\n\n仍不得外推为远端已发布或 CI 已通过:本分支未推送,无远端 run 证据(G14)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:16:25-07:00"},{"Sha1":"a015400b8aa901246315eb213d20354d6ded3133","Message":"fix: 打通契约构建链并补齐方案复核依据\n\n本提交包含两批改动。工作区里它们已交织到同一行/同一 hunk\n(package.json 的 check 串、next.config.ts 的 output),无法拆开单独提交。\n\n── 批次 A:本轮定位并修复(Claude 作业)────────────────────────────\n\n契约包 src/dist 漂移(C23)——P1「运行时到底读哪一份」的隐藏变体:\ntypecheck 与 contracts 单测读 src,两后端运行时经 package main 读 dist。\n`pnpm --filter` 不走 turbo 的 dependsOn ^build,dist 又被 gitignore,\n于是门禁全绿而运行时按旧契约行为。实测症状:dist 缺 versionNo →\nZod 静默 strip → 技术复核恒返 409 STALE_VERSION。\n负向验证:移走 dist 后 typecheck 立刻 TS2307,证明全新 clone/CI 上必红。\n- package.json: check 前置 build:contracts\n- scripts/check-{runtime,ui}-acceptance.mjs: 各加 contracts 构建步骤\n- .claude/launch.json: 四个配置均前置 contracts 构建\n- packages/contracts/package.json: 补 prepare;clean 补删 tsconfig.tsbuildinfo\n (composite 下留着 buildinfo 会让 clean+build 空 emit)\n\n方案表单默认路径不可用(C24):\n「使用客户主联系人」value 为空串,contactId 契约是 uuid().optional(),\n空串不过校验,导致默认状态下表单永不可提交,错误还被汇总成一句\n指不到联系人的话。register 处归一为 undefined。\n\n客户方案复核依据面板:\n技术复核/经理批准需在同一屏看到客户需求、空间与工区、平面图、逐档配置清单。\n清单只渲染规格字段,刻意不展开 product 以免带出 standardPriceCents\n(角色权限单源里技术角色不继承报价域敏感读取)。缺图纸显式标注但不阻断。\n补填资料入口接上此前零消费者的 useUpdateSolution + PATCH /solutions/:id,\n仅在 DRAFT/NEEDS_INFORMATION/REVISION_REQUIRED 开放——修复「目标客群留空\n的方案走到 APPROVED 后永远发布不了且无处补填」的死路。\n\n契约类型补齐:SolutionProduct 增补 product/surveySpace 嵌套(服务端一直下发,\n此前类型比载荷窄)。\n\nE2E 回归锁:新增专打默认联系人路径的用例,兼测复核依据面板与价格红线。\n负向验证:撤回 contactId 修复 → check:ui 报红;还原 → 8 用例全绿。\n\n附带:next.config.ts 的 output 重复定义(TS2783,本轮之前即存在,\n导致 pnpm check 红)改为三元计算,行为等价;check-vm-deploy 的 standalone\n绊网相应收窄为「字面量或该正确三元」,不放宽成 /output:.*standalone/\n(负向验证:三元写反即红)。\n\n── 批次 B:进入本轮前工作区已有的未提交改动(非本轮作业)──────────\n\nVM 部署强化(Dockerfile/compose/vm-deploy.sh/check-vm-deploy.mjs、restore/\ndrill/rollback)、移动端导航 MobileNav、客户方案域后端与验收测试、\n角色权限与模块对接门禁、方案蓝图与验收记录等。这批未经逐项复核,\n如需单独审阅可 `git reset --soft HEAD~1` 后重新拆分。\n\n── 证据(本地工作区,2026-07-31,工作区 dirty)──────────────────\npnpm check ✅ 5/5\npnpm check:runtime ✅ 83 用例 / 0 失败(地板 79→83)\npnpm check:ui ✅ 8 用例 / 0 失败(地板 7→8)\nownTestCases 地板 90→91。未推送、无远端 CI 运行证据(G14 仍 OPEN)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:13:59-07:00"}],"HeadCommit":{"Sha1":"9618d78da3e668f14e3c1611d7090f45eef0c085","Message":"Merge pull request #1: 打通契约构建链、补齐方案复核依据,并按真实 CI 证据更正治理记录\n\nfix: 打通契约构建链、补齐方案复核依据,并按真实 CI 证据更正治理记录","AuthorEmail":"158980461+laoluojuhai@users.noreply.github.com","AuthorName":"laoluojuhai","CommitterEmail":"noreply@github.com","CommitterName":"GitHub","Timestamp":"2026-07-31T06:46:17-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/7638e946e8817308b94a23c028a18ac465c342c6...9618d78da3e668f14e3c1611d7090f45eef0c085","Len":5}...
|
1785505644
|
Edit
Delete
|
|
20269
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/docs/ci-green-on-main
|
0
|
|
1785506104
|
Edit
Delete
|
|
20270
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/docs/ci-green-on-main
|
0
|
{"Commits":[{"Sha1":"ec4bf7fde {"Commits":[{"Sha1":"ec4bf7fdec43629ca034c3b16fa6fd8b3b456286","Message":"test(negative): 受控失败——删除一个测试文件以验证远端门禁真会阻断\n\nG14 关闭条件的最后一项:证明违规确实被 CI + 分支保护阻断,而不是\n「门禁存在但从没拦住过任何东西」(假绿五形态第 5 形态:假生效门禁)。\n\n刻意注入的违规:删除 apps/api-fastify/test/outbox.deadletter.test.ts。\n预期 ownTests 从 11 掉到 10,低于 reports/baseline.json 的地板 11,\nstatic job 的 check:governance 棘轮应判红;runtime job 因 needs 依赖不会启动。\n\n预期结果:PR 无法合并(required checks: Static governance +\nRuntime and UI acceptance,enforce_admins=true)。\n验证完毕后本 PR 直接关闭,绝不合并。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:49:50-07:00"}],"HeadCommit":{"Sha1":"ec4bf7fdec43629ca034c3b16fa6fd8b3b456286","Message":"test(negative): 受控失败——删除一个测试文件以验证远端门禁真会阻断\n\nG14 关闭条件的最后一项:证明违规确实被 CI + 分支保护阻断,而不是\n「门禁存在但从没拦住过任何东西」(假绿五形态第 5 形态:假生效门禁)。\n\n刻意注入的违规:删除 apps/api-fastify/test/outbox.deadletter.test.ts。\n预期 ownTests 从 11 掉到 10,低于 reports/baseline.json 的地板 11,\nstatic job 的 check:governance 棘轮应判红;runtime job 因 needs 依赖不会启动。\n\n预期结果:PR 无法合并(required checks: Static governance +\nRuntime and UI acceptance,enforce_admins=true)。\n验证完毕后本 PR 直接关闭,绝不合并。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:49:50-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/9618d78da3e668f14e3c1611d7090f45eef0c085...ec4bf7fdec43629ca034c3b16fa6fd8b3b456286","Len":1}...
|
1785506104
|
Edit
Delete
|
|
20271
|
5
|
17
|
5
|
72
|
0
|
0
|
refs/heads/docs/ci-green-on-main
|
0
|
|
1785507095
|
Edit
Delete
|
|
20272
|
5
|
17
|
5
|
72
|
0
|
0
|
refs/heads/fix/contracts-build-chain-and-review-pa refs/heads/fix/contracts-build-chain-and-review-panel...
|
0
|
|
1785507126
|
Edit
Delete
|
|
20273
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/chore/gate-negative-proof
|
0
|
|
1785507322
|
Edit
Delete
|
|
20274
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/chore/gate-negative-proof
|
0
|
{"Commits":[{"Sha1":"ec4bf7fde {"Commits":[{"Sha1":"ec4bf7fdec43629ca034c3b16fa6fd8b3b456286","Message":"test(negative): 受控失败——删除一个测试文件以验证远端门禁真会阻断\n\nG14 关闭条件的最后一项:证明违规确实被 CI + 分支保护阻断,而不是\n「门禁存在但从没拦住过任何东西」(假绿五形态第 5 形态:假生效门禁)。\n\n刻意注入的违规:删除 apps/api-fastify/test/outbox.deadletter.test.ts。\n预期 ownTests 从 11 掉到 10,低于 reports/baseline.json 的地板 11,\nstatic job 的 check:governance 棘轮应判红;runtime job 因 needs 依赖不会启动。\n\n预期结果:PR 无法合并(required checks: Static governance +\nRuntime and UI acceptance,enforce_admins=true)。\n验证完毕后本 PR 直接关闭,绝不合并。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:49:50-07:00"}],"HeadCommit":{"Sha1":"ec4bf7fdec43629ca034c3b16fa6fd8b3b456286","Message":"test(negative): 受控失败——删除一个测试文件以验证远端门禁真会阻断\n\nG14 关闭条件的最后一项:证明违规确实被 CI + 分支保护阻断,而不是\n「门禁存在但从没拦住过任何东西」(假绿五形态第 5 形态:假生效门禁)。\n\n刻意注入的违规:删除 apps/api-fastify/test/outbox.deadletter.test.ts。\n预期 ownTests 从 11 掉到 10,低于 reports/baseline.json 的地板 11,\nstatic job 的 check:governance 棘轮应判红;runtime job 因 needs 依赖不会启动。\n\n预期结果:PR 无法合并(required checks: Static governance +\nRuntime and UI acceptance,enforce_admins=true)。\n验证完毕后本 PR 直接关闭,绝不合并。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:49:50-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/9618d78da3e668f14e3c1611d7090f45eef0c085...ec4bf7fdec43629ca034c3b16fa6fd8b3b456286","Len":1}...
|
1785507322
|
Edit
Delete
|
|
20275
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/do-not-merge/gate-negative-proof
|
0
|
|
1785507509
|
Edit
Delete
|
|
20276
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/do-not-merge/gate-negative-proof
|
0
|
{"Commits":[],"HeadCommit":{"S {"Commits":[],"HeadCommit":{"Sha1":"ec4bf7fdec43629ca034c3b16fa6fd8b3b456286","Message":"test(negative): 受控失败——删除一个测试文件以验证远端门禁真会阻断\n\nG14 关闭条件的最后一项:证明违规确实被 CI + 分支保护阻断,而不是\n「门禁存在但从没拦住过任何东西」(假绿五形态第 5 形态:假生效门禁)。\n\n刻意注入的违规:删除 apps/api-fastify/test/outbox.deadletter.test.ts。\n预期 ownTests 从 11 掉到 10,低于 reports/baseline.json 的地板 11,\nstatic job 的 check:governance 棘轮应判红;runtime job 因 needs 依赖不会启动。\n\n预期结果:PR 无法合并(required checks: Static governance +\nRuntime and UI acceptance,enforce_admins=true)。\n验证完毕后本 PR 直接关闭,绝不合并。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T06:49:50-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/main...ec4bf7fdec43629ca034c3b16fa6fd8b3b456286","Len":0}...
|
1785507509
|
Edit
Delete
|
|
20277
|
5
|
17
|
5
|
72
|
0
|
0
|
refs/heads/chore/gate-negative-proof
|
0
|
|
1785507542
|
Edit
Delete
|
|
20278
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/chore/governance-ghost-assets-and-readm refs/heads/chore/governance-ghost-assets-and-readmodel...
|
0
|
|
1785568903
|
Edit
Delete
|
|
20279
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/chore/governance-ghost-assets-and-readm refs/heads/chore/governance-ghost-assets-and-readmodel...
|
0
|
{"Commits":[{"Sha1":"8fe17cd57 {"Commits":[{"Sha1":"8fe17cd57002bf1ed691e63a80c71db5c03d0f5f","Message":"feat(solutions): 项目名称默认取客户名称 + 经营目标/目标客群/硬性约束标签化\n\n本轮直接改动(客户方案域):\n\n- 建项表单选定客户后默认预填客户名称,且**只覆盖上一次自动填入的值**——用户手改过\n 就彻底交还给他,换客户也不再动它。仍是纯 UI 预填:name 在 contracts 里照旧 min(1)\n 必填,后端不替任何调用方脑补名称。\n- 经营目标、目标客群、硬性约束统一改为标签(chips)录入,候选从本租户已有方案现算、\n 按频次排序,不建标签字典表(用户裁决:只做到「表单内标签输入 + 历史候选」这一层;\n 租户级标签库是独立主数据对象,要走 owner-matrix 登记与完整模块流程)。\n- 标签归一(去空白 → 拒空串 → 去重保序)提为 contracts 单源 tagListSchema,读取侧\n 归一为 normalizeTagList。只在前端 chips 去重挡不住 curl([\"A\",\"A \"] 就能撑破上限、\n 读模型里并排出现两个肉眼一样的标签,C26 同一条教训),两后端各补一条读回断言,\n 证明规则真在服务端生效。\n- targetSegment 由单值 VARCHAR(500) 迁为 Json 标签数组,迁移\n 20260731090000_solution_target_segment_tags(两后端同份):就地\n ALTER ... TYPE ... USING,空串→[]、非空单值→单元素数组;**刻意不按分隔符拆**——\n 存量是自由文本,猜标签边界会造出谁也没确认过的半句话标签。转换语义已在真实\n PostgreSQL 上用 legacy 值单独验证。\n- 发布闸门判空由 .trim() 改为经 normalizeTagList 后 length===0,并同步\n check:role-permissions 的绊网正则;normalizeTagList 同时兜住迁移前写下的冻结快照\n (公开页读的就是快照,按定义不可回填)。\n- 定位确认凭证比对标签改用集合语义 sameTagSet:纯拖动排序不改变复核人确认过的那组\n 客群,按数组逐位比对会把已确认误判成 POSITIONING_STALE,逼销售重走复核。\n- E2E 首跑抓到一个真问题:标签成签会让输入框长高一行、提交按钮随之下移,mousedown\n 与 mouseup 落到不同元素上,那一下点击被浏览器吞掉。测试改为显式 Tab 失焦,并保留\n 「只失焦不回车也不丢标签」这条断言(失焦即成签,避免静默丢数据)。\n\n⚠️ 共享工作区提交:提交时本仓有并行会话在途(收款域、报价对客策略与发送对话框、\n操作手册生成、队列隔离与设计令牌门禁、商品目录导入等),其改动一并进入本提交。\n无法按文件拆分——packages/contracts/src/solution.ts 同时含两边内容。\n\n验收(作用域=本地工作区,提交时 dirty,不得外推为远端已验证):\n- pnpm check 全绿(14 个静态门禁 + lint + typecheck)\n- pnpm check:runtime 267 用例 / 地板 265,{contracts:187, api-nestjs:40, api-fastify:40}\n- pnpm check:ui 8/8 真浏览器用例\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T00:21:22-07:00"},{"Sha1":"a79aa437569cad73ecee4ede960c6f80a88bf98d","Message":"docs: 记录 G24 分页形态裁决(方案①:列表分页 + 独立 options 接口)并说明本轮未落地的原因\n\n用户已裁决方案①,设计细节(Paginated/OptionList 契约形状、3 个 options 接口的字段\n及其反推依据)一并写入 G24,下一轮直接落地,不必重新讨论。\n\n本轮未落地的原因写明:这是会改变 4 个接口响应形状的跨层迁移,而同一 checkout 上\n有并行会话正在开发收款域——改到一半的跨层 API 迁移留在共享工作区会直接卡住对方,\n因此整体回退、只留裁决结论。\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T08:15:46-07:00"},{"Sha1":"cafbd90f352d9fae794c4cae88c8435d84ebf132","Message":"feat(overview): 关闭 C27——把总览 KPI 从浏览器搬到服务端聚合 owner\n\n问题不在今天,在加分页那天\n总览 6 个指标全部在 MobileOverview.tsx 里对 GET /api/quotations 的全量返回 reduce,\n且「什么算已提交/已通过/已确认」「主报价金额怎么取」只以三个本地 Set + 一个函数的形式\n存在于这一个前端组件里。当前列表无分页,所以指标确实是对的——但它的正确性依赖\n一个没人承诺过的前提。只要给列表加分页或后端加截断,指标会静默退化成「当前页的统计」,\n页面还印着「全部来自当前租户」,没有任何测试会红。\n\n修法:把「谁决定聚合范围」搬回拥有数据的那一层\n- contracts 出单源:QUOTATION_{SUBMITTED,APPROVED,CONFIRMED,WAITING_CUSTOMER}_STATES\n + summarizeQuotations + countQuotationStates\n- 两后端 GET /api/quotations/summary 只做窄投影取行,算账一律调那个纯函数;\n 采购侧 GET /api/fulfillment/purchase-orders/summary 用 groupBy 让数据库出计数\n- 前端只做展示与单位换算(分→元、小时→天)\n\n顺带买到 G17 的一小块:聚合逻辑放 contracts 而非两后端各写一遍,\n双后端行为对等在这条路径上是结构保证,不需要门禁,因为不存在两份实现。\n\n同轮下线两处假值\n- 写死的「你好,本地报价管理员」→ 按 contracts 角色显示,不编造用户姓名\n- 最近报价表每行恒为「当前团队」的「负责人」列 → 整列移除(Quotation 无归属人字段),\n 口径同「开票收款尚未建模」:宁可不显示,也不用假值占位;同步收窄 grid 列数\n\n证据\n- pnpm check exit=0\n- pnpm check:runtime:本轮净贡献 87 用例(地板 83→87、ownTestCases 93→95)\n 两后端各 1 条聚合验收:空集均值 0 而非 NaN/byState 覆盖状态全集/跨租户不参与/403 负例\n- pnpm check:ui:8/8 全绿\n\n未闭环并显式登记为 G24:列表本身仍无分页。分页形态是真岔路——这 4 个列表同时喂着\n展示列表和 15 个关联对象下拉,天真分页会让 C22 的「关联对象来自真实读模型选择」\n退化成「只能选到第一页」。三个候选方案已写入 G24,待裁决。\n\n注:本仓有并行会话正在开发收款域。本次提交按文件路径逐个对账,\nquotation.ts 用补丁级 hunk 过滤剔除了对方的 ROLE_PERMISSIONS 改动;\nreports/*.latest.json 因计数被对方未提交的测试污染,本轮不提交,只提交经独立核算的 baseline.json。\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T08:06:50-07:00"},{"Sha1":"ec76984fa40261041bf89feeb5d64680a77ad577","Message":"feat(products,customers): 补编辑入口并关闭 C26——partial 更新 schema 丢掉的价格不变量\n\n审计口径「后端有写接口、前端无入口」:PATCH /api/products/:id 与 /api/customers/:id 在\n两后端都已实现且写链治理齐全(权限 + 租户条件写 + 0 行 404 + outbox 同 tx),\n但前端全仓只有 solutions 用过 PATCH——商品和客户建完就再也改不了。\n\n动工前核契约,先发现一个必须先补的洞(C26)\n- 价格不变量「底价/成本价 ≤ 标准价」只写在 createProductSchema 的 superRefine 里;\n updateProductSchema = productBaseSchema.partial() 从 base 派生,PATCH 完全绕过它。\n- 长期不可达只因前端没有编辑入口——补 UI 会把它立刻变成可达。\n- 修法不是给 update schema 也加个 refine:PATCH 可能只带 minimumPriceCents,\n 单看请求体判不出来。拆两半:contracts 提单源 checkProductPriceInvariant;\n update schema 只判同一请求内同时出现的字段,两后端在 tx 内合并现有记录后调同一函数兜底。\n\n前端\n- products/customers 各补 update API + mutation hook + 内联编辑器。\n- 编辑表单刻意用 createProductSchema 校验(它带不变量),让前后端拦同一件事。\n- SKU 与商品类型不开放编辑:已被历史报价明细固化为不可变快照,事后改会让旧报价口径漂移。\n- useUpdateCustomer 一并失效 quotations 缓存:客户名是报价抬头来源,否则报价列表继续显示旧抬头。\n\n证据\n- pnpm check exit=0\n- pnpm check:runtime:85 用例(31/27/27),地板同步 83→85、ownTestCases 91→93\n 新增两后端各 1 条 HTTP 负例:单字段 PATCH→400、双字段 PATCH→400、失败后读回未变、合法 PATCH 写库\n- pnpm check:ui:8/8 全绿,新增编辑闭环与不变量提示断言\n\n过程中自伤两次并已修正(记入 C26)\n- 编辑用例改了共享商品 PRODUCT_NAME → 下游 3 条用例全挂;改用专用 EDIT_SKU 商品并在常量处写明禁令\n- 新增商品让报价下拉选项从 3 变 4 → 更新计数并注明构成,保留其「挡重复项/挡漏建」的作用\n- 顺带把 productLibrary.locator(\"form\") 收窄为 getByTestId(\"product-create-form\")(C16 同款规则)\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T07:48:35-07:00"},{"Sha1":"aed0147384ea12244797a17c46bfe98c4cdeb0a2","Message":"fix(governance): 关闭 C25——删除幽灵 UI 资产并给「文档点名的代码符号」上门禁\n\n审计「每个菜单的真实对接」时发现 OrdersPanel/UsersPanel 在整个 apps/web/src 里\n没有任何 import,且是 9 个 API helper 的唯一消费者——一整棵约 560 行的死子树。\n\n真正的问题不是死代码,是三份治理文档仍拿它们当活资产:\n- owner-matrix 把 User/Order/OrderEvent 的读模型消费方写成这两个面板(追不到可达 UI);\n- CLAUDE.md C16 宣称的防线 getByTestId(\"users-panel\") 在 E2E 里早已不存在;\n- CLAUDE.md 的「apps/web 三面板样板」指向的布局已被 18 入口工作台取代。\n既有门禁交集恰好为空:typecheck 不报未使用导出;check:docs-truth 的幽灵资产断言\n管的是「文档给示例但文件不存在」(这里正相反);check:module-integration 只扫菜单内条目。\n\n处置(用户裁决:删除而非挂回 ADMIN 入口)\n- 删 OrdersPanel/UsersPanel + 9 个仅供其消费的 helper + 0 引用且注释失真的 api 泛型对象\n + 0 引用的 USD 版 formatCentsToCurrency;\n- /api/users、/api/orders、/api/jobs 后端与双后端 HTTP/DB 测试一律不动,只是不再有 UI 路径;\n- owner-matrix 三行改「无 UI 消费方」并加登记规则 5;C16 行改「规则仍生效、原实例已下线」;\n 「三面板样板」更正为现网 shell 结构;quotation-blueprint 两处同步;经验库补 C25 完整叙事。\n\n新增/重锚两处门禁(均已负向测试)\n- check:module-integration 加 owner-matrix-consumer-*:文档点名的组件必须在 apps/web 真实可达。\n 负向证据:真实磁盘造一个无人 import 的 ZombiePanel 并被点名 → 红;\n 摘掉 EventFeed 唯一 import → 红(证明正向路径不是空跑,Outbox 行确实在被断言)。\n- check:contract-consumers 的前端半边原本三条断言全锚在 OrdersPanel 上——即长期在守一个\n 没人走的路口。重锚到报价/商品/履约三个真实工作台,并从「好模式存在」改为「坏模式不存在」:\n 原断言局部改坏 1/3 处不会红(实测),新 reject 改坏一处即红(实测)。\n\n证据:pnpm check exit=0(本地工作区,7f1be32 基线同样 exit=0)\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-31T07:32:18-07:00"}],"HeadCommit":{"Sha1":"8fe17cd57002bf1ed691e63a80c71db5c03d0f5f","Message":"feat(solutions): 项目名称默认取客户名称 + 经营目标/目标客群/硬性约束标签化\n\n本轮直接改动(客户方案域):\n\n- 建项表单选定客户后默认预填客户名称,且**只覆盖上一次自动填入的值**——用户手改过\n 就彻底交还给他,换客户也不再动它。仍是纯 UI 预填:name 在 contracts 里照旧 min(1)\n 必填,后端不替任何调用方脑补名称。\n- 经营目标、目标客群、硬性约束统一改为标签(chips)录入,候选从本租户已有方案现算、\n 按频次排序,不建标签字典表(用户裁决:只做到「表单内标签输入 + 历史候选」这一层;\n 租户级标签库是独立主数据对象,要走 owner-matrix 登记与完整模块流程)。\n- 标签归一(去空白 → 拒空串 → 去重保序)提为 contracts 单源 tagListSchema,读取侧\n 归一为 normalizeTagList。只在前端 chips 去重挡不住 curl([\"A\",\"A \"] 就能撑破上限、\n 读模型里并排出现两个肉眼一样的标签,C26 同一条教训),两后端各补一条读回断言,\n 证明规则真在服务端生效。\n- targetSegment 由单值 VARCHAR(500) 迁为 Json 标签数组,迁移\n 20260731090000_solution_target_segment_tags(两后端同份):就地\n ALTER ... TYPE ... USING,空串→[]、非空单值→单元素数组;**刻意不按分隔符拆**——\n 存量是自由文本,猜标签边界会造出谁也没确认过的半句话标签。转换语义已在真实\n PostgreSQL 上用 legacy 值单独验证。\n- 发布闸门判空由 .trim() 改为经 normalizeTagList 后 length===0,并同步\n check:role-permissions 的绊网正则;normalizeTagList 同时兜住迁移前写下的冻结快照\n (公开页读的就是快照,按定义不可回填)。\n- 定位确认凭证比对标签改用集合语义 sameTagSet:纯拖动排序不改变复核人确认过的那组\n 客群,按数组逐位比对会把已确认误判成 POSITIONING_STALE,逼销售重走复核。\n- E2E 首跑抓到一个真问题:标签成签会让输入框长高一行、提交按钮随之下移,mousedown\n 与 mouseup 落到不同元素上,那一下点击被浏览器吞掉。测试改为显式 Tab 失焦,并保留\n 「只失焦不回车也不丢标签」这条断言(失焦即成签,避免静默丢数据)。\n\n⚠️ 共享工作区提交:提交时本仓有并行会话在途(收款域、报价对客策略与发送对话框、\n操作手册生成、队列隔离与设计令牌门禁、商品目录导入等),其改动一并进入本提交。\n无法按文件拆分——packages/contracts/src/solution.ts 同时含两边内容。\n\n验收(作用域=本地工作区,提交时 dirty,不得外推为远端已验证):\n- pnpm check 全绿(14 个静态门禁 + lint + typecheck)\n- pnpm check:runtime 267 用例 / 地板 265,{contracts:187, api-nestjs:40, api-fastify:40}\n- pnpm check:ui 8/8 真浏览器用例\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T00:21:22-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/9618d78da3e668f14e3c1611d7090f45eef0c085...8fe17cd57002bf1ed691e63a80c71db5c03d0f5f","Len":7}...
|
1785568903
|
Edit
Delete
|
|
20280
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/feat/g24-list-pagination-and-options
|
0
|
|
1785589103
|
Edit
Delete
|
|
20281
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/feat/g24-list-pagination-and-options
|
0
|
{"Commits":[{"Sha1":"ccbb031fd {"Commits":[{"Sha1":"ccbb031fdb47bc913ed2b4ba270c0a49889eb88d","Message":"feat(g24): 列表分页 + 选择器 options 双读路径(contracts 单源/双后端对等/三层负向证据)\n\n- contracts 新增 pagination.ts 单源:Paginated\u003cT\u003e{items,page,pageSize,total}(total=租户全量)、\n paginationQuerySchema(默认 20/上限 100,越界 Zod 400 不静默 clamp)、toPrismaPage/makePaginated、\n OptionList\u003cT\u003e{items,truncated} + OPTION_LIST_LIMIT=200 + makeOptionList,\n 三个 Option 投影重建对象字面量做字段白名单(成本/底价结构性缺席;按选择器反推补 versionNo/taxRateBps)\n- 两后端对等:quotations/products/customers/sales-orders 四列表改 Paginated 信封;\n 新增 /products/options(只返在售)、/customers/options(联系人 id/name/mobile)、\n /fulfillment/contract-requests/options(只返 REQUESTED);权限沿用列表同一 capability\n- 前端真实对接:9 个选择器站点切 options hook(key 挂既有根继承实时失效,\n sales_order.* 额外失效合同 options);合同激活手填 UUID 换真实下拉;\n page.tsx contracts/products prop 下钻退役;4 列表接分页条;truncated 显式提示\n- 对抗性测试三层负向均实跑判红后恢复:contracts 投影透传红 / module-integration\n degrade-selector-to-paginated-list 注入红 / E2E 选择器退化红(第 9 条浏览器用例);\n 顺带发现并修复 drop-fulfillment-realtime 注入被 payment 分支同字面量代码静默拔牙(replace→replaceAll)\n- 棘轮抬地板:testsPassed 265→279、uiTestsPassed 8→9、ownTests 17→18、ownTestCases 194→209\n- 回灌:CLAUDE.md 真源地图+动态区(G24 移入已关闭)、governance-experience 战役记录、\n owner-matrix 登记三个 options 读模型、api-standard 分页章节按裁决修正\n\n证据(本地工作区,2026-08-01):pnpm check exit 0;check:runtime 279/0(PG:55432/juhai_quotation_g24_20260801);\ncheck:ui 9/0(juhai_quotation_ui_g24_20260801)\n\nCo-Authored-By: Claude Fable 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T05:57:57-07:00"}],"HeadCommit":{"Sha1":"ccbb031fdb47bc913ed2b4ba270c0a49889eb88d","Message":"feat(g24): 列表分页 + 选择器 options 双读路径(contracts 单源/双后端对等/三层负向证据)\n\n- contracts 新增 pagination.ts 单源:Paginated\u003cT\u003e{items,page,pageSize,total}(total=租户全量)、\n paginationQuerySchema(默认 20/上限 100,越界 Zod 400 不静默 clamp)、toPrismaPage/makePaginated、\n OptionList\u003cT\u003e{items,truncated} + OPTION_LIST_LIMIT=200 + makeOptionList,\n 三个 Option 投影重建对象字面量做字段白名单(成本/底价结构性缺席;按选择器反推补 versionNo/taxRateBps)\n- 两后端对等:quotations/products/customers/sales-orders 四列表改 Paginated 信封;\n 新增 /products/options(只返在售)、/customers/options(联系人 id/name/mobile)、\n /fulfillment/contract-requests/options(只返 REQUESTED);权限沿用列表同一 capability\n- 前端真实对接:9 个选择器站点切 options hook(key 挂既有根继承实时失效,\n sales_order.* 额外失效合同 options);合同激活手填 UUID 换真实下拉;\n page.tsx contracts/products prop 下钻退役;4 列表接分页条;truncated 显式提示\n- 对抗性测试三层负向均实跑判红后恢复:contracts 投影透传红 / module-integration\n degrade-selector-to-paginated-list 注入红 / E2E 选择器退化红(第 9 条浏览器用例);\n 顺带发现并修复 drop-fulfillment-realtime 注入被 payment 分支同字面量代码静默拔牙(replace→replaceAll)\n- 棘轮抬地板:testsPassed 265→279、uiTestsPassed 8→9、ownTests 17→18、ownTestCases 194→209\n- 回灌:CLAUDE.md 真源地图+动态区(G24 移入已关闭)、governance-experience 战役记录、\n owner-matrix 登记三个 options 读模型、api-standard 分页章节按裁决修正\n\n证据(本地工作区,2026-08-01):pnpm check exit 0;check:runtime 279/0(PG:55432/juhai_quotation_g24_20260801);\ncheck:ui 9/0(juhai_quotation_ui_g24_20260801)\n\nCo-Authored-By: Claude Fable 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T05:57:57-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/8fe17cd57002bf1ed691e63a80c71db5c03d0f5f...ccbb031fdb47bc913ed2b4ba270c0a49889eb88d","Len":1}...
|
1785589103
|
Edit
Delete
|
|
20282
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/feat/solution-tier-multi-product
|
0
|
|
1785590611
|
Edit
Delete
|
|
20283
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/feat/solution-tier-multi-product
|
0
|
{"Commits":[{"Sha1":"815f9b634 {"Commits":[{"Sha1":"815f9b634be98eeea1ead07bc5daaf37dec909e0","Message":"feat(solution): 三档方案支持每档多商品,数量默认取项目包房总数\n\n## 多商品\n契约 `solutionOptionInputSchema.products` 一直是 `.min(1).max(500)`,后端逐条落\nSolutionOptionProduct、转报价桥接逐条转成报价明细、客户页也已在显示「配置 N 项」——\n整条链路早就支持多商品,**只有设计器表单把它写死成单元素数组**,能力在用户唯一\n够得着的那一层被锁掉(同 C25/C26 族:能力挂在哪一层决定它存不存在)。\n\n改法复用仓内既有 AccessoryEditor 模式:选择 + 数量 → 添加成可删除的清单行。\n刻意不用 `\u003cselect multiple\u003e`:每个商品要带自己的数量,多选框表达不了;且 Select\n原语的注释明确禁止把它改造成多选(E2E 按 locator(\"select\") 定位、Capacitor 依赖\n原生选择器)。同档重复添加同一商品累加数量,不并排出现两行肉眼一样的配置。\n\n## 数量默认值\n默认 = 本项目包房总数(kind===\"ROOM\" 的空间数量求和),只预填不锁定。\n回落 1 而非 0:契约 quantity 是 int().positive(),预填 0 会让按钮看着能点、\n提交却被 Zod 挡下(C24 同款:默认值不合法 = 表单永远提交不了)。\nUI 显式写明「数量默认按本项目包房总数 N 间预填,可逐项调整」,不做魔法数字。\n\n## 顺带修掉一个跨项目状态串味\nSolutionDesigner 的已选商品与包房数预填都是挂载时求值的本地状态,\n渲染处此前无 key——切换项目不重挂,会把上一个项目的选择带过去。已加 key={project.id}。\n\n## 证据(本地工作区 2026-08-01)\n- pnpm check exit 0;check:runtime 279/0;check:ui 9/0\n- 端到端读回:推荐档配 2 个商品 → 客户页断言「配置 2 项」→ 成功转成正式报价\n- 负向测试两条均实跑判红后恢复:\n ① addProduct 改为 `products: [line]`(回潮到单商品)→ 恰好 solution-product-row\n 期望 2 实得 1 判红;\n ② roomTotal 改为常量 1 → 恰好 待添加数量 期望 \"8\" 实得 \"1\" 判红\n\nCo-Authored-By: Claude Fable 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T06:23:24-07:00"}],"HeadCommit":{"Sha1":"815f9b634be98eeea1ead07bc5daaf37dec909e0","Message":"feat(solution): 三档方案支持每档多商品,数量默认取项目包房总数\n\n## 多商品\n契约 `solutionOptionInputSchema.products` 一直是 `.min(1).max(500)`,后端逐条落\nSolutionOptionProduct、转报价桥接逐条转成报价明细、客户页也已在显示「配置 N 项」——\n整条链路早就支持多商品,**只有设计器表单把它写死成单元素数组**,能力在用户唯一\n够得着的那一层被锁掉(同 C25/C26 族:能力挂在哪一层决定它存不存在)。\n\n改法复用仓内既有 AccessoryEditor 模式:选择 + 数量 → 添加成可删除的清单行。\n刻意不用 `\u003cselect multiple\u003e`:每个商品要带自己的数量,多选框表达不了;且 Select\n原语的注释明确禁止把它改造成多选(E2E 按 locator(\"select\") 定位、Capacitor 依赖\n原生选择器)。同档重复添加同一商品累加数量,不并排出现两行肉眼一样的配置。\n\n## 数量默认值\n默认 = 本项目包房总数(kind===\"ROOM\" 的空间数量求和),只预填不锁定。\n回落 1 而非 0:契约 quantity 是 int().positive(),预填 0 会让按钮看着能点、\n提交却被 Zod 挡下(C24 同款:默认值不合法 = 表单永远提交不了)。\nUI 显式写明「数量默认按本项目包房总数 N 间预填,可逐项调整」,不做魔法数字。\n\n## 顺带修掉一个跨项目状态串味\nSolutionDesigner 的已选商品与包房数预填都是挂载时求值的本地状态,\n渲染处此前无 key——切换项目不重挂,会把上一个项目的选择带过去。已加 key={project.id}。\n\n## 证据(本地工作区 2026-08-01)\n- pnpm check exit 0;check:runtime 279/0;check:ui 9/0\n- 端到端读回:推荐档配 2 个商品 → 客户页断言「配置 2 项」→ 成功转成正式报价\n- 负向测试两条均实跑判红后恢复:\n ① addProduct 改为 `products: [line]`(回潮到单商品)→ 恰好 solution-product-row\n 期望 2 实得 1 判红;\n ② roomTotal 改为常量 1 → 恰好 待添加数量 期望 \"8\" 实得 \"1\" 判红\n\nCo-Authored-By: Claude Fable 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T06:23:24-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/ccbb031fdb47bc913ed2b4ba270c0a49889eb88d...815f9b634be98eeea1ead07bc5daaf37dec909e0","Len":1}...
|
1785590611
|
Edit
Delete
|
|
20284
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/feat/solution-tier-multi-product
|
0
|
{"Commits":[{"Sha1":"b0ed5cba7 {"Commits":[{"Sha1":"b0ed5cba764d5df24360ea70486bad9b6885431d","Message":"feat(solution): 数量来源可选空间分类或手动输入,选品增加商品分类筛选\n\n## 数量来源可选\n此前默认值写死「包房总数」。但走廊音响、前台设备、设备间机柜这类根本不按包房走,\n把包房硬编码成唯一口径等于只服务一种配置习惯。\n\n改为下拉可选:**按任一空间分类的数量合计**(包房/前台/走廊/水吧/办公室/设备间/其他,\n选项上直接标出该类当前数量)或**手动输入**。默认仍落在包房——点歌设备按包房逐间\n配是这门生意的常识配比。\n\n- 按空间分类走时数量输入框只读:避免出现「显示按包房、值却被手改过」这种谁也说不清\n 依据的数字;要自己填就显式切到「手动输入」。\n- 取值一律 Math.max(1, …):契约 quantity 是 int().positive(),项目里没录前台时\n 合计为 0,预填 0 会让「添加」看着能点、提交却被 Zod 挡下(C24 同款教训)。\n- 空间分类总数用枚举 reduce 统一算,不给某一类空间写死分支。\n\n## 选品增加商品分类\n选品下拉前置「全部分类 / 设备 / 服务 / 配件」筛选(沿用商品库同名口径,不另造说法)。\n切换分类时清空已选商品——否则下拉显示的是新分类、value 仍指向旧分类那件商品,\n提交的是用户此刻根本看不见的东西。\n\n添加一件后**保留分类与来源**、只清商品:连着配同一类设备是常态,每加一件就把筛选\n重置回默认等于逼人重选一遍。\n\n来源与分类只是挑选时的辅助,不进已选行——存进去会让配置多出两个读模型不消费、\n契约也不收的字段。\n\n## 证据(本地工作区 2026-08-01)\n- pnpm check exit 0;check:runtime 279/0;check:ui 9/0\n- E2E 新增断言:切「配件」后候选从 4 项收窄到 2 项(证明筛选真的干活);\n 切「手动输入」填 3 后该行数量为 3,而主设备那行仍是按包房总数的 8\n (证明两种来源可在同一档并存)\n\nCo-Authored-By: Claude Fable 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T06:40:01-07:00"},{"Sha1":"18359985bc7144f7c67c3f17d80e7f848770d956","Message":"fix(ci): 让 UI 验收红盘可判责——失败时打印捕获输出并上传证据产物\n\nPR #6 的 Runtime and UI acceptance 在远端判红,但日志里只有一行\n「✗ playwright-test failed (exit 1)」,看不出是哪条断言、为什么失败。\n\n根因:check-ui-acceptance.mjs 的 runSync 把子进程 stdout/stderr 收进 report JSON\n的 stdoutTail/stderrTail 后**从不打印**,而 workflow 又不上传 report——\n证据在当场就被丢掉了。G23 ④ 记的「2026-07-31 红盘 tests-floor got 0 根因至今\n未定位」是同一个病根。\n\n- runSync 失败时把两条尾巴打到 stderr\n- workflow 失败时上传 reports/*.latest.json + e2e-results.json + playwright traces\n\n本机以全新库复跑 check:ui 为 9/9 全绿,无法复现远端红盘;按治理纪律\n「根因未定位不得归因」,先补证据链再判是偶发还是回归。\n\nCo-Authored-By: Claude Fable 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T06:33:17-07:00"}],"HeadCommit":{"Sha1":"b0ed5cba764d5df24360ea70486bad9b6885431d","Message":"feat(solution): 数量来源可选空间分类或手动输入,选品增加商品分类筛选\n\n## 数量来源可选\n此前默认值写死「包房总数」。但走廊音响、前台设备、设备间机柜这类根本不按包房走,\n把包房硬编码成唯一口径等于只服务一种配置习惯。\n\n改为下拉可选:**按任一空间分类的数量合计**(包房/前台/走廊/水吧/办公室/设备间/其他,\n选项上直接标出该类当前数量)或**手动输入**。默认仍落在包房——点歌设备按包房逐间\n配是这门生意的常识配比。\n\n- 按空间分类走时数量输入框只读:避免出现「显示按包房、值却被手改过」这种谁也说不清\n 依据的数字;要自己填就显式切到「手动输入」。\n- 取值一律 Math.max(1, …):契约 quantity 是 int().positive(),项目里没录前台时\n 合计为 0,预填 0 会让「添加」看着能点、提交却被 Zod 挡下(C24 同款教训)。\n- 空间分类总数用枚举 reduce 统一算,不给某一类空间写死分支。\n\n## 选品增加商品分类\n选品下拉前置「全部分类 / 设备 / 服务 / 配件」筛选(沿用商品库同名口径,不另造说法)。\n切换分类时清空已选商品——否则下拉显示的是新分类、value 仍指向旧分类那件商品,\n提交的是用户此刻根本看不见的东西。\n\n添加一件后**保留分类与来源**、只清商品:连着配同一类设备是常态,每加一件就把筛选\n重置回默认等于逼人重选一遍。\n\n来源与分类只是挑选时的辅助,不进已选行——存进去会让配置多出两个读模型不消费、\n契约也不收的字段。\n\n## 证据(本地工作区 2026-08-01)\n- pnpm check exit 0;check:runtime 279/0;check:ui 9/0\n- E2E 新增断言:切「配件」后候选从 4 项收窄到 2 项(证明筛选真的干活);\n 切「手动输入」填 3 后该行数量为 3,而主设备那行仍是按包房总数的 8\n (证明两种来源可在同一档并存)\n\nCo-Authored-By: Claude Fable 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T06:40:01-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/815f9b634be98eeea1ead07bc5daaf37dec909e0...b0ed5cba764d5df24360ea70486bad9b6885431d","Len":2}...
|
1785591608
|
Edit
Delete
|
|
20285
|
5
|
5
|
5
|
72
|
0
|
0
|
refs/heads/feat/solution-tier-multi-product
|
0
|
{"Commits":[{"Sha1":"47ce4c614 {"Commits":[{"Sha1":"47ce4c6146a13c443db38c5816749d0591339e46","Message":"fix(quotations): 视图筛选下沉服务端 + 公开方案页不再泄漏后端英文报错\n\n## 1. 三个筛选视图的分页回归(G24 引入,本次修复)\n审核中心 / 客户报价页 / 报价版本 原先在浏览器里对列表结果 filter。列表全量返回时\n那样是对的,但 G24 加分页后客户端筛选只作用于**当前页**:待审报价不在最新一页\n就会被静默漏掉,而分页条的 total 仍是全量数,出现「共 N 条却一行不显示」的错位。\n与 C27「聚合范围由前端恰好拿到多少行决定」同族——筛选范围必须由拥有数据的一层决定。\n\n- contracts 新增 QUOTATION_VIEW_FILTERS 单源(inbox/review/customer/versions),\n 两后端各自翻译成 Prisma where;total 随之变成「该视图下的全量」;\n- quotationListViewSchema 刻意不 extend paginationQuerySchema——那会让\n quotation.ts 反向 import pagination.ts 的值,与既有 type import 形成循环;\n- 非法 view 是 400 而不是静默退回全部(静默兜底会让筛选看着生效实则没有);\n- 前端只保留一条**权限谓词**(无 customer_link.read 读不到 accessToken):\n 它对同一角色恒为全真或全假,不会像数据谓词那样把行留在分页窗口外。\n\n⚠️ 期间发现 QuoteOption.accessToken 是 @default(uuid()) **非空**,\n原「客户报价页」的 options.some(accessToken) 实际是权限谓词而非数据谓词。\n\n## 2. 公开方案页把后端英文报错渲染给客户\nPublicCustomerSolutionView 直接渲染 query.error.message,客户看到的是\n「Solution project not found」——看不懂、像坏了,还把内部对象名暴露出去。\n改为统一中文文案,且**不区分**链接无效/未发布/返工中:区分开等于告诉持链接的人\n「方案确实存在,只是没轮到你看」,而服务端刻意用 404 而非 403 正是为了不泄露存在性\n(方案蓝图 S1 审计裁决)。前端说破,那道防线就白立了。\n\n## 门禁断言随执行点搬家(不是放宽)\nquotation-review-server-state / quotation-version-snapshot 钉的是被移走的客户端谓词。\n不变量没变、执行点变了,故改为钉:前端必须把 mode 作为 view 传下去、\n两后端必须从 contracts 单源翻译 where,并加 reject 断言禁止客户端重新实现视图谓词。\n\n## 证据(本地工作区 2026-08-01)\n- pnpm check 0 / check:runtime 294 / check:ui 9\n- 两后端各 +3 条断言(view=review 只回待审、total 随筛选收窄、非法 view 400)\n- 负向两条实跑判红后恢复:\n ① 服务端忽略 view → view=review 期望 1 实得 2 判红\n ② 视图谓词写回客户端 → quotation-view-client-side-filter 判红\n\nCo-Authored-By: Claude Fable 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T08:35:11-07:00"},{"Sha1":"b0ba9576541405a0613ae827ad3c80873437ef53","Message":"docs(flow): 重新梳理业务模块与主干流程,补齐审批中心并画 mermaid 流程图\n\nbusiness-flow-overview.md 写于同一天更早的提交,正文里一次都没提 approval-inbox\n(468a6cd 才落地的 9 类聚合)。本次按 contracts 与前端导航逐条核对后重梳理:\n\n- 新增 §6 待办审批中心:明确它是**横切在主干之上的视图,不是主干的一个节点**\n (无写端点、不重定义「什么算待审」、入口不设独立 capability 而挂 event.read),\n 并给出 9 类条目各自落在主干哪一步;第 8/9 类是待办不是审批闸门。\n- 新增 §1.1 业务模块分层,并标注 owner-matrix 里的 inventory/procurement/logistics\n **不是物理模块**:三个域的写链全部实现在 fulfillment.service.ts(~2100 行,\n 两后端各一份),按目录名去搜会扑空。\n- §3 补两条被 happy path 掩盖的主干分支:报价审批是**条件审批**\n (quotationMachine 的 DRAFT 同时接 send,服务端仅在存在 requiresApproval 的\n 方案档时抛 409 拦截);销售订单可先转 PROCUREMENT_REQUIRED,纯服务订单反向跳过发运。\n- §1 主干图 ASCII 换 mermaid(GitHub 可渲染),信息等价。\n\n仍不复制状态机全图——那是 P1 禁止的第二真源,图里只点 contracts 导出符号名。\n未新建流程图文档:本文件已是该事项的登记位置,另开一份即第二真源。\n\n证据:本地工作区 check:docs-truth / check:naming / check:governance-docs /\ncheck:gate-selftest 均绿(静态级,工作区 dirty,不外推远端与运行态)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T08:08:20-07:00"},{"Sha1":"f315e642beda9d7ccc527955b2397f4702d33a9c","Message":"chore(gate): docs-truth 负向测试固化 + 幽灵资产清单扩面\n\n会话里手工跑一次的红盘不留证据,下轮重构会静默失效(G13)。把 docs-truth 的\n负向测试固化为 scripts/lib/docs-truth.test.mjs,由 check:gate-selftest 重跑,\ngateSelftests 地板 2 → 3。\n\n幽灵资产两条断言扩面:\n- no-phantom-config-prisma 清单补入 docs/README.md 与 naming-standard.md\n- 新增 contracts-package-name,递归扫描 docs/ 全域,真值取自\n packages/contracts/package.json 的 name(非黑名单)\n\n扩清单判据:该文件是在**主张**这条幽灵引用,还是在**否定**它?只有前者进清单——\nADR 澄清段与治理经验库引用它正是为宣告作废,扫进来即咬住纠错本身(C1 同类陷阱)。\n\nCLAUDE.md 会话收尾清单同步回灌两个已实锤两次的坑:注入点是否真落在目标断言上\n(replace 只换第一处),以及红是否红在点子上(崩溃/环境不满足同样非 0 退出)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T08:08:01-07:00"},{"Sha1":"468a6cd2ab36d76237ae9c4d849eda17204d722c","Message":"feat(approval-inbox): 跨域待办审批中心(切片一)——9 类聚合 + 中心内直接审批\n\n经 business-module-intake 接待流程落地,蓝图见 docs/domain/approval-inbox-blueprint.md。\n\n## 解决的问题\n全系统有 7 道审批闸门,只有报价那一道有「审核中心」入口;技术复核、经理批准、\n采购、盘点、红冲、退款全部藏在各自工作台深处,待办不可发现。\n\n## 设计要害:聚合层不得成为第二真源\n- **不新建聚合写入口**:中心里的审批动作一律打各域原有端点,写入唯一点不变;\n- **不重新定义「什么算待审」**:判据只引用各域自己的状态枚举;\n- **入参 schema 直接引用各域已有 Zod schema**(APPROVAL_PAYLOAD_SCHEMAS),\n 某域改入参→改自己的 schema→中心类型立刻变→编译期红,而不是运行时静默 400/409;\n- 描述表 `satisfies Record\u003cApprovalTaskKind, …\u003e` 锁全集,漏一类即编译不过;\n- capability 裁剪、自批过滤、排序计数统一交给 contracts 纯函数 buildApprovalInbox,\n 两后端共用——行为对等由结构保证(G17)。\n\n## 覆盖 9 类\n7 道审批 + 2 类客户决定后的待办(客户已接受待申请合同、客户已选档待转报价)。\n后两类**不是审批闸门**:客户决定仍立即生效,只是把「决定之后必须有人做的那一步」\n从各自工作台捞出来,零状态机改动、零迁移、零对客语义变更。\n\n## 实测暴露并绕开的坑\n- 盘点列表 capability(inventory.stocktake) ≠ 审批 capability(.approve),\n SALES_MANAGER 只持后者——中心按**审批** capability 判定,否则审批人看不到自己该审的单;\n- 采购员不持 procurement.approve(三责分离),中心里必须继续不可见;\n- 方案两类需回传 versionNo 做 STALE_VERSION 校验,中心从聚合结果带出。\n\n## 诚实边界(蓝图 §7,切片二再补)\n发起人字段只有 2/7 个域存在,自批过滤只在红冲/退款生效,UI 如实标注可判定范围。\n**本模块不得宣称「已保证不可自批」**——只有这两类成立。\n\n## 证据(本地工作区 2026-08-01)\n- pnpm check 0 / check:runtime 294(地板 279→294)/ check:ui 9\n- contracts 13 条单测;两后端各 1 条聚合 HTTP 验收(capability 裁剪/跨租户/自批计数/待办类)\n- check:module-integration 新增 5 条断言,三条负向实跑判红后恢复:\n ① 聚合层加写端点 ② capability 裁剪改全放行 ③ 去掉实时失效\n 其中 ② 首轮未判红——断言只查标识符、留着未使用 import 就能骗过,\n 已收紧到锚定调用点(断言剧场自查)\n\nCo-Authored-By: Claude Fable 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T07:45:16-07:00"}],"HeadCommit":{"Sha1":"47ce4c6146a13c443db38c5816749d0591339e46","Message":"fix(quotations): 视图筛选下沉服务端 + 公开方案页不再泄漏后端英文报错\n\n## 1. 三个筛选视图的分页回归(G24 引入,本次修复)\n审核中心 / 客户报价页 / 报价版本 原先在浏览器里对列表结果 filter。列表全量返回时\n那样是对的,但 G24 加分页后客户端筛选只作用于**当前页**:待审报价不在最新一页\n就会被静默漏掉,而分页条的 total 仍是全量数,出现「共 N 条却一行不显示」的错位。\n与 C27「聚合范围由前端恰好拿到多少行决定」同族——筛选范围必须由拥有数据的一层决定。\n\n- contracts 新增 QUOTATION_VIEW_FILTERS 单源(inbox/review/customer/versions),\n 两后端各自翻译成 Prisma where;total 随之变成「该视图下的全量」;\n- quotationListViewSchema 刻意不 extend paginationQuerySchema——那会让\n quotation.ts 反向 import pagination.ts 的值,与既有 type import 形成循环;\n- 非法 view 是 400 而不是静默退回全部(静默兜底会让筛选看着生效实则没有);\n- 前端只保留一条**权限谓词**(无 customer_link.read 读不到 accessToken):\n 它对同一角色恒为全真或全假,不会像数据谓词那样把行留在分页窗口外。\n\n⚠️ 期间发现 QuoteOption.accessToken 是 @default(uuid()) **非空**,\n原「客户报价页」的 options.some(accessToken) 实际是权限谓词而非数据谓词。\n\n## 2. 公开方案页把后端英文报错渲染给客户\nPublicCustomerSolutionView 直接渲染 query.error.message,客户看到的是\n「Solution project not found」——看不懂、像坏了,还把内部对象名暴露出去。\n改为统一中文文案,且**不区分**链接无效/未发布/返工中:区分开等于告诉持链接的人\n「方案确实存在,只是没轮到你看」,而服务端刻意用 404 而非 403 正是为了不泄露存在性\n(方案蓝图 S1 审计裁决)。前端说破,那道防线就白立了。\n\n## 门禁断言随执行点搬家(不是放宽)\nquotation-review-server-state / quotation-version-snapshot 钉的是被移走的客户端谓词。\n不变量没变、执行点变了,故改为钉:前端必须把 mode 作为 view 传下去、\n两后端必须从 contracts 单源翻译 where,并加 reject 断言禁止客户端重新实现视图谓词。\n\n## 证据(本地工作区 2026-08-01)\n- pnpm check 0 / check:runtime 294 / check:ui 9\n- 两后端各 +3 条断言(view=review 只回待审、total 随筛选收窄、非法 view 400)\n- 负向两条实跑判红后恢复:\n ① 服务端忽略 view → view=review 期望 1 实得 2 判红\n ② 视图谓词写回客户端 → quotation-view-client-side-filter 判红\n\nCo-Authored-By: Claude Fable 5 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-08-01T08:35:11-07:00"},"CompareURL":"luoanwu/juhai-quotation-system/compare/b0ed5cba764d5df24360ea70486bad9b6885431d...47ce4c6146a13c443db38c5816749d0591339e46","Len":4}...
|
1785598520
|
Edit
Delete
|