dsh-vibe-math 2.3.12 → 2.3.13
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 +17 -13
- package/{AUDIT-CHECKLIST.md → docs/AUDIT-CHECKLIST.md} +323 -304
- package/docs/COMPAT-AUDIT-ROUND2.md +325 -0
- package/docs/generate_framework_diagram_v2.py +114 -0
- package/docs/generate_framework_diagram_v3.py +127 -0
- package/{RELEASE-NOTES-2.1.0.md → docs/release-notes/RELEASE-NOTES-2.1.0.md} +143 -143
- package/{RELEASE-NOTES-2.2.0.md → docs/release-notes/RELEASE-NOTES-2.2.0.md} +266 -266
- package/{RELEASE-NOTES-2.2.1.md → docs/release-notes/RELEASE-NOTES-2.2.1.md} +43 -43
- package/{RELEASE-NOTES-2.2.2.md → docs/release-notes/RELEASE-NOTES-2.2.2.md} +88 -88
- package/{RELEASE-NOTES-2.3.0.md → docs/release-notes/RELEASE-NOTES-2.3.0.md} +207 -207
- package/{RELEASE-NOTES-2.3.1.md → docs/release-notes/RELEASE-NOTES-2.3.1.md} +134 -134
- package/{RELEASE-NOTES-2.3.10.md → docs/release-notes/RELEASE-NOTES-2.3.10.md} +105 -105
- package/{RELEASE-NOTES-2.3.11.md → docs/release-notes/RELEASE-NOTES-2.3.11.md} +57 -57
- package/{RELEASE-NOTES-2.3.12.md → docs/release-notes/RELEASE-NOTES-2.3.12.md} +80 -80
- package/docs/release-notes/RELEASE-NOTES-2.3.13.md +137 -0
- package/{RELEASE-NOTES-2.3.2.md → docs/release-notes/RELEASE-NOTES-2.3.2.md} +145 -145
- package/{RELEASE-NOTES-2.3.3.md → docs/release-notes/RELEASE-NOTES-2.3.3.md} +115 -115
- package/{RELEASE-NOTES-2.3.4.md → docs/release-notes/RELEASE-NOTES-2.3.4.md} +69 -69
- package/{RELEASE-NOTES-2.3.5.md → docs/release-notes/RELEASE-NOTES-2.3.5.md} +63 -63
- package/{RELEASE-NOTES-2.3.6.md → docs/release-notes/RELEASE-NOTES-2.3.6.md} +66 -66
- package/{RELEASE-NOTES-2.3.7.md → docs/release-notes/RELEASE-NOTES-2.3.7.md} +59 -59
- package/{RELEASE-NOTES-2.3.8.md → docs/release-notes/RELEASE-NOTES-2.3.8.md} +45 -45
- package/{RELEASE-NOTES-2.3.9.md → docs/release-notes/RELEASE-NOTES-2.3.9.md} +70 -70
- package/docs/test-timing.md +18 -17
- package/installer.js +105 -41
- package/package.json +42 -37
- package/{audit-formal-sensitivity.mjs → tests/audit-formal-sensitivity.mjs} +342 -342
- package/{audit-installer-compat.test.mjs → tests/audit-installer-compat.test.mjs} +136 -136
- package/tests/audit-installer-policy.test.mjs +245 -0
- package/{audit-persona-sensitivity.mjs → tests/audit-persona-sensitivity.mjs} +249 -249
- package/{audit-persona-surface.test.mjs → tests/audit-persona-surface.test.mjs} +349 -349
- package/{audit-prompt-invariants.mjs → tests/audit-prompt-invariants.mjs} +508 -508
- package/{audit-spec-traceability.mjs → tests/audit-spec-traceability.mjs} +193 -193
- package/{audit-v5-integrity.mjs → tests/audit-v5-integrity.mjs} +448 -448
- package/{audit-v5-sensitivity.mjs → tests/audit-v5-sensitivity.mjs} +384 -384
- package/{e2e-v5-round2.test.mjs → tests/e2e-v5-round2.test.mjs} +521 -521
- package/{formal-verify-v2.test.mjs → tests/formal-verify-v2.test.mjs} +1315 -1315
- package/{formal-verify-v3.test.mjs → tests/formal-verify-v3.test.mjs} +1257 -1257
- package/{formal-verify-v4.test.mjs → tests/formal-verify-v4.test.mjs} +1082 -1082
- package/{formal-verify-v5.test.mjs → tests/formal-verify-v5.test.mjs} +708 -708
- package/{prompt-v5-integrity.test.mjs → tests/prompt-v5-integrity.test.mjs} +3 -3
- package/{run-tests.mjs → tests/run-tests.mjs} +121 -118
- package/{selfdrive-v5.mjs → tests/selfdrive-v5.mjs} +470 -470
- package/vibe-math-v4//345/256/236/347/216/260/346/226/271/346/241/210.md +1 -1
- package/vibe-math-v5//345/256/236/347/216/260/346/226/271/346/241/210.md +1 -1
- package/vibe-math-v5//346/236/266/346/236/204/345/233/276.md +1 -1
- /package/{RELEASE-NOTES-2.0.22.md → docs/release-notes/RELEASE-NOTES-2.0.22.md} +0 -0
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
// Each case runs in its OWN session root, so one case can never leave a meeting or a
|
|
23
23
|
// verification in flight to pollute the next one.
|
|
24
24
|
//
|
|
25
|
-
// Run: node prompt-v5-integrity.test.mjs
|
|
25
|
+
// Run: node tests/prompt-v5-integrity.test.mjs
|
|
26
26
|
// Env: V5_PLUGIN=<abs path> point the suite at a mutated copy (sensitivity probes)
|
|
27
27
|
// V5_CORPUS_DIR=<dir> where to write the corpus (default: ./prompt-corpus-v5)
|
|
28
28
|
// ============================================================
|
|
@@ -37,8 +37,8 @@ import { fileURLToPath } from 'node:url'
|
|
|
37
37
|
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
38
38
|
const PLUGIN = process.env.V5_PLUGIN
|
|
39
39
|
? new URL('file:///' + String(process.env.V5_PLUGIN).replace(/\\/g, '/'))
|
|
40
|
-
: new URL('
|
|
41
|
-
const CORPUS_DIR = process.env.V5_CORPUS_DIR ? pathResolve(process.env.V5_CORPUS_DIR) : join(HERE, 'prompt-corpus-v5')
|
|
40
|
+
: new URL('../vibe-math-v5/vibe-math-v5.js', import.meta.url)
|
|
41
|
+
const CORPUS_DIR = process.env.V5_CORPUS_DIR ? pathResolve(process.env.V5_CORPUS_DIR) : join(HERE, '..', 'prompt-corpus-v5')
|
|
42
42
|
const WS = mkdtempSync(join(tmpdir(), 'vibe-v5-prompt-'))
|
|
43
43
|
|
|
44
44
|
let passed = 0, failed = 0
|
|
@@ -1,118 +1,121 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* PARALLEL TEST RUNNER — run every shipped suite (or a filtered subset) concurrently and report
|
|
4
|
-
* per-suite timings, so the strategy for the next run is chosen from DATA instead of guesswork.
|
|
5
|
-
*
|
|
6
|
-
* Why this exists: the suites are wildly uneven (one suite is ~160 s, most are under 2 s), so a
|
|
7
|
-
* sequential sweep spends almost all of its wall time waiting for the slowest one. Running them
|
|
8
|
-
* with a worker pool makes the sweep bounded by the slowest SUITE rather than by their SUM.
|
|
9
|
-
* On this machine (4 cores) the sweep went from ~5.5 min to ~2 min; see docs/test-timing.md.
|
|
10
|
-
*
|
|
11
|
-
* Every suite already isolates itself (each creates its own mkdtemp workspace), so parallelism is
|
|
12
|
-
* safe. Suites that WRITE a corpus take a per-run corpus dir from an env var; this runner points
|
|
13
|
-
* them at a scratch dir when it runs a suite more than once, which it never does — but the probe
|
|
14
|
-
* runner (audit-formal-sensitivity.mjs) does, and it passes its own dirs.
|
|
15
|
-
*
|
|
16
|
-
* Usage:
|
|
17
|
-
* node run-tests.mjs # every *.test.mjs, concurrency = min(4, cpus)
|
|
18
|
-
* node run-tests.mjs --concurrency=6
|
|
19
|
-
* node run-tests.mjs --only formal # substring match on the file name (repeatable, OR)
|
|
20
|
-
* node run-tests.mjs --exclude e2e-v4 # substring to skip (repeatable)
|
|
21
|
-
* node run-tests.mjs --json # machine-readable summary on stdout
|
|
22
|
-
*/
|
|
23
|
-
import { spawn } from 'node:child_process'
|
|
24
|
-
import { readdirSync } from 'node:fs'
|
|
25
|
-
import { cpus } from 'node:os'
|
|
26
|
-
import { join } from 'node:path'
|
|
27
|
-
import { fileURLToPath } from 'node:url'
|
|
28
|
-
|
|
29
|
-
const HERE = fileURLToPath(new URL('./', import.meta.url))
|
|
30
|
-
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
child.
|
|
60
|
-
|
|
61
|
-
child.on('
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
console.log('
|
|
115
|
-
console.log('
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* PARALLEL TEST RUNNER — run every shipped suite (or a filtered subset) concurrently and report
|
|
4
|
+
* per-suite timings, so the strategy for the next run is chosen from DATA instead of guesswork.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists: the suites are wildly uneven (one suite is ~160 s, most are under 2 s), so a
|
|
7
|
+
* sequential sweep spends almost all of its wall time waiting for the slowest one. Running them
|
|
8
|
+
* with a worker pool makes the sweep bounded by the slowest SUITE rather than by their SUM.
|
|
9
|
+
* On this machine (4 cores) the sweep went from ~5.5 min to ~2 min; see ../docs/test-timing.md.
|
|
10
|
+
*
|
|
11
|
+
* Every suite already isolates itself (each creates its own mkdtemp workspace), so parallelism is
|
|
12
|
+
* safe. Suites that WRITE a corpus take a per-run corpus dir from an env var; this runner points
|
|
13
|
+
* them at a scratch dir when it runs a suite more than once, which it never does — but the probe
|
|
14
|
+
* runner (audit-formal-sensitivity.mjs) does, and it passes its own dirs.
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* node tests/run-tests.mjs # every *.test.mjs, concurrency = min(4, cpus)
|
|
18
|
+
* node tests/run-tests.mjs --concurrency=6
|
|
19
|
+
* node tests/run-tests.mjs --only formal # substring match on the file name (repeatable, OR)
|
|
20
|
+
* node tests/run-tests.mjs --exclude e2e-v4 # substring to skip (repeatable)
|
|
21
|
+
* node tests/run-tests.mjs --json # machine-readable summary on stdout
|
|
22
|
+
*/
|
|
23
|
+
import { spawn } from 'node:child_process'
|
|
24
|
+
import { readdirSync } from 'node:fs'
|
|
25
|
+
import { cpus } from 'node:os'
|
|
26
|
+
import { join } from 'node:path'
|
|
27
|
+
import { fileURLToPath } from 'node:url'
|
|
28
|
+
|
|
29
|
+
const HERE = fileURLToPath(new URL('./', import.meta.url))
|
|
30
|
+
// Suites live beside this runner, but they resolve the presets and the corpora from the
|
|
31
|
+
// repository root, so they must keep running with that as their working directory.
|
|
32
|
+
const REPO = fileURLToPath(new URL('../', import.meta.url))
|
|
33
|
+
const argv = process.argv.slice(2)
|
|
34
|
+
// Accept BOTH `--only=x` and `--only x` (the help text used the space form, which a value-taking
|
|
35
|
+
// flag() did not understand — the filter silently did nothing and every suite still ran).
|
|
36
|
+
const flag = (name) => {
|
|
37
|
+
const out = []
|
|
38
|
+
for (let i = 0; i < argv.length; i++) {
|
|
39
|
+
const a = argv[i]
|
|
40
|
+
if (a === '--' + name && i + 1 < argv.length && !argv[i + 1].startsWith('--')) out.push(argv[++i])
|
|
41
|
+
else if (a.startsWith('--' + name + '=')) out.push(a.split('=').slice(1).join('='))
|
|
42
|
+
}
|
|
43
|
+
return out
|
|
44
|
+
}
|
|
45
|
+
const has = (name) => argv.includes('--' + name)
|
|
46
|
+
const only = flag('only')
|
|
47
|
+
const exclude = flag('exclude')
|
|
48
|
+
const asJson = has('json')
|
|
49
|
+
const concurrency = Math.max(1, Number(flag('concurrency')[0] || Math.min(4, cpus().length)))
|
|
50
|
+
|
|
51
|
+
let suites = readdirSync(HERE).filter((f) => f.endsWith('.test.mjs')).sort()
|
|
52
|
+
if (only.length) suites = suites.filter((f) => only.some((o) => f.includes(o)))
|
|
53
|
+
if (exclude.length) suites = suites.filter((f) => !exclude.some((o) => f.includes(o)))
|
|
54
|
+
if (!suites.length) { console.error('no suites matched'); process.exit(2) }
|
|
55
|
+
|
|
56
|
+
function runSuite(file) {
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
const t0 = Date.now()
|
|
59
|
+
const child = spawn(process.execPath, [join(HERE, file)], { cwd: REPO, stdio: ['ignore', 'pipe', 'pipe'] })
|
|
60
|
+
let out = '', err = ''
|
|
61
|
+
child.stdout.on('data', (d) => { out += d.toString() })
|
|
62
|
+
child.stderr.on('data', (d) => { err += d.toString() })
|
|
63
|
+
child.on('error', (e) => resolve({ file, code: -1, ms: Date.now() - t0, out, err: err + '\n' + String(e) }))
|
|
64
|
+
child.on('close', (code) => resolve({ file, code, ms: Date.now() - t0, out, err }))
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const results = []
|
|
69
|
+
let cursor = 0
|
|
70
|
+
const started = Date.now()
|
|
71
|
+
async function worker(id) {
|
|
72
|
+
for (;;) {
|
|
73
|
+
const i = cursor++
|
|
74
|
+
if (i >= suites.length) return
|
|
75
|
+
const r = await runSuite(suites[i])
|
|
76
|
+
const tail = String(r.out).trim().split('\n').filter(Boolean).slice(-1)[0] || ''
|
|
77
|
+
results[i] = r
|
|
78
|
+
if (!asJson) {
|
|
79
|
+
const mark = r.code === 0 ? 'PASS' : 'FAIL'
|
|
80
|
+
console.log(
|
|
81
|
+
mark + ' ' + r.file.padEnd(38) +
|
|
82
|
+
' exit=' + String(r.code).padStart(3) +
|
|
83
|
+
' ' + (r.ms / 1000).toFixed(1).padStart(6) + 's' +
|
|
84
|
+
(tail ? ' ' + tail.slice(0, 78) : '')
|
|
85
|
+
)
|
|
86
|
+
if (r.code !== 0) {
|
|
87
|
+
const lines = (r.out + '\n' + r.err).split('\n').filter(Boolean)
|
|
88
|
+
for (const l of lines.slice(-15)) console.log(' ' + l)
|
|
89
|
+
}
|
|
90
|
+
} else if (r.code !== 0) {
|
|
91
|
+
// In --json mode keep stdout machine-readable: the failure detail travels in the JSON.
|
|
92
|
+
const lines = (r.out + '\n' + r.err).split('\n').filter(Boolean)
|
|
93
|
+
r.tailDetail = lines.slice(-15).join('\n')
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, suites.length) }, (_, i) => worker(i)))
|
|
98
|
+
|
|
99
|
+
const wall = (Date.now() - started) / 1000
|
|
100
|
+
const sum = results.reduce((a, r) => a + r.ms, 0) / 1000
|
|
101
|
+
const bad = results.filter((r) => r.code !== 0)
|
|
102
|
+
const slowest = results.slice().sort((a, b) => b.ms - a.ms).slice(0, 5)
|
|
103
|
+
|
|
104
|
+
if (asJson) {
|
|
105
|
+
console.log(JSON.stringify({
|
|
106
|
+
concurrency, wallSeconds: Number(wall.toFixed(1)), sumSeconds: Number(sum.toFixed(1)),
|
|
107
|
+
pass: results.length - bad.length, fail: bad.length,
|
|
108
|
+
suites: results.map((r) => ({
|
|
109
|
+
file: r.file, exit: r.code, seconds: Number((r.ms / 1000).toFixed(1)),
|
|
110
|
+
...(r.tailDetail ? { detail: r.tailDetail } : {}),
|
|
111
|
+
})),
|
|
112
|
+
}, null, 2))
|
|
113
|
+
} else {
|
|
114
|
+
console.log('')
|
|
115
|
+
console.log('concurrency ' + concurrency + ' · wall ' + wall.toFixed(1) + 's · sum of suite times ' + sum.toFixed(1) + 's'
|
|
116
|
+
+ ' · speed-up x' + (sum / Math.max(wall, 0.001)).toFixed(2))
|
|
117
|
+
console.log('slowest: ' + slowest.map((r) => r.file.replace('.test.mjs', '') + ' ' + (r.ms / 1000).toFixed(1) + 's').join(' · '))
|
|
118
|
+
console.log('TOTAL ' + results.length + ' PASS ' + (results.length - bad.length) + ' FAIL ' + bad.length)
|
|
119
|
+
for (const b of bad) console.log(' FAILED: ' + b.file + ' (exit ' + b.code + ')')
|
|
120
|
+
}
|
|
121
|
+
process.exit(bad.length === 0 ? 0 : 1)
|