Files
dsh-web/scripts/sync-shared.test.mjs
zhu1090093659 dc7e26b9f0 refactor(shared): drop dead shared artifacts and realign references
- Remove the sync-manifest entry for shared/host/run-guarded.ts and the three
  generated copies under packages/{dsh-usage,dsh-task-board,dsh-git-graph}/src/host/:
  nothing in this repository imported the module (the satellite repositories
  carry their own copies), so the entry only kept three unread files in sync.
  The shared source and its spec stay.
- Delete the unused mobileBundle helper and its node:module createRequire import
  from shared/tsdown.client.ts; the standalone mobile bundle has been gone since
  0.4.0.
- Update the sync composition guard in scripts/sync-shared.test.mjs (99 -> 96
  copies, 48 -> 45 host copies) and refresh scripts/lib-artifact-fingerprints.json.
- Re-point the notes, READMEs, CONTRIBUTING and docs that still linked the
  skin-center contract files to the dsh-skins repository, and prune the stale
  screenshots.
- Record the decision in
  .agents/notes/implemented/simplification/2026-09-26-dead-shared-artifacts-removed.md
  and correct the run-guarded facts in the aggregate fault-isolation note.
2026-09-27 20:47:07 +08:00

99 lines
6.4 KiB
JavaScript

import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import assert from 'node:assert/strict'
import { test } from 'node:test'
import { REPO_ROOT, applySync, checkSync, copyEntries, headerFor, renderCopy, stripHeader } from './sync-shared.mjs'
test('header/strip round-trips every file kind', () => {
for (const file of ['settings-form.ts', 'PluginSettingsCard.tsx', 'settings-card.module.css']) {
const source = 'export const x = 1' + String.fromCharCode(10)
const sourceRel = 'shared/client/settings/' + file
const rendered = renderCopy(source, file, sourceRel)
assert.ok(rendered.startsWith(headerFor(file, sourceRel)))
assert.equal(stripHeader(rendered, file, sourceRel), source)
assert.equal(stripHeader('mangled ' + rendered.slice(10), file, sourceRel), undefined)
}
})
test('copies cover the settings trio for all consumers plus host and http helpers', () => {
// Normalize separators: node:path join yields backslashes on Windows, and
// the copy-count buckets below match on forward slashes.
const entries = copyEntries().map(entry => ({ ...entry, target: entry.target.replaceAll('\\', '/') }))
// The total is every generated copy in the manifest; the single-instance
// guard alone contributes one mount-once.ts per host half (13 today). The
// buckets below split the same set by target location, and what neither
// bucket holds is the package-root test setup (5 today) plus the per-package
// http.ts and console-output.ts copies. The settings bucket is the card trio
// plus the entry-bound form fallback, the latter one per package whose card
// binds a family namespace (6 today). Every family panel now renders through
// the native layout seats, so the panel-mount-core and sidebar-entry-core
// copies are gone and body-mutations serves only the aggregate shell and the
// usage card. run-guarded.ts is not synced here: no in-repo package imports
// it (the satellite repositories that do carry their own copies), so only the
// shared source and its spec remain in this repository.
assert.equal(entries.length, 96)
const clientTrio = entries.filter(entry => entry.target.includes('/src/client/'))
assert.equal(clientTrio.length, 39)
const hostCopies = entries.filter(entry => entry.target.includes('/src/host/')
|| entry.target.includes('/src/dsh-home.ts')
|| entry.target.includes('/src/mount-once.ts')
|| entry.target.includes('/src/loopback.ts')
|| entry.target.includes('/src/pair-access.ts')
|| entry.target.includes('/src/agent/')
|| entry.target.endsWith('/packages/dsh-task-board/src/http.ts'))
assert.equal(hostCopies.length, 45)
})
test('checkSync detects drift and applySync repairs it', async () => {
const root = await mkdtemp(join(tmpdir(), 'sync-shared-test-'))
try {
// Fake tree: shared source + one consumer copy with wrong content.
const sourceDir = join(root, 'shared', 'client', 'settings')
await mkdir(sourceDir, { recursive: true })
await writeFile(join(sourceDir, 'settings-form.ts'), 'export const good = 1' + String.fromCharCode(10))
await writeFile(join(sourceDir, 'PluginSettingsCard.tsx'), 'export const card = 1' + String.fromCharCode(10))
await writeFile(join(sourceDir, 'settings-card.module.css'), '.card { color: red }' + String.fromCharCode(10))
await writeFile(join(sourceDir, 'plugin-card-seat.ts'), 'export const seat = 1' + String.fromCharCode(10))
await writeFile(join(sourceDir, 'settings-entry-form.ts'), 'export const entry = 1' + String.fromCharCode(10))
await writeFile(join(root, 'shared', 'client', 'telemetry.ts'), 'export const beat = 1' + String.fromCharCode(10))
await writeFile(join(root, 'shared', 'client', 'sse-leader.ts'), 'export const leader = 1' + String.fromCharCode(10))
await writeFile(join(root, 'shared', 'client', 'body-mutations.ts'), 'export const hub = 1' + String.fromCharCode(10))
await writeFile(join(root, 'shared', 'client', 'main-session.ts'), 'export const main = 1' + String.fromCharCode(10))
const hostDir = join(root, 'shared', 'host')
await mkdir(hostDir, { recursive: true })
await writeFile(join(hostDir, 'poll-guard.ts'), 'export const guard = 1' + String.fromCharCode(10))
await writeFile(join(hostDir, 'dsh-home.ts'), 'export const home = 1' + String.fromCharCode(10))
await writeFile(join(hostDir, 'loopback.ts'), 'export const loop = 1' + String.fromCharCode(10))
await writeFile(join(hostDir, 'pair-access.ts'), 'export const fence = 1' + String.fromCharCode(10))
await writeFile(join(root, 'shared', 'vitest.setup.ts'), 'export {}' + String.fromCharCode(10))
await writeFile(join(hostDir, 'git-runner.ts'), 'export const runner = 1' + String.fromCharCode(10))
await writeFile(join(hostDir, 'mount-once.ts'), 'export const once = 1' + String.fromCharCode(10))
await writeFile(join(hostDir, 'http.ts'), 'export const http = 1' + String.fromCharCode(10))
await writeFile(join(hostDir, 'legacy-migration.ts'), 'export const legacy = 1' + String.fromCharCode(10))
await writeFile(join(hostDir, 'run-guarded.ts'), 'export const guard2 = 1' + String.fromCharCode(10))
await writeFile(join(hostDir, 'console-output.ts'), 'export const capture = 1' + String.fromCharCode(10))
const targetDir = join(root, 'packages', 'dsh-task-board', 'src', 'client')
await mkdir(targetDir, { recursive: true })
await writeFile(join(targetDir, 'settings-form.ts'), renderCopy('export const bad = 2' + String.fromCharCode(10), 'settings-form.ts', 'shared/client/settings/settings-form.ts'))
// checkSync compares all consumers; the missing files count as drift too.
const before = await checkSync(root)
assert.ok(before.some(entry => entry.reason === 'content drifted from shared source'))
assert.ok(before.some(entry => entry.reason === 'missing'))
await applySync(root)
const after = await checkSync(root)
assert.deepEqual(after, [])
const fixed = await readFile(join(targetDir, 'settings-form.ts'), 'utf8')
assert.equal(stripHeader(fixed, 'settings-form.ts', 'shared/client/settings/settings-form.ts'), 'export const good = 1' + String.fromCharCode(10))
} finally {
await rm(root, { recursive: true, force: true })
}
})
test('the live tree is in sync', async () => {
const drift = await checkSync()
assert.deepEqual(drift, [])
})