t32-commit-visibility.mjs 6.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. // Isolate ticket32 visibility changes; preserve concurrent worktree and staged files.
  2. import { spawnSync } from 'node:child_process'
  3. import { mkdtempSync, readFileSync } from 'node:fs'
  4. import { tmpdir } from 'node:os'
  5. import { join } from 'node:path'
  6. const paths=[
  7. 'CONTEXT.md','public/cockpit/models/pipes/README.md','tools/pipe-models/README.md',
  8. 'tools/pipe-models/visibility.html','tools/pipe-models/cockpitAcceptance.js',
  9. 'src/modules/cockpit/domain/pipeVisual.js','src/modules/cockpit/domain/pipeModels.js','src/modules/cockpit/domain/pipeNetwork.js','src/modules/cockpit/domain/viewModes.js',
  10. 'src/modules/cockpit/services/pipeModelShader.js','src/modules/cockpit/services/cesiumPipeModels.js',
  11. '.scratch/cockpit-real-data-wayfinding/issues/32-32.md',
  12. '.scratch/cockpit-real-data-wayfinding/verify/t32-visibility-style.mjs','.scratch/cockpit-real-data-wayfinding/verify/t32-color-layer.mjs','.scratch/cockpit-real-data-wayfinding/verify/t32-adapter-behavior.mjs',
  13. '.scratch/cockpit-real-data-wayfinding/verify/artifacts/t32/visibility-fix-and-evidence.md',
  14. '.scratch/cockpit-real-data-wayfinding/verify/artifacts/t32/visibility-performance.json',
  15. '.scratch/cockpit-real-data-wayfinding/verify/artifacts/t32/visibility-4k-real-pipes.jpg',
  16. '.scratch/cockpit-real-data-wayfinding/verify/artifacts/t32/visibility-shared-cockpit-near.jpg',
  17. '.scratch/cockpit-real-data-wayfinding/verify/artifacts/t32/visibility-shared-manhole-purple.jpg',
  18. ]
  19. const shared=['src/modules/cockpit/components/MapInfoPanel.vue','src/modules/cockpit/services/cesiumEngine.js','src/modules/cockpit/services/cesiumPipeLayer.js']
  20. function git(args,{input,env=process.env}={}) {const r=spawnSync('git',args,{input,env,encoding:'utf8'});if(r.status!==0)throw new Error(r.stderr||r.stdout);return r.stdout}
  21. function once(s,a,b){if(s.split(a).length!==2)throw new Error('Stage anchor ambiguous: '+a.slice(0,60));return s.replace(a,b)}
  22. const head=git(['rev-parse','HEAD']).trim()
  23. const other=git(['diff','--cached','--name-only']).trim().split('\n').filter(Boolean)
  24. if(other.some(p=>paths.includes(p)||shared.includes(p)))throw new Error('Concurrent staged path overlap; inspect before committing')
  25. const env={...process.env,GIT_INDEX_FILE:join(mkdtempSync(join(tmpdir(),'t32-visibility-index-')),'index')}
  26. git(['read-tree',head],{env});git(['add','--',...paths],{env})
  27. for(const p of shared){
  28. let s=git(['show',head+':'+p]).replace(/\r\n/g,'\n')
  29. const current=readFileSync(p,'utf8').replace(/\r\n/g,'\n')
  30. if(p.endsWith('MapInfoPanel.vue')){
  31. const marker=' <p class="map-info__note" data-pipe-model-note>'
  32. const start=current.indexOf(' <div class="map-info__pipe-colors"'),end=current.indexOf(marker,start)
  33. s=once(s,marker,current.slice(start,end)+marker)
  34. s=once(s,"import { PIPE_MODEL_NOTE } from '../domain/pipeModels.js'", "import { PIPE_MODEL_NOTE } from '../domain/pipeModels.js'\nimport { PIPE_PALETTE } from '../domain/pipeVisual.js'\nconst PIPE_COLOR_KEYS = ['GAS','WATER_SUPPLY','SEWAGE','RAINWATER','MANHOLE','DRAINAGE_UNKNOWN']")
  35. const style=current.slice(current.indexOf('.map-info__pipe-colors {'),current.indexOf('.map-info__layers {'))
  36. s=once(s,'.map-info__layers {',style+'.map-info__layers {')
  37. }else if(p.endsWith('cesiumEngine.js')){
  38. if(s.includes('varying vec2 v_textureCoordinates;')) s=once(s,'varying vec2 v_textureCoordinates;','in vec2 v_textureCoordinates;')
  39. else if(!s.includes('in vec2 v_textureCoordinates;')) throw new Error('Unexpected scene-grade shader baseline')
  40. }else{
  41. // Existing ticket33 diff implementation is deliberately left in the worktree only.
  42. s=once(s,"import { pipeWidth } from '../domain/pipeNetwork.js'","import { PIPE_DISPLAY, PIPE_PALETTE, pipeColorKey } from '../domain/pipeVisual.js'")
  43. const start=s.indexOf('/** 行业色'),end=s.indexOf('/** 一个瓦片数据源内的实体索引',start)
  44. if(start<0||end<start)throw new Error('Missing original palette range')
  45. const palette=`function visualColor(row) {\n return Color.fromCssColorString(PIPE_PALETTE[pipeColorKey(row)].color)\n}\n\n/** 构件只决定形状尺寸与标签;颜色统一由行业/备注决定。 */\nconst COMPONENT_STYLE = {\n valve: { label: '阀门', size: 9 },\n elbow: { label: '角管道', size: 7 },\n branch: { label: '支管管道', size: 8 },\n other: { label: '其它构件', size: 6 },\n}\n\n`
  46. s=s.slice(0,start)+palette+s.slice(end)
  47. s=once(s,' const color = industryColor(pipe.industry)',' const color = visualColor(pipe)')
  48. s=once(s,' width: pipeWidth(pipe.diameter),\n material: color.withAlpha(0.85),',' width: PIPE_DISPLAY.guideWidthPx,\n material: color.withAlpha(1),')
  49. s=once(s,' const style = Object.prototype.hasOwnProperty.call(COMPONENT_STYLE, component.kind) ? COMPONENT_STYLE[component.kind] : COMPONENT_STYLE.other'," const style = component.industry === 'MANHOLE'\n ? { label:'窨井', size:12 }\n : (Object.prototype.hasOwnProperty.call(COMPONENT_STYLE, component.kind) ? COMPONENT_STYLE[component.kind] : COMPONENT_STYLE.other)")
  50. s=once(s,' color: Color.fromCssColorString(style.color),',' color: visualColor(component),')
  51. s=once(s,' // Keep fallback entities until ALL model spans for that business object signal ready.\n // The model adapter alone controls entity.show; unchanged geometries still stay untouched (ticket 33).',' // Pending/failed objects keep guides; ready pipes retain only distant guides and show close-up volume.\n // The model adapter controls visibility/distance without reassigning unchanged geometry.')
  52. }
  53. const hash=git(['hash-object','-w','--stdin'],{input:s}).trim();git(['update-index','--cacheinfo',`100644,${hash},${p}`],{env})
  54. }
  55. git(['diff','--cached','--check'],{env});console.log(git(['diff','--cached','--stat'],{env}))
  56. if(git(['rev-parse','HEAD']).trim()!==head)throw new Error('Concurrent HEAD changed; retry with current baseline')
  57. console.log(git(['commit','-m','fix(cockpit): make 3D pipes visible with semantic colors (#32)'],{env}))
  58. git(['reset','--quiet','HEAD','--',...paths,...shared])
  59. const after=git(['diff','--cached','--name-only']).trim().split('\n').filter(Boolean)
  60. if(after.join('\n')!==other.join('\n'))throw new Error('Concurrent index path list changed; inspect')
  61. console.log('Unrelated staged paths preserved:',after.length)