Skip to content

Commit ab762fa

Browse files
committed
fix: detect malformed entry check free-text rows
1 parent eb8eac3 commit ab762fa

2 files changed

Lines changed: 38 additions & 2 deletions

File tree

‎hooks/_runtime/lifecycle-visible-reply.cjs‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ function analyzeEntryCheckCompleteness(text, options = {}) {
2525
const sourceSchemaVersion = marker ? `DevCodexVisibleEnvelopeV${marker[1]}` : null
2626
const legacyReadOnly = marker && ['1', '2'].includes(marker[1])
2727
const lastOrdinal = legacyReadOnly ? 7 : 10
28-
const claimed = /入口检查|预检查(\s*DEV|###\s*DevCodex\s*·\s*入口检查|DevCodexVisibleEnvelopeV(?:1|2|3)\s*·\s*entry-check|PC0\s*(?:上下文|版本|\[|()|PC0\s*[::]/i.test(body)
28+
const freeTextPcLines = detectFreeTextPcLines(body, lastOrdinal)
29+
const claimed = /入口检查|预检查(\s*DEV|###\s*DevCodex\s*·\s*入口检查|DevCodexVisibleEnvelopeV(?:1|2|3)\s*·\s*entry-check|PC0\s*(?:上下文|版本|\[|()|PC0\s*[::]/i.test(body) || freeTextPcLines.length >= 3
2930
if (!claimed) {
3031
return {
3132
claimed: false,
@@ -74,6 +75,9 @@ function analyzeEntryCheckCompleteness(text, options = {}) {
7475
if (!presentPcs.includes(id)) missingPcs.push(id)
7576
}
7677
if (missingPcs.length) missingItems.push('pc-columns-incomplete')
78+
if (freeTextPcLines.length >= 3 && presentPcs.length < freeTextPcLines.length) {
79+
missingItems.push('pc-free-text-lines')
80+
}
7781

7882
// Legacy V1/V2 PC0 carried context. V3 PC0 carries installed/runtime/source version facts and alignment.
7983
const currentRowPrefix = legacyReadOnly ? '(?:[-*]\\s*)?(?:\\|\\s*)?' : '(?:[-*]\\s+|\\|\\s*)'
@@ -139,6 +143,20 @@ function analyzeEntryCheckCompleteness(text, options = {}) {
139143
}
140144
}
141145

146+
function detectFreeTextPcLines(body, lastOrdinal) {
147+
const seen = []
148+
for (const line of String(body || '').split(/\r?\n/u)) {
149+
if (/^\s*(?:[-*]\s+|\|)/u.test(line)) continue
150+
const match = line.match(/^\s*PC\s*(10|[0-9])\b(?!\s*[-–—~~至到])[^\n]*[::]/iu)
151+
if (!match) continue
152+
const ordinal = Number(match[1])
153+
if (!Number.isInteger(ordinal) || ordinal > lastOrdinal) continue
154+
const id = `PC${ordinal}`
155+
if (!seen.includes(id)) seen.push(id)
156+
}
157+
return seen
158+
}
159+
142160
function projectWorkflowCompletionVisibleState(projection) {
143161
const valid = projection?.schemaVersion === 'WorkflowCompletionProjectionV1' &&
144162
Array.isArray(projection.phaseTerminals) && projection.phaseTerminals.length === 4 &&
@@ -337,7 +355,7 @@ function buildLifecycleVisibleReplyUtils(ctx) {
337355
// Accept V1/V2 as read-only compatibility; current V3 requires free-text PC0~PC10 completeness.
338356
const entryCompleteness = analyzeEntryCheckCompleteness(text, { mode: state.mode })
339357
state.visible.entryCheckCompleteness = entryCompleteness
340-
if (/入口检查(|预检查(DEV 模式)|PC0 (?:上下文|版本)|###\s*DevCodex\s*·\s*入口检查|DevCodexVisibleEnvelopeV(?:1|2|3)\s*·\s*entry-check|PC0\s*[\[(]/.test(text)) {
358+
if (entryCompleteness.claimed) {
341359
if (entryCompleteness.complete) {
342360
state.visible.precheck = true
343361
state.visible.precheckStatus = 'verified-present'

‎scripts/test-visible-output-contract.js‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,24 @@ const paragraphEntryCheck = [
464464
const paragraphAnalysis = analyzeEntryCheckCompleteness(paragraphEntryCheck, { mode: 'dev' })
465465
assert.strictEqual(paragraphAnalysis.complete, false)
466466
assert(paragraphAnalysis.missingItems.includes('pc-columns-incomplete'))
467+
const colonFreeTextEntryCheck = [
468+
'PC0 范围:整理 vextjs-mcp-verify 的完整博客需求,先形成可确认的产品与技术方案,不直接改代码。',
469+
'PC1 目标:覆盖前台博客、后台管理、本地 MongoDB、Redis 响应缓存及必要的配套能力。',
470+
'PC2 变更意图:当前阶段是需求分析与方案确认;确认后再进入实现。',
471+
'PC3 项目边界:仅针对 D:\\Worker\\vextjs-mcp-verify,先检查现有结构与技术栈。',
472+
'PC4 规范状态:N/A(当前不是开发执行阶段)。',
473+
'PC5 数据范围:文章、分类、标签、用户/管理员、评论、媒体及缓存策略需纳入设计。',
474+
'PC6 外部依赖:本地 MongoDB 与 Redis;连接方式、端口和启动约定需以项目现状为准。',
475+
'PC7 风险提示:权限、缓存一致性、草稿发布、删除恢复、输入安全和后台审计需要在需求中明确。',
476+
'PC8 交付物:一份分层需求清单、页面/接口/数据模型、非功能要求、验收标准和待确认项。',
477+
'PC9 验证方式:读取项目现状后,检查方案是否与现有框架、脚本和目录兼容。',
478+
'PC10 当前状态:准备读取项目上下文并整理需求,等待你确认后再实施。'
479+
].join('\n')
480+
const colonFreeTextAnalysis = analyzeEntryCheckCompleteness(colonFreeTextEntryCheck, { mode: 'dev' })
481+
assert.strictEqual(colonFreeTextAnalysis.claimed, true)
482+
assert.strictEqual(colonFreeTextAnalysis.complete, false)
483+
assert(colonFreeTextAnalysis.missingItems.includes('pc-columns-incomplete'))
484+
assert(colonFreeTextAnalysis.missingItems.includes('pc-free-text-lines'))
467485
assert.match(codexDesktopRendered, /\[.+\]\([^)]+\)/)
468486
assert.doesNotMatch(codexDesktopRendered, /使用 Codex 文件面板打开/)
469487
const vscodeLink = createHostLinkCapabilityDecisionV2({

0 commit comments

Comments
 (0)