chore(format): run prettier over src/ and scripts/

Formatting was configured but never enforced: `bun run format:check`
reported 199 unformatted files and ran in no workflow and in no git hook,
so .prettierrc (printWidth 100, trailing commas) described an intention
rather than the tree.

This is the one-time sweep that makes the check gateable. Whitespace and
token-reflow only -- no behavioural change: `bun run check` reports 0
errors and all 1053 frontend tests pass before and after.

Kept out of every other commit on purpose. A 199-file diff mixed with
real changes is unreviewable, and the next commit turns format:check
into a hard CI gate so this cannot silently accumulate again.
This commit is contained in:
2026-08-21 17:41:44 +02:00
parent d095e1f410
commit ad48d89dfe
199 changed files with 4698 additions and 3453 deletions
+7 -11
View File
@@ -140,9 +140,10 @@ describe("findDanglingIds", () => {
});
it("deduplicates and sorts, so one typo is reported once", () => {
expect(
findDanglingIds(["DR-189", "DR-189", "UR-999", "DR-189"], defined)
).toEqual(["DR-189", "UR-999"]);
expect(findDanglingIds(["DR-189", "DR-189", "UR-999", "DR-189"], defined)).toEqual([
"DR-189",
"UR-999",
]);
});
it("ignores IDs whose prefix is not a known trace type", () => {
@@ -158,7 +159,7 @@ describe("coverage threshold", () => {
// passes, which is how the 50%-while-actually-86% slack went unnoticed.
const workflow = fs.readFileSync(
path.resolve(HERE, "../.gitea/workflows/traceability-check.yml"),
"utf-8"
"utf-8",
);
const match = workflow.match(/^\s*MIN_THRESHOLD=(\d+)\s*$/m);
expect(match).not.toBeNull();
@@ -307,9 +308,7 @@ describe("generated matrix file links", () => {
it("keeps the #Lnn line anchor on the href", () => {
const link = formatMatrixFileLink("scripts/extract-traces.ts", 427);
expect(link).toBe(
"[`scripts/extract-traces.ts`](../scripts/extract-traces.ts#L427)"
);
expect(link).toBe("[`scripts/extract-traces.ts`](../scripts/extract-traces.ts#L427)");
});
it("does not produce a bare repo-root href, which resolves to docs/<path>", () => {
@@ -334,10 +333,7 @@ describe("live requirements.md", () => {
// row. Worse, the pins never guarded the actual defect — a stale denominator
// is caught by the sum-consistency check below, and the >100% ratio it
// produced is covered directly by the computeCoverage tests, on fixtures.
const md = fs.readFileSync(
path.resolve(HERE, "../docs/requirements.md"),
"utf-8"
);
const md = fs.readFileSync(path.resolve(HERE, "../docs/requirements.md"), "utf-8");
const defined = countDefinedRequirements(md);
// The parser found real rows of every type: a section silently failing to
+11 -30
View File
@@ -64,8 +64,7 @@ export const MIN_COVERAGE_PERCENT = 88;
// `import.meta.dir` is a Bun extension and is undefined when this module is
// imported by vitest (which runs it as an ordinary ESM module), so fall back to
// import.meta.url — this file must stay importable for extract-traces.test.ts.
const SCRIPT_DIR =
import.meta.dir ?? path.dirname(new URL(import.meta.url).pathname);
const SCRIPT_DIR = import.meta.dir ?? path.dirname(new URL(import.meta.url).pathname);
const BASE_DIR = path.resolve(SCRIPT_DIR, "..");
const TRACES_PATTERN = /TRACES:\s*([^\n]+)/gi;
@@ -283,8 +282,7 @@ export function countDefinedRequirements(markdown: string): DefinedRequirements
else ids.add(id);
}
const countOf = (type: string) =>
[...ids].filter((id) => id.startsWith(`${type}-`)).length;
const countOf = (type: string) => [...ids].filter((id) => id.startsWith(`${type}-`)).length;
return {
UR: countOf("UR"),
@@ -311,16 +309,13 @@ export function countDefinedRequirements(markdown: string): DefinedRequirements
*
* TRACES: | DR-093
*/
export function findDanglingIds(
tracedIds: string[],
defined: DefinedRequirements
): string[] {
export function findDanglingIds(tracedIds: string[], defined: DefinedRequirements): string[] {
const KNOWN_TYPE = /^(UR|IR|DR|JA|UT|IT)-\d{3}$/;
const dangling = new Set(
tracedIds
.filter((id) => KNOWN_TYPE.test(id))
.filter((id) => !defined.ids.has(id) && !defined.testIds.has(id))
.filter((id) => !defined.ids.has(id) && !defined.testIds.has(id)),
);
return [...dangling].sort();
@@ -336,10 +331,7 @@ export function findDanglingIds(
*
* TRACES: | DR-093
*/
export function computeCoverage(
tracedIds: string[],
defined: DefinedRequirements
): CoverageResult {
export function computeCoverage(tracedIds: string[], defined: DefinedRequirements): CoverageResult {
// Only the four *requirement* types participate in coverage. UT/IT are test
// identifiers defined in §4 of requirements.md — a different taxonomy, and
// flagging them as orphans would bury real typos in ~60 lines of noise.
@@ -352,10 +344,7 @@ export function computeCoverage(
return {
covered: covered.length,
total: defined.total,
percent:
defined.total === 0
? 0
: Math.round((covered.length / defined.total) * 100),
percent: defined.total === 0 ? 0 : Math.round((covered.length / defined.total) * 100),
orphaned,
};
}
@@ -488,16 +477,14 @@ function reportCoverage(data: TracesData, minThreshold: number): number {
if (cov.orphaned.length > 0) {
console.log("");
console.log(
`⚠️ Traced but not defined in requirements.md: ${cov.orphaned.join(", ")}`
);
console.log(`⚠️ Traced but not defined in requirements.md: ${cov.orphaned.join(", ")}`);
console.log(" Fix the TRACES comment or add the requirement.");
}
if (data.dangling && data.dangling.length > 0) {
console.log("");
console.log(
`⚠️ Dangling IDs (incl. UT/IT): ${data.dangling.join(", ")} — run \`bun run traces:validate\`.`
`⚠️ Dangling IDs (incl. UT/IT): ${data.dangling.join(", ")} — run \`bun run traces:validate\`.`,
);
}
@@ -538,9 +525,7 @@ function reportDangling(data: TracesData): number {
console.log("❌ TRACES reference IDs that docs/requirements.md does not define:");
console.log("");
for (const id of dangling) {
const files = [
...new Set((data.requirements[id] ?? []).map((e) => e.file)),
].sort();
const files = [...new Set((data.requirements[id] ?? []).map((e) => e.file))].sort();
console.log(` ${id}`);
for (const file of files) console.log(` ${file}`);
}
@@ -554,9 +539,7 @@ function reportDangling(data: TracesData): number {
// Main — guarded so this module stays importable from extract-traces.test.ts.
if (import.meta.main) {
const args = process.argv.slice(2);
const format = args.includes("--format")
? args[args.indexOf("--format") + 1]
: "markdown";
const format = args.includes("--format") ? args[args.indexOf("--format") + 1] : "markdown";
console.error("🔍 Extracting TRACES from codebase...");
const data = extractTraces();
@@ -583,7 +566,5 @@ if (import.meta.main) {
console.log(generateMarkdown(data));
}
console.error(
`\n✅ Complete! Found ${data.totalTraces} TRACES across ${data.totalFiles} files`
);
console.error(`\n✅ Complete! Found ${data.totalTraces} TRACES across ${data.totalFiles} files`);
}
+1 -3
View File
@@ -55,9 +55,7 @@ function loadRequirementDescriptions(): Map<string, string> {
}
function changedFiles(range: string): string[] {
const cmd = range
? `git diff --name-only ${range}`
: "git ls-files"; // untagged repo: describe everything currently traced
const cmd = range ? `git diff --name-only ${range}` : "git ls-files"; // untagged repo: describe everything currently traced
return sh(cmd)
.split("\n")
.filter((f) => f && existsSync(f));
+24 -7
View File
@@ -34,30 +34,47 @@ function seed(dir: string) {
fs.writeFileSync(
path.join(dir, "package.json"),
JSON.stringify({ name: "jellytau", version: "0.0.1", dependencies: { hls: "1.2.3" } }, null, 2)
JSON.stringify({ name: "jellytau", version: "0.0.1", dependencies: { hls: "1.2.3" } }, null, 2),
);
fs.writeFileSync(
path.join(dir, "src-tauri", "tauri.conf.json"),
JSON.stringify({ productName: "jellytau", version: "0.0.1" }, null, 2)
JSON.stringify({ productName: "jellytau", version: "0.0.1" }, null, 2),
);
// A dependency carrying its own `version =` is the trap: a greedy regex
// rewrites it too and the build then resolves the wrong crate.
fs.writeFileSync(
path.join(dir, "src-tauri", "Cargo.toml"),
['[package]', 'name = "jellytau"', 'version = "0.0.1"', '', '[dependencies]', 'serde = { version = "1.0.100" }', ''].join("\n")
[
"[package]",
'name = "jellytau"',
'version = "0.0.1"',
"",
"[dependencies]",
'serde = { version = "1.0.100" }',
"",
].join("\n"),
);
fs.writeFileSync(
path.join(dir, "src-tauri", "Cargo.lock"),
['[[package]]', 'name = "serde"', 'version = "1.0.100"', '', '[[package]]', 'name = "jellytau"', 'version = "0.0.1"', ''].join("\n")
[
"[[package]]",
'name = "serde"',
'version = "1.0.100"',
"",
"[[package]]",
'name = "jellytau"',
'version = "0.0.1"',
"",
].join("\n"),
);
fs.writeFileSync(
path.join(dir, "src-tauri", "gen", "android", "app", "tauri.properties"),
"tauri.android.versionCode=1\n"
"tauri.android.versionCode=1\n",
);
fs.mkdirSync(path.join(dir, "packaging", "arch"), { recursive: true });
fs.writeFileSync(
path.join(dir, "packaging", "arch", "PKGBUILD"),
['pkgname=jellytau', 'pkgver=0.0.1', 'pkgrel=3', 'pkgdesc="x"', ''].join("\n")
["pkgname=jellytau", "pkgver=0.0.1", "pkgrel=3", 'pkgdesc="x"', ""].join("\n"),
);
}
@@ -74,7 +91,7 @@ function read(rel: string): string {
function versionCode(): number {
const m = read("src-tauri/gen/android/app/tauri.properties").match(
/^tauri\.android\.versionCode=(\d+)$/m
/^tauri\.android\.versionCode=(\d+)$/m,
);
return m ? Number(m[1]) : NaN;
}
+1 -1
View File
@@ -16,7 +16,7 @@ import { readFileSync } from "fs";
import { resolve } from "path";
const config = JSON.parse(
readFileSync(resolve(__dirname, "../src-tauri/tauri.conf.json"), "utf-8")
readFileSync(resolve(__dirname, "../src-tauri/tauri.conf.json"), "utf-8"),
);
const security = config.app.security;