Skip to content

Commit 833fe17

Browse files
committed
fix: close scan residual workflow gaps
1 parent fd8c228 commit 833fe17

15 files changed

Lines changed: 272 additions & 41 deletions

‎grok/plugins/devcodex-workspace/hooks/devcodex-workspace.cjs‎

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,38 @@ const {
1515
resolveGrokRuntimeRoot
1616
} = require('../lib/runtime-root.cjs')
1717

18+
const STDIO_MAX_FRAME_BYTES = 4 * 1024 * 1024
19+
20+
function byteLength(value) {
21+
return Buffer.byteLength(String(value || ''), 'utf8')
22+
}
23+
24+
function createBoundedTextAccumulator(options = {}) {
25+
const maxBytes = options.maxBytes || STDIO_MAX_FRAME_BYTES
26+
let text = ''
27+
let overflowed = false
28+
return {
29+
push(chunk) {
30+
if (overflowed) return false
31+
const next = String(chunk || '')
32+
if (byteLength(text) + byteLength(next) > maxBytes) {
33+
text = ''
34+
overflowed = true
35+
return false
36+
}
37+
text += next
38+
return true
39+
},
40+
snapshot() {
41+
return text
42+
},
43+
get overflowed() {
44+
return overflowed
45+
},
46+
maxBytes
47+
}
48+
}
49+
1850
function samePath(left, right) {
1951
const a = path.resolve(left)
2052
const b = path.resolve(right)
@@ -54,11 +86,20 @@ function findWorkspaceRoot(start) {
5486

5587
function readInput() {
5688
return new Promise((resolve, reject) => {
57-
let input = ''
89+
const input = createBoundedTextAccumulator({ maxBytes: STDIO_MAX_FRAME_BYTES })
5890
process.stdin.setEncoding('utf8')
59-
process.stdin.on('data', (chunk) => { input += chunk })
91+
process.stdin.on('data', (chunk) => {
92+
if (!input.push(chunk)) {
93+
const error = new Error(`DevCodex Grok hook stdin exceeds ${input.maxBytes} bytes`)
94+
error.code = 'DEVCODEX_GROK_HOOK_STDIN_TOO_LARGE'
95+
reject(error)
96+
}
97+
})
6098
process.stdin.on('end', () => {
61-
try { resolve(input.trim() ? JSON.parse(input) : {}) } catch (error) { reject(error) }
99+
try {
100+
const text = input.snapshot()
101+
resolve(text.trim() ? JSON.parse(text) : {})
102+
} catch (error) { reject(error) }
62103
})
63104
})
64105
}

‎hooks/_runtime/host-skill-route-capabilities.v1.json‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,13 @@
1010
},
1111
{
1212
"hostVariant": "codex-cli/exec-user-global-local-stdio",
13-
"status": "PASS",
13+
"status": "UNVERIFIED",
1414
"testedVersion": "codex-cli 0.145.0",
1515
"protocol": "MCP 2024-11-05",
16-
"runtimeContractDigest": "d60c401ae9041d6bfd4607d19be8bf64e92b3093d325692b6c1454e8fe849ae8",
17-
"hostAdapterDigest": "03d2476cd269a40e9ada285cc50de5eaf34857ef1805401aeee715c3ee13e8fe",
18-
"evidenceRef": "hooks/_runtime/evidence/codex-skill-route-pass.v1.json",
19-
"evidenceDigest": "6af6fcbefca64f5fa961fc06d2bef691361b3a1be58895d3f8ec6704b529fc97",
16+
"evidenceRef": null,
2017
"entrySurface": "codex exec --ephemeral",
2118
"bootstrapDelivery": "stable user-global Hook launcher UserPromptSubmit or profile_context_plan fallback",
22-
"defaultEligible": true
19+
"defaultEligible": false
2320
},
2421
{
2522
"hostVariant": "codex-desktop/app-user-global-local-stdio",

‎mcp/hot-reload-supervisor.cjs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,6 @@ async function main () {
321321
}
322322

323323
async function handle (message) {
324-
if (!message || typeof message !== 'object' || Array.isArray(message)) return
325324
if (!current) await startCurrent()
326325
if (message.method !== 'initialize') await maybeReload()
327326
if (message.id === undefined) {
@@ -345,6 +344,10 @@ async function main () {
345344
process.stdout.write(`${JSON.stringify({ jsonrpc: '2.0', id: null, error: { code: -32700, message: 'Parse error' } })}\n`)
346345
return
347346
}
347+
if (!message || typeof message !== 'object' || Array.isArray(message)) {
348+
process.stdout.write(`${JSON.stringify({ jsonrpc: '2.0', id: null, error: { code: -32600, message: 'Invalid Request' } })}\n`)
349+
return
350+
}
348351
try {
349352
await handle(message)
350353
} catch (error) {

‎mcp/memory-file-transaction.cjs‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ function createNodeMemoryFileAdapter(options = {}) {
436436
faultInjector('before-create-final-cas', input)
437437
const finalObserved = readSnapshot(input.filePath)
438438
assertExpectedSnapshot(input.expected, finalObserved, input.filePath)
439+
let createRoute = 'hardlink-create-if-absent'
439440
try {
440441
fsImpl.linkSync(temp, input.filePath)
441442
} catch (error) {
@@ -445,7 +446,12 @@ function createNodeMemoryFileAdapter(options = {}) {
445446
`Memory create target won by another writer: ${input.filePath}`
446447
)
447448
}
448-
throw error
449+
if (error?.code === 'EACCES' || error?.code === 'EPERM') {
450+
fsImpl.copyFileSync(temp, input.filePath, fsImpl.constants?.COPYFILE_EXCL || 1)
451+
createRoute = 'copy-create-if-absent'
452+
} else {
453+
throw error
454+
}
449455
}
450456
const directoryFlush = flushDirectory(directory)
451457
const readback = readSnapshot(input.filePath)
@@ -471,7 +477,7 @@ function createNodeMemoryFileAdapter(options = {}) {
471477
durability: {
472478
fileFlush,
473479
directoryFlush,
474-
readback: { status: 'PASS', scope: 'hardlink-create-if-absent+whole-file-exact' }
480+
readback: { status: 'PASS', scope: `${createRoute}+whole-file-exact` }
475481
}
476482
}
477483
} finally {

‎mcp/memory-server.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2346,7 +2346,7 @@ function resolveMemoryTarget(args) {
23462346
}
23472347

23482348
function memoryClientPath(target, ...segments) {
2349-
return resolveInside(target.activeRoot, '.memory', 'clients', target.agent, ...segments)
2349+
return resolveWritePathInside(target.activeRoot, '.memory', 'clients', target.agent, ...segments)
23502350
}
23512351

23522352
function memoryFileMetadata(filePath) {

‎mcp/profile-server.js‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const crypto = require('crypto')
1818
const fs = require('fs')
1919
const path = require('path')
2020
const { execFileSync } = require('child_process')
21-
const { assertSingleSegment, resolveInside, resolveExistingRegularFileInside } = require('./path-guard')
21+
const { assertSingleSegment, resolveInside, resolveExistingRegularFileInside, resolveWritePathInside } = require('./path-guard')
2222
const { createJsonLineServer } = require('./stdio-jsonrpc.cjs')
2323
const {
2424
PROFILE_BASE_FILES,
@@ -752,7 +752,7 @@ function resolveProfileFile(name, projectName, options = {}) {
752752
if (!LAYOUT.enabled) {
753753
const sourceSnapshots = []
754754
for (const dir of getLegacyProfileDirs(projectName)) {
755-
const fullPath = resolveInside(dir, safeName)
755+
const fullPath = resolveWritePathInside(dir, safeName)
756756
const document = readProfileTextDocument(fullPath, options)
757757
sourceSnapshots.push(profileSourceSnapshot(fullPath, document))
758758
if (document.exists) {
@@ -774,8 +774,8 @@ function resolveProfileFile(name, projectName, options = {}) {
774774

775775
const projectDir = getProjectNamespaceProfileDir(projectName)
776776
const workspaceDir = getWorkspaceProfileDir()
777-
const projectPath = projectDir ? resolveInside(projectDir, safeName) : null
778-
const workspacePath = resolveInside(workspaceDir, safeName)
777+
const projectPath = projectDir ? resolveWritePathInside(projectDir, safeName) : null
778+
const workspacePath = resolveWritePathInside(workspaceDir, safeName)
779779
const sourceSnapshots = []
780780

781781
if (projectPath) {
@@ -845,7 +845,7 @@ function resolveProfileSectionFile(name, projectName, options = {}) {
845845

846846
if (!LAYOUT.enabled) {
847847
for (const dir of getLegacyProfileDirs(projectName)) {
848-
const fullPath = resolveInside(dir, safeName)
848+
const fullPath = resolveWritePathInside(dir, safeName)
849849
const selected = selectAt(fullPath, getLegacySourceLabel(dir, projectName))
850850
if (selected) return selected
851851
}
@@ -856,11 +856,11 @@ function resolveProfileSectionFile(name, projectName, options = {}) {
856856

857857
const projectDir = getProjectNamespaceProfileDir(projectName)
858858
if (projectDir) {
859-
const projectPath = resolveInside(projectDir, safeName)
859+
const projectPath = resolveWritePathInside(projectDir, safeName)
860860
const selected = selectAt(projectPath, `项目命名空间(${resolveProjectName(projectName)})`)
861861
if (selected) return selected
862862
}
863-
const workspacePath = resolveInside(getWorkspaceProfileDir(), safeName)
863+
const workspacePath = resolveWritePathInside(getWorkspaceProfileDir(), safeName)
864864
const selected = selectAt(workspacePath, '工作区基座(workspace)')
865865
return selected || (options.captureMissingSnapshots === true
866866
? { exists: false, content: null, fullPath: null, sourceLabel: '未命中', sourcePaths: [], sourceSnapshots, sourceBytesRead: 0 }
@@ -893,7 +893,7 @@ function resolveConfigFile(projectName, options = {}) {
893893
if (!LAYOUT.enabled) {
894894
const sourceSnapshots = []
895895
for (const dir of getLegacyProfileDirs(projectName)) {
896-
const fullPath = path.join(dir, 'config.json')
896+
const fullPath = resolveWritePathInside(dir, 'config.json')
897897
const loaded = loadConfig(fullPath)
898898
if (loaded?.sourceSnapshot) sourceSnapshots.push(loaded.sourceSnapshot)
899899
if (loaded?.config !== null && loaded?.config !== undefined) {
@@ -927,8 +927,8 @@ function resolveConfigFile(projectName, options = {}) {
927927

928928
const workspaceDir = getWorkspaceProfileDir()
929929
const projectDir = getProjectNamespaceProfileDir(projectName)
930-
const workspacePath = path.join(workspaceDir, 'config.json')
931-
const projectPath = projectDir ? path.join(projectDir, 'config.json') : null
930+
const workspacePath = resolveWritePathInside(workspaceDir, 'config.json')
931+
const projectPath = projectDir ? resolveWritePathInside(projectDir, 'config.json') : null
932932
const workspaceLoaded = loadConfig(workspacePath)
933933
const projectLoaded = projectPath ? loadConfig(projectPath) : null
934934
const workspaceConfig = workspaceLoaded?.config || null

‎package.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"test:governance-status-summary": "node scripts/test-governance-status-summary.js",
7171
"test:derived-index-contract": "node scripts/test-derived-index-contract.js",
7272
"test:memory-index": "node scripts/test-memory-index.js",
73+
"test:memory-template-production": "node scripts/test-memory-template-production.js",
7374
"test:report-index": "node scripts/test-report-index.js",
7475
"test:always-on-governance": "node scripts/test-always-on-governance.js",
7576
"test:intent-consistency": "node scripts/test-intent-consistency.js",
@@ -342,6 +343,7 @@
342343
"scripts/test-real-codex-host-probe.js",
343344
"scripts/test-global-install-smoke.js",
344345
"scripts/test-mcp-runtime-closure.js",
346+
"scripts/test-mcp-hot-reload-supervisor.js",
345347
"scripts/fixtures/global-host-config/",
346348
"scripts/test-security-audit.js",
347349
"scripts/lib/security-audit-runner.js",

‎public-site/data/public-product-projection.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"schemaVersion": "PublicProductProjectionV2",
3-
"generatedAt": "2026-09-09T02:10:12.178Z",
3+
"generatedAt": "2026-09-13T15:19:55.285Z",
44
"release": {
55
"version": "1.20.2"
66
},
@@ -1184,10 +1184,10 @@
11841184
}
11851185
],
11861186
"sourceIdentities": {
1187-
"package": "199bae54b2c3243290dcb9830b3af4deaaf933b9351c2de1eeb3125fc070cc38",
1187+
"package": "17de2c775a633075c6b1236b37651d48c009997fe1eb02bbcf8a179f6e1c565a",
11881188
"expression": "60e525d34e5531e6b4bbbb77f8b34bb93c9ca9ebee5df4fe2812749232175c3c",
11891189
"workflows": "d9eb7086866fe3c3815f673957ed978c1594079261009ac775bf3e1336ad44fd",
1190-
"portfolio": "bd64d4c138ac43491cef4be8ed291d6f2a501e27c3f3c8fa70be4b7e9a2bc150",
1190+
"portfolio": "2fdc83be80eaef9d6342d2c91f2d18c2fadd20b2a48b2f2806575e8a93b37eb4",
11911191
"taxonomy": "b673f27fa58c2d7a57b9aa906562faed2aca094a727c8686d941c39a5490f030"
11921192
}
11931193
}

‎scripts/generate-public-site-data.js‎

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,19 @@ const ROOT = path.resolve(__dirname, '..')
99
const DATA_DIR = path.join(ROOT, 'public-site', 'data')
1010
const DATA_FILE = path.join(DATA_DIR, 'public-product-projection.json')
1111

12-
function writeProjection (projection) {
13-
const payload = {
12+
function stableStringify (value) {
13+
return `${JSON.stringify(value, null, 2)}\n`
14+
}
15+
16+
function readExistingProjection () {
17+
if (!fs.existsSync(DATA_FILE)) return null
18+
return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8'))
19+
}
20+
21+
function buildProjectionPayload (projection, options = {}) {
22+
return {
1423
schemaVersion: projection.schemaVersion,
15-
generatedAt: new Date().toISOString(),
24+
generatedAt: options.generatedAt || new Date().toISOString(),
1625
release: projection.release,
1726
expression: projection.expression,
1827
expressionCompatibility: projection.expressionCompatibility,
@@ -28,13 +37,37 @@ function writeProjection (projection) {
2837
})),
2938
sourceIdentities: projection.sourceIdentities
3039
}
40+
}
41+
42+
function writeProjection (projection) {
43+
const payload = buildProjectionPayload(projection)
3144
fs.mkdirSync(DATA_DIR, { recursive: true })
32-
fs.writeFileSync(DATA_FILE, `${JSON.stringify(payload, null, 2)}\n`, 'utf8')
45+
fs.writeFileSync(DATA_FILE, stableStringify(payload), 'utf8')
3346
return payload
3447
}
3548

3649
function main () {
50+
const check = process.argv.includes('--check')
3751
const projection = buildPublicProductProjection({ root: ROOT })
52+
if (check) {
53+
const existing = readExistingProjection()
54+
if (!existing) {
55+
console.error(`public-site data missing: ${path.relative(ROOT, DATA_FILE).replace(/\\/g, '/')}`)
56+
process.exit(1)
57+
}
58+
const expected = buildProjectionPayload(projection, { generatedAt: existing.generatedAt })
59+
const currentText = stableStringify(existing)
60+
const expectedText = stableStringify(expected)
61+
if (currentText !== expectedText) {
62+
console.error('public-site data stale: run node scripts/generate-public-site-data.js')
63+
process.exit(1)
64+
}
65+
console.log(
66+
`public-site data fresh: skills=${projection.skills.total}/${projection.skills.active}/${projection.skills.gray}`
67+
)
68+
return
69+
}
70+
3871
writeProjection(projection)
3972

4073
console.log(
@@ -45,5 +78,6 @@ function main () {
4578
if (require.main === module) main()
4679

4780
module.exports = {
81+
buildProjectionPayload,
4882
writeProjection
4983
}

‎scripts/lib/skill-route-test-fixture.js‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -209,12 +209,20 @@ function createSkillRouteFixture (options = {}) {
209209
process.stderr.write(`[skill-route-test-fixture] retained ${root}\n`)
210210
return
211211
}
212-
fs.rmSync(root, {
213-
recursive: true,
214-
force: true,
215-
maxRetries: 10,
216-
retryDelay: 250
217-
})
212+
try {
213+
fs.rmSync(root, {
214+
recursive: true,
215+
force: true,
216+
maxRetries: 10,
217+
retryDelay: 250
218+
})
219+
} catch (error) {
220+
if (error?.code === 'EPERM' || error?.code === 'EACCES') {
221+
process.stderr.write(`[skill-route-test-fixture] cleanup retained ${root}: ${error.code}\n`)
222+
return
223+
}
224+
throw error
225+
}
218226
}
219227
if (options.workspaceSkill !== false) {
220228
writeWorkspaceSkill(root, options.skillId || 'workspace-probe')

0 commit comments

Comments
 (0)