@openmixer/plugin-qualify 0.18.5 → 0.20.0
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.
- package/README.md +19 -730
- package/bin/plugin-qualify-sync.mjs +1 -1
- package/bin/plugin-qualify.mjs +9 -1
- package/dist/clap-qualify.d.ts +1 -1
- package/dist/compare.d.ts +311 -0
- package/dist/compare.js +502 -0
- package/dist/compare.js.map +1 -0
- package/dist/distributed-records.d.ts +0 -2
- package/dist/distributed-records.js +0 -2
- package/dist/distributed-records.js.map +1 -1
- package/dist/host-admission.d.ts +2 -2
- package/dist/host-admission.js +7 -0
- package/dist/host-admission.js.map +1 -1
- package/dist/hosting-codes.generated.d.ts +1 -0
- package/dist/hosting-codes.generated.js +1 -0
- package/dist/hosting-codes.generated.js.map +1 -1
- package/dist/hosting-suitability.d.ts +3 -1
- package/dist/hosting-suitability.js +9 -0
- package/dist/hosting-suitability.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lv2-loader.js +6 -5
- package/dist/lv2-loader.js.map +1 -1
- package/dist/measurement/format.d.ts +15 -0
- package/dist/measurement/format.js +19 -0
- package/dist/measurement/format.js.map +1 -1
- package/dist/measurement/sweep-jsonl.js +5 -1
- package/dist/measurement/sweep-jsonl.js.map +1 -1
- package/dist/measurement-grid.js +1 -1
- package/dist/pins-file.d.ts +22 -2
- package/dist/pins-file.js +118 -17
- package/dist/pins-file.js.map +1 -1
- package/dist/probe-merge.js +6 -0
- package/dist/probe-merge.js.map +1 -1
- package/dist/probe-runner.d.ts +4 -0
- package/dist/probe-runner.js +12 -3
- package/dist/probe-runner.js.map +1 -1
- package/dist/qualification-record.d.ts +33 -1
- package/dist/qualification-record.js +36 -3
- package/dist/qualification-record.js.map +1 -1
- package/dist/qualify-declarations.d.ts +6 -0
- package/dist/qualify-declarations.js +8 -0
- package/dist/qualify-declarations.js.map +1 -1
- package/dist/qualify-isolated.d.ts +16 -3
- package/dist/qualify-isolated.js +31 -3
- package/dist/qualify-isolated.js.map +1 -1
- package/dist/qualify-pool.d.ts +129 -0
- package/dist/qualify-pool.js +290 -0
- package/dist/qualify-pool.js.map +1 -0
- package/dist/qualify-rejudge.js +7 -0
- package/dist/qualify-rejudge.js.map +1 -1
- package/dist/qualify-sync.d.ts +37 -2
- package/dist/qualify-sync.js +148 -24
- package/dist/qualify-sync.js.map +1 -1
- package/dist/records-package.d.ts +5 -0
- package/dist/records-package.js +25 -8
- package/dist/records-package.js.map +1 -1
- package/fixtures/clap-scan/fake.json +8 -2
- package/fixtures/probe-output/success-msi.json +2 -2
- package/package.json +3 -3
- package/src/clap-qualify.ts +1 -1
- package/src/compare.ts +699 -0
- package/src/distributed-records.ts +0 -3
- package/src/host-admission.ts +9 -2
- package/src/hosting-codes.generated.ts +1 -0
- package/src/hosting-suitability.ts +14 -0
- package/src/index.ts +1 -0
- package/src/lv2-loader.ts +5 -4
- package/src/measurement/format.ts +32 -0
- package/src/measurement/sweep-jsonl.ts +5 -1
- package/src/measurement-grid.ts +1 -1
- package/src/pins-file.ts +109 -16
- package/src/probe-merge.ts +4 -0
- package/src/probe-runner.ts +16 -6
- package/src/qualification-record.ts +59 -4
- package/src/qualify-declarations.ts +8 -0
- package/src/qualify-isolated.ts +31 -5
- package/src/qualify-pool.ts +318 -0
- package/src/qualify-rejudge.ts +8 -0
- package/src/qualify-sync.ts +145 -24
- package/src/records-package.ts +25 -8
- package/tools/benchmark.py +9 -3
- package/tools/compare-host.mjs +432 -0
- package/tools/compare-run.mjs +355 -0
- package/tools/descriptors.py +27 -0
- package/tools/isolated-step.mjs +3 -1
- package/tools/lilv_load.py +25 -0
- package/tools/lv2_resolve.py +3 -1
- package/tools/pool-step.mjs +186 -0
- package/tools/scan.py +16 -20
- package/tools/audit-overlap.sh +0 -250
- package/tools/commit-message-check.sh +0 -128
- package/tools/commit-message-patterns.json +0 -41
- package/tools/private-refs-check.sh +0 -90
package/tools/scan.py
CHANGED
|
@@ -62,23 +62,17 @@ REPORTS_LATENCY = LV2 + "reportsLatency"
|
|
|
62
62
|
MINOR_VERSION = LV2 + "minorVersion"
|
|
63
63
|
MICRO_VERSION = LV2 + "microVersion"
|
|
64
64
|
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
UNITS + "s": "s", UNITS + "ms": "ms", UNITS + "pc": "%",
|
|
70
|
-
UNITS + "semitone12TET": "semi", UNITS + "cent": "ct",
|
|
71
|
-
UNITS + "degree": "deg", UNITS + "coef": "x", UNITS + "oct": "oct",
|
|
72
|
-
UNITS + "bpm": "BPM", UNITS + "midiNote": "note", UNITS + "frame": "fr",
|
|
73
|
-
}
|
|
65
|
+
# A port's unit is spelled as omx-contract's units sheet spells it (desc.unit_words), in the catalog and in the
|
|
66
|
+
# descriptor alike; a unit the sheet has no word for falls to the plugin's own units:symbol in the catalog, and
|
|
67
|
+
# is `unknown` in the descriptor.
|
|
68
|
+
_UNIT_WORDS = None
|
|
74
69
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
70
|
+
|
|
71
|
+
def unit_words():
|
|
72
|
+
global _UNIT_WORDS
|
|
73
|
+
if _UNIT_WORDS is None:
|
|
74
|
+
_UNIT_WORDS = desc.unit_words()
|
|
75
|
+
return _UNIT_WORDS
|
|
82
76
|
|
|
83
77
|
# lv2:designation -> the descriptor's meaning, where the meaning carries the LV2 term's name
|
|
84
78
|
DESIGNATED_MEANINGS = {
|
|
@@ -178,7 +172,9 @@ class Scanner:
|
|
|
178
172
|
def __init__(self):
|
|
179
173
|
# lilv is imported here, not at module load: the owner mapping and the pure helpers
|
|
180
174
|
# (test_scan.py) run on a host without the bindings, the way benchmark.py's worker does.
|
|
181
|
-
import
|
|
175
|
+
from lilv_load import load_lilv
|
|
176
|
+
|
|
177
|
+
lilv = load_lilv()
|
|
182
178
|
|
|
183
179
|
self.w = lilv.World()
|
|
184
180
|
self.w.load_all()
|
|
@@ -206,8 +202,8 @@ class Scanner:
|
|
|
206
202
|
if un is None:
|
|
207
203
|
return None
|
|
208
204
|
uri = str(un)
|
|
209
|
-
if uri in
|
|
210
|
-
return
|
|
205
|
+
if uri in unit_words():
|
|
206
|
+
return unit_words()[uri]
|
|
211
207
|
sym = first(self.w.find_nodes(un, self.u[UNITS + "symbol"], None))
|
|
212
208
|
return str(sym) if sym is not None else None
|
|
213
209
|
|
|
@@ -377,7 +373,7 @@ class Scanner:
|
|
|
377
373
|
|
|
378
374
|
def descriptor_unit(self, port):
|
|
379
375
|
un = first(port.get_value(self.u[UNITS + "unit"]))
|
|
380
|
-
return
|
|
376
|
+
return unit_words().get(str(un), "unknown") if un is not None else "unknown"
|
|
381
377
|
|
|
382
378
|
def descriptor_control(self, port, link, readonly=False):
|
|
383
379
|
"""An input (or, readonly, an output) control port as a descriptor control."""
|
package/tools/audit-overlap.sh
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
3
|
-
# Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
4
|
-
#
|
|
5
|
-
# audit-overlap.sh — every number in docs/audit-qualify-vs-compat.md, from source, by one command each.
|
|
6
|
-
#
|
|
7
|
-
# tools/audit-overlap.sh <omx-clap-core dir> <plugin-hostd dir>
|
|
8
|
-
# tools/audit-overlap.sh --self-test
|
|
9
|
-
#
|
|
10
|
-
# It prints one line per unit (a function, or a set of functions, in one repository):
|
|
11
|
-
# unit <id> <repo> <file>:<first>-<last> lines=<n>
|
|
12
|
-
# one line per pair that does the same job in two places:
|
|
13
|
-
# pair <a> <b> shared=<s> a=<na> b=<nb> overlap=<s/min(na,nb) %> diff=<changed lines or "-"> strings=<both/a/b>
|
|
14
|
-
# and one line per counted marker:
|
|
15
|
-
# count <id> <repo> <n>
|
|
16
|
-
# A unit is found by its name (a C or TypeScript function runs to the first column-0 `}`, a Python def or class
|
|
17
|
-
# to the next column-0 statement), never by a line number, so the numbers follow the code. The audited commits are
|
|
18
|
-
# printed first (`tree <repo> <commit>`); the document states which ones it quotes.
|
|
19
|
-
#
|
|
20
|
-
# Similarity: both bodies are normalised (comments, blank lines and lone braces dropped, whitespace squeezed), then
|
|
21
|
-
# `shared` is the number of normalised lines the two have in common (comm -12 over the sorted lines, duplicates
|
|
22
|
-
# kept) and `diff` the number of lines `diff` adds or removes between them. Code in two languages shares no line;
|
|
23
|
-
# for it the pair prints overlap=0 and diff=-. `strings` is shared/a/b of the distinct string literals (three or
|
|
24
|
-
# more characters) each body spells: messages, field names and codes, which survive a change of brace style or of
|
|
25
|
-
# language, so a port of the same code shows there when its lines do not.
|
|
26
|
-
set -euo pipefail
|
|
27
|
-
export LC_ALL=C
|
|
28
|
-
Q="$(cd "$(dirname "$0")/.." && pwd)"
|
|
29
|
-
|
|
30
|
-
die() { echo "audit-overlap: $*" >&2; exit 2; }
|
|
31
|
-
|
|
32
|
-
# span <lang> <file> <name> — print "<first> <last>" of the named unit, nothing when there is none
|
|
33
|
-
span() { # <lang> <file> <name>
|
|
34
|
-
awk -v lang="$1" -v name="$3" '
|
|
35
|
-
function starts(l) {
|
|
36
|
-
if (lang == "py") return l ~ ("^(def|class) " name "[(:]")
|
|
37
|
-
if (lang == "ts") return l ~ ("^(export )?(async )?function " name "[(<]")
|
|
38
|
-
return l ~ ("^[A-Za-z].*[ *]" name "\\(") && l !~ /;[ \t]*$/
|
|
39
|
-
}
|
|
40
|
-
!on && starts($0) { on = 1; first = NR; last = NR; next }
|
|
41
|
-
on && lang != "py" && /^}/ { last = NR; print first, last; exit }
|
|
42
|
-
on && lang == "py" && /^[^ \t#\n]/ { print first, last; exit }
|
|
43
|
-
on && lang == "py" && /[^ \t]/ { last = NR }
|
|
44
|
-
END { if (on && lang == "py") print first, last }
|
|
45
|
-
' "$2"
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
WORK="$(mktemp -d)"; trap 'rm -rf "$WORK"' EXIT
|
|
49
|
-
declare -A ROOT LANG_OF
|
|
50
|
-
|
|
51
|
-
# unit <id> <repo> <lang> <file> <name>... — one unit, the names' bodies concatenated
|
|
52
|
-
unit() {
|
|
53
|
-
local id="$1" repo="$2" lang="$3" file="$4"; shift 4
|
|
54
|
-
local root="${ROOT[$repo]}" n total=0 where="" s
|
|
55
|
-
: > "$WORK/$id"
|
|
56
|
-
for n in "$@"; do
|
|
57
|
-
s="$(span "$lang" "$root/$file" "$n")"
|
|
58
|
-
[ -n "$s" ] || die "$repo $file: no $lang unit named $n"
|
|
59
|
-
local a b; read -r a b <<<"$s"
|
|
60
|
-
sed -n "${a},${b}p" "$root/$file" >> "$WORK/$id"
|
|
61
|
-
total=$((total + b - a + 1)); where="${where:+$where,}$a-$b"
|
|
62
|
-
done
|
|
63
|
-
LANG_OF[$id]="$lang"
|
|
64
|
-
echo "unit $id $repo $file:$where lines=$total"
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
# whole <id> <repo> <lang> <file> — a whole file as one unit
|
|
68
|
-
whole() {
|
|
69
|
-
local id="$1" repo="$2" lang="$3" file="$4" n
|
|
70
|
-
cp "${ROOT[$repo]}/$file" "$WORK/$id"; n=$(wc -l < "$WORK/$id")
|
|
71
|
-
LANG_OF[$id]="$lang"
|
|
72
|
-
echo "unit $id $repo $file:1-$n lines=$n"
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
norm() { # <lang> < body
|
|
76
|
-
case "$1" in
|
|
77
|
-
py) sed -E 's/#.*$//' ;;
|
|
78
|
-
*) sed -E 's#//.*$##; s#/\*.*\*/##g; /^[[:space:]]*\*( |\/|$)/d; /^[[:space:]]*\/\*/d' ;;
|
|
79
|
-
esac | sed -E 's/[[:space:]]+/ /g; s/^ //; s/ $//' | grep -vE '^[{}();, ]*$' || true
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
lits() { grep -oE "\"[^\"\\\\]{3,}\"|'[^'\\\\]{3,}'" | sed -E "s/^.(.*).$/\\1/"; } # quotes dropped: '' and "" alike
|
|
83
|
-
|
|
84
|
-
pair() { # <a> <b>
|
|
85
|
-
local a="$1" b="$2" na nb s d m l
|
|
86
|
-
norm "${LANG_OF[$a]}" < "$WORK/$a" | sort > "$WORK/$a.n"
|
|
87
|
-
norm "${LANG_OF[$b]}" < "$WORK/$b" | sort > "$WORK/$b.n"
|
|
88
|
-
na=$(wc -l < "$WORK/$a.n"); nb=$(wc -l < "$WORK/$b.n")
|
|
89
|
-
s=$(comm -12 "$WORK/$a.n" "$WORK/$b.n" | wc -l)
|
|
90
|
-
m=$(( na < nb ? na : nb ))
|
|
91
|
-
if [ "${LANG_OF[$a]}" = "${LANG_OF[$b]}" ]; then
|
|
92
|
-
norm "${LANG_OF[$a]}" < "$WORK/$a" > "$WORK/$a.o"; norm "${LANG_OF[$b]}" < "$WORK/$b" > "$WORK/$b.o"
|
|
93
|
-
d=$(diff "$WORK/$a.o" "$WORK/$b.o" | grep -c '^[<>]' || true)
|
|
94
|
-
else d="-"; fi
|
|
95
|
-
# the string literals (messages, field names, codes) both spell: what survives a change of style or language
|
|
96
|
-
norm "${LANG_OF[$a]}" < "$WORK/$a" | lits | sort -u > "$WORK/$a.l" || true
|
|
97
|
-
norm "${LANG_OF[$b]}" < "$WORK/$b" | lits | sort -u > "$WORK/$b.l" || true
|
|
98
|
-
l="$(comm -12 "$WORK/$a.l" "$WORK/$b.l" | wc -l)/$(wc -l < "$WORK/$a.l")/$(wc -l < "$WORK/$b.l")"
|
|
99
|
-
echo "pair $a $b shared=$s a=$na b=$nb overlap=$(( m ? 100 * s / m : 0 ))% diff=$d strings=$l"
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
count() { # <id> <repo> <git grep args> -- <pathspec>... (this audit's own two files are never counted)
|
|
103
|
-
local id="$1" repo="$2"; shift 2
|
|
104
|
-
local self=(":(exclude)tools/audit-overlap.sh" ":(exclude)docs/audit-qualify-vs-compat.md")
|
|
105
|
-
echo "count $id $repo $(git -C "${ROOT[$repo]}" grep -IE "$@" "${self[@]}" | wc -l)"
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
audit() {
|
|
109
|
-
local r
|
|
110
|
-
for r in qualify clap-core hostd; do echo "tree $r $(git -C "${ROOT[$r]}" rev-parse --short HEAD)"; done
|
|
111
|
-
|
|
112
|
-
# 1. plugin enumeration
|
|
113
|
-
unit q.clap-walk qualify c native/clap-qualify.c is_clap walk scan
|
|
114
|
-
unit c.clap-walk clap-core c src/scan.c has_suffix walk main
|
|
115
|
-
unit q.clap-fork qualify c native/clap-qualify.c scan_file
|
|
116
|
-
unit c.clap-fork clap-core c src/scan.c scan_file
|
|
117
|
-
unit q.clap-describe qualify c native/clap-qualify.c scan_file_entry scan_plugin scan_params scan_audio_ports
|
|
118
|
-
unit c.clap-describe clap-core c src/scan.c put_file put_plugin put_descriptor put_params put_audio_ports
|
|
119
|
-
unit q.clap-path qualify ts src/clap-loader.ts clapSearchPath
|
|
120
|
-
unit c.clap-path clap-core c src/scan.c default_paths
|
|
121
|
-
unit q.lv2-manifest qualify ts src/lv2-loader.ts pluginsInManifest lv2BundlesOnPath
|
|
122
|
-
unit c.lv2-manifest clap-core c src/lv2_locate.c lv2_locate_manifest_names walk_dir lv2_locate
|
|
123
|
-
unit q.lv2-lilv qualify py tools/scan.py Scanner
|
|
124
|
-
unit c.lv2-lilv clap-core py tests/lv2_parity.py lilv_facts
|
|
125
|
-
pair q.clap-walk c.clap-walk
|
|
126
|
-
pair q.clap-fork c.clap-fork
|
|
127
|
-
pair q.clap-describe c.clap-describe
|
|
128
|
-
pair q.clap-path c.clap-path
|
|
129
|
-
pair q.lv2-manifest c.lv2-manifest
|
|
130
|
-
pair q.lv2-lilv c.lv2-lilv
|
|
131
|
-
count q.calls-omx-clap-scan qualify -e 'omx-clap-scan' -- src
|
|
132
|
-
# clap-qualify's whole scan mode (--json), which writes the document omx-clap-scan writes, plus labels and pages
|
|
133
|
-
unit q.scan-mode qualify c native/clap-qualify.c put_labels scan_params scan_remote_controls scan_audio_ports \
|
|
134
|
-
scan_plugin put_file_error scan_file_entry scan_file list_add is_clap walk scan
|
|
135
|
-
count c.scan-labels-pages clap-core -i -e 'remote_controls|enum_labels|"labels"' -- src/scan.c
|
|
136
|
-
|
|
137
|
-
# 2. deterministic input
|
|
138
|
-
count q.lcg-nr qualify -e '1664525u' -- native
|
|
139
|
-
count q.lcg-glibc qualify -e '1103515245u' -- native
|
|
140
|
-
count c.lcg-nr clap-core -e '1664525u' -- tests src
|
|
141
|
-
unit q.noise-lv2 qualify c native/lv2-measure.c fill_input
|
|
142
|
-
unit c.signal clap-core c tests/jack_parity.c noise signal_at
|
|
143
|
-
pair q.noise-lv2 c.signal
|
|
144
|
-
unit q.notes qualify c native/clap-qualify.c note_event note_midi note_key note_block note_dialect
|
|
145
|
-
unit q.notes-py qualify py tools/benchmark.py held_keys midi_sequence
|
|
146
|
-
unit c.notes clap-core c tests/jack_parity.c midi_events
|
|
147
|
-
pair q.notes c.notes
|
|
148
|
-
pair q.notes-py q.notes
|
|
149
|
-
|
|
150
|
-
# 3. isolated PipeWire, the feeder
|
|
151
|
-
count q.pipewire qualify -i -e 'pipewire|unshare' -- src native tools bin
|
|
152
|
-
count c.unshare clap-core -e 'unshare' -- tests
|
|
153
|
-
unit c.pw-parity clap-core py tests/lv2_parity.py start_pipewire
|
|
154
|
-
unit c.pw-coverage clap-core py tests/clap_coverage.py start_pipewire
|
|
155
|
-
unit c.ns-parity clap-core py tests/lv2_parity.py inside_run cmd_run
|
|
156
|
-
unit c.ns-coverage clap-core py tests/clap_coverage.py inside_host cmd_host
|
|
157
|
-
unit c.clock clap-core c tests/jack_parity.c clock_process clock_state clock_wait clock_start clock_cycle clock_run
|
|
158
|
-
pair c.pw-parity c.pw-coverage
|
|
159
|
-
pair c.ns-parity c.ns-coverage
|
|
160
|
-
|
|
161
|
-
# 4. host launch, teardown, crash and hang
|
|
162
|
-
unit q.probe-runner qualify ts src/probe-runner.ts runOne probeTarget
|
|
163
|
-
unit h.run-child hostd c src/probe.c apply_limits kill_tree run_child child_end
|
|
164
|
-
unit q.bench-worker qualify py tools/benchmark.py WorkerQueue _Worker
|
|
165
|
-
unit c.host-parity clap-core py tests/lv2_parity.py Host run_plugin
|
|
166
|
-
unit c.host-coverage clap-core py tests/clap_coverage.py Host
|
|
167
|
-
pair c.host-parity c.host-coverage
|
|
168
|
-
pair q.bench-worker c.host-parity
|
|
169
|
-
count h.runs-clap-qualify hostd -e 'clap-qualify|clap_qualify' -- src
|
|
170
|
-
count h.runs-lv2-measure hostd -e 'lv2_measure|lv2-measure' -- src
|
|
171
|
-
|
|
172
|
-
# 5. records, classification, vocabulary, reports
|
|
173
|
-
unit q.records qualify ts src/measurement/sweep-jsonl.ts measuredPluginsFromSweep parseJsonl
|
|
174
|
-
unit c.tsv-parity clap-core py tests/lv2_parity.py read_tsv write_tsv
|
|
175
|
-
unit c.tsv-coverage clap-core py tests/clap_coverage.py read_tsv write_tsv append_tsv
|
|
176
|
-
pair c.tsv-parity c.tsv-coverage
|
|
177
|
-
unit q.classify qualify ts src/hosting-suitability.ts classifyPluginHosting
|
|
178
|
-
unit c.classify clap-core py tests/lv2_parity.py _classify
|
|
179
|
-
pair q.classify c.classify
|
|
180
|
-
unit c.report clap-core py tests/lv2_parity.py report_text
|
|
181
|
-
count q.contract-imports qualify -e "from \"@openmixer/omx-contract" -- src
|
|
182
|
-
count c.contract-macros clap-core -e 'OMX_HOSTING_[A-Z_]+' -- src lv2
|
|
183
|
-
count q.handtyped-hosting qualify -e '"hosting\.[a-z-]+\.[a-z-]+"' -- 'src/*.ts' ':!src/*.test.ts'
|
|
184
|
-
|
|
185
|
-
# 6. cost and latency
|
|
186
|
-
unit q.pct-c qualify c native/clap-qualify.c percentile_sorted
|
|
187
|
-
unit q.pct-py qualify py tools/benchmark.py percentile
|
|
188
|
-
unit q.cost-c qualify c native/clap-qualify.c cost_rate
|
|
189
|
-
unit c.stage-bench clap-core c tests/stage_bench.c main
|
|
190
|
-
pair q.pct-c q.pct-py
|
|
191
|
-
pair q.cost-c c.stage-bench
|
|
192
|
-
|
|
193
|
-
# the probing programs plugin-hostd's probe runs as its children today, and what the move into its child deletes
|
|
194
|
-
whole q.prober-clap qualify c native/clap-qualify.c
|
|
195
|
-
whole q.prober-lv2 qualify c native/lv2-measure.c
|
|
196
|
-
whole q.benchmark qualify py tools/benchmark.py
|
|
197
|
-
|
|
198
|
-
# 7. mod-host in plugin-qualify: code that runs it, and words that name it
|
|
199
|
-
count q.modhost-spawn qualify -e "spawn[A-Za-z]*\\(['\"]mod-host|execvp?\\(\"mod-host" -- src native tools bin
|
|
200
|
-
count q.modhost-words qualify -i -e 'mod-host' -- .
|
|
201
|
-
count c.modhost-words clap-core -i -e 'mod-host' -- tests
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
self_test() {
|
|
205
|
-
T="$(mktemp -d)"; local t="$T"; trap 'rm -rf "$T" "$WORK"' EXIT
|
|
206
|
-
for r in a b c; do mkdir -p "$t/$r"; git -C "$t/$r" init -q; done
|
|
207
|
-
cat > "$t/a/x.c" <<'EOF'
|
|
208
|
-
static int one(int v)
|
|
209
|
-
{
|
|
210
|
-
/* a comment */
|
|
211
|
-
return v + !"same"; /* "comment" */
|
|
212
|
-
}
|
|
213
|
-
static int two(int v) {
|
|
214
|
-
return v * 2;
|
|
215
|
-
}
|
|
216
|
-
EOF
|
|
217
|
-
cat > "$t/b/y.py" <<'EOF'
|
|
218
|
-
def one(v):
|
|
219
|
-
# a comment
|
|
220
|
-
return v + len("same") # "comment"
|
|
221
|
-
|
|
222
|
-
X = 1
|
|
223
|
-
EOF
|
|
224
|
-
cp "$t/a/x.c" "$t/c/z.c"; sed -i 's/v \* 2/v * 3/' "$t/c/z.c"
|
|
225
|
-
for r in a b c; do git -C "$t/$r" add -A; git -C "$t/$r" -c user.name=t -c user.email=t@t commit -qm t; done
|
|
226
|
-
ROOT[qualify]="$t/a"; ROOT[clap-core]="$t/b"; ROOT[hostd]="$t/c"
|
|
227
|
-
local out fail=0
|
|
228
|
-
expect() { grep -qxF -- "$1" <<<"$out" || { echo "self-test: missing: $1" >&2; fail=1; }; }
|
|
229
|
-
out="$(unit u1 qualify c x.c one; unit u2 qualify c x.c two; unit p1 clap-core py y.py one
|
|
230
|
-
unit h1 hostd c z.c one two; unit h2 qualify c x.c one two
|
|
231
|
-
pair h2 h1; pair u1 p1; count n qualify -e 'return' -- .)"
|
|
232
|
-
expect "unit u1 qualify x.c:1-5 lines=5"
|
|
233
|
-
expect "unit u2 qualify x.c:6-8 lines=3"
|
|
234
|
-
expect "unit p1 clap-core y.py:1-3 lines=3"
|
|
235
|
-
expect "pair h2 h1 shared=3 a=4 b=4 overlap=75% diff=2 strings=1/1/1"
|
|
236
|
-
expect "pair u1 p1 shared=0 a=2 b=2 overlap=0% diff=- strings=1/1/1"
|
|
237
|
-
expect "count n qualify 2"
|
|
238
|
-
# a name that is not there is refused, never counted as zero
|
|
239
|
-
if (unit u3 qualify c x.c three) 2>/dev/null; then echo "self-test: a missing unit was not refused" >&2; fail=1; fi
|
|
240
|
-
[ "$fail" = 0 ] && echo "audit-overlap self-test: ok"
|
|
241
|
-
return "$fail"
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
case "${1:-}" in
|
|
245
|
-
--self-test) self_test ;;
|
|
246
|
-
-h|--help|"") sed -n '5,9p' "$0"; [ -n "${1:-}" ] ;;
|
|
247
|
-
*) [ $# = 2 ] || die "usage: $0 <omx-clap-core dir> <plugin-hostd dir>"
|
|
248
|
-
ROOT[qualify]="$Q"; ROOT[clap-core]="$(cd "$1" && pwd)"; ROOT[hostd]="$(cd "$2" && pwd)"
|
|
249
|
-
audit ;;
|
|
250
|
-
esac
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
3
|
-
# commit-message-check.sh: fail when a commit message carries an attribution line.
|
|
4
|
-
#
|
|
5
|
-
# commit-message-check.sh <range> every commit in the range (e.g. origin/main..HEAD)
|
|
6
|
-
# commit-message-check.sh --msg-file FILE one message (the commit-msg hook; # lines are git comments, skipped)
|
|
7
|
-
# commit-message-check.sh --text-file FILE any text, every line judged (PR titles and bodies)
|
|
8
|
-
# commit-message-check.sh --selftest fixtures plus a sabotage run
|
|
9
|
-
#
|
|
10
|
-
# Exit 0 clean, 1 a hit (each commit and offending line is named), 2 a range, file or pattern list that cannot be read
|
|
11
|
-
# (any crash is 2). Callers refuse on 2: a checker that cannot judge is never a pass.
|
|
12
|
-
# The patterns are commit-message-patterns.json beside this script, the same list the ops sweep strips
|
|
13
|
-
# issue and PR text with, and the one list every door reads: merge-pr.sh, integrate-check.sh, pr-from-devel.sh
|
|
14
|
-
# (ops/tools/tests/commit-message-one-list.t.sh refuses a second list). COMMIT_MESSAGE_PATTERNS names another JSON (self-tests). Repos that cannot see the ops tree carry a copy of both files.
|
|
15
|
-
set -euo pipefail
|
|
16
|
-
export COMMIT_MESSAGE_CHECK_SELF="${BASH_SOURCE[0]}"
|
|
17
|
-
exec python3 -I - "$@" <<'PY'
|
|
18
|
-
import json, os, re, subprocess, sys
|
|
19
|
-
|
|
20
|
-
here = os.path.dirname(os.path.realpath(os.environ["COMMIT_MESSAGE_CHECK_SELF"]))
|
|
21
|
-
pfile = os.environ.get("COMMIT_MESSAGE_PATTERNS") or os.path.join(here, "commit-message-patterns.json")
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def load():
|
|
25
|
-
with open(pfile, encoding="utf-8") as f:
|
|
26
|
-
return [(m["name"], re.compile(m["pattern"], re.I | re.M)) for m in json.load(f)["markers"]]
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def hits(text, markers):
|
|
30
|
-
out = []
|
|
31
|
-
for n, line in enumerate(text.splitlines(), 1):
|
|
32
|
-
for name, rx in markers:
|
|
33
|
-
if rx.search(line):
|
|
34
|
-
out.append((n, name, line.strip()))
|
|
35
|
-
return out
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def report(label, text, markers):
|
|
39
|
-
h = hits(text, markers)
|
|
40
|
-
for n, name, line in h:
|
|
41
|
-
print(f"{label}: line {n} [{name}]: {line}")
|
|
42
|
-
return len(h)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def git(*a):
|
|
46
|
-
p = subprocess.run(["git", *a], capture_output=True, text=True)
|
|
47
|
-
if p.returncode:
|
|
48
|
-
print(f"commit-message-check: git {' '.join(a[:3])}: {p.stderr.strip()}", file=sys.stderr)
|
|
49
|
-
sys.exit(2)
|
|
50
|
-
return p.stdout
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def selftest():
|
|
54
|
-
# every marker is joined from fragments, so this file carries none of the lines it must refuse
|
|
55
|
-
CL, cl, AN, OP, CP, GEN = "Cl" + "aude", "cl" + "aude", "anthr" + "opic", "Op" + "us", "Copi" + "lot", "Gener" + "ated"
|
|
56
|
-
fx = {
|
|
57
|
-
"co-authored-by": f"Fix x\n\nCo-Authored-By: {CL} {OP} <noreply@{AN}.com>\n",
|
|
58
|
-
"session-trailer": f"Fix x\n\n{CL}-Session: https://{cl}.ai/code/session_01\n",
|
|
59
|
-
"generated-footer": f"Fix x\n\n\U0001F916 {GEN} with [{CL} Code](https://{cl}.com/{cl}-code)\n",
|
|
60
|
-
"session-url": f"Fix x\n\nsee https://{cl}.ai/code/session_9\n",
|
|
61
|
-
# the shapes the omx-dsp#155 review saw pass
|
|
62
|
-
"assisted-by": f"Fix x\n\nAssisted-by: {CL}\n",
|
|
63
|
-
"made-with": f"Fix x\n\nMade with {CL} Code\n",
|
|
64
|
-
"generated-with-claude": f"Fix x\n\n{GEN} with {CL}\n",
|
|
65
|
-
"generated-by-trailer": f"Fix x\n\nGenerated-by: {CL}\n",
|
|
66
|
-
"co-author-model": f"Fix x\n\nCo-authored-by: {OP} 5.5 <x@example.invalid>\n",
|
|
67
|
-
"co-author-github-copilot": f"Fix x\n\nCo-authored-by: GitHub {CP} <{CP.lower()}@github.com>\n",
|
|
68
|
-
}
|
|
69
|
-
clean = ("Fix x\n\nGenerated by the build; mentions .claude/ and a Co-Authored-By: Pau line.\n"
|
|
70
|
-
"Assisted-by: Pau Aliagas\nMade with care; generated with tools/rules-index-gen.sh\n"
|
|
71
|
-
f"A review quoted 'Assisted-by: {CL}' and 'Co-authored-by: {OP} 5.5 <x>' as shapes that passed.\n")
|
|
72
|
-
def run(markers):
|
|
73
|
-
bad = [k for k, v in fx.items() if not hits(v, markers)]
|
|
74
|
-
if hits(clean, markers):
|
|
75
|
-
bad.append("clean-flagged")
|
|
76
|
-
return bad
|
|
77
|
-
m = load()
|
|
78
|
-
first = run(m)
|
|
79
|
-
print("selftest:", "GREEN" if not first else f"RED {first}")
|
|
80
|
-
sab = run([x for x in m if x[0] not in ("co-authored-by", "ai-co-author", "anthropic-noreply", "session-trailer")])
|
|
81
|
-
print("sabotage (the co-author, email and session patterns removed):", "RED as expected" if sab else "still GREEN: blind")
|
|
82
|
-
# each #152 shape is seen by a pattern of its own family, not by luck
|
|
83
|
-
new = ["assisted-by", "made-with", "generated-with-claude", "generated-by-trailer", "co-author-model", "co-author-github-copilot"]
|
|
84
|
-
sab2 = run([x for x in m if x[0] not in ("ai-assisted-by", "generated-footer", "ai-co-author-model")])
|
|
85
|
-
blind = [k for k in new if k not in sab2]
|
|
86
|
-
print("sabotage (the assisted-by, generated and model co-author patterns removed):",
|
|
87
|
-
"RED as expected" if not blind else f"still GREEN for {blind}: blind")
|
|
88
|
-
return 0 if not first and sab and not blind else 1
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def main(a):
|
|
92
|
-
if a == ["--selftest"]:
|
|
93
|
-
return selftest()
|
|
94
|
-
markers = load()
|
|
95
|
-
if len(a) == 2 and a[0] == "--msg-file":
|
|
96
|
-
try:
|
|
97
|
-
text = open(a[1], encoding="utf-8", errors="replace").read()
|
|
98
|
-
except OSError as e:
|
|
99
|
-
print(f"commit-message-check: {e}", file=sys.stderr)
|
|
100
|
-
return 2
|
|
101
|
-
# lines git adds as comments are not part of the message
|
|
102
|
-
text = "\n".join(l for l in text.splitlines() if not l.startswith("#"))
|
|
103
|
-
return 1 if report("commit message", text, markers) else 0
|
|
104
|
-
if len(a) == 2 and a[0] == "--text-file":
|
|
105
|
-
try:
|
|
106
|
-
text = open(a[1], encoding="utf-8", errors="replace").read()
|
|
107
|
-
except OSError as e:
|
|
108
|
-
print(f"commit-message-check: {e}", file=sys.stderr)
|
|
109
|
-
return 2
|
|
110
|
-
return 1 if report("text", text, markers) else 0
|
|
111
|
-
if len(a) == 1 and not a[0].startswith("-"):
|
|
112
|
-
shas = git("rev-list", a[0]).split()
|
|
113
|
-
bad = 0
|
|
114
|
-
for sha in shas:
|
|
115
|
-
bad += report(sha[:12], git("log", "-1", "--format=%B", sha), markers)
|
|
116
|
-
print(f"commit-message-check: {len(shas)} commits, {bad} offending lines")
|
|
117
|
-
return 1 if bad else 0
|
|
118
|
-
print(__doc__ if False else "usage: commit-message-check.sh <range> | --msg-file FILE | --text-file FILE | --selftest", file=sys.stderr)
|
|
119
|
-
return 2
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
try:
|
|
123
|
-
rc = main(sys.argv[1:])
|
|
124
|
-
except Exception as e: # a bad or missing pattern file, a decode error: unreadable, never "a hit"
|
|
125
|
-
print(f"commit-message-check: {type(e).__name__}: {e}", file=sys.stderr)
|
|
126
|
-
rc = 2
|
|
127
|
-
sys.exit(rc)
|
|
128
|
-
PY
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$comment": "Single source of the attribution patterns (Python re, flags IGNORECASE|MULTILINE). Read by the ops sweep and commit-message-check.sh. Edit here only. A trailer-shaped pattern that eats the rest of its line is anchored at the line start, so prose quoting a trailer keeps its text.",
|
|
3
|
-
"markers": [
|
|
4
|
-
{
|
|
5
|
-
"name": "robot-footer",
|
|
6
|
-
"pattern": "^[^\\S\\r\\n]*[_*>]*[^\\S\\r\\n]*🤖[^\\r\\n]*?(?:Claude|claude\\.(?:ai|com))[^\\r\\n]*"
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
"name": "generated-footer",
|
|
10
|
-
"pattern": "(?:🤖[^\\S\\r\\n]*)?(?:Generated|Made)[^\\S\\r\\n]+(?:with|by)[^\\S\\r\\n]+\\[?Claude(?:[^\\S\\r\\n]+Code)?\\]?(?:\\([^)\\s]*\\))?"
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
"name": "co-authored-by",
|
|
14
|
-
"pattern": "Co-Authored-By:[^\\S\\r\\n]*Claude\\b[^\\r\\n<`]*(?:<[^>\\r\\n]*>)?"
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"name": "ai-co-author",
|
|
18
|
-
"pattern": "Co-Authored-By:[^\\S\\r\\n]*(?:Anthropic|OpenAI|ChatGPT|Copilot|Gemini|Codex|Cursor|Aider|Devin)\\b[^\\r\\n<`]*(?:<[^>\\r\\n]*>)?"
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"name": "ai-co-author-model",
|
|
22
|
-
"pattern": "^[^\\S\\r\\n]*Co-Authored-By:[^\\S\\r\\n]*(?:GitHub[^\\S\\r\\n]+Copilot|Opus|Sonnet|Haiku|Fable|GPT)\\b[^\\r\\n<`]*(?:<[^>\\r\\n]*>)?"
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"name": "ai-assisted-by",
|
|
26
|
-
"pattern": "^[^\\S\\r\\n]*(?:Assisted|Generated)-By:[^\\S\\r\\n]*(?:Claude|Anthropic|OpenAI|ChatGPT|(?:GitHub[^\\S\\r\\n]+)?Copilot|Gemini|Codex|Cursor|Aider|Devin|Opus|Sonnet|Haiku|Fable|GPT)\\b[^\\r\\n<`]*(?:<[^>\\r\\n]*>)?"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"name": "anthropic-noreply",
|
|
30
|
-
"pattern": "noreply@anthropic\\.com"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"name": "claude-session",
|
|
34
|
-
"pattern": "Claude-Session:[^\\S\\r\\n]*[^\\s`]*"
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"name": "claude.ai/code",
|
|
38
|
-
"pattern": "\\[[^\\]\\r\\n]*\\]\\([^\\S\\r\\n]*<?https?://claude\\.ai/code[^)\\s]*>?[^\\S\\r\\n]*\\)|<?https?://claude\\.ai/code\\b[^\\s)>`]*>?"
|
|
39
|
-
}
|
|
40
|
-
]
|
|
41
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
3
|
-
# Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
4
|
-
#
|
|
5
|
-
# private-refs-check.sh — this repository is public, so its tracked files state facts and never point
|
|
6
|
-
# into a private repository: no private repository name, no private issue or pull request number, no
|
|
7
|
-
# private branch name or file path, no name of a private specification file. Say what the value is and
|
|
8
|
-
# why instead, and cite only public repositories (omx-dsp, omx-contract, omx-plugins, omx-clap-core, plugin-qualify).
|
|
9
|
-
# Product-name mentions of OpenMixer, and values such as the org.openmixer.* CLAP ids, the
|
|
10
|
-
# urn:openmixer:* LV2 URIs and the @openmixer npm scope, are not pointers and are not matched.
|
|
11
|
-
#
|
|
12
|
-
# tools/private-refs-check.sh the check, over every tracked file (generated ones included)
|
|
13
|
-
# tools/private-refs-check.sh --self-test each sabotage, in every kind of file, must go red
|
|
14
|
-
#
|
|
15
|
-
# ALLOW lists the tracked files exempt from the check, each with the reason; nothing else is.
|
|
16
|
-
set -euo pipefail
|
|
17
|
-
HERE="$(cd "$(dirname "$0")/.." && pwd)"
|
|
18
|
-
|
|
19
|
-
# <file> — <why it may name them>
|
|
20
|
-
ALLOW=(
|
|
21
|
-
"tools/private-refs-check.sh" # it spells the patterns it looks for
|
|
22
|
-
)
|
|
23
|
-
EXTRA_PATHSPEC=() # the self-test sets a bad one, to prove a git grep error is red
|
|
24
|
-
|
|
25
|
-
# Extended regexps, matched case-insensitively. A new kind of pointer is one line here.
|
|
26
|
-
PATTERNS=(
|
|
27
|
-
'FreeMixer/openmixer([^A-Za-z0-9_-]|$)' # the private repository
|
|
28
|
-
'openmixer-ops' # the private operations repository
|
|
29
|
-
'openmixer ?#[0-9]' # one of its issues or pull requests
|
|
30
|
-
'[A-Za-z0-9_.]-dev#[0-9]' # an issue of a private *-dev repository
|
|
31
|
-
'integration/[A-Za-z0-9]' # a private integration branch
|
|
32
|
-
'packages/[a-z][a-z0-9-]+' # a path into the private repository's packages
|
|
33
|
-
'\.vue([^A-Za-z0-9_]|$)' # its web UI components
|
|
34
|
-
"openmixer's spec" # its specification files
|
|
35
|
-
'docs/design/' # its design documents
|
|
36
|
-
'harness/' # its test harness
|
|
37
|
-
'20[0-9]{2}-[0-9]{2}-[0-9]{2}-[a-z][a-z0-9-]+\.md' # a dated specification file name
|
|
38
|
-
'spec 20[0-9]{2}-[0-9]{2}-[0-9]{2}' # a citation of one
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
check() { # <root>
|
|
42
|
-
local root="$1" fail=0 args=() p a hits
|
|
43
|
-
for p in "${PATTERNS[@]}"; do args+=(-e "$p"); done
|
|
44
|
-
local excl=()
|
|
45
|
-
for a in "${ALLOW[@]}"; do excl+=(":(exclude)${a%% *}"); done
|
|
46
|
-
[ -n "$(git -C "$root" ls-files)" ] || { echo "private-refs-check: git lists no file" >&2; return 1; }
|
|
47
|
-
# git grep exits 1 for no match and 128 or more for an error; an error must not read as "no hits"
|
|
48
|
-
hits=$(git -C "$root" grep -nIiE "${args[@]}" -- . "${excl[@]}" "${EXTRA_PATHSPEC[@]}") || rc=$?
|
|
49
|
-
case "${rc:-0}" in 0|1) ;; *) echo "private-refs-check: git grep failed (exit $rc)" >&2; return 1 ;; esac
|
|
50
|
-
hits=$(printf '%s' "$hits" | cut -c1-200)
|
|
51
|
-
[ -z "$hits" ] || { printf '%s\n' "$hits" >&2; fail=1; }
|
|
52
|
-
[ "$fail" = 0 ] || { echo "private-refs-check: the lines above point into private repositories; state the fact instead" >&2; return 1; }
|
|
53
|
-
echo "private-refs-check: no tracked file points into a private repository"
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if [ "${1:-}" = --self-test ]; then
|
|
57
|
-
scratch="$(mktemp -d)"; trap 'rm -rf "$scratch"' EXIT
|
|
58
|
-
fail=0
|
|
59
|
-
# a clean tree with one file of each kind the repository tracks; every sabotage writes one private pointer into one
|
|
60
|
-
mk() { rm -rf "$scratch/t"; mkdir -p "$scratch/t/src" "$scratch/t/tools" "$scratch/t/docs"
|
|
61
|
-
git -C "$scratch" init -q t
|
|
62
|
-
printf 'rdfs:comment "The OpenMixer console x." ;\nlv2:binary <x.so> ; # urn:openmixer:x\n' > "$scratch/t/src/x.ttl"
|
|
63
|
-
printf '// org.openmixer.x, @openmixer/x\n' > "$scratch/t/tools/gen.mjs"
|
|
64
|
-
printf '# Docs\n\nOpenMixer plugins.\n' > "$scratch/t/docs/a.md"
|
|
65
|
-
printf '/* x */\n' > "$scratch/t/src/x.h"; printf '#!/bin/sh\n# x\n' > "$scratch/t/tools/x.sh"; }
|
|
66
|
-
sab() { # <name> <file> <line>
|
|
67
|
-
mk; printf '%s\n' "$3" >> "$scratch/t/$2"; git -C "$scratch/t" add -A
|
|
68
|
-
if check "$scratch/t" >/dev/null 2>&1; then echo "SABOTAGE $1: STAYED GREEN"; fail=1; else echo "SABOTAGE $1: red"; fi; }
|
|
69
|
-
mk; git -C "$scratch/t" add -A
|
|
70
|
-
check "$scratch/t" >/dev/null || { echo "self-test: the clean tree is not green" >&2; exit 1; }
|
|
71
|
-
sab repo-in-header src/x.h '/* as FreeMixer/openmixer draws it */'
|
|
72
|
-
sab branch-in-sh tools/x.sh '# drawn on integration/lean-engine'
|
|
73
|
-
sab issue-in-md docs/a.md 'see openmixer#1580'
|
|
74
|
-
sab path-in-md docs/a.md 'packages/web-ui/Foo.vue'
|
|
75
|
-
sab default-path tools/x.sh 'plugin=${P:-$root/../openmixer/packages/omx-plugins/bin/omx-delay.clap}'
|
|
76
|
-
sab ops-in-mjs tools/gen.mjs '// see openmixer-ops'
|
|
77
|
-
sab dev-in-mjs tools/gen.mjs '// omx-dsp-dev#32'
|
|
78
|
-
sab spec-in-mjs tools/gen.mjs "// openmixer's spec 2026-10-09-plugin-from-contract.md"
|
|
79
|
-
sab ttl src/x.ttl 'rdfs:comment "see FreeMixer/openmixer#12" ;'
|
|
80
|
-
sab header src/x.h '/* packages/core/src/x.ts */'
|
|
81
|
-
sab design-dir docs/a.md 'the notes in docs/design/specs'
|
|
82
|
-
sab harness-dir tools/gen.mjs '// harness/dsp-check.sh'
|
|
83
|
-
mk; git -C "$scratch/t" add -A
|
|
84
|
-
if ( EXTRA_PATHSPEC=(":(bogus)x"); check "$scratch/t" >/dev/null 2>&1 ); then echo "SABOTAGE git-grep-error: STAYED GREEN"; fail=1; else echo "SABOTAGE git-grep-error: red"; fi
|
|
85
|
-
[ "$fail" = 0 ] || exit 1
|
|
86
|
-
check "$HERE" >/dev/null || { echo "self-test: the repository is not green" >&2; exit 1; }
|
|
87
|
-
echo "private-refs-check self-test: every sabotage red"
|
|
88
|
-
exit 0
|
|
89
|
-
fi
|
|
90
|
-
check "$HERE"
|