fix(release): make August 1 handoff reproducible
This commit is contained in:
@@ -4,12 +4,19 @@ import path from 'node:path'
|
||||
|
||||
const scriptDir = path.dirname(fileURLToPath(import.meta.url))
|
||||
const rootDir = path.resolve(scriptDir, '..')
|
||||
const candidatePath = path.join(
|
||||
const defaultCandidatePath = path.join(
|
||||
rootDir,
|
||||
'docs',
|
||||
'content-candidates',
|
||||
'aug1-life-advisor-content-candidates-v0.1.json',
|
||||
)
|
||||
if (process.argv.length > 3) {
|
||||
console.error('Usage: node verify-aug1-content-candidates.mjs [candidate-json]')
|
||||
process.exit(2)
|
||||
}
|
||||
const candidatePath = process.argv[2]
|
||||
? path.resolve(process.argv[2])
|
||||
: defaultCandidatePath
|
||||
const content = JSON.parse(await readFile(candidatePath, 'utf8'))
|
||||
|
||||
const failures = []
|
||||
@@ -38,12 +45,14 @@ const credentialPattern = /(?:门禁|家门|开门|访问)\s*(?:密码|口令|
|
||||
|
||||
check(content.candidateStatus === 'PENDING_BUSINESS_REVIEW', 'root status must remain pending review')
|
||||
check(content.publishable === false, 'root publishable must be false')
|
||||
check(Boolean(content.contentVersion?.trim()), 'content version is required')
|
||||
check(Array.isArray(content.scenarios) && content.scenarios.length === 5, 'exactly five scenario candidates are required')
|
||||
check(
|
||||
Array.isArray(content.policyQuestionCandidates) && content.policyQuestionCandidates.length === 30,
|
||||
'exactly thirty policy question candidates are required',
|
||||
)
|
||||
|
||||
const scenarioIds = new Set()
|
||||
for (const scenario of content.scenarios ?? []) {
|
||||
const label = scenario.candidateId ?? 'unknown scenario'
|
||||
const draft = scenario.scenarioDraft ?? {}
|
||||
@@ -61,13 +70,20 @@ for (const scenario of content.scenarios ?? []) {
|
||||
draft.goal,
|
||||
]
|
||||
|
||||
check(Boolean(scenario.candidateId?.trim()), `${label}: candidate ID is required`)
|
||||
check(!scenarioIds.has(scenario.candidateId), `${label}: candidate ID is duplicated`)
|
||||
scenarioIds.add(scenario.candidateId)
|
||||
check(scenario.candidateStatus === 'PENDING_BUSINESS_REVIEW', `${label}: status must remain pending review`)
|
||||
check(scenario.publishable === false, `${label}: publishable must be false`)
|
||||
check(draft.enabled === false, `${label}: scenario must be disabled`)
|
||||
check(draft.riskLevel === '待评估', `${label}: risk must remain pending until business review`)
|
||||
check(rubric.enabled === false, `${label}: rubric must be disabled`)
|
||||
check(placeholderPattern.test(draft.sopRefs ?? ''), `${label}: missing-source marker must remain explicit`)
|
||||
check((scenario.sourceRefs ?? []).length >= 2, `${label}: at least two source references are required`)
|
||||
check(
|
||||
(scenario.sourceRefs ?? []).length >= 2
|
||||
&& scenario.sourceRefs.every((item) => typeof item === 'string' && item.trim()),
|
||||
`${label}: at least two source references are required`,
|
||||
)
|
||||
check((scenario.requiredReviewers ?? []).length >= 2, `${label}: at least two reviewer roles are required`)
|
||||
check((scenario.reviewChecklist ?? []).length >= 4, `${label}: review checklist is incomplete`)
|
||||
check(requiredText.every((value) => typeof value === 'string' && value.trim()), `${label}: required scenario fields are incomplete`)
|
||||
@@ -93,14 +109,22 @@ for (const scenario of content.scenarios ?? []) {
|
||||
}
|
||||
|
||||
const categoryCounts = new Map()
|
||||
const questionIds = new Set()
|
||||
for (const question of content.policyQuestionCandidates ?? []) {
|
||||
const label = question.id ?? 'unknown question'
|
||||
categoryCounts.set(question.category, (categoryCounts.get(question.category) ?? 0) + 1)
|
||||
check(Boolean(question.id?.trim()), `${label}: question ID is required`)
|
||||
check(!questionIds.has(question.id), `${label}: question ID is duplicated`)
|
||||
questionIds.add(question.id)
|
||||
check(question.status === 'PENDING_REVIEW', `${label}: status must remain pending review`)
|
||||
check(Boolean(question.question?.trim()), `${label}: question is missing`)
|
||||
check(Boolean(question.sourceNeed?.trim()), `${label}: source requirement is missing`)
|
||||
check(Boolean(question.expectedBehavior?.trim()), `${label}: expected boundary behavior is missing`)
|
||||
check(Boolean(question.reviewerRole?.trim()), `${label}: reviewer role is missing`)
|
||||
check(
|
||||
['NEEDS_FORMAL_SOURCE', 'BOUNDARY_EXPECTATION_DEFINED'].includes(question.answerStatus),
|
||||
`${label}: answer status is invalid`,
|
||||
)
|
||||
check(!Object.hasOwn(question, 'answer'), `${label}: answer must not exist before formal sourcing`)
|
||||
check(!Object.hasOwn(question, 'standardAnswer'), `${label}: standardAnswer must not exist before formal sourcing`)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user