feat(code-runtime-python): add the fd-3 frame protocol

Introduce @deepseek-ai/dsh-code-runtime-python with the versionless
JSON-lines protocol between the Node host and the CPython subprocess:
the host-side hostile-frame codec (validateChildFrame, encodeJsonPlain,
checkDoneValue, hasUnsafeIntegerToken, hasNonLosslessNumber,
logTruncationMarker) and the Python-side wire-vocabulary mirror
(py/protocol.py).

This is the protocol layer of the code-runtime-python stack, split from
#436 and based on the multi-language seam extension. The PythonCodeRuntime
implementation and its Python JSON codec land in the backend-core PR on
top of this branch.

Ship the minimal buildable package skeleton (package.json, tsconfig,
tsdown, barrel index, invariant companion, bilingual README) because the
workspace-constraint, coverage, and invariant-topology gates require the
package to exist and build the moment its directory does; the backend-core
PR extends those files rather than creating them.

Align py/protocol.py with src/protocol.ts (the round-12 review of #436
found LogMessage.truncated, DoneMessage.error.kind, and Namespace.errorClass
stale) and guard the two runtime-executed surfaces (PROTOCOL_FD and the log
truncation marker) with a real-python3 cross-language mirror e2e test.
This commit is contained in:
Chinesezjc
2026-08-07 13:27:54 +08:00
parent 2d5256fd91
commit e0f22aeaad
22 changed files with 1148 additions and 0 deletions
@@ -0,0 +1,60 @@
import { execFile } from 'node:child_process'
import { existsSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { promisify } from 'node:util'
import { describe, expect, it } from 'vitest'
import { logTruncationMarker } from '../src/protocol.ts'
/**
* Cross-language mirror check for the two protocol surfaces the host and the
* CPython subprocess share at runtime, spawning a real `python3` to read them
* from `py/protocol.py`. `src/protocol.ts` and `py/protocol.py` declare the same
* frame vocabulary on two sides of the wire; the only values both sides EXECUTE
* against are `PROTOCOL_FD` (the fd the channel is pinned to) and the log
* truncation marker text (emitted verbatim by whichever ledger exhausts first),
* so a drift there silently corrupts a live run. Self-skips when no `python3` is
* on PATH — CI provides one; the pure-TS `protocol.spec.ts` covers the host
* codec unconditionally.
*/
const execFileAsync = promisify(execFile)
const pyDir = fileURLToPath(new URL('../py', import.meta.url))
async function hasPython3(): Promise<boolean> {
try {
await execFileAsync('python3', ['--version'])
return true
} catch {
return false
}
}
const python3Available = await hasPython3()
describe.skipIf(!python3Available)('protocol.py mirrors protocol.ts at runtime', () => {
it('agrees on PROTOCOL_FD and the log truncation marker across byte budgets', async () => {
const budgets = [1, 65536, 1048576]
const probe = [
'import json, sys',
`sys.path.insert(0, ${JSON.stringify(pyDir)})`,
'from protocol import PROTOCOL_FD, log_truncation_marker',
`budgets = ${JSON.stringify(budgets)}`,
'print(json.dumps({',
' "fd": PROTOCOL_FD,',
' "markers": [log_truncation_marker(b) for b in budgets],',
'}))',
].join('\n')
const { stdout } = await execFileAsync('python3', ['-I', '-c', probe])
const seen = JSON.parse(stdout) as { fd: number; markers: string[] }
// fd 3 is the wire contract, not a tunable: index.ts pins it positionally.
expect(seen.fd).toBe(3)
expect(seen.markers).toEqual(budgets.map(budget => logTruncationMarker(budget)))
})
})
it('names the py/ directory that ships with the package', () => {
// The package.json `files` list ships `py/**/*.py`; the mirror test resolves
// the marker source relative to the built package, so the directory must exist
// beside the tests even when python3 is absent from the runner.
expect(existsSync(pyDir)).toBe(true)
})