Skip to content

Commit b3b25a5

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
refactor: consolidate design policy and remove obsolete analysis
1 parent 7ee32ff commit b3b25a5

13 files changed

Lines changed: 97 additions & 215 deletions

File tree

‎design-diff.config.json‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,7 @@
111111
"list": "apps/docs/lib/openapi-specs.ts",
112112
"export": "OPENAPI_SPEC_FILES",
113113
"root": "apps/docs",
114-
"renderer": "apps/docs/lib/openapi.ts",
115-
"contentOnly": true
114+
"renderer": "apps/docs/lib/openapi.ts"
116115
}
117116
],
118117
"environmentAdapters": [

‎scripts/design-diff/README.md‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ Large opaque resolver trees can themselves exceed the supported analysis budget;
133133
uncertainty, not evidence of an appearance edit.
134134

135135
Operational failures remain distinct from completed policy exemptions. Configured file-loaded
136-
OpenAPI inputs are validated as Git data; content is exempt and malformed inputs retain diagnostic
137-
evidence. Lockfile rendering-dependency changes retain diagnostics but do not qualify by themselves.
136+
OpenAPI inputs in the head revision are validated as Git data; content is exempt and malformed
137+
inputs retain diagnostic evidence. Lockfile rendering-dependency changes retain diagnostics but do not qualify by themselves.
138138

139139
## Files
140140

@@ -151,7 +151,7 @@ scripts/design-diff/
151151
finite.ts, environment.ts Finite key and environment projections
152152
appearance.ts Supported appearance evidence projection
153153
tailwind.ts Pinned compiler and trusted class helpers
154-
compare.ts, policy.ts, movement.ts Matching, decisions and categories
154+
compare.ts, policy.ts Matching, decisions and categories
155155
group.ts, report.ts, semantic.ts Grouping, full hashes and bounded JSON
156156
inputs.ts Configured file inputs
157157
infrastructure.ts Rendering dependency diagnostics
@@ -200,8 +200,10 @@ Fixtures stay inside test strings/JSON so application builds and styling scans d
200200

201201
The frozen manifest contains the original 120 comparisons plus 60 later sampled holdouts. Its
202202
original labels use a broader visual/content policy and must not be treated as policy-5 ground
203-
truth. Preserve original labels and document policy-specific review separately. The prior policy-4
204-
run completed 178/180 comparisons, flagging 112; two timed out. That is historical context only.
203+
truth. Both cohorts have now informed development and are no longer unseen validation. Keep the
204+
engine and configuration fixed while evaluating the next sample, label it independently, and
205+
report disagreements before changing rules. The production CLI never reads benchmark labels or PR
206+
numbers to make decisions; repository conventions belong in configuration, not per-PR exceptions.
205207

206208
The runner verifies exact commits and GitHub file sets. Its cache identity includes immutable
207209
engine SHA, configuration, lockfile, runtime and comparison commits. It records elapsed time,

‎scripts/design-diff/analyze.ts‎

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { extractTsx } from '#design-diff/extract/tsx'
77
import { GitReader } from '#design-diff/git'
88
import { groupFindings } from '#design-diff/group'
99
import { renderingLock } from '#design-diff/infrastructure'
10-
import { fileLoadedInputs } from '#design-diff/inputs'
10+
import { fileLoadedInputDiagnostics } from '#design-diff/inputs'
1111
import { reclaimMemory } from '#design-diff/memory'
1212
import { limitations } from '#design-diff/policy'
1313
import { Resolver } from '#design-diff/resolve'
@@ -165,15 +165,6 @@ export async function analyze(
165165
'Native menus, palettes and embedded rendering need review'
166166
)
167167
)
168-
for (const definition of defs) {
169-
if (
170-
definition.movement &&
171-
[...tree.texts].some(
172-
([name, text]) => name.endsWith('.css') && /\b(?:svg|rect|circle)\b|\*/.test(text)
173-
)
174-
)
175-
definition.movement = undefined
176-
}
177168
const normalized: Definition[] = []
178169
for (const definition of defs) normalized.push(await tailwind.normalize(definition))
179170
return normalized
@@ -250,7 +241,7 @@ export async function analyze(
250241
...b.flatMap((definition) => definition.unresolved),
251242
]),
252243
].sort()
253-
findings.push(...compareDefinitions(a, b, affected))
244+
findings.push(...compareDefinitions(a, b))
254245
if (!changed.has(file) && (a.length || b.length)) indirectExamples++
255246
if (
256247
changed.has(file) &&
@@ -271,8 +262,7 @@ export async function analyze(
271262
after.entries.get(file)?.oid ?? '',
272263
'Rendering infrastructure is not executed'
273264
)
274-
: undefined,
275-
'Rendering infrastructure changed'
265+
: undefined
276266
)
277267
)
278268
}
@@ -350,7 +340,7 @@ export async function analyze(
350340
)
351341
}
352342
}
353-
findings.push(...fileLoadedInputs(before, after, config))
343+
findings.push(...fileLoadedInputDiagnostics(after, config))
354344
if (findings.length && !before.graph) {
355345
before.buildGraph()
356346
after.buildGraph()

‎scripts/design-diff/compare.ts‎

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { createHash } from 'node:crypto'
22
import { appearanceValue } from '#design-diff/appearance'
3-
import { pureMovement } from '#design-diff/movement'
43
import { changedCategory } from '#design-diff/policy'
54
import { previewChange } from '#design-diff/report'
65
import type { Change, Definition } from '#design-diff/types'
@@ -9,44 +8,27 @@ function signature(definition: Definition) {
98
return JSON.stringify([definition.value, definition.conditions])
109
}
1110

12-
export function finding(
13-
before: Definition | undefined,
14-
after: Definition | undefined,
15-
reason?: string
16-
): Change {
11+
export function finding(before: Definition | undefined, after: Definition | undefined): Change {
1712
const definition = after ?? before
1813
if (!definition) throw new Error('Finding needs evidence')
1914
const unresolved = [
2015
...new Set([...(before?.unresolved ?? []), ...(after?.unresolved ?? [])]),
2116
].sort()
22-
const movement = before && after && pureMovement(before, after)
2317
const category = changedCategory(before, after)
24-
const uncertain =
25-
unresolved.length ||
26-
definition.kind === 'review' ||
27-
['movement', 'unresolved'].includes(category)
2818
const a = before && appearanceValue(before)
2919
const b = after && appearanceValue(after)
3020
const supported =
3121
(!before || a !== undefined) &&
3222
(!after || b !== undefined) &&
3323
(a !== undefined || b !== undefined)
3424
const changed = JSON.stringify(a) !== JSON.stringify(b)
35-
const flag = supported && changed && !movement && category !== 'movement'
25+
const flag = supported && changed && category !== 'movement'
3626
const result: Omit<Change, 'id'> = {
3727
decision: flag ? 'flag' : 'exempt',
38-
category: movement ? 'movement' : category,
39-
reason:
40-
(flag
41-
? 'Supported authored appearance values changed'
42-
: !movement
43-
? 'No established change to authored appearance under the designer policy'
44-
: reason) ??
45-
(movement
46-
? 'Static geometry establishes movement within unchanged bounds'
47-
: uncertain
48-
? 'Potential visual effect; static evidence is incomplete'
49-
: 'Visual definition changed'),
28+
category,
29+
reason: flag
30+
? 'Supported authored appearance values changed'
31+
: 'No established change to authored appearance under the designer policy',
5032
before: before
5133
? {
5234
value: before.value,
@@ -84,11 +66,7 @@ export function finding(
8466
})
8567
}
8668

87-
export function compareDefinitions(
88-
before: Definition[],
89-
after: Definition[],
90-
_changed?: Set<string>
91-
): Change[] {
69+
export function compareDefinitions(before: Definition[], after: Definition[]): Change[] {
9270
const signatures = new Map<Definition, string | undefined>()
9371
const appearance = (definition: Definition) => {
9472
if (!signatures.has(definition))

‎scripts/design-diff/extract/tsx.ts‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import type { NodePath } from '@babel/traverse'
22
import * as t from '@babel/types'
33
import { appearanceAttributes, mediaElement } from '#design-diff/appearance'
44
import { location, propertyName, symbolName, traverse } from '#design-diff/ast'
5-
import { svgMovement } from '#design-diff/movement'
65
import { child, children, object, type Resolver } from '#design-diff/resolve'
76
import type { Data, Definition, Evidence } from '#design-diff/types'
87

@@ -79,7 +78,6 @@ export function extractTsx(resolver: Resolver, file: string): Definition[] {
7978
symbol,
8079
location: location(file, path.node),
8180
conditions,
82-
movement: svgMovement(path),
8381
})
8482
}
8583
const literal = (value: Data): Evidence => ({ value, dependencies: [file], unresolved: [] })

‎scripts/design-diff/group.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,7 @@ export function groupFindings(
9696
dependencies: [file, reference.location.file],
9797
unresolved: ['Resolved component reference; its runtime appearance is not established'],
9898
})
99-
example = finding(
100-
definition(previous?.oid),
101-
definition(next?.oid),
102-
'Resolved reference to a changed component'
103-
)
99+
example = finding(definition(previous?.oid), definition(next?.oid))
104100
}
105101
}
106102
const limitations = new Set([

‎scripts/design-diff/inputs.ts‎

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,31 @@
11
import path from 'node:path'
2-
import { canonicalJson } from '#design-diff/ast'
3-
import { compareDefinitions, finding } from '#design-diff/compare'
2+
import { finding } from '#design-diff/compare'
43
import { Resolver } from '#design-diff/resolve'
54
import type { SourceTree } from '#design-diff/source'
6-
import type { Change, Config, Data, Definition } from '#design-diff/types'
5+
import type { Change, Config } from '#design-diff/types'
76

8-
/** Explicit file-loading conventions are data edges, never runtime filesystem reads. */
9-
export function fileLoadedInputs(before: SourceTree, after: SourceTree, config: Config): Change[] {
10-
const read = (
11-
tree: SourceTree,
12-
input: NonNullable<Config['fileInputs']>[number]
13-
): Definition[] => {
14-
if (!tree.entries.has(input.list) && !tree.entries.has(input.renderer)) return []
15-
const definitions: Definition[] = []
16-
const emit = (file: string, value: Data, unresolved: string[] = []) =>
17-
definitions.push({
18-
key: file,
19-
kind: unresolved.length ? 'review' : 'content',
20-
property: 'file-loaded-documentation',
21-
value,
22-
location: { file, line: 1, column: 1 },
23-
symbol: input.export,
24-
conditions: [{ renderer: input.renderer, list: input.list }],
25-
dependencies: [file, input.list, input.renderer],
26-
unresolved,
27-
})
7+
/** Content never qualifies; validate current file-loaded documentation only for coverage notes. */
8+
export function fileLoadedInputDiagnostics(tree: SourceTree, config: Config): Change[] {
9+
const diagnostics = new Map<string, Change>()
10+
for (const input of config.fileInputs ?? []) {
11+
if (!tree.entries.has(input.list) && !tree.entries.has(input.renderer)) continue
12+
const emit = (file: string, reason: string) => {
13+
if (diagnostics.has(file)) return
14+
diagnostics.set(
15+
file,
16+
finding(undefined, {
17+
key: file,
18+
kind: 'review',
19+
property: 'file-loaded-documentation',
20+
value: tree.entries.get(file)?.oid ?? 'missing',
21+
location: { file, line: 1, column: 1 },
22+
symbol: input.export,
23+
conditions: [{ renderer: input.renderer, list: input.list }],
24+
dependencies: [file, input.list, input.renderer],
25+
unresolved: [reason],
26+
})
27+
)
28+
}
2829
try {
2930
const resolver = new Resolver(tree)
3031
const exported = resolver.module(input.list).exports.get(input.export)
@@ -37,36 +38,22 @@ export function fileLoadedInputs(before: SourceTree, after: SourceTree, config:
3738
!evidence.value.every((file) => typeof file === 'string')
3839
)
3940
throw new Error('Configured input list is not a static string array')
40-
if (!input.contentOnly) emit(input.list, evidence.value)
4141
for (const name of evidence.value as string[]) {
4242
const file = path.posix.normalize(path.posix.join(input.root, name))
4343
if (!file.startsWith(`${input.root}/`) || !file.endsWith('.json'))
4444
throw new Error('Unsupported configured input path')
4545
try {
46-
const value = JSON.parse(tree.texts.get(file) ?? '')
47-
if (!input.contentOnly) emit(file, canonicalJson(value))
46+
JSON.parse(tree.texts.get(file) ?? '')
4847
} catch {
49-
emit(file, tree.entries.get(file)?.oid ?? 'missing', [
50-
'Configured documentation JSON is missing, malformed or exceeds the source budget',
51-
])
48+
emit(
49+
file,
50+
'Configured documentation JSON is missing, malformed or exceeds the source budget'
51+
)
5252
}
5353
}
5454
} catch {
55-
emit(input.list, tree.entries.get(input.list)?.oid ?? 'missing', [
56-
'Configured documentation list or renderer could not be resolved',
57-
])
55+
emit(input.list, 'Configured documentation list or renderer could not be resolved')
5856
}
59-
return definitions
60-
}
61-
const findings: Change[] = []
62-
for (const input of config.fileInputs ?? []) {
63-
const a = read(before, input)
64-
const b = read(after, input)
65-
findings.push(...compareDefinitions(a, b))
66-
/** Invalid documentation remains an explicit coverage note without notifying the designer. */
67-
for (const definition of b.filter((definition) => definition.unresolved.length))
68-
if (!findings.some((finding) => finding.after?.location.file === definition.location.file))
69-
findings.push(finding(undefined, definition))
7057
}
71-
return findings
58+
return [...diagnostics.values()]
7259
}

‎scripts/design-diff/movement.ts‎

Lines changed: 0 additions & 103 deletions
This file was deleted.

0 commit comments

Comments
 (0)