Skip to content

Commit 536c924

Browse files
committed
test: align closure reminders and terminal receipt handshake
1 parent 36d3d18 commit 536c924

5 files changed

Lines changed: 136 additions & 13 deletions

File tree

‎scripts/replay-stop-gate-hook-matrix.js‎

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -235,16 +235,16 @@ function scenarioRt3 () {
235235
cwd
236236
})
237237
const kind = classifyStop(stop.json)
238-
const reason = String(stop.json?.reason || '')
238+
const reason = String(stop.json?.reason || stop.json?.systemMessage || '')
239239
const pass =
240-
kind === 'block' &&
240+
kind !== 'block' && stop.json?.continue !== false &&
241241
/Stop gate|incomplete|entry-check/i.test(reason)
242-
// F-13: adapter must preserve block
242+
// The adapter must preserve the reminder without adding a workflow Stop block.
243243
const { adaptHostOutput } = require('../hooks/_runtime/lifecycle-host-adapters.cjs')
244244
if (pass && stop.json) {
245245
const adapted = adaptHostOutput('grok', 'Stop', stop.json)
246-
if (adapted.decision !== 'block') {
247-
return { id: 'R-T3', pass: false, kind, decision: adapted.decision, reason: 'adapter-stripped-block', state: readHonesty(cwd), cwd }
246+
if (adapted.decision === 'block' || adapted.continue === false) {
247+
return { id: 'R-T3', pass: false, kind, decision: adapted.decision, reason: 'adapter-added-workflow-block', state: readHonesty(cwd), cwd }
248248
}
249249
}
250250
return {
@@ -301,10 +301,8 @@ function scenarioRt6 () {
301301
})
302302
const kind = classifyStop(stop.json)
303303
const reason = String(stop.json?.reason || stop.json?.systemMessage || '')
304-
// Expect no completion-gate hard block (allow or soft-only reminder ok)
305-
const hardCompletionBlock =
306-
kind === 'block' && /Stop gate: incomplete/i.test(reason)
307-
const pass = !hardCompletionBlock
304+
// Closure or context reminders must both leave the task able to continue.
305+
const pass = kind !== 'block' && stop.json?.continue !== false
308306
return {
309307
id: 'R-T6',
310308
pass,

‎scripts/test-delivery-honesty.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ assert.ok(badHits >= 10, `golden bad hits=${badHits}`)
130130
'5/6 完成 只差验收 控制面 全部完成 可关闭需求'
131131
].join('\n')
132132
})
133-
assert.strictEqual(r.decision, 'block')
133+
assert.strictEqual(r.decision, 'allow')
134+
assert.match(r.reason, /Do not claim unverified completion/)
134135
assert.ok(
135136
r.gaps.includes('stage-report-missing') ||
136137
r.gaps.includes('progress-overclaim') ||

‎scripts/test-ecr-closure.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ assert.ok(hits >= 8, `hits=${hits}`)
9797
'任务已完成 可关闭需求'
9898
].join('\n')
9999
})
100-
assert.strictEqual(r.decision, 'block')
100+
assert.strictEqual(r.decision, 'allow')
101+
assert.match(r.reason, /Record unfinished work and recoverable content/)
101102
assert.ok(r.gaps.includes('ecr-missing'), `gaps=${r.gaps.join(',')}`)
102103
}
103104

‎scripts/test-validation-wave-executor.js‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,12 @@ function executeActualValidationWorker({ manifest, plan, candidate, repoRoot, ac
8383
try { child.kill('SIGKILL') } catch { }
8484
reject(new Error('actual validation worker fixture timed out'))
8585
}, 15000)
86-
child.on('message', message => messages.push(message))
86+
child.on('message', message => {
87+
messages.push(message)
88+
// Match the production runner: acknowledge terminal delivery by closing
89+
// the channel only after the receiver has observed the final message.
90+
if (['result', 'error'].includes(message.type) && child.connected) child.disconnect()
91+
})
8792
child.once('error', reject)
8893
child.once('exit', code => {
8994
clearTimeout(timer)

‎scripts/validation-manifest.json‎

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,10 @@
632632
"public-skill-catalog-build",
633633
"generated-site-postcheck",
634634
"docs-surface-inventory",
635-
"process-enforcement-e2e"
635+
"process-enforcement-e2e",
636+
"delivery-honesty",
637+
"ecr-closure",
638+
"stop-gate-hook-matrix"
636639
]
637640
},
638641
"changed": {
@@ -6904,6 +6907,121 @@
69046907
"evidenceArtifacts": [
69056908
"ValidationExecutionReceiptV1"
69066909
]
6910+
},
6911+
{
6912+
"schemaVersion": "ValidationNodeV1",
6913+
"id": "delivery-honesty",
6914+
"owner": "process-enforcement",
6915+
"command": "node",
6916+
"args": [
6917+
"scripts/test-delivery-honesty.js"
6918+
],
6919+
"dependencies": [
6920+
"artifact-mutation-authority"
6921+
],
6922+
"inputs": [
6923+
"scripts/test-delivery-honesty.js",
6924+
"scripts/lib/process-enforcement.js",
6925+
"hooks/_runtime/lifecycle-stop-gate.cjs"
6926+
],
6927+
"consumers": [],
6928+
"invariants": [
6929+
"closure-gaps-remain-visible",
6930+
"workflow-observations-never-force-stop"
6931+
],
6932+
"riskClass": "normal",
6933+
"cachePolicy": "never",
6934+
"writeScopes": [
6935+
"isolated-temp"
6936+
],
6937+
"timeoutMs": 120000,
6938+
"exitMap": {
6939+
"success": [
6940+
0
6941+
],
6942+
"failure": "nonzero-or-signal",
6943+
"timeout": "ETIMEDOUT"
6944+
},
6945+
"evidenceArtifacts": [
6946+
"ValidationExecutionReceiptV1"
6947+
]
6948+
},
6949+
{
6950+
"schemaVersion": "ValidationNodeV1",
6951+
"id": "ecr-closure",
6952+
"owner": "process-enforcement",
6953+
"command": "node",
6954+
"args": [
6955+
"scripts/test-ecr-closure.js"
6956+
],
6957+
"dependencies": [
6958+
"artifact-mutation-authority"
6959+
],
6960+
"inputs": [
6961+
"scripts/test-ecr-closure.js",
6962+
"scripts/lib/process-enforcement.js",
6963+
"hooks/_runtime/lifecycle-stop-gate.cjs"
6964+
],
6965+
"consumers": [],
6966+
"invariants": [
6967+
"closure-gaps-remain-visible",
6968+
"workflow-observations-never-force-stop"
6969+
],
6970+
"riskClass": "normal",
6971+
"cachePolicy": "never",
6972+
"writeScopes": [
6973+
"isolated-temp"
6974+
],
6975+
"timeoutMs": 120000,
6976+
"exitMap": {
6977+
"success": [
6978+
0
6979+
],
6980+
"failure": "nonzero-or-signal",
6981+
"timeout": "ETIMEDOUT"
6982+
},
6983+
"evidenceArtifacts": [
6984+
"ValidationExecutionReceiptV1"
6985+
]
6986+
},
6987+
{
6988+
"schemaVersion": "ValidationNodeV1",
6989+
"id": "stop-gate-hook-matrix",
6990+
"owner": "process-enforcement",
6991+
"command": "node",
6992+
"args": [
6993+
"scripts/replay-stop-gate-hook-matrix.js"
6994+
],
6995+
"dependencies": [
6996+
"artifact-mutation-authority"
6997+
],
6998+
"inputs": [
6999+
"scripts/replay-stop-gate-hook-matrix.js",
7000+
"hooks/_runtime/lifecycle.cjs",
7001+
"hooks/_runtime/lifecycle-stop-gate.cjs",
7002+
"hooks/_runtime/lifecycle-host-adapters.cjs"
7003+
],
7004+
"consumers": [],
7005+
"invariants": [
7006+
"closure-gaps-remain-visible",
7007+
"workflow-observations-never-force-stop"
7008+
],
7009+
"riskClass": "normal",
7010+
"cachePolicy": "never",
7011+
"writeScopes": [
7012+
"isolated-temp"
7013+
],
7014+
"timeoutMs": 120000,
7015+
"exitMap": {
7016+
"success": [
7017+
0
7018+
],
7019+
"failure": "nonzero-or-signal",
7020+
"timeout": "ETIMEDOUT"
7021+
},
7022+
"evidenceArtifacts": [
7023+
"ValidationExecutionReceiptV1"
7024+
]
69077025
}
69087026
]
69097027
}

0 commit comments

Comments
 (0)