feat: 增加人机共管场景决策树 (#8)

Co-authored-by: yige <yige@yigedeMacBook-Neo.local>
This commit is contained in:
2026-08-30 14:01:19 -04:00
committed by GitHub
parent af338dc13b
commit 3261135305
10 changed files with 1044 additions and 26 deletions

View File

@@ -9,11 +9,13 @@ const html = readFileSync(join(root, 'source', 'index.html'), 'utf8')
const css = readFileSync(join(root, 'source', 'report.css'), 'utf8')
const javascript = readFileSync(join(root, 'source', 'report.js'), 'utf8')
const builder = readFileSync(join(root, 'scripts', 'build-report-web.mjs'), 'utf8')
const validator = readFileSync(join(root, 'scripts', 'validate-report-web.mjs'), 'utf8')
const ocrValidator = readFileSync(join(root, 'scripts', 'validate-screenshot-privacy-ocr.mjs'), 'utf8')
const deploymentValidator = readFileSync(join(root, 'scripts', 'validate-deployed-report.mjs'), 'utf8')
const attestationSchema = JSON.parse(
readFileSync(join(root, 'public-release-attestation.schema.json'), 'utf8')
)
const decisionTreeSchema = JSON.parse(readFileSync(join(root, 'decision-tree.schema.json'), 'utf8'))
test('图片查看器暴露完整的可访问缩放控制', () => {
for (const id of [
@@ -54,6 +56,55 @@ test('响应式样式约束全屏查看器且允许平移', () => {
assert.match(css, /height:\s*100dvh/)
})
test('场景决策树由证据数据驱动并支持完整分支、实际路径和 SVG 导出', () => {
assert.match(builder, /buildDecisionTree/)
assert.match(builder, /solver\.human-agent-decision-tree\/v1/)
assert.match(builder, /scenarioPackSha256/)
assert.match(javascript, /renderDecisionTree/)
assert.match(javascript, /decisionTreePath/)
assert.match(javascript, /data-tree-mode/)
assert.match(javascript, /data-tree-export/)
assert.match(javascript, /downloadDecisionTreeSvg/)
assert.match(css, /\.tree-flow/)
assert.match(css, /\.tree-alternatives/)
assert.match(css, /\.decision-tree\.path-only/)
assert.match(builder, /workflowKind === 'optimization'/)
assert.match(builder, /workflowKind === 'validation'/)
assert.match(builder, /OptimizationEvidenceLedger/)
assert.match(builder, /cannot hide an observed OptimizationCompile step/)
assert.match(builder, /workflowKind !== 'optimization' && compile/)
assert.match(builder, /solveSummary\.status/)
assert.match(builder, /validation\.verdict/)
assert.doesNotMatch(builder, /const resultStatus = pack\.oracle/)
assert.match(builder, /exactly one selected outgoing edge/)
assert.match(validator, /validateDecisionTreeSchema\(tree\)/)
assert.match(validator, /\['optimization', 'validation', 'recovery'\]\.includes/)
assert.match(validator, /source\.data\.status !== 'passed'/)
})
test('决策树 Schema 自描述人类、Agent、校核和证据绑定边界', () => {
assert.equal(decisionTreeSchema.$schema, 'http://json-schema.org/draft-07/schema#')
assert.match(decisionTreeSchema.description, /humans confirm/)
assert.deepEqual(decisionTreeSchema.properties.nodes.items.properties.owner.enum, [
'human',
'agent',
'shared',
'validator',
'platform',
])
assert.match(decisionTreeSchema.properties.evidenceBindings.description, /Immutable bindings/)
for (const field of [
'sourceSessionSha256',
'sourceToolInvocationsSha256',
'resultPayloadSha256',
'validationReportSha256',
]) {
assert.ok(decisionTreeSchema.properties.evidenceBindings.required.includes(field))
assert.ok(decisionTreeSchema.properties.evidenceBindings.properties[field].description)
}
assert.match(decisionTreeSchema.properties.observed.description, /oracle expectations never substitute/i)
})
test('构建器从 Agent 仓库读取代码、从显式目录读取证据', () => {
assert.match(builder, /SOLVER_REPORT_INPUT_ROOT/)
assert.match(builder, /SOLVER_REPORT_OUTPUT_ROOT/)