chore: establish YCode replication baseline and TODO
This commit is contained in:
commit
6dc59f89ba
1118 files changed
+196002
No files matched your search
@@ -0,0 +1,423 @@
|
||||
import { createHash } from 'node:crypto'
|
||||
import fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import { parse } from '@babel/parser'
|
||||
import traverseModule from '@babel/traverse'
|
||||
import postcss from 'postcss'
|
||||
|
||||
const EXPECTED_ROOT_SHA256 = '035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918'
|
||||
const MAIN_EVIDENCE_PATH = '.tmp/rea-selected-editor-evidence.json'
|
||||
const DEPENDENCY_EVIDENCE_PATH = '.tmp/rea-selected-pierre-dependencies.json'
|
||||
const LEAF_EVIDENCE_PATH = '.tmp/rea-selected-pierre-leaf-dependencies.json'
|
||||
const LANGUAGE_EVIDENCE_PATH = '.tmp/rea-selected-pierre-ui-languages.json'
|
||||
const OUTPUT_DIRECTORY = path.resolve('src/renderer/src/workbuddy/artifacts/recovered-pierre')
|
||||
const VITE_PRELOAD_HELPER = '__vite__mapDeps'
|
||||
const RECOVERED_PRELOAD_HELPER = '__ycodePierreMapDeps'
|
||||
const traverse = traverseModule.default
|
||||
|
||||
const SOURCE_FILES = {
|
||||
'renderer/assets/codeEditor-D3P9alks.js': 'main',
|
||||
'renderer/assets/codeEditor-Bxmo_AI3.css': 'css',
|
||||
'package.json': 'package',
|
||||
'renderer/assets/rolldown-runtime-BJCASTsb.js': 'asset',
|
||||
'renderer/assets/preload-helper-D30X3e06.js': 'asset',
|
||||
'renderer/assets/dist-BAqWIeie.js': 'asset',
|
||||
'renderer/assets/dist-BUGqZtx5.js': 'asset',
|
||||
'renderer/assets/worker-portable-D1lwTqsk.js': 'asset',
|
||||
'renderer/assets/zwitch-B8a51bts.js': 'asset',
|
||||
'renderer/assets/stringify-entities-i2atvqYU.js': 'asset',
|
||||
'renderer/assets/hast-util-whitespace-DbScqzu3.js': 'asset',
|
||||
'renderer/assets/pierre-dark-Daa2n9wr.js': 'asset',
|
||||
'renderer/assets/pierre-light-D_hZXvUj.js': 'asset',
|
||||
'renderer/assets/javascript-AfZCJ9Uc.js': 'asset',
|
||||
'renderer/assets/typescript-4sRsPriL.js': 'asset',
|
||||
'renderer/assets/diff-lAxbRYdS.js': 'asset',
|
||||
'renderer/assets/css-NFwnoVns.js': 'asset',
|
||||
'renderer/assets/html-Dq1ixqYb.js': 'asset',
|
||||
'renderer/assets/json-CKKhFIOr.js': 'asset',
|
||||
'renderer/assets/markdown-BSrOIEaF.js': 'asset',
|
||||
}
|
||||
|
||||
const COPYING_ASSETS = Object.keys(SOURCE_FILES).filter((sourcePath) => SOURCE_FILES[sourcePath] === 'asset')
|
||||
const REACT_IMPORTS = new Map([
|
||||
['./react-z__Ncn__.js', 's'],
|
||||
['./react-dom-mnR6psRT.js', 'c'],
|
||||
['./jsx-runtime-DM1VED__.js', 'f'],
|
||||
])
|
||||
const sha256 = (value) => createHash('sha256').update(value).digest('hex')
|
||||
const fail = (message) => {
|
||||
throw new Error(message)
|
||||
}
|
||||
|
||||
async function loadEvidence(filePath) {
|
||||
const evidence = JSON.parse(await fs.readFile(filePath, 'utf8'))
|
||||
if (evidence.authority !== 'shipped-artifact') fail(`Evidence is not shipped-artifact authority: ${filePath}`)
|
||||
if (evidence.normalized_result?.root_sha256 !== EXPECTED_ROOT_SHA256) {
|
||||
fail(`Evidence root SHA-256 does not match the selected WorkBuddy archive: ${filePath}`)
|
||||
}
|
||||
const files = new Map()
|
||||
for (const file of evidence.normalized_result.files) {
|
||||
const actualBytes = Buffer.byteLength(file.text, 'utf8')
|
||||
const actualSha256 = sha256(file.text)
|
||||
if (actualBytes !== file.size_bytes || actualSha256 !== file.sha256) {
|
||||
fail(`Evidence text failed size/SHA validation: ${file.path}`)
|
||||
}
|
||||
files.set(file.path, file)
|
||||
}
|
||||
return { evidence, files }
|
||||
}
|
||||
|
||||
function collectPatternNames(node, names = []) {
|
||||
if (!node) return names
|
||||
if (node.type === 'Identifier') names.push(node.name)
|
||||
else if (node.type === 'RestElement') collectPatternNames(node.argument, names)
|
||||
else if (node.type === 'AssignmentPattern') collectPatternNames(node.left, names)
|
||||
else if (node.type === 'ArrayPattern') node.elements.forEach((entry) => collectPatternNames(entry, names))
|
||||
else if (node.type === 'ObjectPattern') {
|
||||
for (const property of node.properties) {
|
||||
if (property.type === 'RestElement') collectPatternNames(property.argument, names)
|
||||
else collectPatternNames(property.value, names)
|
||||
}
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
function collectDynamicImportPaths(source) {
|
||||
const ast = parse(source, { sourceType: 'module' })
|
||||
const paths = new Set()
|
||||
traverse(ast, {
|
||||
ImportExpression(pathRef) {
|
||||
const sourceNode = pathRef.node.source
|
||||
if (sourceNode.type === 'StringLiteral') paths.add(sourceNode.value)
|
||||
else if (sourceNode.type === 'TemplateLiteral' && sourceNode.expressions.length === 0) {
|
||||
paths.add(sourceNode.quasis[0].value.cooked)
|
||||
}
|
||||
},
|
||||
})
|
||||
return paths
|
||||
}
|
||||
|
||||
function renameTopLevelBinding(source, fromName, toName, sourcePath) {
|
||||
if (!source.includes(fromName)) return { source, renameCount: 0 }
|
||||
if (source.includes(toName)) fail(`Reserved recovery identifier already exists in ${sourcePath}`)
|
||||
|
||||
const ast = parse(source, { sourceType: 'module' })
|
||||
let foundBinding = false
|
||||
traverse(ast, {
|
||||
Program(pathRef) {
|
||||
pathRef.scope.crawl()
|
||||
if (pathRef.scope.getBinding(fromName)) {
|
||||
pathRef.scope.rename(fromName, toName)
|
||||
foundBinding = true
|
||||
}
|
||||
pathRef.stop()
|
||||
},
|
||||
})
|
||||
if (!foundBinding) return { source, renameCount: 0 }
|
||||
|
||||
const edits = []
|
||||
traverse(ast, {
|
||||
Identifier(pathRef) {
|
||||
const { start, end, name } = pathRef.node
|
||||
if (name === toName && source.slice(start, end) === fromName) edits.push({ start, end })
|
||||
},
|
||||
})
|
||||
if (edits.length < 2) fail(`Babel scope rename did not capture the binding and its references in ${sourcePath}`)
|
||||
let renamedSource = source
|
||||
for (const { start, end } of edits.sort((left, right) => right.start - left.start)) {
|
||||
renamedSource = `${renamedSource.slice(0, start)}${toName}${renamedSource.slice(end)}`
|
||||
}
|
||||
return { source: renamedSource, renameCount: edits.length }
|
||||
}
|
||||
|
||||
function closeBindings(source) {
|
||||
const ast = parse(source, { sourceType: 'module' })
|
||||
let programPath
|
||||
traverse(ast, {
|
||||
Program(pathRef) {
|
||||
programPath = pathRef
|
||||
pathRef.scope.crawl()
|
||||
pathRef.stop()
|
||||
},
|
||||
})
|
||||
|
||||
const included = new Map()
|
||||
const queue = []
|
||||
const imported = new Map()
|
||||
const enqueue = (binding) => {
|
||||
if (!binding || binding.scope !== programPath.scope || included.has(binding.identifier.name)) return
|
||||
included.set(binding.identifier.name, binding)
|
||||
queue.push(binding)
|
||||
}
|
||||
const visitReferences = (pathRef) => {
|
||||
pathRef.traverse({
|
||||
Identifier(reference) {
|
||||
if (!reference.isReferencedIdentifier() && !reference.isBindingIdentifier()) return
|
||||
enqueue(reference.scope.getBinding(reference.node.name))
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
enqueue(programPath.scope.getBinding('Po'))
|
||||
while (queue.length > 0) {
|
||||
const binding = queue.shift()
|
||||
if (binding.kind === 'module') {
|
||||
const declaration = binding.path.findParent((candidate) => candidate.isImportDeclaration())
|
||||
if (declaration) {
|
||||
const locals = imported.get(declaration.node.source.value) ?? new Set()
|
||||
locals.add(binding.identifier.name)
|
||||
imported.set(declaration.node.source.value, locals)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (binding.path.isFunctionDeclaration() || binding.path.isClassDeclaration()) {
|
||||
visitReferences(binding.path)
|
||||
continue
|
||||
}
|
||||
if (!binding.path.isVariableDeclarator()) continue
|
||||
|
||||
if (binding.path.node.init) visitReferences(binding.path.get('init'))
|
||||
else {
|
||||
for (const violation of binding.constantViolations) {
|
||||
visitReferences(violation)
|
||||
const owner = violation.findParent((candidate) => candidate.isVariableDeclarator())
|
||||
if (owner && owner !== binding.path && owner.node.id.type === 'Identifier') {
|
||||
enqueue(programPath.scope.getBinding(owner.node.id.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const declarationChunks = []
|
||||
for (const statement of ast.program.body) {
|
||||
if (statement.type === 'ImportDeclaration') {
|
||||
if (REACT_IMPORTS.has(statement.source.value)) continue
|
||||
const names = imported.get(statement.source.value)
|
||||
if (!names || names.size === 0) continue
|
||||
const specifiers = statement.specifiers.filter((specifier) => names.has(specifier.local.name))
|
||||
if (specifiers.length === 0) continue
|
||||
const defaultImport = specifiers.find((specifier) => specifier.type === 'ImportDefaultSpecifier')
|
||||
const namespaceImport = specifiers.find((specifier) => specifier.type === 'ImportNamespaceSpecifier')
|
||||
const namedImports = specifiers.filter((specifier) => specifier.type === 'ImportSpecifier')
|
||||
const parts = []
|
||||
if (defaultImport) parts.push(defaultImport.local.name)
|
||||
if (namespaceImport) parts.push(`* as ${namespaceImport.local.name}`)
|
||||
if (namedImports.length > 0) {
|
||||
parts.push(`{ ${namedImports.map((specifier) => {
|
||||
const importedName = specifier.imported.name ?? specifier.imported.value
|
||||
return importedName === specifier.local.name ? importedName : `${importedName} as ${specifier.local.name}`
|
||||
}).join(', ')} }`)
|
||||
}
|
||||
declarationChunks.push(`import ${parts.join(', ')} from ${JSON.stringify(statement.source.value)};`)
|
||||
continue
|
||||
}
|
||||
|
||||
if (statement.type === 'VariableDeclaration') {
|
||||
for (const declaration of statement.declarations) {
|
||||
const names = collectPatternNames(declaration.id)
|
||||
if (!names.some((name) => included.has(name))) continue
|
||||
declarationChunks.push(`${statement.kind} ${source.slice(declaration.start, declaration.end)};`)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if ((statement.type === 'FunctionDeclaration' || statement.type === 'ClassDeclaration') &&
|
||||
included.has(statement.id?.name)) {
|
||||
declarationChunks.push(source.slice(statement.start, statement.end))
|
||||
}
|
||||
}
|
||||
|
||||
const reactImports = [
|
||||
`import * as __ycodeReact from 'react';`,
|
||||
`import * as __ycodeReactDOM from 'react-dom';`,
|
||||
`import * as __ycodeJsxRuntime from 'react/jsx-runtime';`,
|
||||
`const s = () => __ycodeReact;`,
|
||||
`const c = () => __ycodeReactDOM;`,
|
||||
`const f = () => __ycodeJsxRuntime;`,
|
||||
]
|
||||
const prefix = [
|
||||
`// Generated from REA shipped-artifact Evidence; edits belong in recover-pierre-diff.mjs.`,
|
||||
`// Source: renderer/assets/codeEditor-D3P9alks.js; sha256: 5e9a16dca97c102afc3c73cd7dd32ba63daf5e7ddff12707ee1ea63e7a427b19.`,
|
||||
...reactImports,
|
||||
].join('\n')
|
||||
const body = declarationChunks.join('\n')
|
||||
const suffix = [
|
||||
`Po();`,
|
||||
`export { No as PierreDiffEditor, buildFileDiff, processFile, parseDiffFromFile, getFiletypeFromFileName };`,
|
||||
].join('\n')
|
||||
return { code: `${prefix}\n${body}\n${suffix}\n`, bindingCount: included.size, imports: new Set(imported.keys()) }
|
||||
}
|
||||
|
||||
async function writeIfAbsentOrSame(filePath, text) {
|
||||
try {
|
||||
const previous = await fs.readFile(filePath, 'utf8')
|
||||
if (previous === text) return
|
||||
const generatedEngine = path.basename(filePath) === 'engine.mjs' &&
|
||||
previous.startsWith('// Generated from REA shipped-artifact Evidence; edits belong in recover-pierre-diff.mjs.')
|
||||
let generatedManifest = false
|
||||
if (path.basename(filePath) === 'manifest.json') {
|
||||
try {
|
||||
generatedManifest = JSON.parse(previous).kind === 'rea-selected-pierre-diff-recovery'
|
||||
} catch {
|
||||
generatedManifest = false
|
||||
}
|
||||
}
|
||||
if (!generatedEngine && !generatedManifest) fail(`Refusing to overwrite changed recovered artifact: ${filePath}`)
|
||||
await fs.writeFile(filePath, text, 'utf8')
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT') throw error
|
||||
await fs.writeFile(filePath, text, 'utf8')
|
||||
}
|
||||
}
|
||||
|
||||
const [mainSource, dependencies, leafDependencies, uiLanguages] = await Promise.all([
|
||||
loadEvidence(MAIN_EVIDENCE_PATH),
|
||||
loadEvidence(DEPENDENCY_EVIDENCE_PATH),
|
||||
loadEvidence(LEAF_EVIDENCE_PATH),
|
||||
loadEvidence(LANGUAGE_EVIDENCE_PATH),
|
||||
])
|
||||
const dynamicEvidencePaths = (await fs.readdir('.tmp'))
|
||||
.filter((fileName) => /^rea-selected-pierre-chunks-\d{3}\.json$/u.test(fileName))
|
||||
.map((fileName) => path.join('.tmp', fileName))
|
||||
.sort()
|
||||
if (dynamicEvidencePaths.length === 0) fail('No REA-selected Pierre dynamic chunk Evidence was found')
|
||||
const dynamicEvidence = await Promise.all(dynamicEvidencePaths.map(loadEvidence))
|
||||
const evidenceSet = [mainSource, dependencies, leafDependencies, uiLanguages, ...dynamicEvidence]
|
||||
const sources = new Map()
|
||||
for (const evidence of evidenceSet) {
|
||||
for (const [sourcePath, file] of evidence.files) {
|
||||
const existing = sources.get(sourcePath)
|
||||
if (existing && (existing.sha256 !== file.sha256 || existing.size_bytes !== file.size_bytes)) {
|
||||
fail(`Conflicting REA Evidence for selected file ${sourcePath}`)
|
||||
}
|
||||
sources.set(sourcePath, file)
|
||||
}
|
||||
}
|
||||
|
||||
for (const [sourcePath, expectedKind] of Object.entries(SOURCE_FILES)) {
|
||||
if (!sources.has(sourcePath)) fail(`Required selected REA source is missing (${expectedKind}): ${sourcePath}`)
|
||||
}
|
||||
const appPackage = JSON.parse(sources.get('package.json').text)
|
||||
if (appPackage.version !== '5.8.2') fail(`Unexpected WorkBuddy app version: ${appPackage.version}`)
|
||||
|
||||
const mainText = sources.get('renderer/assets/codeEditor-D3P9alks.js').text
|
||||
const dynamicImportPaths = collectDynamicImportPaths(mainText)
|
||||
const dynamicAssetPaths = [...dynamicImportPaths].map((importPath) => {
|
||||
if (!importPath.startsWith('./') || !importPath.endsWith('.js')) {
|
||||
fail(`Unexpected non-local dynamic chunk path in CodeView: ${importPath}`)
|
||||
}
|
||||
return `renderer/assets/${importPath.slice(2)}`
|
||||
})
|
||||
for (const sourcePath of dynamicAssetPaths) {
|
||||
if (!sources.has(sourcePath)) fail(`REA dynamic chunk evidence is missing ${sourcePath}`)
|
||||
}
|
||||
const extracted = closeBindings(mainText)
|
||||
if (extracted.bindingCount < 700) fail(`Pierre closure is unexpectedly incomplete: ${extracted.bindingCount} bindings`)
|
||||
if (extracted.imports.has('./src-0FGg1seX.js') || extracted.imports.has('./monaco-init-CE4MbM4x.js')) {
|
||||
fail('Pierre closure unexpectedly depends on app shared code or Monaco initialization')
|
||||
}
|
||||
const renamedEngine = renameTopLevelBinding(
|
||||
extracted.code,
|
||||
VITE_PRELOAD_HELPER,
|
||||
RECOVERED_PRELOAD_HELPER,
|
||||
'recovered engine.mjs',
|
||||
)
|
||||
|
||||
const cssSource = sources.get('renderer/assets/codeEditor-Bxmo_AI3.css').text
|
||||
const cssAst = postcss.parse(cssSource)
|
||||
const cssRules = []
|
||||
cssAst.walkRules((rule) => {
|
||||
if (rule.selectors?.some((selector) => selector.includes('_pierre-diff-editor'))) {
|
||||
cssRules.push(cssSource.slice(rule.source.start.offset, rule.source.end.offset))
|
||||
}
|
||||
})
|
||||
if (cssRules.length !== 8) fail(`Expected eight exact Pierre CSS module rules, found ${cssRules.length}`)
|
||||
|
||||
await fs.mkdir(OUTPUT_DIRECTORY, { recursive: true })
|
||||
await writeIfAbsentOrSame(path.join(OUTPUT_DIRECTORY, 'engine.mjs'), renamedEngine.source)
|
||||
await writeIfAbsentOrSame(path.join(OUTPUT_DIRECTORY, 'engine.css'), `${cssRules.join('\n')}\n`)
|
||||
|
||||
const assetRecords = []
|
||||
const copyingAssetPaths = [...new Set([...COPYING_ASSETS, ...dynamicAssetPaths])]
|
||||
for (const sourcePath of copyingAssetPaths) {
|
||||
const source = sources.get(sourcePath)
|
||||
if (!source) fail(`Required selected REA asset is missing: ${sourcePath}`)
|
||||
const fileName = path.posix.basename(sourcePath)
|
||||
const renamedAsset = renameTopLevelBinding(
|
||||
source.text,
|
||||
VITE_PRELOAD_HELPER,
|
||||
RECOVERED_PRELOAD_HELPER,
|
||||
sourcePath,
|
||||
)
|
||||
await writeIfAbsentOrSame(path.join(OUTPUT_DIRECTORY, fileName), renamedAsset.source)
|
||||
assetRecords.push({
|
||||
path: fileName,
|
||||
bytes: source.size_bytes,
|
||||
sha256: source.sha256,
|
||||
renamed_top_level_preload_helper_references: renamedAsset.renameCount,
|
||||
})
|
||||
}
|
||||
|
||||
const outputs = ['engine.mjs', 'engine.css', ...assetRecords.map((asset) => asset.path)]
|
||||
const outputRecords = []
|
||||
for (const fileName of outputs) {
|
||||
const content = await fs.readFile(path.join(OUTPUT_DIRECTORY, fileName))
|
||||
outputRecords.push({ path: fileName, bytes: content.length, sha256: sha256(content) })
|
||||
}
|
||||
const manifest = {
|
||||
kind: 'rea-selected-pierre-diff-recovery',
|
||||
target: { name: appPackage.name, version: appPackage.version, root_sha256: EXPECTED_ROOT_SHA256 },
|
||||
evidence: {
|
||||
renderer: mainSource.evidence.evidence_id,
|
||||
dependencies: dependencies.evidence.evidence_id,
|
||||
leaf_dependencies: leafDependencies.evidence.evidence_id,
|
||||
ui_languages: uiLanguages.evidence.evidence_id,
|
||||
dynamic_chunks: dynamicEvidence.map(({ evidence }) => evidence.evidence_id),
|
||||
},
|
||||
renderer_source: {
|
||||
path: 'renderer/assets/codeEditor-D3P9alks.js',
|
||||
sha256: '5e9a16dca97c102afc3c73cd7dd32ba63daf5e7ddff12707ee1ea63e7a427b19',
|
||||
closure_program_bindings: extracted.bindingCount,
|
||||
imports: [...extracted.imports].sort(),
|
||||
dynamic_import_count: dynamicImportPaths.size,
|
||||
dynamic_import_files: dynamicAssetPaths,
|
||||
renamed_top_level_preload_helper: {
|
||||
from: VITE_PRELOAD_HELPER,
|
||||
to: RECOVERED_PRELOAD_HELPER,
|
||||
references: renamedEngine.renameCount,
|
||||
},
|
||||
},
|
||||
css_source: {
|
||||
path: 'renderer/assets/codeEditor-Bxmo_AI3.css',
|
||||
sha256: '1c8f2210c731a25f9051088df0db78b9de5b087c802b3a9e36828c1b6b54c353',
|
||||
exact_pierre_rules: cssRules.length,
|
||||
},
|
||||
dynamic_chunk_assets: dynamicAssetPaths.length,
|
||||
vite_preload_helper_rename: {
|
||||
from: VITE_PRELOAD_HELPER,
|
||||
to: RECOVERED_PRELOAD_HELPER,
|
||||
affected_assets: assetRecords.filter((asset) => asset.renamed_top_level_preload_helper_references > 0)
|
||||
.map((asset) => ({ path: asset.path, references: asset.renamed_top_level_preload_helper_references })),
|
||||
},
|
||||
limitations: [
|
||||
'The original package manifest contains no Pierre or Shiki package version; this is a source-locked bundle recovery, not an npm package pin.',
|
||||
'The optional shiki-wasm branch references renderer/assets/wasm-B9ZqxnKj.js, which the REA selector reports absent; the recovered component config uses the shiki-js engine.',
|
||||
'Every static dynamic import in codeEditor-D3P9alks.js was selected through REA and copied; unselected app-shared and Monaco bundles are excluded from this component closure.',
|
||||
],
|
||||
assets: assetRecords,
|
||||
outputs: outputRecords,
|
||||
}
|
||||
await writeIfAbsentOrSame(path.join(OUTPUT_DIRECTORY, 'manifest.json'), `${JSON.stringify(manifest, null, 2)}\n`)
|
||||
|
||||
console.log(JSON.stringify({
|
||||
outputDirectory: OUTPUT_DIRECTORY,
|
||||
closureProgramBindings: extracted.bindingCount,
|
||||
closureBytes: Buffer.byteLength(extracted.code, 'utf8'),
|
||||
renamedPreloadHelperReferences: renamedEngine.renameCount,
|
||||
importedModules: [...extracted.imports].sort(),
|
||||
dynamicChunks: dynamicImportPaths.size,
|
||||
cssRules: cssRules.length,
|
||||
assets: assetRecords.length,
|
||||
manifest: path.join(OUTPUT_DIRECTORY, 'manifest.json'),
|
||||
}, null, 2))
|
||||
Reference in new issue
Block a user