@openmixer/plugin-qualify 0.20.1 → 0.20.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/bin/plugin-qualify-sync.mjs +1 -0
  2. package/catalogs/ca.json +251 -0
  3. package/catalogs/de.json +49 -0
  4. package/catalogs/es.json +49 -0
  5. package/catalogs/fr.json +49 -0
  6. package/catalogs/it.json +49 -0
  7. package/catalogs/pt.json +49 -0
  8. package/dist/clap-loader.js +2 -1
  9. package/dist/clap-loader.js.map +1 -1
  10. package/dist/clap-qualify.d.ts +11 -0
  11. package/dist/clap-qualify.js +16 -0
  12. package/dist/clap-qualify.js.map +1 -1
  13. package/dist/compare.d.ts +12 -11
  14. package/dist/compare.js +71 -38
  15. package/dist/compare.js.map +1 -1
  16. package/dist/host-admission.d.ts +25 -0
  17. package/dist/host-admission.js +41 -5
  18. package/dist/host-admission.js.map +1 -1
  19. package/dist/hostd-pin-files.d.ts +6 -2
  20. package/dist/hostd-pin-files.js +10 -6
  21. package/dist/hostd-pin-files.js.map +1 -1
  22. package/dist/hostd-search-path.d.ts +38 -0
  23. package/dist/hostd-search-path.js +58 -0
  24. package/dist/hostd-search-path.js.map +1 -0
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.js +4 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/jack-registry.js +1 -1
  29. package/dist/lv2-loader.d.ts +33 -1
  30. package/dist/lv2-loader.js +82 -19
  31. package/dist/lv2-loader.js.map +1 -1
  32. package/dist/measurement/vocabulary.js +3 -3
  33. package/dist/measurement/vocabulary.js.map +1 -1
  34. package/dist/measurement-grid.d.ts +1 -1
  35. package/dist/measurement-grid.js +5 -3
  36. package/dist/measurement-grid.js.map +1 -1
  37. package/dist/pins-file.d.ts +3 -2
  38. package/dist/pins-file.js +3 -2
  39. package/dist/pins-file.js.map +1 -1
  40. package/dist/plugin-db-cli.d.ts +28 -0
  41. package/dist/plugin-db-cli.js +43 -0
  42. package/dist/plugin-db-cli.js.map +1 -0
  43. package/dist/plugin-db-pin.d.ts +8 -0
  44. package/dist/plugin-db-pin.js +29 -0
  45. package/dist/plugin-db-pin.js.map +1 -0
  46. package/dist/probe-judge.js +5 -0
  47. package/dist/probe-judge.js.map +1 -1
  48. package/dist/probe-output.d.ts +10 -0
  49. package/dist/probe-output.js +16 -0
  50. package/dist/probe-output.js.map +1 -1
  51. package/dist/probe-runner.js +24 -5
  52. package/dist/probe-runner.js.map +1 -1
  53. package/dist/qualification-record.d.ts +5 -0
  54. package/dist/qualification-record.js +13 -1
  55. package/dist/qualification-record.js.map +1 -1
  56. package/dist/qualify-adapter-pass.d.ts +1 -2
  57. package/dist/qualify-adapter-pass.js +6 -6
  58. package/dist/qualify-adapter-pass.js.map +1 -1
  59. package/dist/qualify-declarations.d.ts +23 -6
  60. package/dist/qualify-declarations.js +25 -6
  61. package/dist/qualify-declarations.js.map +1 -1
  62. package/dist/qualify-isolated.d.ts +9 -0
  63. package/dist/qualify-isolated.js +16 -5
  64. package/dist/qualify-isolated.js.map +1 -1
  65. package/dist/qualify-pool.js +4 -3
  66. package/dist/qualify-pool.js.map +1 -1
  67. package/dist/qualify-rejudge.js +3 -3
  68. package/dist/qualify-rejudge.js.map +1 -1
  69. package/dist/qualify-sync.d.ts +12 -5
  70. package/dist/qualify-sync.js +51 -30
  71. package/dist/qualify-sync.js.map +1 -1
  72. package/dist/record-figures.d.ts +52 -0
  73. package/dist/record-figures.js +58 -0
  74. package/dist/record-figures.js.map +1 -0
  75. package/dist/refused-stderr-kept.d.ts +12 -0
  76. package/dist/refused-stderr-kept.js +67 -0
  77. package/dist/refused-stderr-kept.js.map +1 -0
  78. package/dist/run-home.d.ts +4 -0
  79. package/dist/run-home.js +26 -0
  80. package/dist/run-home.js.map +1 -0
  81. package/dist/text-catalog.d.ts +41 -0
  82. package/dist/text-catalog.js +97 -0
  83. package/dist/text-catalog.js.map +1 -0
  84. package/dist/text-codes.d.ts +29 -0
  85. package/dist/text-codes.generated.d.ts +88 -0
  86. package/dist/text-codes.generated.js +96 -0
  87. package/dist/text-codes.generated.js.map +1 -0
  88. package/dist/text-codes.js +19 -0
  89. package/dist/text-codes.js.map +1 -0
  90. package/package.json +8 -6
  91. package/schema/codes.json +386 -0
  92. package/src/clap-loader.ts +2 -1
  93. package/src/clap-qualify.ts +25 -0
  94. package/src/compare.ts +85 -45
  95. package/src/host-admission.ts +52 -5
  96. package/src/hostd-pin-files.ts +13 -8
  97. package/src/hostd-search-path.ts +85 -0
  98. package/src/index.ts +4 -0
  99. package/src/jack-registry.ts +1 -1
  100. package/src/lv2-loader.ts +89 -17
  101. package/src/measurement/vocabulary.ts +3 -3
  102. package/src/measurement-grid.ts +5 -3
  103. package/src/pins-file.ts +3 -2
  104. package/src/plugin-db-cli.ts +78 -0
  105. package/src/plugin-db-pin.ts +33 -0
  106. package/src/probe-judge.ts +5 -0
  107. package/src/probe-output.ts +23 -0
  108. package/src/probe-runner.ts +25 -4
  109. package/src/qualification-record.ts +13 -1
  110. package/src/qualify-adapter-pass.ts +6 -5
  111. package/src/qualify-declarations.ts +27 -6
  112. package/src/qualify-isolated.ts +18 -5
  113. package/src/qualify-pool.ts +4 -3
  114. package/src/qualify-rejudge.ts +3 -3
  115. package/src/qualify-sync.ts +55 -33
  116. package/src/record-figures.ts +114 -0
  117. package/src/refused-stderr-kept.ts +84 -0
  118. package/src/run-home.ts +28 -0
  119. package/src/text-catalog.ts +116 -0
  120. package/src/text-codes.generated.ts +97 -0
  121. package/src/text-codes.ts +35 -0
  122. package/tools/_declarations.py +2 -1
  123. package/tools/catalogs-gate.sh +22 -0
  124. package/tools/compare-host.mjs +1 -1
  125. package/tools/compare-run.mjs +10 -6
  126. package/tools/descriptors.py +40 -3
  127. package/tools/gen-python-declarations.mjs +1 -0
  128. package/tools/gen-text-codes.d.mts +8 -0
  129. package/tools/gen-text-codes.mjs +77 -0
  130. package/tools/isolated-step.mjs +24 -3
  131. package/tools/mod-host-admit.mjs +57 -1
  132. package/tools/scan.py +29 -5
@@ -0,0 +1,26 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ // Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
3
+ /**
4
+ * The HOME every process that loads a plugin starts with: a scratch directory of this plugin-qualify run, never the
5
+ * caller's real home. A plugin that reads its user data from HOME (Surge XT) segfaults or stays silent without one,
6
+ * and a probe must not write into a user's home. Created on first use, removed when the process exits.
7
+ */
8
+ import { mkdirSync, mkdtempSync, rmSync } from "node:fs";
9
+ import { tmpdir } from "node:os";
10
+ import { join } from "node:path";
11
+ let home;
12
+ /** The run's scratch HOME, made on first use. */
13
+ export function runHome() {
14
+ if (home === undefined) {
15
+ const dir = mkdtempSync(join(tmpdir(), "plugin-qualify-home-"));
16
+ process.on("exit", () => rmSync(dir, { recursive: true, force: true }));
17
+ home = join(dir, "home");
18
+ mkdirSync(home);
19
+ }
20
+ return home;
21
+ }
22
+ /** `env` with HOME set to the run's scratch HOME. */
23
+ export function withRunHome(env) {
24
+ return { ...env, HOME: runHome() };
25
+ }
26
+ //# sourceMappingURL=run-home.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-home.js","sourceRoot":"","sources":["../src/run-home.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,sDAAsD;AACtD;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,IAAI,IAAwB,CAAC;AAE7B,iDAAiD;AACjD,MAAM,UAAU,OAAO;IACrB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACxE,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACzB,SAAS,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,WAAW,CAAC,GAAiD;IAC3E,OAAO,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC;AACrC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { ReasonText, TextRef } from "./text-codes.js";
2
+ export declare const OWNER = "plugin-qualify";
3
+ export declare const CATALOGS_DIR_ENV = "PLUGIN_QUALIFY_CATALOGS_DIR";
4
+ /** Where this package's own `catalogs/<lang>.json` live: `PLUGIN_QUALIFY_CATALOGS_DIR`, else beside this module's package. */
5
+ export declare function catalogsDir(env?: Readonly<Record<string, string | undefined>>): string;
6
+ /** One code of `schema/codes.json`: the code, the args its sentence names and the sentence. */
7
+ export interface DeclaredCode {
8
+ readonly code: string;
9
+ readonly doc?: string;
10
+ readonly text: {
11
+ readonly en: string;
12
+ };
13
+ readonly args: readonly string[];
14
+ }
15
+ /** One catalog entry: the sentence, or the sentence with how it was made (omx-contract's `catalogEntry`). */
16
+ export type CatalogEntry = string | {
17
+ readonly text: string;
18
+ readonly by: "human" | "machine";
19
+ readonly model?: string;
20
+ readonly source?: string;
21
+ };
22
+ /** Where the codes are declared: `schema/codes.json` of this package. */
23
+ export declare const CODES_FILE: string;
24
+ /** Every code `schema/codes.json` declares, by its code; none where the file does not read. */
25
+ export declare function declaredCodes(): ReadonlyMap<string, DeclaredCode>;
26
+ /** `catalogs/<lang>.json`'s `messages`, or `undefined` where the file is absent or does not read as one. */
27
+ export declare function loadMessages(lang: string, dir?: string): Record<string, CatalogEntry> | undefined;
28
+ /** `sentence` with each `{name}` replaced by `args[name]`; a placeholder with no value is left as written. */
29
+ export declare function fill(sentence: string, args?: Readonly<Record<string, string | number>>): string;
30
+ /** The sha256 of a source sentence, lowercase hex of its UTF-8 bytes: what a model's entry records as `source`. */
31
+ export declare const sourceHash: (sentence: string) => string;
32
+ /** The sentence of `entry`; `undefined` for no entry, or a model's entry made from another sentence than `source`. */
33
+ export declare function entrySentence(entry: CatalogEntry | undefined, source: string): string | undefined;
34
+ /** The source sentence `code` was declared with (`schema/codes.json`); throws on a code this package never declared. */
35
+ export declare function sourceOf(code: string): string;
36
+ /** `ref` rendered for `lang`: the catalog's sentence, else the source, its `{placeholder}`s filled. `lang` undefined or "en" skips the catalog. */
37
+ export declare function textOf(ref: TextRef, lang?: string): string;
38
+ /** A {@link ReasonText} rendered for `lang`: another tool's own words pass straight through; plugin-qualify's own go through {@link textOf}. */
39
+ export declare function reasonText(reason: ReasonText, lang?: string): string;
40
+ /** The language of `LC_ALL`, else `LANG` (the POSIX precedence), as the two letters before `_` or `.`; `undefined` unset, unparsed, or `C`/`POSIX` (textOf's own fallback to the source sentence is the same as leaving this undefined). */
41
+ export declare function localeOf(env?: Readonly<Record<string, string | undefined>>): string | undefined;
@@ -0,0 +1,97 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ // Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
3
+ /**
4
+ * The sentence a surface shows for one of plugin-qualify's own {@link TextRef}s: the catalog's, for the given
5
+ * language, else the source sentence `schema/codes.json` declares; its `{placeholder}`s filled from `args`
6
+ * An entry is the sentence, or the sentence with how it was made (omx-contract 3.16.0's `catalogEntry`); a model's
7
+ * entry made from another source sentence is stale and skipped. This is the lookup of
8
+ * `@openmixer/omx-contract/catalog` (`sentenceOf`, `fill`), made here: that module reads its schema through ajv, which
9
+ * this package does not depend on, and the npm floor is below the release that knows an entry's provenance.
10
+ *
11
+ * `schema/codes.json` and `catalogs/<lang>.json` ship inside this package (`package.json`'s `files`), read relative
12
+ * to this module so it works from `src/` under vitest and from `dist/` once built alike. `PLUGIN_QUALIFY_CATALOGS_DIR`
13
+ * names another catalogs directory instead, for a test that wants its own fixture catalogs.
14
+ */
15
+ import { createHash } from "node:crypto";
16
+ import { readFileSync } from "node:fs";
17
+ import { dirname, join, resolve } from "node:path";
18
+ import { fileURLToPath } from "node:url";
19
+ export const OWNER = "plugin-qualify";
20
+ export const CATALOGS_DIR_ENV = "PLUGIN_QUALIFY_CATALOGS_DIR";
21
+ const PKG = resolve(dirname(fileURLToPath(import.meta.url)), "..");
22
+ /** Where this package's own `catalogs/<lang>.json` live: `PLUGIN_QUALIFY_CATALOGS_DIR`, else beside this module's package. */
23
+ export function catalogsDir(env = process.env) {
24
+ return env[CATALOGS_DIR_ENV] ?? join(PKG, "catalogs");
25
+ }
26
+ /** Where the codes are declared: `schema/codes.json` of this package. */
27
+ export const CODES_FILE = join(PKG, "schema", "codes.json");
28
+ let declared;
29
+ /** Every code `schema/codes.json` declares, by its code; none where the file does not read. */
30
+ export function declaredCodes() {
31
+ if (declared !== undefined)
32
+ return declared;
33
+ let codes = {};
34
+ try {
35
+ codes = JSON.parse(readFileSync(CODES_FILE, "utf8")).codes ?? {};
36
+ }
37
+ catch {
38
+ codes = {};
39
+ }
40
+ declared = new Map(Object.values(codes).map((c) => [c.code, c]));
41
+ return declared;
42
+ }
43
+ const messagesCache = new Map();
44
+ /** `catalogs/<lang>.json`'s `messages`, or `undefined` where the file is absent or does not read as one. */
45
+ export function loadMessages(lang, dir = catalogsDir()) {
46
+ const cacheKey = `${dir}\0${lang}`;
47
+ if (messagesCache.has(cacheKey))
48
+ return messagesCache.get(cacheKey);
49
+ let messages;
50
+ try {
51
+ const catalog = JSON.parse(readFileSync(join(dir, `${lang}.json`), "utf8"));
52
+ messages = catalog.messages;
53
+ }
54
+ catch {
55
+ messages = undefined;
56
+ }
57
+ messagesCache.set(cacheKey, messages);
58
+ return messages;
59
+ }
60
+ /** `sentence` with each `{name}` replaced by `args[name]`; a placeholder with no value is left as written. */
61
+ export function fill(sentence, args = {}) {
62
+ return sentence.replace(/\{([^{}]*)\}/g, (m, n) => (Object.hasOwn(args, n) ? String(args[n]) : m));
63
+ }
64
+ /** The sha256 of a source sentence, lowercase hex of its UTF-8 bytes: what a model's entry records as `source`. */
65
+ export const sourceHash = (sentence) => createHash("sha256").update(sentence, "utf8").digest("hex");
66
+ /** The sentence of `entry`; `undefined` for no entry, or a model's entry made from another sentence than `source`. */
67
+ export function entrySentence(entry, source) {
68
+ if (entry === undefined || typeof entry === "string")
69
+ return entry;
70
+ return entry.source !== undefined && entry.source !== sourceHash(source) ? undefined : entry.text;
71
+ }
72
+ /** The source sentence `code` was declared with (`schema/codes.json`); throws on a code this package never declared. */
73
+ export function sourceOf(code) {
74
+ const source = declaredCodes().get(code)?.text.en;
75
+ if (source === undefined)
76
+ throw new Error(`plugin-qualify declares no source sentence for ${code}`);
77
+ return source;
78
+ }
79
+ /** `ref` rendered for `lang`: the catalog's sentence, else the source, its `{placeholder}`s filled. `lang` undefined or "en" skips the catalog. */
80
+ export function textOf(ref, lang) {
81
+ const source = sourceOf(ref.code);
82
+ const sentence = lang === undefined || lang === "en" ? source : (entrySentence(loadMessages(lang)?.[ref.code], source) ?? source);
83
+ return fill(sentence, ref.args ?? {});
84
+ }
85
+ /** A {@link ReasonText} rendered for `lang`: another tool's own words pass straight through; plugin-qualify's own go through {@link textOf}. */
86
+ export function reasonText(reason, lang) {
87
+ return typeof reason === "string" ? reason : textOf(reason, lang);
88
+ }
89
+ /** The language of `LC_ALL`, else `LANG` (the POSIX precedence), as the two letters before `_` or `.`; `undefined` unset, unparsed, or `C`/`POSIX` (textOf's own fallback to the source sentence is the same as leaving this undefined). */
90
+ export function localeOf(env = process.env) {
91
+ const raw = env["LC_ALL"] || env["LANG"];
92
+ if (raw === undefined || raw === "")
93
+ return undefined;
94
+ const m = /^([a-z]{2})(?:[_.].*)?$/.exec(raw);
95
+ return m?.[1];
96
+ }
97
+ //# sourceMappingURL=text-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-catalog.js","sourceRoot":"","sources":["../src/text-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * plugin-qualify's own verdict and reason sentences, as codes (omx-contract#2, "codes then catalogs", owner
3
+ * ruling 2026-11-09: a code carries its identifier, its arguments and one source sentence in English with named
4
+ * placeholders; translations live in catalogs the owner ships, keyed by code, checked for placeholders against the
5
+ * code's `args`; a surface looks up the sentence for the user's locale and falls back to this source sentence).
6
+ *
7
+ * plugin-qualify is the owner of these codes (the hosting.* codes of {@link ../hosting-codes.js} are omx-clap-core's
8
+ * instead, and that package owns their catalogs). A code, its args and its source sentence are written once, in
9
+ * `schema/codes.json`; {@link TEXT_CODE} is that file's `key: code` map, generated (`tools/gen-text-codes.mjs`), so a
10
+ * call site names a code by its key and no sentence is written in a module. `catalogs/<lang>.json`, read by
11
+ * {@link ../text-catalog.js}, hold each listed language's sentences; `src/text-catalog-conformance.test.ts` turns red
12
+ * on a code without its source sentence or without an entry in a language, and on a sentence whose placeholders are
13
+ * not its code's `args`.
14
+ */
15
+ import { TEXT_CODE, TEXT_CODE_ARGS } from "./text-codes.generated.js";
16
+ export { TEXT_CODE, TEXT_CODE_ARGS };
17
+ /** A key of {@link TEXT_CODE}. */
18
+ export type TextCodeKey = keyof typeof TEXT_CODE;
19
+ /** A code of {@link TEXT_CODE} with the arguments its source sentence names. A reader renders it; it is never prose itself. */
20
+ export interface TextRef {
21
+ readonly code: string;
22
+ readonly args?: Readonly<Record<string, string | number>>;
23
+ }
24
+ /**
25
+ * A reason as plugin-qualify writes it: its own sentence as a {@link TextRef}, or another tool's own words passed
26
+ * through unclassified (the shape `UnmeasuredFigure.detail` already uses elsewhere: a prober's raw text is never
27
+ * coded, since nothing here can translate words it did not write).
28
+ */
29
+ export type ReasonText = TextRef | string;
@@ -0,0 +1,88 @@
1
+ /** plugin-qualify's own codes, by key (schema/codes.json). */
2
+ export declare const TEXT_CODE: Readonly<{
3
+ readonly descriptorDuplicateSymbol: "qualify.descriptor.duplicate-symbol";
4
+ readonly compareHostNotInstalled: "qualify.compare.host-not-installed";
5
+ readonly compareHostDidNotStart: "qualify.compare.host-did-not-start";
6
+ readonly compareHostNotAsked: "qualify.compare.host-not-asked";
7
+ readonly compareHostDidNotRun: "qualify.compare.host-did-not-run";
8
+ readonly compareFormatNotTaken: "qualify.compare.format-not-taken";
9
+ readonly compareRtNotReported: "qualify.compare.rt-not-reported";
10
+ readonly compareRtNoCallback: "qualify.compare.rt-no-callback";
11
+ readonly compareRtNoWarmUp: "qualify.compare.rt-no-warm-up";
12
+ readonly compareRtTrylocksOnly: "qualify.compare.rt-trylocks-only";
13
+ readonly compareRtUnsafe: "qualify.compare.rt-unsafe";
14
+ readonly compareLoadHostEnded: "qualify.compare.load-host-ended";
15
+ readonly compareLoadResp: "qualify.compare.load-resp";
16
+ readonly compareLoadTimeout: "qualify.compare.load-timeout";
17
+ readonly compareNotLoaded: "qualify.compare.not-loaded";
18
+ readonly compareNoPort: "qualify.compare.no-port";
19
+ readonly compareNotRunning: "qualify.compare.not-running";
20
+ readonly compareNoAudioOutput: "qualify.compare.no-audio-output";
21
+ readonly compareOutputNotFinite: "qualify.compare.output-not-finite";
22
+ readonly compareNoStimulusSilent: "qualify.compare.no-stimulus-silent";
23
+ readonly compareSilentUnderStimulus: "qualify.compare.silent-under-stimulus";
24
+ readonly compareCyclesNotRun: "qualify.compare.cycles-not-run";
25
+ readonly compareCycleHostEnded: "qualify.compare.cycle-host-ended";
26
+ readonly compareCycleFailed: "qualify.compare.cycle-failed";
27
+ readonly compareCycleFailedAt: "qualify.compare.cycle-failed-at";
28
+ readonly compareSoakHostEnded: "qualify.compare.soak-host-ended";
29
+ readonly compareSoakEnded: "qualify.compare.soak-ended";
30
+ readonly compareLatencyPortObservable: "qualify.compare.latency-port-observable";
31
+ readonly compareLatencyHostdPortObservable: "qualify.compare.latency-hostd-port-observable";
32
+ readonly compareLatencyNotObservableModHost: "qualify.compare.latency-not-observable-mod-host";
33
+ readonly compareLatencyUnreadable: "qualify.compare.latency-unreadable";
34
+ readonly compareSkippedReason: "qualify.compare.skipped-reason";
35
+ readonly compareDoesBetterOn: "qualify.compare.does-better-on";
36
+ readonly compareBeatDescription: "qualify.compare.beat-description";
37
+ readonly compareNotPublishableWithMissing: "qualify.compare.not-publishable-with-missing";
38
+ readonly compareNotPublishableNoFlag: "qualify.compare.not-publishable-no-flag";
39
+ readonly pinHostdNotInstalled: "qualify.pin.hostd-not-installed";
40
+ readonly pinHostdNoPinFiles: "qualify.pin.hostd-no-pin-files";
41
+ readonly pinHostdExited: "qualify.pin.hostd-exited";
42
+ readonly pinHostdNoRootOrFile: "qualify.pin.hostd-no-root-or-file";
43
+ readonly pinFileUnreadable: "qualify.pin.file-unreadable";
44
+ }>;
45
+ /** The args each code's source sentence names, by the same key. */
46
+ export declare const TEXT_CODE_ARGS: Readonly<{
47
+ readonly descriptorDuplicateSymbol: readonly ["symbol"];
48
+ readonly compareHostNotInstalled: readonly ["program"];
49
+ readonly compareHostDidNotStart: readonly ["program"];
50
+ readonly compareHostNotAsked: readonly [];
51
+ readonly compareHostDidNotRun: readonly ["program"];
52
+ readonly compareFormatNotTaken: readonly ["program", "format"];
53
+ readonly compareRtNotReported: readonly [];
54
+ readonly compareRtNoCallback: readonly [];
55
+ readonly compareRtNoWarmUp: readonly [];
56
+ readonly compareRtTrylocksOnly: readonly ["trylocks", "cycles"];
57
+ readonly compareRtUnsafe: readonly ["cycles", "allocations", "locks", "syscalls"];
58
+ readonly compareLoadHostEnded: readonly ["died"];
59
+ readonly compareLoadResp: readonly ["resp"];
60
+ readonly compareLoadTimeout: readonly [];
61
+ readonly compareNotLoaded: readonly [];
62
+ readonly compareNoPort: readonly [];
63
+ readonly compareNotRunning: readonly [];
64
+ readonly compareNoAudioOutput: readonly [];
65
+ readonly compareOutputNotFinite: readonly ["count"];
66
+ readonly compareNoStimulusSilent: readonly [];
67
+ readonly compareSilentUnderStimulus: readonly ["stimulus"];
68
+ readonly compareCyclesNotRun: readonly [];
69
+ readonly compareCycleHostEnded: readonly ["cycle", "died"];
70
+ readonly compareCycleFailed: readonly ["cycle"];
71
+ readonly compareCycleFailedAt: readonly ["cycle", "step"];
72
+ readonly compareSoakHostEnded: readonly ["died"];
73
+ readonly compareSoakEnded: readonly [];
74
+ readonly compareLatencyPortObservable: readonly [];
75
+ readonly compareLatencyHostdPortObservable: readonly [];
76
+ readonly compareLatencyNotObservableModHost: readonly [];
77
+ readonly compareLatencyUnreadable: readonly [];
78
+ readonly compareSkippedReason: readonly ["reason"];
79
+ readonly compareDoesBetterOn: readonly ["host", "count", "detail"];
80
+ readonly compareBeatDescription: readonly ["id", "on", "over"];
81
+ readonly compareNotPublishableWithMissing: readonly ["missing"];
82
+ readonly compareNotPublishableNoFlag: readonly [];
83
+ readonly pinHostdNotInstalled: readonly [];
84
+ readonly pinHostdNoPinFiles: readonly [];
85
+ readonly pinHostdExited: readonly ["status"];
86
+ readonly pinHostdNoRootOrFile: readonly [];
87
+ readonly pinFileUnreadable: readonly ["error"];
88
+ }>;
@@ -0,0 +1,96 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ // Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
3
+ //
4
+ // GENERATED by tools/gen-text-codes.mjs from schema/codes.json — do not hand-edit.
5
+ //
6
+ // Regenerate: node tools/gen-text-codes.mjs --write
7
+ // Verify: node tools/gen-text-codes.mjs --check
8
+ /** plugin-qualify's own codes, by key (schema/codes.json). */
9
+ export const TEXT_CODE = Object.freeze({
10
+ descriptorDuplicateSymbol: "qualify.descriptor.duplicate-symbol",
11
+ compareHostNotInstalled: "qualify.compare.host-not-installed",
12
+ compareHostDidNotStart: "qualify.compare.host-did-not-start",
13
+ compareHostNotAsked: "qualify.compare.host-not-asked",
14
+ compareHostDidNotRun: "qualify.compare.host-did-not-run",
15
+ compareFormatNotTaken: "qualify.compare.format-not-taken",
16
+ compareRtNotReported: "qualify.compare.rt-not-reported",
17
+ compareRtNoCallback: "qualify.compare.rt-no-callback",
18
+ compareRtNoWarmUp: "qualify.compare.rt-no-warm-up",
19
+ compareRtTrylocksOnly: "qualify.compare.rt-trylocks-only",
20
+ compareRtUnsafe: "qualify.compare.rt-unsafe",
21
+ compareLoadHostEnded: "qualify.compare.load-host-ended",
22
+ compareLoadResp: "qualify.compare.load-resp",
23
+ compareLoadTimeout: "qualify.compare.load-timeout",
24
+ compareNotLoaded: "qualify.compare.not-loaded",
25
+ compareNoPort: "qualify.compare.no-port",
26
+ compareNotRunning: "qualify.compare.not-running",
27
+ compareNoAudioOutput: "qualify.compare.no-audio-output",
28
+ compareOutputNotFinite: "qualify.compare.output-not-finite",
29
+ compareNoStimulusSilent: "qualify.compare.no-stimulus-silent",
30
+ compareSilentUnderStimulus: "qualify.compare.silent-under-stimulus",
31
+ compareCyclesNotRun: "qualify.compare.cycles-not-run",
32
+ compareCycleHostEnded: "qualify.compare.cycle-host-ended",
33
+ compareCycleFailed: "qualify.compare.cycle-failed",
34
+ compareCycleFailedAt: "qualify.compare.cycle-failed-at",
35
+ compareSoakHostEnded: "qualify.compare.soak-host-ended",
36
+ compareSoakEnded: "qualify.compare.soak-ended",
37
+ compareLatencyPortObservable: "qualify.compare.latency-port-observable",
38
+ compareLatencyHostdPortObservable: "qualify.compare.latency-hostd-port-observable",
39
+ compareLatencyNotObservableModHost: "qualify.compare.latency-not-observable-mod-host",
40
+ compareLatencyUnreadable: "qualify.compare.latency-unreadable",
41
+ compareSkippedReason: "qualify.compare.skipped-reason",
42
+ compareDoesBetterOn: "qualify.compare.does-better-on",
43
+ compareBeatDescription: "qualify.compare.beat-description",
44
+ compareNotPublishableWithMissing: "qualify.compare.not-publishable-with-missing",
45
+ compareNotPublishableNoFlag: "qualify.compare.not-publishable-no-flag",
46
+ pinHostdNotInstalled: "qualify.pin.hostd-not-installed",
47
+ pinHostdNoPinFiles: "qualify.pin.hostd-no-pin-files",
48
+ pinHostdExited: "qualify.pin.hostd-exited",
49
+ pinHostdNoRootOrFile: "qualify.pin.hostd-no-root-or-file",
50
+ pinFileUnreadable: "qualify.pin.file-unreadable",
51
+ });
52
+ /** The args each code's source sentence names, by the same key. */
53
+ export const TEXT_CODE_ARGS = Object.freeze({
54
+ descriptorDuplicateSymbol: ["symbol"],
55
+ compareHostNotInstalled: ["program"],
56
+ compareHostDidNotStart: ["program"],
57
+ compareHostNotAsked: [],
58
+ compareHostDidNotRun: ["program"],
59
+ compareFormatNotTaken: ["program", "format"],
60
+ compareRtNotReported: [],
61
+ compareRtNoCallback: [],
62
+ compareRtNoWarmUp: [],
63
+ compareRtTrylocksOnly: ["trylocks", "cycles"],
64
+ compareRtUnsafe: ["cycles", "allocations", "locks", "syscalls"],
65
+ compareLoadHostEnded: ["died"],
66
+ compareLoadResp: ["resp"],
67
+ compareLoadTimeout: [],
68
+ compareNotLoaded: [],
69
+ compareNoPort: [],
70
+ compareNotRunning: [],
71
+ compareNoAudioOutput: [],
72
+ compareOutputNotFinite: ["count"],
73
+ compareNoStimulusSilent: [],
74
+ compareSilentUnderStimulus: ["stimulus"],
75
+ compareCyclesNotRun: [],
76
+ compareCycleHostEnded: ["cycle", "died"],
77
+ compareCycleFailed: ["cycle"],
78
+ compareCycleFailedAt: ["cycle", "step"],
79
+ compareSoakHostEnded: ["died"],
80
+ compareSoakEnded: [],
81
+ compareLatencyPortObservable: [],
82
+ compareLatencyHostdPortObservable: [],
83
+ compareLatencyNotObservableModHost: [],
84
+ compareLatencyUnreadable: [],
85
+ compareSkippedReason: ["reason"],
86
+ compareDoesBetterOn: ["host", "count", "detail"],
87
+ compareBeatDescription: ["id", "on", "over"],
88
+ compareNotPublishableWithMissing: ["missing"],
89
+ compareNotPublishableNoFlag: [],
90
+ pinHostdNotInstalled: [],
91
+ pinHostdNoPinFiles: [],
92
+ pinHostdExited: ["status"],
93
+ pinHostdNoRootOrFile: [],
94
+ pinFileUnreadable: ["error"],
95
+ });
96
+ //# sourceMappingURL=text-codes.generated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-codes.generated.js","sourceRoot":"","sources":["../src/text-codes.generated.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ // Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
3
+ /**
4
+ * plugin-qualify's own verdict and reason sentences, as codes (omx-contract#2, "codes then catalogs", owner
5
+ * ruling 2026-11-09: a code carries its identifier, its arguments and one source sentence in English with named
6
+ * placeholders; translations live in catalogs the owner ships, keyed by code, checked for placeholders against the
7
+ * code's `args`; a surface looks up the sentence for the user's locale and falls back to this source sentence).
8
+ *
9
+ * plugin-qualify is the owner of these codes (the hosting.* codes of {@link ../hosting-codes.js} are omx-clap-core's
10
+ * instead, and that package owns their catalogs). A code, its args and its source sentence are written once, in
11
+ * `schema/codes.json`; {@link TEXT_CODE} is that file's `key: code` map, generated (`tools/gen-text-codes.mjs`), so a
12
+ * call site names a code by its key and no sentence is written in a module. `catalogs/<lang>.json`, read by
13
+ * {@link ../text-catalog.js}, hold each listed language's sentences; `src/text-catalog-conformance.test.ts` turns red
14
+ * on a code without its source sentence or without an entry in a language, and on a sentence whose placeholders are
15
+ * not its code's `args`.
16
+ */
17
+ import { TEXT_CODE, TEXT_CODE_ARGS } from "./text-codes.generated.js";
18
+ export { TEXT_CODE, TEXT_CODE_ARGS };
19
+ //# sourceMappingURL=text-codes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-codes.js","sourceRoot":"","sources":["../src/text-codes.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,sDAAsD;AACtD;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEtE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@openmixer/plugin-qualify",
3
- "version": "0.20.1",
3
+ "version": "0.20.4",
4
4
  "description": "Qualify audio plugins for real-time hosting: scan, offline latency and cost measurement, and a fail-closed rating.",
5
5
  "type": "module",
6
6
  "license": "GPL-3.0-or-later",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/FreeMixer/plugin-qualify.git"
9
+ "url": "git+https://github.com/Open-Mixer/plugin-qualify.git"
10
10
  },
11
11
  "author": "Pau Aliagas <linuxnow@gmail.com>",
12
- "homepage": "https://github.com/FreeMixer/plugin-qualify#readme",
12
+ "homepage": "https://github.com/Open-Mixer/plugin-qualify#readme",
13
13
  "bugs": {
14
- "url": "https://github.com/FreeMixer/plugin-qualify/issues"
14
+ "url": "https://github.com/Open-Mixer/plugin-qualify/issues"
15
15
  },
16
16
  "engines": {
17
17
  "node": ">=18"
@@ -75,16 +75,18 @@
75
75
  "!**/__pycache__",
76
76
  "!**/*.pyc",
77
77
  "fixtures",
78
+ "schema/codes.json",
79
+ "catalogs",
78
80
  "README.md",
79
81
  "LICENSE"
80
82
  ],
81
83
  "scripts": {
82
- "build": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && node tools/gen-hosting-codes.mjs --build && tsc -p tsconfig.json",
84
+ "build": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && node tools/gen-hosting-codes.mjs --build && node tools/gen-text-codes.mjs --write && tsc -p tsconfig.json",
83
85
  "prepare": "npm run build",
84
86
  "test": "vitest run src",
85
87
  "lint": "tsc -p tsconfig.lint.json",
86
88
  "test:py": "python3 -m pytest tools -q",
87
- "check:generated": "node tools/gen-python-declarations.mjs --check && node tools/gen-hosting-codes.mjs --check",
89
+ "check:generated": "node tools/gen-python-declarations.mjs --check && node tools/gen-hosting-codes.mjs --check && node tools/gen-text-codes.mjs --check",
88
90
  "check:private-refs": "${FREEMIXER_DOTGITHUB:-../freemixer-dotgithub}/.github/actions/private-refs-check/check.sh ."
89
91
  },
90
92
  "devDependencies": {