Просмотр исходного кода

fix(workshop): preserve account binding contract and clarify identity feedback

pengzhikang 2 часов назад
Родитель
Сommit
7b4d02ae13

BIN
docs/workshop-final-files-20261111/final-康师傅工作坊.skill


+ 3 - 3
docs/workshop-final-files-20261111/skill-package-receipt.json

@@ -1,10 +1,10 @@
 {
 {
   "ok": true,
   "ok": true,
   "file": "final-康师傅工作坊.skill",
   "file": "final-康师傅工作坊.skill",
-  "bytes": 374834,
-  "sha256": "c7fc15321281064deec680f30451757218b393796de8085650f7def178c6764d",
+  "bytes": 376175,
+  "sha256": "710672e85694431b675e23fc3b283ff58e68970ef0061902303620e1c736ab52",
   "publicFilesVerified": 55,
   "publicFilesVerified": 55,
-  "entrySha256": "b798b417de70c0d9c15d1eefe72ca069179bb3d2686402399f3aa4e3830c103b",
+  "entrySha256": "f4c738a3b0381c6808c47150064bbd29fc018764cb83946eb85f6b75c8d70a11",
   "canonicalEntry": "skills/ksf-workshop-runtime/final-SKILL.md",
   "canonicalEntry": "skills/ksf-workshop-runtime/final-SKILL.md",
   "archiveEntry": "ksf-workshop-runtime/SKILL.md",
   "archiveEntry": "ksf-workshop-runtime/SKILL.md",
   "format": "zip-compatible .skill",
   "format": "zip-compatible .skill",

+ 29 - 0
docs/workshop-r15-contract-fix-20261112/README.md

@@ -0,0 +1,29 @@
+# Skill r15-local.4:保留公开账号绑定契约
+
+r15-local.3 的 `redactIdentity()` 把所有名为 `accountBinding` 的字段删除,误删了 `workshop-contract` 中的公开能力声明及 `workshop-start` 的安全绑定摘要。数字人因此无法识别首次账号绑定入口。该问题来自我方客户端脱敏范围,非生产函数代码未加载。
+
+## 核验与修正
+
+- 生产接口在匿名、管理员、受限服务身份下共6次独立请求都返回 `workshop.accountBinding.enabled=true`。旧版脱敏函数可稳定重现“原始接口有字段、受控结果没有字段”。
+- 修正版按位置、schema及允许字段保留两种公开对象:`workshop.accountBinding`能力声明、会话回执顶层且`status=bound`的安全摘要。报告记录内`meta.attribution.accountBinding`仍被移除,平台内部编号、服务身份及私有档案字段继续脱敏。
+- 新增2个回归测试覆盖真实`runWorkshop('workshop-contract')`调用路径及公开摘要/私有快照的差异。工作坊126项、绑定/身份/凭据27项全部通过;Skill校验通过;完整`.skill`包55个公开文件逐字节核验通过。
+- 新本地模块连真实线上服务读取契约成功。这是本地执行,不等同于容器已安装r15-local.4。
+- 按用户补充要求,首次询问称呼和账号后必须反馈查找结果:找到账号、未找到、查询尚未完成分别说明;绑定成功才告知对话已关联。查找沿用受控注册名册/持久绑定接口,本人确认时实时核对平台账号,不能把报出用户名当认证。后续课堂提交沿用同一账号的memberKey,一个账号一个看板成员。
+
+## 交付与升级
+
+固定包:`docs/workshop-final-files-20261111/final-康师傅工作坊.skill`;入口维护源仍为`skills/ksf-workshop-runtime/final-SKILL.md`。新哈希和逐文件差异见`release.json`。已知旧版完整字节基线见`baseline-r15-local.3.json`,包含55个公开文件与final别名,可按当前组织库适配器格式纳入`previous-release.json`,不可关闭完整性保护或照搬旧r14安装器。
+
+使用本次固定源码提交,更新`kangshifu/workshop-config`内Skill payload、final别名、发行元数据和清单。普通提交推送并回读;固定组织提交后刷新fmode01映射并升级`agent-node-kangshifu`。完整56件组织Skill载荷替换中保留容器私有件;未知差异继续停止。
+
+确认无运行任务后受控重载`gateway-default`。运行`ksf-secure.mjs workshop-contract`,检查`entryResult.result.workshop.accountBinding.enabled === true`;再用容器原服务身份运行果鹏既有档案的`account-status`,应保持`bound`及原`memberKey`。从真实网关任务核对版本r15-local.4与入口SHA,首次使用时询问称呼和已开通账号、本人登录确认、绑定后提交成果。
+
+本次不需要重载/重发平台云函数,不修改`employeeAccountsProvisioned`旧标记。v3手册及13段提示词、VOC 0.3.45、后端函数、数据库结构和看板界面均无变更。冻结`ksf-workshop.mjs`、`ksf.mjs`及`ksf-account.mjs`原字节保留;受控包装只同步新的身份模块校验值。
+
+## 现状与边界
+
+运维回执确认r15-local.3已安装、VOC 0.3.45在线;本补丁的组织库同步与容器安装仍待运维回执。本机现有组织库Git身份此前返回403,无已授权宿主连接,源码推送不代表运行容器已更新。
+
+线上成员与分组接口仍为27人,果鹏原报告`JLF4v5MpyR`保留且绑定同一规范成员。只读核验未创建成员或报告、未改后端。首次新学员的本人登录确认交互与真实报告闭环仍需在实际使用中验收,本次未伪造员工会话。
+
+本地受限连接文件对应的服务身份与容器报告归属服务身份不同,其绑定查询受服务隔离约束,不能用它返回的unbound否定容器既有bound结果;补验必须使用容器原凭据。

+ 235 - 0
docs/workshop-r15-contract-fix-20261112/baseline-r15-local.3.json

@@ -0,0 +1,235 @@
+{
+  "schema": "ksf.skill-known-baseline.v1",
+  "version": "r15-local.3",
+  "sourceCommit": "ad8a5e90e48eeeae94bb4a26826fb7db6eb902fb",
+  "organizationCommit": "9cdb20b93cfa427bb72ace947c0e13f325b5e858",
+  "organizationManifestSha256": "e144848fdf5bff23a537340bdbb1aefe79a62029e6a7eec19669baeab3c9850b",
+  "publicFileCount": 55,
+  "publicFiles": [
+    {
+      "file": "SKILL.md",
+      "sha256": "b798b417de70c0d9c15d1eefe72ca069179bb3d2686402399f3aa4e3830c103b"
+    },
+    {
+      "file": "references/business-data-dictionary.json",
+      "sha256": "11863b16216f8746f24189444fc5ffd40512d313cfddd6fa99111b84ac3acfc2"
+    },
+    {
+      "file": "references/full-schema-and-intake.md",
+      "sha256": "08859f32fa51399c638cb9cc0669e69f53a630ebdfa0ad965b1d360115b3a901"
+    },
+    {
+      "file": "references/identity.md",
+      "sha256": "1f7ee67333604603497494e4247d28987db0fab0b80913eae8d5e06246ba558d"
+    },
+    {
+      "file": "references/research-library/data-contract.md",
+      "sha256": "a9af25da32e769443af4565ca400c9136745c9d30c2c190dedf978841bf977c1"
+    },
+    {
+      "file": "references/research-library/full-schema-and-intake.md",
+      "sha256": "78dedd84d8560ee3f0492769db81562841193fa40bef7028836745b0958ab6b8"
+    },
+    {
+      "file": "references/research-library/operations.md",
+      "sha256": "a154e01d3f3efb47f643c27adf22fe963d507dc68a50f8747e8ffda8bb7180bb"
+    },
+    {
+      "file": "references/research-library/product-overview-and-intake.md",
+      "sha256": "fe3462b121fc3f8d5ec0392f68229c463e05a5b3bed985b3d356a1b975f5602e"
+    },
+    {
+      "file": "references/research-library/query-rules.md",
+      "sha256": "3de4f2aeca43792a37e2d514defebf641b80db11639853ff60e48843dc3405bd"
+    },
+    {
+      "file": "references/research-library/research-data-dictionary.json",
+      "sha256": "270b998fca0d4dcd0ad53ff0bc7e2b5a11f88016133965053cf54f5a50bc525f"
+    },
+    {
+      "file": "references/research-library/retrieval-rules.md",
+      "sha256": "c00b9a1520866f36f1f4bf26865ee20b4e461d5a998447136bce31cc42fc9b7f"
+    },
+    {
+      "file": "references/workshop-analysis.md",
+      "sha256": "c41219e3f0d48dd687af253475f6971f4929e650450bad7995ffd60770208de6"
+    },
+    {
+      "file": "references/workshop-autonomous-research.md",
+      "sha256": "5af981a8a10acc39470482a09397ea26e8be42d1416efff1e6b2e2baf3bd797f"
+    },
+    {
+      "file": "references/workshop-category-scan.md",
+      "sha256": "b2c6aa939aa4801c77146430f099d3973bf5961cc9291d03a345a9d6a4fe74f6"
+    },
+    {
+      "file": "references/workshop-commercial-feasibility.md",
+      "sha256": "c75a97ec3d31ed626d7e447d3621351a966eb7f953cc7aa7eee5a40a7a71ebec"
+    },
+    {
+      "file": "references/workshop-competitor-landscape.md",
+      "sha256": "d67158d7294bb0581489e01182d0a5fafd121bf6a2fced5a0926263cdfb0dbaf"
+    },
+    {
+      "file": "references/workshop-concept-presentation.md",
+      "sha256": "464977265ed0cd1367f6f478a318ab115738af22793e0b97c4930b4f52d5e694"
+    },
+    {
+      "file": "references/workshop-course-flow.md",
+      "sha256": "85c29ea6798868d5515386e73cc008a228b45a19aa9d072bf4217781207f4300"
+    },
+    {
+      "file": "references/workshop-deliverable-contracts.md",
+      "sha256": "5966a9efd787ab86eae6b78dd28634a6130f2e4dfba3509a7716a67201dfbfc5"
+    },
+    {
+      "file": "references/workshop-delivery.md",
+      "sha256": "8dff9e307769f5cd40f10115dabe02d68ae678de5398db5d5fdaef7bddba073f"
+    },
+    {
+      "file": "references/workshop-dialogue.md",
+      "sha256": "27498cf6b48a8fe3f28aab88c9d5e1fabb5357570a15a06f313d4db9c1c694b6"
+    },
+    {
+      "file": "references/workshop-evidence-counting.md",
+      "sha256": "b741b244f1a1c3cce205aa0c92ac12bd303f015f4bf9ffda87ec520141508e8a"
+    },
+    {
+      "file": "references/workshop-feedback.md",
+      "sha256": "e6613c6f55858f326c2fed5b9b61d6b376871c92b9216d1c9155cb4ed79bac3c"
+    },
+    {
+      "file": "references/workshop-innovation-reasoning.md",
+      "sha256": "19de27e102f8ed0c00c4a1457e7b1902680f2c79201dc274ad22ae66301a1c12"
+    },
+    {
+      "file": "references/workshop-intake.md",
+      "sha256": "13345a8a554256d94db730bae70701be02c3d2a7becf8c7c12b44909cb88465e"
+    },
+    {
+      "file": "references/workshop-opportunity-discovery.md",
+      "sha256": "0c413a47ef1dfbc496280c29a4141568b1a28c58ad3dc92509336748ba2480ec"
+    },
+    {
+      "file": "references/workshop-opportunity-validation.md",
+      "sha256": "db66616e1011e2855d920725242e4a6af086f315e38310efd11f89d5cb2b3453"
+    },
+    {
+      "file": "references/workshop-output-navigation.md",
+      "sha256": "1498f3d19f42ee921ef45559fce7d63e9c7fd5c3062c79d489814cdb96d0a412"
+    },
+    {
+      "file": "references/workshop-report-design.md",
+      "sha256": "d2b02e0ea74e35a32994e5ac11beeccf1c48f4b0903a6ce4e425fdc3e92af7ad"
+    },
+    {
+      "file": "references/workshop-report-parity.md",
+      "sha256": "4df8aaeb0a9587c4b987a5902c6ab3e91b5307daee5c7978eeb6d68b83c6b5e2"
+    },
+    {
+      "file": "references/workshop-research-acceptance.md",
+      "sha256": "26a2fdcae8631a0a66d41d159442525f950835b6057bd1475b4d131f97a10aba"
+    },
+    {
+      "file": "references/workshop-research-loop.md",
+      "sha256": "c480f229baf5d3d84b145649f9cf8a992a2bb7c4a44e2baf11ccedf530eb6786"
+    },
+    {
+      "file": "references/workshop-research-tasking.md",
+      "sha256": "f8b7fbb72b57ae088c411e510dd2cd371aac98d10903a0b4b6e2ce16caae4a51"
+    },
+    {
+      "file": "references/workshop-tasks.md",
+      "sha256": "a4e0bc238966ea7a119986f383f4f6ea99dd8d9de63bdc32571a35b740d8f96d"
+    },
+    {
+      "file": "references/workshop-three-source-opportunities.md",
+      "sha256": "e0200259e92644bf55ca2fe3f60b1eea4c7df512b1300f2643b8b6991ebc6ca3"
+    },
+    {
+      "file": "references/workshop-v3-outputs.md",
+      "sha256": "3d9855fccf3250c54317e7bb4060d3185e77e61be82c0494df5fb1d21d67fee2"
+    },
+    {
+      "file": "references/workshop-value-proposition.md",
+      "sha256": "1589247eade7243f430be161ed987ecbddf9eb9fdcf1873a5d1f5a141ac89c05"
+    },
+    {
+      "file": "references/workshop-verification.md",
+      "sha256": "01451f1565983eba85f26d3403b35f67c19cf501b5b5da29f52270dc68fd55f6"
+    },
+    {
+      "file": "references/workshop-voc-clustering.md",
+      "sha256": "d1c04203dde6a7eb424b2316a13964d2d63a6e91836dd5c1eef55f858f59fe02"
+    },
+    {
+      "file": "references/write-tasks.md",
+      "sha256": "a685c3a1c2b907e19cc7e94e42325012a82e09978e267219a0938a42fb9beace"
+    },
+    {
+      "file": "runtime-lock.json",
+      "sha256": "2605cbe8fd7be43b5969a4991f978dc0768dee5b4d65d18f7af15f75e9004a79"
+    },
+    {
+      "file": "scripts/course-assessment.mjs",
+      "sha256": "7ad2aebd30fbc244f4617c9559f076ff7df4196901a31465b5a70bfe5055bb55"
+    },
+    {
+      "file": "scripts/course-deliverables.mjs",
+      "sha256": "7200354296d2b605247ac0cd41927e55fd741f5dd29beb1387b92373f88df617"
+    },
+    {
+      "file": "scripts/describe-business-schema.mjs",
+      "sha256": "e96e8c3fc1a71f1edc39dfc250199aacfb1457aec851d29e6f3b2c35e918a279"
+    },
+    {
+      "file": "scripts/ksf-account.mjs",
+      "sha256": "9bfda45c53192d70fefb31b378851aeb19e075b6f5adcd8217ba4838cc133f7d"
+    },
+    {
+      "file": "scripts/ksf-identity-bridge.mjs",
+      "sha256": "6ba3f0cb6527bc4a0a6218a898472ac65aa3dd9f3f57b597d77efcee641a7540"
+    },
+    {
+      "file": "scripts/ksf-identity.mjs",
+      "sha256": "ab6838afd140e4b84ef39a255fcbdd80ece9b0b7c245f65cd8ba81d892036513"
+    },
+    {
+      "file": "scripts/ksf-secure.mjs",
+      "sha256": "25e42387ea9e3cbf5b60c431eaaf09bc381dcc04acbb82d0f0a7dd071f357fea"
+    },
+    {
+      "file": "scripts/ksf-workshop.mjs",
+      "sha256": "7a04eb22d3429cdced23513717f36594f639539738994d45712a8bea738100a1"
+    },
+    {
+      "file": "scripts/ksf.mjs",
+      "sha256": "7ef128f7d022bfbc15c0ec813bfd87995c6297c6efe407a563c840f014aba477"
+    },
+    {
+      "file": "scripts/render-report-html.mjs",
+      "sha256": "246588294da6975d80d0f1b1e338bc30cf737421c43cea38cf33745eb52e40a9"
+    },
+    {
+      "file": "scripts/report-contract.mjs",
+      "sha256": "4c6e05ca3f6e65d57d55f743de39307181f8427626e355a5d2698905c17dd8c4"
+    },
+    {
+      "file": "scripts/report-statistics.mjs",
+      "sha256": "ede7e98ee941e4ca2ce867d53eb29fa289b9047070e9e6797d20d5d547d24325"
+    },
+    {
+      "file": "scripts/save-report.mjs",
+      "sha256": "022c1833f733ac321ce588ea1dd74e12a1609370f35fe3749c35bf8059a97d17"
+    },
+    {
+      "file": "FILES.sha256",
+      "sha256": "9c3c8fc60af395d6ee808cc33bef26e8f76d9d9588b690655dcfe91ce6ade53e"
+    }
+  ],
+  "alias": {
+    "file": "final-SKILL.md",
+    "sha256": "b798b417de70c0d9c15d1eefe72ca069179bb3d2686402399f3aa4e3830c103b"
+  },
+  "purpose": "供当前组织库适配器识别已知r15-local.3;本文件是完整字节基线资料,不直接替换其previous-release.json格式。"
+}

+ 333 - 0
docs/workshop-r15-contract-fix-20261112/release.json

@@ -0,0 +1,333 @@
+{
+  "schema": "ksf.skill-patch-release.v1",
+  "date": "2026-11-12",
+  "skillVersion": "r15-local.4",
+  "sourceBaseCommit": "ad8a5e90e48eeeae94bb4a26826fb7db6eb902fb",
+  "previousVersion": "r15-local.3",
+  "priorBaseline": "docs/workshop-r15-contract-fix-20261112/baseline-r15-local.3.json",
+  "publicFileCount": 55,
+  "manifestEntryCount": 54,
+  "organizationPayloadFileCount": 56,
+  "publicFiles": [
+    {
+      "file": "SKILL.md",
+      "sha256": "f4c738a3b0381c6808c47150064bbd29fc018764cb83946eb85f6b75c8d70a11"
+    },
+    {
+      "file": "references/business-data-dictionary.json",
+      "sha256": "11863b16216f8746f24189444fc5ffd40512d313cfddd6fa99111b84ac3acfc2"
+    },
+    {
+      "file": "references/full-schema-and-intake.md",
+      "sha256": "08859f32fa51399c638cb9cc0669e69f53a630ebdfa0ad965b1d360115b3a901"
+    },
+    {
+      "file": "references/identity.md",
+      "sha256": "0f4c40ac569b4c53f16f2190b898f14cfa012a4ca9173260434a47ee5d1c0e05"
+    },
+    {
+      "file": "references/research-library/data-contract.md",
+      "sha256": "a9af25da32e769443af4565ca400c9136745c9d30c2c190dedf978841bf977c1"
+    },
+    {
+      "file": "references/research-library/full-schema-and-intake.md",
+      "sha256": "78dedd84d8560ee3f0492769db81562841193fa40bef7028836745b0958ab6b8"
+    },
+    {
+      "file": "references/research-library/operations.md",
+      "sha256": "a154e01d3f3efb47f643c27adf22fe963d507dc68a50f8747e8ffda8bb7180bb"
+    },
+    {
+      "file": "references/research-library/product-overview-and-intake.md",
+      "sha256": "fe3462b121fc3f8d5ec0392f68229c463e05a5b3bed985b3d356a1b975f5602e"
+    },
+    {
+      "file": "references/research-library/query-rules.md",
+      "sha256": "3de4f2aeca43792a37e2d514defebf641b80db11639853ff60e48843dc3405bd"
+    },
+    {
+      "file": "references/research-library/research-data-dictionary.json",
+      "sha256": "270b998fca0d4dcd0ad53ff0bc7e2b5a11f88016133965053cf54f5a50bc525f"
+    },
+    {
+      "file": "references/research-library/retrieval-rules.md",
+      "sha256": "c00b9a1520866f36f1f4bf26865ee20b4e461d5a998447136bce31cc42fc9b7f"
+    },
+    {
+      "file": "references/workshop-analysis.md",
+      "sha256": "c41219e3f0d48dd687af253475f6971f4929e650450bad7995ffd60770208de6"
+    },
+    {
+      "file": "references/workshop-autonomous-research.md",
+      "sha256": "5af981a8a10acc39470482a09397ea26e8be42d1416efff1e6b2e2baf3bd797f"
+    },
+    {
+      "file": "references/workshop-category-scan.md",
+      "sha256": "b2c6aa939aa4801c77146430f099d3973bf5961cc9291d03a345a9d6a4fe74f6"
+    },
+    {
+      "file": "references/workshop-commercial-feasibility.md",
+      "sha256": "c75a97ec3d31ed626d7e447d3621351a966eb7f953cc7aa7eee5a40a7a71ebec"
+    },
+    {
+      "file": "references/workshop-competitor-landscape.md",
+      "sha256": "d67158d7294bb0581489e01182d0a5fafd121bf6a2fced5a0926263cdfb0dbaf"
+    },
+    {
+      "file": "references/workshop-concept-presentation.md",
+      "sha256": "464977265ed0cd1367f6f478a318ab115738af22793e0b97c4930b4f52d5e694"
+    },
+    {
+      "file": "references/workshop-course-flow.md",
+      "sha256": "85c29ea6798868d5515386e73cc008a228b45a19aa9d072bf4217781207f4300"
+    },
+    {
+      "file": "references/workshop-deliverable-contracts.md",
+      "sha256": "5966a9efd787ab86eae6b78dd28634a6130f2e4dfba3509a7716a67201dfbfc5"
+    },
+    {
+      "file": "references/workshop-delivery.md",
+      "sha256": "8dff9e307769f5cd40f10115dabe02d68ae678de5398db5d5fdaef7bddba073f"
+    },
+    {
+      "file": "references/workshop-dialogue.md",
+      "sha256": "27498cf6b48a8fe3f28aab88c9d5e1fabb5357570a15a06f313d4db9c1c694b6"
+    },
+    {
+      "file": "references/workshop-evidence-counting.md",
+      "sha256": "b741b244f1a1c3cce205aa0c92ac12bd303f015f4bf9ffda87ec520141508e8a"
+    },
+    {
+      "file": "references/workshop-feedback.md",
+      "sha256": "e6613c6f55858f326c2fed5b9b61d6b376871c92b9216d1c9155cb4ed79bac3c"
+    },
+    {
+      "file": "references/workshop-innovation-reasoning.md",
+      "sha256": "19de27e102f8ed0c00c4a1457e7b1902680f2c79201dc274ad22ae66301a1c12"
+    },
+    {
+      "file": "references/workshop-intake.md",
+      "sha256": "13345a8a554256d94db730bae70701be02c3d2a7becf8c7c12b44909cb88465e"
+    },
+    {
+      "file": "references/workshop-opportunity-discovery.md",
+      "sha256": "0c413a47ef1dfbc496280c29a4141568b1a28c58ad3dc92509336748ba2480ec"
+    },
+    {
+      "file": "references/workshop-opportunity-validation.md",
+      "sha256": "db66616e1011e2855d920725242e4a6af086f315e38310efd11f89d5cb2b3453"
+    },
+    {
+      "file": "references/workshop-output-navigation.md",
+      "sha256": "1498f3d19f42ee921ef45559fce7d63e9c7fd5c3062c79d489814cdb96d0a412"
+    },
+    {
+      "file": "references/workshop-report-design.md",
+      "sha256": "d2b02e0ea74e35a32994e5ac11beeccf1c48f4b0903a6ce4e425fdc3e92af7ad"
+    },
+    {
+      "file": "references/workshop-report-parity.md",
+      "sha256": "4df8aaeb0a9587c4b987a5902c6ab3e91b5307daee5c7978eeb6d68b83c6b5e2"
+    },
+    {
+      "file": "references/workshop-research-acceptance.md",
+      "sha256": "26a2fdcae8631a0a66d41d159442525f950835b6057bd1475b4d131f97a10aba"
+    },
+    {
+      "file": "references/workshop-research-loop.md",
+      "sha256": "c480f229baf5d3d84b145649f9cf8a992a2bb7c4a44e2baf11ccedf530eb6786"
+    },
+    {
+      "file": "references/workshop-research-tasking.md",
+      "sha256": "f8b7fbb72b57ae088c411e510dd2cd371aac98d10903a0b4b6e2ce16caae4a51"
+    },
+    {
+      "file": "references/workshop-tasks.md",
+      "sha256": "a4e0bc238966ea7a119986f383f4f6ea99dd8d9de63bdc32571a35b740d8f96d"
+    },
+    {
+      "file": "references/workshop-three-source-opportunities.md",
+      "sha256": "e0200259e92644bf55ca2fe3f60b1eea4c7df512b1300f2643b8b6991ebc6ca3"
+    },
+    {
+      "file": "references/workshop-v3-outputs.md",
+      "sha256": "3d9855fccf3250c54317e7bb4060d3185e77e61be82c0494df5fb1d21d67fee2"
+    },
+    {
+      "file": "references/workshop-value-proposition.md",
+      "sha256": "1589247eade7243f430be161ed987ecbddf9eb9fdcf1873a5d1f5a141ac89c05"
+    },
+    {
+      "file": "references/workshop-verification.md",
+      "sha256": "01451f1565983eba85f26d3403b35f67c19cf501b5b5da29f52270dc68fd55f6"
+    },
+    {
+      "file": "references/workshop-voc-clustering.md",
+      "sha256": "d1c04203dde6a7eb424b2316a13964d2d63a6e91836dd5c1eef55f858f59fe02"
+    },
+    {
+      "file": "references/write-tasks.md",
+      "sha256": "a685c3a1c2b907e19cc7e94e42325012a82e09978e267219a0938a42fb9beace"
+    },
+    {
+      "file": "runtime-lock.json",
+      "sha256": "2605cbe8fd7be43b5969a4991f978dc0768dee5b4d65d18f7af15f75e9004a79"
+    },
+    {
+      "file": "scripts/course-assessment.mjs",
+      "sha256": "7ad2aebd30fbc244f4617c9559f076ff7df4196901a31465b5a70bfe5055bb55"
+    },
+    {
+      "file": "scripts/course-deliverables.mjs",
+      "sha256": "7200354296d2b605247ac0cd41927e55fd741f5dd29beb1387b92373f88df617"
+    },
+    {
+      "file": "scripts/describe-business-schema.mjs",
+      "sha256": "e96e8c3fc1a71f1edc39dfc250199aacfb1457aec851d29e6f3b2c35e918a279"
+    },
+    {
+      "file": "scripts/ksf-account.mjs",
+      "sha256": "9bfda45c53192d70fefb31b378851aeb19e075b6f5adcd8217ba4838cc133f7d"
+    },
+    {
+      "file": "scripts/ksf-identity-bridge.mjs",
+      "sha256": "6ba3f0cb6527bc4a0a6218a898472ac65aa3dd9f3f57b597d77efcee641a7540"
+    },
+    {
+      "file": "scripts/ksf-identity.mjs",
+      "sha256": "18f5f3e03e76d1db7df9b7d076ea58b913c69fe923591ecdc39b152309827cbc"
+    },
+    {
+      "file": "scripts/ksf-secure.mjs",
+      "sha256": "b05e9f9d702b55e1f77b710bd40e7125e9f9b5395f4c240d18e0510c984b50a3"
+    },
+    {
+      "file": "scripts/ksf-workshop.mjs",
+      "sha256": "7a04eb22d3429cdced23513717f36594f639539738994d45712a8bea738100a1"
+    },
+    {
+      "file": "scripts/ksf.mjs",
+      "sha256": "7ef128f7d022bfbc15c0ec813bfd87995c6297c6efe407a563c840f014aba477"
+    },
+    {
+      "file": "scripts/render-report-html.mjs",
+      "sha256": "246588294da6975d80d0f1b1e338bc30cf737421c43cea38cf33745eb52e40a9"
+    },
+    {
+      "file": "scripts/report-contract.mjs",
+      "sha256": "4c6e05ca3f6e65d57d55f743de39307181f8427626e355a5d2698905c17dd8c4"
+    },
+    {
+      "file": "scripts/report-statistics.mjs",
+      "sha256": "ede7e98ee941e4ca2ce867d53eb29fa289b9047070e9e6797d20d5d547d24325"
+    },
+    {
+      "file": "scripts/save-report.mjs",
+      "sha256": "022c1833f733ac321ce588ea1dd74e12a1609370f35fe3749c35bf8059a97d17"
+    },
+    {
+      "file": "FILES.sha256",
+      "sha256": "8219cdf870d0d9d969b044db6342bea1215e29b679539e95c26aac219049ed8a"
+    }
+  ],
+  "changedPublicFiles": [
+    {
+      "file": "SKILL.md",
+      "beforeSha256": "b798b417de70c0d9c15d1eefe72ca069179bb3d2686402399f3aa4e3830c103b",
+      "afterSha256": "f4c738a3b0381c6808c47150064bbd29fc018764cb83946eb85f6b75c8d70a11"
+    },
+    {
+      "file": "references/identity.md",
+      "beforeSha256": "1f7ee67333604603497494e4247d28987db0fab0b80913eae8d5e06246ba558d",
+      "afterSha256": "0f4c40ac569b4c53f16f2190b898f14cfa012a4ca9173260434a47ee5d1c0e05"
+    },
+    {
+      "file": "scripts/ksf-identity.mjs",
+      "beforeSha256": "ab6838afd140e4b84ef39a255fcbdd80ece9b0b7c245f65cd8ba81d892036513",
+      "afterSha256": "18f5f3e03e76d1db7df9b7d076ea58b913c69fe923591ecdc39b152309827cbc"
+    },
+    {
+      "file": "scripts/ksf-secure.mjs",
+      "beforeSha256": "25e42387ea9e3cbf5b60c431eaaf09bc381dcc04acbb82d0f0a7dd071f357fea",
+      "afterSha256": "b05e9f9d702b55e1f77b710bd40e7125e9f9b5395f4c240d18e0510c984b50a3"
+    },
+    {
+      "file": "FILES.sha256",
+      "beforeSha256": "9c3c8fc60af395d6ee808cc33bef26e8f76d9d9588b690655dcfe91ce6ade53e",
+      "afterSha256": "8219cdf870d0d9d969b044db6342bea1215e29b679539e95c26aac219049ed8a"
+    }
+  ],
+  "artifacts": [
+    {
+      "file": "docs/workshop-final-files-20261111/final-康师傅工作坊.skill",
+      "bytes": 376175,
+      "sha256": "710672e85694431b675e23fc3b283ff58e68970ef0061902303620e1c736ab52"
+    },
+    {
+      "file": "skills/ksf-workshop-runtime/SKILL.md",
+      "bytes": 41426,
+      "sha256": "f4c738a3b0381c6808c47150064bbd29fc018764cb83946eb85f6b75c8d70a11"
+    },
+    {
+      "file": "skills/ksf-workshop-runtime/scripts/ksf-identity.mjs",
+      "bytes": 21639,
+      "sha256": "18f5f3e03e76d1db7df9b7d076ea58b913c69fe923591ecdc39b152309827cbc"
+    },
+    {
+      "file": "skills/ksf-workshop-runtime/scripts/ksf-secure.mjs",
+      "bytes": 9673,
+      "sha256": "b05e9f9d702b55e1f77b710bd40e7125e9f9b5395f4c240d18e0510c984b50a3"
+    },
+    {
+      "file": "skills/ksf-workshop-runtime/FILES.sha256",
+      "bytes": 5514,
+      "sha256": "8219cdf870d0d9d969b044db6342bea1215e29b679539e95c26aac219049ed8a"
+    }
+  ],
+  "unchanged": {
+    "manual": {
+      "file": "docs/workshop-quality-r13-20261110/final-康师傅工作坊操作手册.html",
+      "bytes": 303679,
+      "sha256": "51d182e50b97143e196e60e62fcc289380abb013d2899239912876f0db18521b"
+    },
+    "prompts": {
+      "file": "docs/workshop-quality-r13-20261110/manual/workshop-dialogue-prompts.json",
+      "bytes": 19569,
+      "sha256": "a02b29765de4c238540c5c918440fcbdcf44a827a30794b90c5ba46d6f1e1ae0"
+    },
+    "vocVersion": "0.3.45",
+    "backendFunctions": true,
+    "backendSchema": true,
+    "boardUi": true,
+    "workshopAndLegacyEntries": true,
+    "accountHelper": true,
+    "runtimeLock": true
+  },
+  "tests": {
+    "workshop": {
+      "passed": 126,
+      "failed": 0,
+      "command": "npm run test:workshop"
+    },
+    "identityBindingAndCredentials": {
+      "passed": 27,
+      "failed": 0,
+      "command": "node --test server/test/account-binding.test.mjs server/test/account-binding-deploy.test.mjs test/workshop-identity.test.js test/workshop-credential-envelope.test.mjs"
+    },
+    "skillValidation": "passed",
+    "archiveByteValidation": "55 public files verified"
+  },
+  "verification": "docs/workshop-r15-contract-fix-20261112/verification.json",
+  "productionApiBindingEnabled": true,
+  "platformFunctionsRestartRequired": false,
+  "backendChanged": false,
+  "businessWrites": 0,
+  "newMembersCreated": 0,
+  "newReportsCreated": 0,
+  "organizationSynced": false,
+  "runtimeInstalled": false,
+  "runtimeLoadingVerified": false,
+  "organizationAccess": "existing local Git identity was denied HTTP403; deployment requires current authorized ops channel",
+  "runtimeAccess": "no authorized host connection available in this workspace",
+  "deploymentScope": "Only Skill r15-local.3 to r15-local.4; preserve VOC 0.3.45, manual, prompts, board and all private runtime files."
+}

+ 92 - 0
docs/workshop-r15-contract-fix-20261112/verification.json

@@ -0,0 +1,92 @@
+{
+  "at": "2026-11-12T06:21:50.603Z",
+  "readOnly": true,
+  "databaseWrites": 0,
+  "productionApiBindingEnabled": true,
+  "productionChecks": [
+    {
+      "auth": "anonymous",
+      "http": 200,
+      "requestId": "r15-contract-read-d53796c9-b55f-4eca-b547-8032073d4a33",
+      "responseRequestId": "r15-contract-read-d53796c9-b55f-4eca-b547-8032073d4a33",
+      "enabled": true
+    },
+    {
+      "auth": "anonymous",
+      "http": 200,
+      "requestId": "r15-contract-read-009c12e7-73c2-45d4-b374-70b04abe6a32",
+      "responseRequestId": "r15-contract-read-009c12e7-73c2-45d4-b374-70b04abe6a32",
+      "enabled": true
+    },
+    {
+      "auth": "admin",
+      "http": 200,
+      "requestId": "r15-contract-read-7c4ed9d4-16ba-49f6-b966-079198c218b1",
+      "responseRequestId": "r15-contract-read-7c4ed9d4-16ba-49f6-b966-079198c218b1",
+      "enabled": true
+    },
+    {
+      "auth": "admin",
+      "http": 200,
+      "requestId": "r15-contract-read-aa86896d-9a5e-4bcc-9796-579ad76fa648",
+      "responseRequestId": "r15-contract-read-aa86896d-9a5e-4bcc-9796-579ad76fa648",
+      "enabled": true
+    },
+    {
+      "auth": "service",
+      "http": 200,
+      "requestId": "r15-contract-read-ce605324-80b3-4dbf-9a0a-e45b308d86f4",
+      "responseRequestId": "r15-contract-read-ce605324-80b3-4dbf-9a0a-e45b308d86f4",
+      "enabled": true
+    },
+    {
+      "auth": "service",
+      "http": 200,
+      "requestId": "r15-contract-read-962f2501-ad75-46be-a190-134936e080e9",
+      "responseRequestId": "r15-contract-read-962f2501-ad75-46be-a190-134936e080e9",
+      "enabled": true
+    }
+  ],
+  "r15_3Reproduction": {
+    "rawEnabled": true,
+    "afterRedactionHasAccountBinding": false
+  },
+  "r15_4LocalCommand": {
+    "command": "workshop-contract",
+    "realServiceApi": true,
+    "enabled": true,
+    "contract": {
+      "schema": "ksf.workshop-account-binding.v1",
+      "enabled": true,
+      "requiredFor": [
+        "fmode"
+      ],
+      "function": "ksfWorkshopAccount",
+      "firstUse": "confirm-display-name-and-account",
+      "proof": "platform-session",
+      "canonicalMember": "platform-account",
+      "oneMemberPerAccount": true,
+      "unboundSubmission": "reject",
+      "historicalAttributionPreserved": true
+    },
+    "containerExecuted": false
+  },
+  "existingGuopengBinding": {
+    "persistedBindingAndReportMatch": true,
+    "memberKey": "platform-account:bbdeba81de5687b88b54ff70fa1cafdbcdbe12c4d6488e33e253c9ecc9bf721f",
+    "containerCommandBound": "verified-in-ops-receipt"
+  },
+  "localServiceIsolation": {
+    "sameServiceAsReportOwner": false,
+    "status": "unbound"
+  },
+  "memberCount": 27,
+  "groupMemberCount": 27,
+  "existingReportId": "JLF4v5MpyR",
+  "existingReportMemberKey": "platform-account:bbdeba81de5687b88b54ff70fa1cafdbcdbe12c4d6488e33e253c9ecc9bf721f",
+  "employeeAccountsProvisioned": false,
+  "employeeAccountsProvisionedIsBindingGate": false,
+  "platformFunctionRestartPerformed": false,
+  "backendChanged": false,
+  "newContainerReleaseInstalled": false
+}

+ 4 - 4
skills/ksf-workshop-runtime/FILES.sha256

@@ -1,7 +1,7 @@
-b798b417de70c0d9c15d1eefe72ca069179bb3d2686402399f3aa4e3830c103b  SKILL.md
+f4c738a3b0381c6808c47150064bbd29fc018764cb83946eb85f6b75c8d70a11  SKILL.md
 11863b16216f8746f24189444fc5ffd40512d313cfddd6fa99111b84ac3acfc2  references/business-data-dictionary.json
 11863b16216f8746f24189444fc5ffd40512d313cfddd6fa99111b84ac3acfc2  references/business-data-dictionary.json
 08859f32fa51399c638cb9cc0669e69f53a630ebdfa0ad965b1d360115b3a901  references/full-schema-and-intake.md
 08859f32fa51399c638cb9cc0669e69f53a630ebdfa0ad965b1d360115b3a901  references/full-schema-and-intake.md
-1f7ee67333604603497494e4247d28987db0fab0b80913eae8d5e06246ba558d  references/identity.md
+0f4c40ac569b4c53f16f2190b898f14cfa012a4ca9173260434a47ee5d1c0e05  references/identity.md
 a9af25da32e769443af4565ca400c9136745c9d30c2c190dedf978841bf977c1  references/research-library/data-contract.md
 a9af25da32e769443af4565ca400c9136745c9d30c2c190dedf978841bf977c1  references/research-library/data-contract.md
 78dedd84d8560ee3f0492769db81562841193fa40bef7028836745b0958ab6b8  references/research-library/full-schema-and-intake.md
 78dedd84d8560ee3f0492769db81562841193fa40bef7028836745b0958ab6b8  references/research-library/full-schema-and-intake.md
 a154e01d3f3efb47f643c27adf22fe963d507dc68a50f8747e8ffda8bb7180bb  references/research-library/operations.md
 a154e01d3f3efb47f643c27adf22fe963d507dc68a50f8747e8ffda8bb7180bb  references/research-library/operations.md
@@ -44,8 +44,8 @@ a685c3a1c2b907e19cc7e94e42325012a82e09978e267219a0938a42fb9beace  references/wri
 e96e8c3fc1a71f1edc39dfc250199aacfb1457aec851d29e6f3b2c35e918a279  scripts/describe-business-schema.mjs
 e96e8c3fc1a71f1edc39dfc250199aacfb1457aec851d29e6f3b2c35e918a279  scripts/describe-business-schema.mjs
 9bfda45c53192d70fefb31b378851aeb19e075b6f5adcd8217ba4838cc133f7d  scripts/ksf-account.mjs
 9bfda45c53192d70fefb31b378851aeb19e075b6f5adcd8217ba4838cc133f7d  scripts/ksf-account.mjs
 6ba3f0cb6527bc4a0a6218a898472ac65aa3dd9f3f57b597d77efcee641a7540  scripts/ksf-identity-bridge.mjs
 6ba3f0cb6527bc4a0a6218a898472ac65aa3dd9f3f57b597d77efcee641a7540  scripts/ksf-identity-bridge.mjs
-ab6838afd140e4b84ef39a255fcbdd80ece9b0b7c245f65cd8ba81d892036513  scripts/ksf-identity.mjs
-25e42387ea9e3cbf5b60c431eaaf09bc381dcc04acbb82d0f0a7dd071f357fea  scripts/ksf-secure.mjs
+18f5f3e03e76d1db7df9b7d076ea58b913c69fe923591ecdc39b152309827cbc  scripts/ksf-identity.mjs
+b05e9f9d702b55e1f77b710bd40e7125e9f9b5395f4c240d18e0510c984b50a3  scripts/ksf-secure.mjs
 7a04eb22d3429cdced23513717f36594f639539738994d45712a8bea738100a1  scripts/ksf-workshop.mjs
 7a04eb22d3429cdced23513717f36594f639539738994d45712a8bea738100a1  scripts/ksf-workshop.mjs
 7ef128f7d022bfbc15c0ec813bfd87995c6297c6efe407a563c840f014aba477  scripts/ksf.mjs
 7ef128f7d022bfbc15c0ec813bfd87995c6297c6efe407a563c840f014aba477  scripts/ksf.mjs
 246588294da6975d80d0f1b1e338bc30cf737421c43cea38cf33745eb52e40a9  scripts/render-report-html.mjs
 246588294da6975d80d0f1b1e338bc30cf737421c43cea38cf33745eb52e40a9  scripts/render-report-html.mjs

+ 2 - 2
skills/ksf-workshop-runtime/SKILL.md

@@ -2,7 +2,7 @@
 name: ksf-workshop-runtime
 name: ksf-workshop-runtime
 description: 康师傅面类研究与产品创新工作坊统一Skill。先用模型专业能力拆题与形成假设,结合已有数据取证,自查关键缺口并调度现有VOC补充外部资料;按课表分析需求、机会、可行性与产品概念,保存成果并回读看板。
 description: 康师傅面类研究与产品创新工作坊统一Skill。先用模型专业能力拆题与形成假设,结合已有数据取证,自查关键缺口并调度现有VOC补充外部资料;按课表分析需求、机会、可行性与产品概念,保存成果并回读看板。
 metadata:
 metadata:
-  version: r15-local.3
+  version: r15-local.4
 ---
 ---
 
 
 # 康师傅产品创新工作坊
 # 康师傅产品创新工作坊
@@ -173,7 +173,7 @@ node /opt/data/skills/ksf-workshop-runtime/scripts/ksf-secure.mjs <命令> --age
 
 
 ### 首次账号绑定与后续复用
 ### 首次账号绑定与后续复用
 
 
-首次调用工作坊且尚未绑定本人账号时,先进行一轮必要身份确认:询问希望使用的称呼和已开通的工作坊账号;已有信息直接请本人确认,不重复收集。按[首次账号绑定](references/identity.md#网站账号与称呼)核验本人登录、企业归属与注册成员编号,绑定成功并回读后再创建课堂会话和保存报告。此为成果归属规则,不收集其他个人资料。已有绑定直接复用,不因新课题、新会话、改称呼或重试新增看板成员。必要的产品目标、真实业务约束及方案确认仍按研究流程处理。
+首次调用工作坊且尚未绑定本人账号时,先进行一轮必要身份确认:询问希望使用的称呼和已开通的工作坊账号;已有信息直接请本人确认,不重复收集。按[首次账号绑定](references/identity.md#网站账号与称呼)通过受控接口查询注册账号和既有绑定,明确反馈找到、未找到或查询未完成,不只在后台处理。找到账号后核验本人登录、企业归属与注册成员编号;绑定成功并回读后,告知当前对话已关联该账号、后续相关成果都归该账号,再创建课堂会话和保存报告。此为成果归属规则,不收集其他个人资料。一个平台注册账号只对应一个看板成员;已有绑定直接复用,不因新课题、新会话、改称呼或重试新增成员。必要的产品目标、真实业务约束及方案确认仍按研究流程处理。
 
 
 称呼只作显示,归属以已核对的本人稳定账号/发送者键为准。读取已有绑定并沿用,不按姓名合并人员、重建档案或切换会话。网页账号与称呼的私有接续、当前接口支持范围及待同步处理见 [身份细则](references/identity.md#网站账号与称呼)。没有可信账号上下文时只记本人自报信息为待核对,独立研究继续,不能将成果写到猜测的员工名下。
 称呼只作显示,归属以已核对的本人稳定账号/发送者键为准。读取已有绑定并沿用,不按姓名合并人员、重建档案或切换会话。网页账号与称呼的私有接续、当前接口支持范围及待同步处理见 [身份细则](references/identity.md#网站账号与称呼)。没有可信账号上下文时只记本人自报信息为待核对,独立研究继续,不能将成果写到猜测的员工名下。
 
 

+ 2 - 2
skills/ksf-workshop-runtime/final-SKILL.md

@@ -2,7 +2,7 @@
 name: ksf-workshop-runtime
 name: ksf-workshop-runtime
 description: 康师傅面类研究与产品创新工作坊统一Skill。先用模型专业能力拆题与形成假设,结合已有数据取证,自查关键缺口并调度现有VOC补充外部资料;按课表分析需求、机会、可行性与产品概念,保存成果并回读看板。
 description: 康师傅面类研究与产品创新工作坊统一Skill。先用模型专业能力拆题与形成假设,结合已有数据取证,自查关键缺口并调度现有VOC补充外部资料;按课表分析需求、机会、可行性与产品概念,保存成果并回读看板。
 metadata:
 metadata:
-  version: r15-local.3
+  version: r15-local.4
 ---
 ---
 
 
 # 康师傅产品创新工作坊
 # 康师傅产品创新工作坊
@@ -173,7 +173,7 @@ node /opt/data/skills/ksf-workshop-runtime/scripts/ksf-secure.mjs <命令> --age
 
 
 ### 首次账号绑定与后续复用
 ### 首次账号绑定与后续复用
 
 
-首次调用工作坊且尚未绑定本人账号时,先进行一轮必要身份确认:询问希望使用的称呼和已开通的工作坊账号;已有信息直接请本人确认,不重复收集。按[首次账号绑定](references/identity.md#网站账号与称呼)核验本人登录、企业归属与注册成员编号,绑定成功并回读后再创建课堂会话和保存报告。此为成果归属规则,不收集其他个人资料。已有绑定直接复用,不因新课题、新会话、改称呼或重试新增看板成员。必要的产品目标、真实业务约束及方案确认仍按研究流程处理。
+首次调用工作坊且尚未绑定本人账号时,先进行一轮必要身份确认:询问希望使用的称呼和已开通的工作坊账号;已有信息直接请本人确认,不重复收集。按[首次账号绑定](references/identity.md#网站账号与称呼)通过受控接口查询注册账号和既有绑定,明确反馈找到、未找到或查询未完成,不只在后台处理。找到账号后核验本人登录、企业归属与注册成员编号;绑定成功并回读后,告知当前对话已关联该账号、后续相关成果都归该账号,再创建课堂会话和保存报告。此为成果归属规则,不收集其他个人资料。一个平台注册账号只对应一个看板成员;已有绑定直接复用,不因新课题、新会话、改称呼或重试新增成员。必要的产品目标、真实业务约束及方案确认仍按研究流程处理。
 
 
 称呼只作显示,归属以已核对的本人稳定账号/发送者键为准。读取已有绑定并沿用,不按姓名合并人员、重建档案或切换会话。网页账号与称呼的私有接续、当前接口支持范围及待同步处理见 [身份细则](references/identity.md#网站账号与称呼)。没有可信账号上下文时只记本人自报信息为待核对,独立研究继续,不能将成果写到猜测的员工名下。
 称呼只作显示,归属以已核对的本人稳定账号/发送者键为准。读取已有绑定并沿用,不按姓名合并人员、重建档案或切换会话。网页账号与称呼的私有接续、当前接口支持范围及待同步处理见 [身份细则](references/identity.md#网站账号与称呼)。没有可信账号上下文时只记本人自报信息为待核对,独立研究继续,不能将成果写到猜测的员工名下。
 
 

+ 9 - 5
skills/ksf-workshop-runtime/references/identity.md

@@ -17,13 +17,17 @@
 学员自报账号只用于查找;受控名册只能证明账号存在,不能证明说话者就是本人。优先用当前消息宿主提供并经服务端验证的登录绑定;没有适用可信桥接时,使用服务合同声明的 `ksfWorkshopAccount` 首次确认链路:
 学员自报账号只用于查找;受控名册只能证明账号存在,不能证明说话者就是本人。优先用当前消息宿主提供并经服务端验证的登录绑定;没有适用可信桥接时,使用服务合同声明的 `ksfWorkshopAccount` 首次确认链路:
 
 
 1. 复用当前员工的本地 profileKey;尚无档案时按已提供账号登记待核对档案,不创建业务会话或空报告。
 1. 复用当前员工的本地 profileKey;尚无档案时按已提供账号登记待核对档案,不创建业务会话或空报告。
-2. 先执行 `account-status`。已绑定则复用返回的 memberKey,当前自报账号冲突时停止受影响写入;未绑定才执行 `account-prepare`,传本人提供的账号和称呼。
-3. 把服务返回的 confirmationUrl 发给学员。学员在该页面登录本人平台账号并明确确认;页面直接与平台校验,密码与Token不进聊天或报告。仅回复“已绑定”不算成功。
-4. 再执行 `account-status`,必须读到 status=bound、正确账号/企业和同一 memberKey,才说绑定完成。随后用原 profileKey 执行 workshop-start;核其 accountBinding.status=bound、memberKey 与上述一致。
-5. 每次保存后精确回读报告和公开看板,核会话、报告都映射至同一 memberKey。首次账号确认本身不产出报告。
+2. 先执行 `account-status`。已绑定则复用返回的 memberKey并告知学员正在沿用哪个账号,当前自报账号冲突时停止受影响写入;未绑定才执行 `account-prepare`,传本人提供的账号和称呼。prepare在服务端查已核验的注册名册,status查询持久绑定,后续本人登录再核实时平台账号;不要把模型记忆或客户端姓名匹配当作数据库查询。
+3. prepare返回`awaiting_account_confirmation`时,明确告知已找到该账号、尚待本人确认,再发送服务返回的confirmationUrl;不要提前说已绑定。学员在该页面登录本人平台账号并明确确认;页面直接与平台校验,密码与Token不进聊天或报告。仅回复“已绑定”不算成功。prepare若直接返回bound,按已绑定分支核对后复用,无需另开确认链接。
+4. 再执行 `account-status`,必须读到 status=bound、正确账号/企业和同一 memberKey,才告知学员当前对话已绑定该账号、称呼用于显示、后续相关成果将归该账号。随后用原 profileKey 执行 workshop-start;核其 accountBinding.status=bound、memberKey 与上述一致。当前学员的私有接续状态同时记录已核验账号、profileKey、memberKey与sessionId;不把别人的对话绑定沿用到当前发送者。
+5. 报告、机会卡、方案、项目及相关课堂提交沿用该账号对应的会话和memberKey,不以称呼或每次提交另建成员。每次保存后精确回读报告和公开看板,核会话、报告都映射至同一memberKey。提交仍使用现有受控服务授权,成果作者归属为已绑定学员,不能把服务账号当作学员。首次账号确认本身不产出报告。
+
+查找与绑定结果必须反馈给学员:`ACCOUNT_NOT_REGISTERED`明确说明未在工作坊已开通账号中找到该账号,请核对输入或联系管理员,不自动注册或创建替代成员;`COMPANY_FORBIDDEN`或`ACCOUNT_BINDING_CONFLICT`说明企业或绑定不一致,不擅自改绑。接口不可用、超时或请求结果未知只能说明查询尚未完成,不能说账号不存在。学员纠正账号后重新核对;遇到已有绑定冲突不能通过新档案或换键绕过。
 
 
-工具命令沿既有受控凭据入口(仅在服务合同已声明支持时使用):
+`workshop.accountBinding`是公开能力契约,`workshop-start`回执顶层`accountBinding`是安全绑定摘要,读取结果应保留二者;记录`meta.attribution.accountBinding`则是私有归属快照,仍须脱敏。若原始接口与受控命令的契约字段不同,先核调用链的本地转换,不据此认定服务未部署或重载平台。
 
 
+工具命令沿既有受控凭据入口(仅在服务合同已声明支持时使用):
+
 `node <Skill根目录>/scripts/ksf-secure.mjs account-prepare --input <私有绝对路径JSON> --request-id <本次请求ID> --agent-profile <自身完整Agent档案键>`
 `node <Skill根目录>/scripts/ksf-secure.mjs account-prepare --input <私有绝对路径JSON> --request-id <本次请求ID> --agent-profile <自身完整Agent档案键>`
 
 
 prepare JSON为 `{"participant":{"profileKey":"当前员工完整档案键"},"username":"本人确认的账号","displayName":"本人提供的称呼"}`;status改用 `account-status`,JSON只保留participant。不要替学员调用confirm;服务身份不能冒充本人登录。链接过期可为同一profileKey重新prepare,不换员工键。
 prepare JSON为 `{"participant":{"profileKey":"当前员工完整档案键"},"username":"本人确认的账号","displayName":"本人提供的称呼"}`;status改用 `account-status`,JSON只保留participant。不要替学员调用confirm;服务身份不能冒充本人登录。链接过期可为同一profileKey重新prepare,不换员工键。

+ 27 - 1
skills/ksf-workshop-runtime/scripts/ksf-identity.mjs

@@ -68,7 +68,33 @@ export function adoptLegacyAgentProfile(file,{profileDir=PROFILE_DIR}={}){const
 export function bindOwnAgent(task,profile){if(!profile)fail('AGENT_PROFILE_REQUIRED');if(profile.role!=='workshop')fail('AGENT_ROLE_MISMATCH');const agent={key:profile.key,name:profile.name,identityBasis:profile.identityBasis,account:normalizeAgentAccount(profile.account),role:profile.role,runtimePlatform:profile.runtimePlatform??null,channel:profile.channel??null,collectedAt:profile.collectedAt??profile.registeredAt};if(task.agent!==undefined){exact(task.agent,['key','name','identityBasis','account','role','runtimePlatform','channel','collectedAt']);for(const key of ['key','name','identityBasis','role','runtimePlatform','channel','collectedAt'])if(task.agent[key]!==undefined&&task.agent[key]!==agent[key])fail('AGENT_IDENTITY_MISMATCH');if(task.agent.account!==undefined&&canonical(normalizeAgentAccount(task.agent.account))!==canonical(agent.account))fail('AGENT_IDENTITY_MISMATCH');}return{...task,agent};}
 export function bindOwnAgent(task,profile){if(!profile)fail('AGENT_PROFILE_REQUIRED');if(profile.role!=='workshop')fail('AGENT_ROLE_MISMATCH');const agent={key:profile.key,name:profile.name,identityBasis:profile.identityBasis,account:normalizeAgentAccount(profile.account),role:profile.role,runtimePlatform:profile.runtimePlatform??null,channel:profile.channel??null,collectedAt:profile.collectedAt??profile.registeredAt};if(task.agent!==undefined){exact(task.agent,['key','name','identityBasis','account','role','runtimePlatform','channel','collectedAt']);for(const key of ['key','name','identityBasis','role','runtimePlatform','channel','collectedAt'])if(task.agent[key]!==undefined&&task.agent[key]!==agent[key])fail('AGENT_IDENTITY_MISMATCH');if(task.agent.account!==undefined&&canonical(normalizeAgentAccount(task.agent.account))!==canonical(agent.account))fail('AGENT_IDENTITY_MISMATCH');}return{...task,agent};}
 export function bindRegisteredParticipant(input,profile){if(!profile)fail('PARTICIPANT_PROFILE_REQUIRED');if(!object(input)||Object.keys(input).some(k=>!['profileKey','name'].includes(k)))fail('INVALID_IDENTITY_FIELDS');if(input.profileKey!==profile.key||input.name&&input.name!==profile.name)fail('PARTICIPANT_PROFILE_CONFLICT');return{key:profile.key,name:profile.name,identityBasis:profile.identityBasis,...(profile.userId?{userId:profile.userId}:{}),account:normalizeParticipantAccount(profile.account)};}
 export function bindRegisteredParticipant(input,profile){if(!profile)fail('PARTICIPANT_PROFILE_REQUIRED');if(!object(input)||Object.keys(input).some(k=>!['profileKey','name'].includes(k)))fail('INVALID_IDENTITY_FIELDS');if(input.profileKey!==profile.key||input.name&&input.name!==profile.name)fail('PARTICIPANT_PROFILE_CONFLICT');return{key:profile.key,name:profile.name,identityBasis:profile.identityBasis,...(profile.userId?{userId:profile.userId}:{}),account:normalizeParticipantAccount(profile.account)};}
 export function assertOwnSession(row,profile){if(!profile)fail('AGENT_PROFILE_REQUIRED');if(profile.role!=='workshop')fail('AGENT_ROLE_MISMATCH');const a=row?.meta?.attribution;if(a?.agentKey!==profile.key||a?.agentName!==profile.name||a?.agentRuntimePlatform!==(profile.runtimePlatform??null)||a?.agentChannel!==(profile.channel??null))fail('AGENT_SESSION_MISMATCH');}
 export function assertOwnSession(row,profile){if(!profile)fail('AGENT_PROFILE_REQUIRED');if(profile.role!=='workshop')fail('AGENT_ROLE_MISMATCH');const a=row?.meta?.attribution;if(a?.agentKey!==profile.key||a?.agentName!==profile.name||a?.agentRuntimePlatform!==(profile.runtimePlatform??null)||a?.agentChannel!==(profile.channel??null))fail('AGENT_SESSION_MISMATCH');}
-export function redactIdentity(value){if(Array.isArray(value))return value.map(redactIdentity);if(!object(value))return value;const hidden=new Set(['accountBinding','accountProfileKey','platformUserId','participantAccount','agentAccount','conversationKey','ownerId','userRef','accountId','tenantId','runtimeAgentId','wecomAppAgentId','employeeNumber','scopeId','botId','senderId']);return Object.fromEntries(Object.entries(value).filter(([k,v])=>!hidden.has(k)&&v!==undefined).map(([k,v])=>[k,k==='producer'&&object(v)?redactIdentity({...v,...(v.agent?{agent:{key:v.agent.key,name:v.agent.name,identityBasis:v.agent.identityBasis}}:{})}):redactIdentity(v)]));}
+export function redactIdentity(value){
+ const hidden=new Set(['accountProfileKey','platformUserId','participantAccount','agentAccount','conversationKey','ownerId','userRef','accountId','tenantId','runtimeAgentId','wecomAppAgentId','employeeNumber','scopeId','botId','senderId']);
+ const contractFields=['schema','enabled','requiredFor','function','firstUse','proof','canonicalMember','oneMemberPerAccount','unboundSubmission','historicalAttributionPreserved'];
+ const summaryFields=['schema','status','memberKey','username','displayName','companyId','verifiedAt','source'];
+ function visit(current,location=[]){
+  if(Array.isArray(current))return current.map(item=>visit(item,location));
+  if(!object(current))return current;
+  const result={};
+  for(const[k,original]of Object.entries(current)){
+   if(hidden.has(k)||original===undefined)continue;
+   let v=original;
+   if(k==='accountBinding'){
+    // Capability descriptors and start receipts are public API data. The same
+    // key inside a stored attribution is a private snapshot and stays hidden.
+    if(v?.schema!=='ksf.workshop-account-binding.v1')continue;
+    const contract=location.length===1&&location[0]==='workshop';
+    const summary=location.length===0&&v.status==='bound'&&/^platform-account:[a-f0-9]{64}$/.test(v.memberKey||'');
+    if(!contract&&!summary)continue;
+    v=Object.fromEntries((contract?contractFields:summaryFields).filter(field=>v[field]!==undefined).map(field=>[field,v[field]]));
+   }
+   if(k==='producer'&&object(v))v={...v,...(v.agent?{agent:{key:v.agent.key,name:v.agent.name,identityBasis:v.agent.identityBasis}}:{})};
+   result[k]=visit(v,[...location,k]);
+  }
+  return result;
+ }
+ return visit(value);
+}
 export function executeIdentity(argv,options={}){
 export function executeIdentity(argv,options={}){
  const[command,...args]=argv;let result;
  const[command,...args]=argv;let result;
  if(command==='status'&&args.length===0)result={...listIdentityProfiles(options)};
  if(command==='status'&&args.length===0)result={...listIdentityProfiles(options)};

+ 1 - 1
skills/ksf-workshop-runtime/scripts/ksf-secure.mjs

@@ -12,7 +12,7 @@ const LOCK_HASH = '2605cbe8fd7be43b5969a4991f978dc0768dee5b4d65d18f7af15f75e9004
 const WORKSHOP_ENTRY_HASH = '7a04eb22d3429cdced23513717f36594f639539738994d45712a8bea738100a1';
 const WORKSHOP_ENTRY_HASH = '7a04eb22d3429cdced23513717f36594f639539738994d45712a8bea738100a1';
 const ACCOUNT_ENTRY_HASH = '9bfda45c53192d70fefb31b378851aeb19e075b6f5adcd8217ba4838cc133f7d';
 const ACCOUNT_ENTRY_HASH = '9bfda45c53192d70fefb31b378851aeb19e075b6f5adcd8217ba4838cc133f7d';
 const ACCOUNT_COMMANDS = ['account-prepare','account-status'];
 const ACCOUNT_COMMANDS = ['account-prepare','account-status'];
-const IDENTITY_MODULE_HASH = 'ab6838afd140e4b84ef39a255fcbdd80ece9b0b7c245f65cd8ba81d892036513';
+const IDENTITY_MODULE_HASH = '18f5f3e03e76d1db7df9b7d076ea58b913c69fe923591ecdc39b152309827cbc';
 const WORKSHOP_COMMANDS = [...ACCOUNT_COMMANDS,'workshop-start','workshop-save','project-create','project-progress','concept-save','project-status','workshop-import','workshop-dedup','workshop-search','workshop-read','workshop-contract','workshop-schema','employee-read','employee-name'];
 const WORKSHOP_COMMANDS = [...ACCOUNT_COMMANDS,'workshop-start','workshop-save','project-create','project-progress','concept-save','project-status','workshop-import','workshop-dedup','workshop-search','workshop-read','workshop-contract','workshop-schema','employee-read','employee-name'];
 const fail = code => { throw Object.assign(new Error(code), { code }); };
 const fail = code => { throw Object.assign(new Error(code), { code }); };
 const requireThat = (value, code) => { if (!value) fail(code); };
 const requireThat = (value, code) => { if (!value) fail(code); };

+ 14 - 0
test/workshop-account.test.js

@@ -4,6 +4,7 @@ import path from 'node:path';
 import {runAccountBinding} from '../skills/ksf-workshop-runtime/scripts/ksf-account.mjs';
 import {runAccountBinding} from '../skills/ksf-workshop-runtime/scripts/ksf-account.mjs';
 import {parseArgs} from '../skills/ksf-workshop-runtime/scripts/ksf-secure.mjs';
 import {parseArgs} from '../skills/ksf-workshop-runtime/scripts/ksf-secure.mjs';
 import {redactIdentity} from '../skills/ksf-workshop-runtime/scripts/ksf-identity.mjs';
 import {redactIdentity} from '../skills/ksf-workshop-runtime/scripts/ksf-identity.mjs';
+import {runWorkshop} from '../skills/ksf-workshop-runtime/scripts/ksf-workshop.mjs';
 const profile={key:'participant-registration:1ab680ff-4ad4-4377-9333-3b2f23e26bb7',account:{platform:'fmode',accountName:'guopeng',accountId:null}};
 const profile={key:'participant-registration:1ab680ff-4ad4-4377-9333-3b2f23e26bb7',account:{platform:'fmode',accountName:'guopeng',accountId:null}};
 const task={participant:{profileKey:profile.key},username:'guopeng',displayName:'果鹏'};
 const task={participant:{profileKey:profile.key},username:'guopeng',displayName:'果鹏'};
 const opts={requestId:'first-link',agentProfile:{role:'workshop'},participantProfile:profile};
 const opts={requestId:'first-link',agentProfile:{role:'workshop'},participantProfile:profile};
@@ -27,3 +28,16 @@ test('报告回读移除新增私有绑定快照和平台编号,只保留公
  const result=redactIdentity({memberKey:'public-member',meta:{attribution:{participantKey:'old-participant',accountBinding:{platformUserId:'private-user'},accountProfileKey:'private-profile',platformUserId:'private-user'}}});
  const result=redactIdentity({memberKey:'public-member',meta:{attribution:{participantKey:'old-participant',accountBinding:{platformUserId:'private-user'},accountProfileKey:'private-profile',platformUserId:'private-user'}}});
  assert.deepEqual(result,{memberKey:'public-member',meta:{attribution:{participantKey:'old-participant'}}});
  assert.deepEqual(result,{memberKey:'public-member',meta:{attribution:{participantKey:'old-participant'}}});
 });
 });
+const bindingContract={schema:'ksf.workshop-account-binding.v1',enabled:true,requiredFor:['fmode'],function:'ksfWorkshopAccount',firstUse:'confirm-display-name-and-account',proof:'platform-session',canonicalMember:'platform-account',oneMemberPerAccount:true,unboundSubmission:'reject',historicalAttributionPreserved:true};
+test('真实workshop-contract路径保留公开账号绑定契约,不把正常脱敏当成服务端未部署',async()=>{
+ const contract={workshop:{version:'ksf.workshop.v1',accountBinding:bindingContract}};
+ const result=await runWorkshop('workshop-contract',{}, {requestId:'contract-regression',call:async(name)=>{assert.equal(name,'ksfGetIngestContract');return structuredClone(contract);}});
+ assert.deepEqual(result.workshop.accountBinding,bindingContract);
+});
+test('会话创建回执保留安全绑定摘要,私有归属快照即使伪装成公开契约仍不透出',()=>{
+ const summary={schema:'ksf.workshop-account-binding.v1',status:'bound',memberKey:'platform-account:'+'a'.repeat(64),username:'guopeng',displayName:'果鹏',companyId:'FKieRbIoGt',verifiedAt:'2026-11-12T06:00:00.000Z',source:'platform_session'};
+ const input={sessionId:'session-one',accountBinding:{...summary,platformUserId:'private-user'},record:{meta:{attribution:{accountBinding:{...bindingContract,platformUserId:'private-user'},accountProfileKey:'private-profile'}}}};
+ const result=redactIdentity(input);
+ assert.deepEqual(result.accountBinding,summary);assert.equal(result.record.meta.attribution.accountBinding,undefined);
+ assert.ok(!JSON.stringify(result).includes('private-user'));assert.ok(!JSON.stringify(result).includes('private-profile'));
+});