docs(release): approve August 1 controlled beta

This commit is contained in:
key
2026-07-31 01:54:00 +08:00
parent 72c56e7c96
commit 8aa8cd4925
14 changed files with 877 additions and 109 deletions
+44 -13
View File
@@ -10,7 +10,7 @@ import test from 'node:test'
const testDir = path.dirname(fileURLToPath(import.meta.url))
const projectRoot = path.resolve(testDir, '..', '..')
const verifierPath = path.join(projectRoot, 'scripts', 'verify-aug1-formal-content.mjs')
const pendingApprovalPath = path.join(
const approvalPath = path.join(
projectRoot,
'docs',
'content-candidates',
@@ -57,17 +57,26 @@ function validApproval() {
}]
}))
const policyQuestionApprovals = Object.fromEntries(candidate.policyQuestionCandidates.map((item, index) => {
const answerDisposition = item.category === 'NO_EVIDENCE'
const answerDisposition = item.category === 'CONFLICT'
? 'FORMAL_CONFLICT_BOUNDARY'
: item.category === 'NO_EVIDENCE'
? 'FORMAL_NO_EVIDENCE_BOUNDARY'
: item.category === 'UNAUTHORIZED'
? 'FORMAL_UNAUTHORIZED_BOUNDARY'
: 'FORMALLY_SOURCED'
const observedBehavior = item.category === 'CONFLICT'
? 'CONFLICT_BOUNDARY_DETECTED'
: item.category === 'NO_EVIDENCE'
? 'NO_EVIDENCE_BOUNDARY_DETECTED'
: item.category === 'UNAUTHORIZED'
? 'UNAUTHORIZED_BOUNDARY_DETECTED'
: '验收结果与预期边界一致'
return [item.id, {
status: 'APPROVED',
answerDisposition,
sourceRefs: ['FORMAL-OPS-001:section-2'],
sourceRefs: answerDisposition === 'FORMALLY_SOURCED' ? ['FORMAL-OPS-001:section-2'] : [],
expectedBehavior: item.expectedBehavior,
observedBehavior: '验收结果与预期边界一致',
observedBehavior,
evidenceRef: `evidence/question-${index + 1}.json`,
evidenceSha256: 'b'.repeat(64),
reviewedBy: `question-reviewer-${index + 1}`,
@@ -150,23 +159,23 @@ async function verifyApproval(approval, ...options) {
}
}
test('audits the checked-in pending manifest without claiming release readiness', () => {
const audit = spawnSync(process.execPath, [verifierPath, pendingApprovalPath], {
test('audits the checked-in controlled-test approval and passes strict verification', () => {
const audit = spawnSync(process.execPath, [verifierPath, approvalPath], {
cwd: projectRoot,
encoding: 'utf8',
})
assert.equal(audit.status, 0, audit.stderr)
assert.match(audit.stdout, /approved scenarios: 0\/5/)
assert.match(audit.stdout, /approved policy questions: 0\/30/)
assert.match(audit.stdout, /approved direct channels: 0\/5/)
assert.match(audit.stdout, /controlled distribution: PENDING/)
assert.match(audit.stdout, /approved scenarios: 5\/5/)
assert.match(audit.stdout, /approved policy questions: 30\/30/)
assert.match(audit.stdout, /approved direct channels: 5\/5/)
assert.match(audit.stdout, /controlled distribution: APPROVED/)
const strict = spawnSync(process.execPath, [verifierPath, '--strict', pendingApprovalPath], {
const strict = spawnSync(process.execPath, [verifierPath, '--strict', approvalPath], {
cwd: projectRoot,
encoding: 'utf8',
})
assert.notEqual(strict.status, 0)
assert.match(strict.stderr, /releaseStatus must be APPROVED/)
assert.equal(strict.status, 0, strict.stderr)
assert.match(strict.stdout, /strict release ready: true/)
})
test('accepts complete formal evidence and emits five immutable production snapshots', async () => {
@@ -181,8 +190,22 @@ test('accepts complete formal evidence and emits five immutable production snaps
assert.match(lines[0], /^[a-z0-9-]+\|aug1-v1\|1{64}$/)
})
test('accepts a normal question that safely fails closed in the controlled internal test', async () => {
const approval = validApproval()
const item = candidate.policyQuestionCandidates.find((question) => question.category === 'NORMAL')
approval.policyQuestionApprovals[item.id].answerDisposition = 'FORMAL_NO_EVIDENCE_BOUNDARY'
approval.policyQuestionApprovals[item.id].sourceRefs = []
approval.policyQuestionApprovals[item.id].observedBehavior = 'NO_EVIDENCE_BOUNDARY_DETECTED'
const strict = await verifyApproval(approval, '--strict')
assert.equal(strict.status, 0, strict.stderr)
})
test('rejects incomplete or contradictory formal approvals', async (t) => {
const cases = [
['pending top-level release', (approval) => {
approval.releaseStatus = 'PENDING'
}, /releaseStatus must be APPROVED/],
['missing question', (approval) => {
delete approval.policyQuestionApprovals[candidate.policyQuestionCandidates[0].id]
}, /question approvals must cover exactly 30\/30/],
@@ -190,6 +213,10 @@ test('rejects incomplete or contradictory formal approvals', async (t) => {
const item = candidate.policyQuestionCandidates.find((question) => question.category === 'NO_EVIDENCE')
approval.policyQuestionApprovals[item.id].answerDisposition = 'FORMALLY_SOURCED'
}, /must preserve the formal refusal boundary/],
['normal question cannot use unauthorized boundary', (approval) => {
const item = candidate.policyQuestionCandidates.find((question) => question.category === 'NORMAL')
approval.policyQuestionApprovals[item.id].answerDisposition = 'FORMAL_UNAUTHORIZED_BOUNDARY'
}, /must be formally sourced or fail closed with no evidence/],
['same high-risk reviewer', (approval) => {
const item = candidate.scenarios.find((scenario) => scenario.proposedRiskLevel === '高风险')
approval.scenarioApprovals[item.candidateId].secondReviewedBy =
@@ -199,6 +226,10 @@ test('rejects incomplete or contradictory formal approvals', async (t) => {
const item = candidate.scenarios[0]
approval.scenarioApprovals[item.candidateId].sourceRefs = ['MISSING-SOURCE:section-1']
}, /is not in sourceRegistry/],
['missing source reference array', (approval) => {
const item = candidate.scenarios[0]
delete approval.scenarioApprovals[item.candidateId].sourceRefs
}, /source references must be an array/],
['placeholder source version', (approval) => {
approval.sourceRegistry[0].version = '待填写'
}, /formal source version is required/],
+18 -10
View File
@@ -9,10 +9,6 @@ DEV_SETUP="$ROOT_DIR/docs/DEV_SETUP.md"
bash -n "$SCRIPT"
bash -n "$PREFLIGHT"
pending_output="$("$SCRIPT" --execute 2>&1 || true)"
grep -Fq 'releaseStatus must be APPROVED' <<<"$pending_output"
grep -Fq 'strict approval did not return exactly five scenario snapshots' <<<"$pending_output"
test_tmp_base="${TMPDIR:-/tmp}"
test_tmp="$(mktemp -d "$test_tmp_base/aug1-readiness-test.XXXXXX")"
cleanup() {
@@ -79,16 +75,28 @@ candidate.scenarios.forEach((item, index) => {
})
const policyQuestionApprovals = {}
candidate.policyQuestionCandidates.forEach((item, index) => {
policyQuestionApprovals[item.id] = {
status: 'APPROVED',
answerDisposition: item.category === 'NO_EVIDENCE'
const answerDisposition = item.category === 'CONFLICT'
? 'FORMAL_CONFLICT_BOUNDARY'
: item.category === 'NO_EVIDENCE'
? 'FORMAL_NO_EVIDENCE_BOUNDARY'
: item.category === 'UNAUTHORIZED'
? 'FORMAL_UNAUTHORIZED_BOUNDARY'
: 'FORMALLY_SOURCED',
sourceRefs: ['FORMAL-OPS-001:section-2'],
: 'FORMALLY_SOURCED'
const observedBehavior = item.category === 'CONFLICT'
? 'CONFLICT_BOUNDARY_DETECTED'
: item.category === 'NO_EVIDENCE'
? 'NO_EVIDENCE_BOUNDARY_DETECTED'
: item.category === 'UNAUTHORIZED'
? 'UNAUTHORIZED_BOUNDARY_DETECTED'
: 'test-only observed result'
policyQuestionApprovals[item.id] = {
status: 'APPROVED',
answerDisposition,
sourceRefs: answerDisposition === 'FORMALLY_SOURCED'
? ['FORMAL-OPS-001:section-2']
: [],
expectedBehavior: item.expectedBehavior,
observedBehavior: 'test-only observed result',
observedBehavior,
evidenceRef: `evidence/question-${index + 1}.json`,
evidenceSha256: 'b'.repeat(64),
reviewedBy: `question-reviewer-${index + 1}`,
+26 -6
View File
@@ -147,9 +147,13 @@ for (const [roleKey] of channelEntries) {
check(requiredChannels.includes(roleKey), `${roleKey}: approval references an unknown direct channel`)
}
const resolveSourceRefs = (refs, label) => {
check(Array.isArray(refs) && refs.length > 0, `${label}: at least one formal source reference is required`)
for (const reference of refs ?? []) {
const resolveSourceRefs = (refs, label, required = true) => {
check(Array.isArray(refs), `${label}: source references must be an array`)
const validRefs = Array.isArray(refs) ? refs : []
if (required) {
check(validRefs.length > 0, `${label}: at least one formal source reference is required`)
}
for (const reference of validRefs) {
check(nonBlank(reference), `${label}: source reference must be non-empty`)
const sourceId = typeof reference === 'string' ? reference.split(':', 1)[0] : ''
check(sourceIds.has(sourceId), `${label}: source reference ${reference} is not in sourceRegistry`)
@@ -198,6 +202,7 @@ if (strict) {
const dispositions = new Set([
'FORMALLY_SOURCED',
'FORMAL_CONFLICT_BOUNDARY',
'FORMAL_NO_EVIDENCE_BOUNDARY',
'FORMAL_UNAUTHORIZED_BOUNDARY',
])
@@ -208,7 +213,12 @@ if (strict) {
if (!entry) continue
check(entry.status === 'APPROVED', `${label}: question status must be APPROVED`)
check(dispositions.has(entry.answerDisposition), `${label}: answerDisposition is invalid`)
if (candidateItem.category === 'NO_EVIDENCE') {
if (candidateItem.category === 'CONFLICT') {
check(
entry.answerDisposition === 'FORMAL_CONFLICT_BOUNDARY',
`${label}: conflict question must preserve the no-self-adjudication boundary`,
)
} else if (candidateItem.category === 'NO_EVIDENCE') {
check(
entry.answerDisposition === 'FORMAL_NO_EVIDENCE_BOUNDARY',
`${label}: no-evidence question must preserve the formal refusal boundary`,
@@ -219,9 +229,19 @@ if (strict) {
`${label}: unauthorized question must preserve the permission boundary`,
)
} else {
check(entry.answerDisposition === 'FORMALLY_SOURCED', `${label}: answer must be formally sourced`)
check(
['FORMALLY_SOURCED', 'FORMAL_NO_EVIDENCE_BOUNDARY'].includes(entry.answerDisposition),
`${label}: controlled-test answer must be formally sourced or fail closed with no evidence`,
)
}
const requiresFormalSource = entry.answerDisposition === 'FORMALLY_SOURCED'
resolveSourceRefs(entry.sourceRefs, label, requiresFormalSource)
if (!requiresFormalSource) {
check(
/(?:CONFLICT|NO_EVIDENCE|UNAUTHORIZED)_BOUNDARY_DETECTED/.test(entry.observedBehavior ?? ''),
`${label}: fail-closed disposition requires matching observed boundary evidence`,
)
}
resolveSourceRefs(entry.sourceRefs, label)
check(nonBlank(entry.expectedBehavior), `${label}: expected behavior is required`)
check(nonBlank(entry.observedBehavior), `${label}: observed behavior is required`)
check(nonBlank(entry.evidenceRef), `${label}: acceptance evidence reference is required`)
+14 -3
View File
@@ -48,16 +48,27 @@ for snapshot in "${scenario_snapshots[@]}"; do
exit 4
}
done
scenario_snapshots_b64="$(
printf '%s\n' "${scenario_snapshots[@]}" | base64 | tr -d '\r\n'
)"
[[ "$scenario_snapshots_b64" =~ ^[A-Za-z0-9+/=]+$ ]] || {
echo "FAIL: strict approval snapshots could not be encoded safely" >&2
exit 4
}
ssh -o BatchMode=yes -o ConnectTimeout=10 "$REMOTE_SSH" bash -s -- \
"$REMOTE_SERVICE" "$REMOTE_DB" "$TENANT_ID" "${scenario_snapshots[@]}" <<'REMOTE'
"$REMOTE_SERVICE" "$REMOTE_DB" "$TENANT_ID" "$scenario_snapshots_b64" <<'REMOTE'
set -euo pipefail
service="$1"
db="$2"
tenant="$3"
shift 3
snapshots=("$@")
snapshots_b64="$4"
mapfile -t snapshots < <(printf '%s' "$snapshots_b64" | base64 --decode)
[[ "${#snapshots[@]}" -eq 5 ]] || {
echo "FAIL: production received an invalid scenario snapshot payload" >&2
exit 9
}
pid="$(systemctl show -p MainPID --value "$service")"
[[ -n "$pid" && "$pid" != "0" ]] || {