Formatting Toolchain Policy
wp-typia keeps code diagnostics and formatting ownership explicit instead of
allowing each package to assemble a different lint stack.
Current baseline
Section titled “Current baseline”- the repository root owns TypeScript
7.0.2 - the repository root owns
ttsc,@ttsc/lint, and@ttsc/unpluginat0.26.2 - packaged project tools fall back to
@wp-typia/ttsc-lint-plugin-wp^0.2.0 - the repository root owns ESLint
9.39.4for repo JavaScript and Prettier3.8.2for selected non-TypeScript files bun run typecheckis the root TypeScript, lint, unused, and format gatebun run formatting-policy:validatechecks package manifests, generated templates, patches, examples, and CI against this policy
Repository ownership
Section titled “Repository ownership”The root lint.config.ts and TypeScript project are owned by ttsc. ESLint
does not parse TypeScript or TSX in this repository. The root configuration
enables compiler unused diagnostics, formatting diagnostics, and safe rules
such as no-var, prefer-const, and eqeqeq.
JavaScript, CJS, and MJS used by repository infrastructure remain under ESLint. Prettier owns Markdown, JSON, YAML, styles, and the other explicitly listed non-TypeScript inputs. Generated artifacts stay under their generator or synchronizer rather than being rewritten by a blanket formatter pass.
Use:
bun run typecheckfor the root non-mutating TypeScript and lint gatebun run lint:repofor root JavaScript diagnosticsbun run format:checkfor the non-mutating non-TypeScript format gatebun run lint:fixfor ESLint andttsc fixbun run format:writeforttsc formatand Prettier writes
Generated projects and examples
Section titled “Generated projects and examples”New projects, retrofit plans, and WordPress examples expose the same contract:
check:coderuns the project sync check followed byttsc check --noEmitcheck:styleretains@wordpress/scriptsStylelint behaviorcheck:formatuses Prettier for JavaScript and non-code filescheckcombines those three gatesformatusesttsc formatfor code, then Prettier restores the WordPress JavaScript and non-code formatting contract
Generated lint configs set format.severity to off. This keeps ttsc check --noEmit focused on compiler and lint diagnostics while ttsc format remains
the TypeScript write path. Prettier gates JavaScript, JSON, Markdown, YAML, and
styles and restores the WordPress JavaScript contract after a format write.
Generated metadata artifacts remain formatter-ignored because their owning
synchronizer produces them deterministically.
There is intentionally no lint:js compatibility alias. The code gate also
performs TypeScript checking, so check:code describes its behavior without
claiming to be lint-only.
Generated TypeScript configurations set allowJs: true and include project
JavaScript, JSX, CJS, and MJS entrypoints. Consequently the compiled
configs.wpScriptsRecommended preset applies supported WordPress, React,
import, and TypeScript diagnostics across both JavaScript and TypeScript source
files. The text-domain rule is specialized to the generated plugin slug.
The compiled preset records intentional behavior downgrades when a nominally
available native rule cannot safely reproduce WordPress behavior. The current
baseline omits no-shadow because its native implementation panics on catch
clauses, omits two JSX accessibility rules that misclassify imported WordPress
components as DOM elements, and omits role-supports-aria-props because it
rejects valid progressbar value properties. These omissions are manifest-backed
and executable parity probes require every failure to remain reproducible. A
new toolchain that fixes one of them intentionally fails the probe until the
corresponding downgrade and documentation are removed.
CommonJS package manifests use lint.config.mts. This makes the configuration
module unambiguously ESM when ttsc loads the ESM WordPress contributor.
Existing project-owned lint configurations are never overwritten; wp-typia init --apply stops with merge guidance when it cannot prove a safe managed
upgrade.
The generated package does not install the TypeScript 6 compatibility package, ESLint, the WordPress ESLint plugin, resolver shims, or JSX accessibility plugins. TypeScript 6 remains limited to repository tools that directly need the JavaScript Compiler API. React and its type packages remain direct generated dependencies so TS7 JSX resolution is reproducible across supported package managers.
Native plugin cache and CI
Section titled “Native plugin cache and CI”CI stores content-addressed ttsc source-plugin binaries in
.ttsc-cache/plugins. Preparation happens once and the finished plugin cache
and built workspace packages are shared with downstream project-tool and
generated-project jobs. Large Go build caches are runner-local and are not
uploaded for every matrix entry.
ttsc 0.26.2 resolves its launcher and native TypeScript compiler from the
project that owns the lint config. CI therefore exercises normal project
resolution and does not inject TTSC_TSGO_BINARY; environment overrides would
hide regressions in the same resolution path generated projects use. Contributor
parity runs against both the minimum supported ttsc release and the repository’s
installed release. A local parity run defaults to the installed release rather
than silently falling back to the minimum compatibility lane.
Generated smoke coverage is intentionally representative rather than a full Cartesian product. Unit and template-source tests cover deterministic manifest differences; installed smoke lanes cover every template family, package-manager boundary, and workspace add workflow at least once.
Compatibility patches
Section titled “Compatibility patches”The root Bun workspace carries two exact-version development-tool patches:
typia@13.2.0forwards the JSON--tsgo-argsenvelope so CLI flags such as--strictreach the tsgo program used by typia transforms@ttsc/lint@0.26.2guards mapped andinfertype parameters while formatting trailing commas, preventing a TypeScript-Go declaration lookup panic, and widens the affected symlink-target buffers in the TypeScript source, the distributed JavaScript runtime, and the native sidecar’s embedded TypeScript config loader so executable lint configs compile across the supported Node 24 type-definition range
Registry @ttsc/lint@0.26.2 still reproduces both lint-host failures. Generated
and retrofitted projects therefore exact-pin that version and run
scripts/apply-ttsc-lint-compat.mjs from postinstall. The helper verifies the
package version and expected source/runtime/sidecar files, applies the same narrow
repairs atomically per file, preserves file permissions, cleans abandoned
temporary files, and fails closed before writing if the upstream layout changes.
Its distributed JavaScript check is scoped to the embedded ttsx TypeScript
template so the container remains valid JavaScript. Production-only installs
that omit the development lint dependency skip the hook successfully. Yarn
scaffolds use the node-modules linker so the helper never edits a shared
Plug’n’Play archive.
The project-tools template is the canonical helper source. Run
bun run ttsc-lint-compat:sync after changing it and
bun run ttsc-lint-compat:check to verify the create-workspace template and
external-template fixture remain byte-identical. The formatting policy validator
also enforces these invariants.
The generated helper is a development compiler repair, not a WordPress runtime
dependency. It does not inherit Bun’s root patchedDependencies; publish and
generated-install smoke independently prove the consumer path.
The formatting policy validator pins each patch path and SHA-256 digest to the exact package version. To upgrade either dependency:
- install the unpatched release and run the compatibility regressions;
- remove the patch and generated helper only when CLI option forwarding,
typia transforms, mapped/
inferformatting, and executable lint-config evaluation with Node 24 typings all pass; - otherwise port the narrow patch, update the exact version and digest, and rerun installed generated-project smoke.
CI posture
Section titled “CI posture”The primary lint job validates this policy, runs the non-TypeScript format
gate, checks examples with their combined check command, and runs the root
TypeScript gate. Local development should run the narrow tests relevant to a
change first; the full CI matrix remains the release and cross-environment
proof.