Skip to content

Commit df34b2a

Browse files
committed
fix: 对齐 MCP 链接能力的共享状态契约
1 parent 609dcf2 commit df34b2a

5 files changed

Lines changed: 43 additions & 12 deletions

File tree

‎changelogs/releases/v1.20.2.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- 修复卸载配置恢复依赖当前包配置、残留重试和 generation 清理扫描重复问题;项目历史与用户文件遵守各自保留边界。
1616
- 消除卸载中逐阶段重写整份事务日志的重复开销,保留写前恢复资料、最终持久化及旧版本崩溃恢复能力。
1717
- 记忆、报告和任务产物使用对应模板或明确的模板扩展,记录实际生成来源;避免同一产物槽重复生成。
18+
- 修复 MCP 链接工具公开状态与底层校验器不一致的问题;共享同一状态词表,未核实点击能力时保留可移植链接及真实证据状态。
1819
- 模板结构检查与用户意图满足度分别留证。历史产物对比新版模板得到诊断结果,不回填虚假的历史生成依据,也不批量改写历史报告。
1920
- 检查优化任务目录,记录有界扫描未覆盖的范围;包含流程简称的正文不能让整个任务跳过检查。
2021
- 实际隔离 Codex CLI 探针核对工具调用、上下文重绑和业务文件;协议探针、自然语言业务结果、模型自述与外部宿主拒绝分别记录。

‎hooks/_runtime/evidence/codex-skill-route-pass.v1.json‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,24 @@
55
"hostVariant": "codex-cli/exec-user-global-local-stdio",
66
"testedVersion": "codex-cli 0.153.4",
77
"protocol": "MCP 2024-11-05",
8-
"runtimeContractDigest": "817bcbf6b7725c0aaa833246a58c67c9b87b2450256f566ac23a2d1f2d2e77be",
8+
"runtimeContractDigest": "8c2ad999d19e8e3510e7d65f01e2dc42eea2eb388a30a3189fc905191475824c",
99
"hostAdapterDigest": "1095efd90a80d223c5990a70a8503f5cbbe818e4d2f5253b944bce92536873a3",
10-
"sourceEvidenceDigest": "2370b83d264e524303aef870da1f92c8e35cdfccc16c111a7000554e379af59e",
10+
"sourceEvidenceDigest": "0896badef267d5cb9189ad179191864a10a85ce424d556a08b01ddf52579280c",
1111
"sourceProbe": {
1212
"schemaVersion": "SkillRouteS15EvidenceV1",
13-
"probeRunId": "s15-codex-probe-6d08427b-174f-42fc-87d5-b4d05e19702e",
13+
"probeRunId": "s15-codex-probe-ef147927-de37-42a9-8ccc-53f1489f7814",
1414
"authorizationSource": "isolated-probe-authority",
1515
"contextSource": "host-hooks",
1616
"observationMode": "hook-post-history",
1717
"receiptStatus": "relevant-complete",
18-
"completedAt": "2026-09-09T02:16:04.857Z"
18+
"completedAt": "2026-09-09T03:01:11.039Z"
1919
},
2020
"runtimeBinding": {
2121
"source": "isolated-source-candidate",
22-
"expectedDigest": "817bcbf6b7725c0aaa833246a58c67c9b87b2450256f566ac23a2d1f2d2e77be",
23-
"generationDigest": "817bcbf6b7725c0aaa833246a58c67c9b87b2450256f566ac23a2d1f2d2e77be",
24-
"modeReceiptDigest": "817bcbf6b7725c0aaa833246a58c67c9b87b2450256f566ac23a2d1f2d2e77be",
25-
"routeEnvelopeDigest": "817bcbf6b7725c0aaa833246a58c67c9b87b2450256f566ac23a2d1f2d2e77be"
22+
"expectedDigest": "8c2ad999d19e8e3510e7d65f01e2dc42eea2eb388a30a3189fc905191475824c",
23+
"generationDigest": "8c2ad999d19e8e3510e7d65f01e2dc42eea2eb388a30a3189fc905191475824c",
24+
"modeReceiptDigest": "8c2ad999d19e8e3510e7d65f01e2dc42eea2eb388a30a3189fc905191475824c",
25+
"routeEnvelopeDigest": "8c2ad999d19e8e3510e7d65f01e2dc42eea2eb388a30a3189fc905191475824c"
2626
},
2727
"probe": {
2828
"schemaVersion": "SkillRouteProbeSummaryV1",

‎hooks/_runtime/host-skill-route-capabilities.v1.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
"status": "PASS",
1414
"testedVersion": "codex-cli 0.153.4",
1515
"protocol": "MCP 2024-11-05",
16-
"runtimeContractDigest": "817bcbf6b7725c0aaa833246a58c67c9b87b2450256f566ac23a2d1f2d2e77be",
16+
"runtimeContractDigest": "8c2ad999d19e8e3510e7d65f01e2dc42eea2eb388a30a3189fc905191475824c",
1717
"hostAdapterDigest": "1095efd90a80d223c5990a70a8503f5cbbe818e4d2f5253b944bce92536873a3",
1818
"evidenceRef": "hooks/_runtime/evidence/codex-skill-route-pass.v1.json",
19-
"evidenceDigest": "13ef8b58b0335d32a957e8778fcaf2e8dcdcbd188a3e0a231effa5184808b7e0",
19+
"evidenceDigest": "1e798a5d4f0d5b5a2eeed3e15a76c7503f613233ac44ffe8da0be475b4dae324",
2020
"entrySurface": "codex exec --ephemeral",
2121
"bootstrapDelivery": "stable user-global Hook launcher UserPromptSubmit or profile_context_plan fallback",
2222
"defaultEligible": true

‎mcp/memory-server.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ const {
150150
renderTaskContinuityViewHuman
151151
} = require('../hooks/_runtime/task-continuity-view-v1.cjs')
152152
const { normalizeLanguageTag } = require('../hooks/_runtime/language-context.cjs')
153-
const { createLinkCapabilityDecision } = require('../hooks/_runtime/visible-output-contract.cjs')
153+
const { createLinkCapabilityDecision, EVIDENCE_STATES } = require('../hooks/_runtime/visible-output-contract.cjs')
154154
const {
155155
createWorkspaceSessionRouteIndex,
156156
digestSessionRef
@@ -324,7 +324,7 @@ const LINK_CAPABILITY_DECISION_SCHEMA = Object.freeze({
324324
properties: {
325325
schemaVersion: { const: 'LinkCapabilityDecisionV1' },
326326
surface: { type: 'string', minLength: 1 },
327-
evidenceState: { type: 'string', enum: ['verified', 'inferred', 'failed'] },
327+
evidenceState: { type: 'string', enum: [...EVIDENCE_STATES] },
328328
mode: { type: 'string', enum: ['clickable', 'portable', 'plain', 'failed'] },
329329
workspaceRoot: { anyOf: [{ type: 'string' }, { type: 'null' }] },
330330
targetRelation: { type: 'string', enum: ['workspace', 'external', 'ambiguous'] },

‎scripts/test-mcp-servers.js‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6621,6 +6621,14 @@ function testMemoryArtifactLinkProjectionAndWriterIntegration() {
66216621
targetPath: 'reports/Report One.md',
66226622
purpose: 'dedupe probe'
66236623
}
6624+
const unverifiedCapability = createLinkCapabilityDecision({
6625+
surface: 'unverified-memory-mcp-test',
6626+
evidenceState: 'unverified',
6627+
supportsMarkdown: true,
6628+
workspaceRoot: activeRoot,
6629+
targetRelation: 'workspace'
6630+
})
6631+
assert.strictEqual(unverifiedCapability.validation.valid, true)
66246632
const projected = runServer('mcp/memory-server.js', [
66256633
rpcRequest(1, 'tools/list'),
66266634
rpcRequest(2, 'tools/call', {
@@ -6631,12 +6639,34 @@ function testMemoryArtifactLinkProjectionAndWriterIntegration() {
66316639
artifacts: [reportArtifact, duplicateArtifact],
66326640
linkCapability: capability
66336641
}
6642+
}),
6643+
rpcRequest(20, 'tools/call', {
6644+
name: 'memory_artifact_link_project',
6645+
arguments: {
6646+
documentPath: dailyDocument,
6647+
artifacts: [reportArtifact],
6648+
linkCapability: unverifiedCapability
6649+
}
66346650
})
66356651
], projectRoot)
66366652
const listedTools = resultById(projected, 1).tools
66376653
const projectionSchema = findToolSchema(listedTools, 'memory_artifact_link_project')
66386654
assert.deepStrictEqual(projectionSchema.required, ['documentPath', 'artifacts', 'linkCapability'])
66396655
assert.deepStrictEqual(projectionSchema.properties.operation.enum, ['project', 'validate-existing'])
6656+
const declaredEvidenceStates = projectionSchema.properties.linkCapability.properties.evidenceState.enum
6657+
assert(declaredEvidenceStates.includes(unverifiedCapability.evidenceState), 'tools/list must accept the producer unverified fallback')
6658+
for (const evidenceState of declaredEvidenceStates) {
6659+
const decision = createLinkCapabilityDecision({
6660+
surface: 'declared-memory-mcp-state', evidenceState, supportsMarkdown: true,
6661+
workspaceRoot: activeRoot, targetRelation: 'workspace', evidenceRefs: ['test:canonical-containment']
6662+
})
6663+
assert.strictEqual(decision.validation.valid, true, `tools/list declares an unsupported state: ${evidenceState}`)
6664+
}
6665+
const portableProjection = toolJson(resultById(projected, 20))
6666+
assert.strictEqual(portableProjection.capability.evidenceState, 'unverified')
6667+
assert.strictEqual(portableProjection.capability.mode, 'portable')
6668+
assert.strictEqual(portableProjection.capability.absolutePathFallback, false)
6669+
assert.strictEqual(portableProjection.links[0].markdown, '[Report One](<../../../../reports/Report One.md>)')
66406670
const projection = toolJson(resultById(projected, 2))
66416671
assert.strictEqual(projection.schemaVersion, 'ArtifactLinkProjectionSetV1')
66426672
assert.strictEqual(projection.dedupe.inputCount, 2)

0 commit comments

Comments
 (0)