dsh-vibe-math 2.7.0 → 2.7.1

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 (41) hide show
  1. package/README.en.md +5 -0
  2. package/README.md +5 -0
  3. package/cordis.patch.yml +6 -0
  4. package/docs/math-computation.md +44 -2
  5. package/docs/release-notes/RELEASE-NOTES-2.7.1.en.md +86 -0
  6. package/docs/release-notes/RELEASE-NOTES-2.7.1.md +86 -0
  7. package/package.json +5 -3
  8. package/prompt-corpus-persona/persona-corpus.json +8 -8
  9. package/prompt-corpus-persona/persona-corpus.md +12 -0
  10. package/prompt-corpus-v2/formal-verify-v2.json +162 -96
  11. package/prompt-corpus-v2/formal-verify-v2.md +949 -0
  12. package/prompt-corpus-v3/formal-verify-v3.json +171 -57
  13. package/prompt-corpus-v3/formal-verify-v3.md +1146 -0
  14. package/prompt-corpus-v4/formal-verify-v4.json +10 -10
  15. package/prompt-corpus-v4/formal-verify-v4.md +20 -0
  16. package/prompt-corpus-v5/prompt-corpus-v5.json +61 -61
  17. package/prompt-corpus-v5/prompt-corpus-v5.md +61 -0
  18. package/tests/audit-math-computation-contract.mjs +13 -0
  19. package/tests/audit-math-computation-parity.mjs +30 -1
  20. package/tests/audit-math-computation-sensitivity.mjs +1 -1
  21. package/tests/e2e-v5-round2.test.mjs +7 -0
  22. package/tests/formal-verify-v2.test.mjs +70 -2
  23. package/tests/formal-verify-v3.test.mjs +84 -2
  24. package/tests/helpers/math-computation-fake-seam.mjs +30 -2
  25. package/tests/math-computation-shared.test.mjs +304 -2
  26. package/vibe-math-v2/agent.cordis.yml +2 -0
  27. package/vibe-math-v2/math-computation.js +390 -47
  28. package/vibe-math-v2/math-engines.js +47 -6
  29. package/vibe-math-v2/vibe-math-v2.js +17 -1
  30. package/vibe-math-v3/agent.cordis.yml +2 -0
  31. package/vibe-math-v3/math-computation.js +390 -47
  32. package/vibe-math-v3/math-engines.js +47 -6
  33. package/vibe-math-v3/vibe-math-v3.js +17 -1
  34. package/vibe-math-v4/agent.cordis.yml +4 -0
  35. package/vibe-math-v4/math-computation.js +390 -47
  36. package/vibe-math-v4/math-engines.js +47 -6
  37. package/vibe-math-v4/vibe-math-v4.js +15 -0
  38. package/vibe-math-v5/agent.cordis.yml +4 -0
  39. package/vibe-math-v5/math-computation.js +390 -47
  40. package/vibe-math-v5/math-engines.js +47 -6
  41. package/vibe-math-v5/vibe-math-v5.js +15 -3
@@ -22,14 +22,47 @@ export const MATH_ENGINES = {
22
22
  candidates: ['python3', 'python', 'py'], winPrefix: ['-3'],
23
23
  versionArgv: ['--version'], versionRe: '(\\d+\\.\\d+\\.\\d+)',
24
24
  scriptArgv: ['<script>'], evalArgv: ['-c', '<expr>'], stdinArgv: ['-'], ext: '.py',
25
- probeCode: "import importlib.util,sys;print('|'.join('%s:%s'%(p,'ok' if importlib.util.find_spec(p) else 'missing') for p in sys.argv[1:]))",
26
- packageProbe: { argv: ['-c', '<probeCode>', '<pkgs>'], parse: 'pairs' },
25
+ // round-7 (live): NO shell metacharacters (`|`, `%`) in any probe argv - a real host rejected
26
+ // them with a null spawn. One line per package: "name ok|missing".
27
+ probeCode: "import importlib.util,sys\nfor p in sys.argv[1:]: print(p, 'ok' if importlib.util.find_spec(p) is not None else 'missing')",
28
+ // round-7 (finding 6, found on the real bundled python): the probe code iterates `sys.argv[1:]`,
29
+ // so the names must be SEPARATE argv items - the old comma-joined `<pkgs>` made it look up one
30
+ // package literally named "numpy,pandas" and reported everything missing.
31
+ packageProbe: { argv: ['-c', '<probeCode>', '<pkgs...>'], parse: 'pairs' },
27
32
  license: 'free', argErrorHints: ARG_ERROR_HINTS,
28
33
  install: {
29
34
  manager: 'pip',
30
35
  userArgv: ['<exe>', '-m', 'pip', 'install', '--user', '<pkg>'],
31
36
  systemArgv: ['<exe>', '-m', 'pip', 'install', '<pkg>'],
32
37
  uninstallArgv: ['<exe>', '-m', 'pip', 'uninstall', '-y', '<pkg>'],
38
+ // Round-6 (B): DISPATCH by the detected interpreter environment. `pip` is the documented
39
+ // fallback; the module picks conda/mamba/uv only when the interpreter's OWN environment says so
40
+ // (detect, don't guess) and the plan states which manager it assumed.
41
+ managers: {
42
+ conda: {
43
+ detect: 'conda-markers',
44
+ userArgv: ['conda', 'install', '-y', '-c', 'conda-forge', '<pkg>'],
45
+ uninstallArgv: ['conda', 'remove', '-y', '<pkg>'],
46
+ systemUnsupportedReason: 'conda 环境是用户级的;系统级安装不在 conda 的概念里(本工具只出用户级计划)',
47
+ },
48
+ mamba: {
49
+ detect: 'conda-markers',
50
+ userArgv: ['mamba', 'install', '-y', '-c', 'conda-forge', '<pkg>'],
51
+ uninstallArgv: ['mamba', 'remove', '-y', '<pkg>'],
52
+ systemUnsupportedReason: 'mamba 环境是用户级的;系统级安装不在 mamba 的概念里(本工具只出用户级计划)',
53
+ },
54
+ uv: {
55
+ detect: 'uv-next-to-interpreter',
56
+ userArgv: ['uv', 'pip', 'install', '<pkg>'],
57
+ uninstallArgv: ['uv', 'pip', 'uninstall', '<pkg>'],
58
+ systemUnsupportedReason: 'uv 装进当前虚拟环境(用户级);系统级需要发行版包管理器,本工具只出用户级计划',
59
+ },
60
+ pip: {
61
+ detect: 'fallback',
62
+ systemArgv: ['<exe>', '-m', 'pip', 'install', '<pkg>'],
63
+ uninstallArgv: ['<exe>', '-m', 'pip', 'uninstall', '-y', '<pkg>'],
64
+ },
65
+ },
33
66
  },
34
67
  userInstall: { windows: 'winget install --id Python.Python.3.12', macos: 'brew install python', linux: 'apt install python3' },
35
68
  },
@@ -38,13 +71,16 @@ export const MATH_ENGINES = {
38
71
  candidates: ['Rscript', 'R'],
39
72
  versionArgv: ['--version'], versionRe: '(\\d+\\.\\d+\\.\\d+)',
40
73
  scriptArgv: ['<script>'], evalArgv: ['-e', '<expr>'], stdinArgv: ['--no-save', '--slave'], ext: '.R',
41
- probeCode: "cat(paste(sapply(strsplit('__PKGS__',',')[[1]],function(p) paste0(p,':',requireNamespace(p,quietly=TRUE))),collapse='|'))",
74
+ // round-7 (live): line-per-package, no `|` in the argv.
75
+ probeCode: "for (p in strsplit('__PKGS__',',')[[1]]) cat(p, if (requireNamespace(p, quietly=TRUE)) 'ok' else 'missing', '\\n')",
42
76
  packageProbe: { argv: ['-e', '<probeCode>'], parse: 'pairs' },
43
77
  license: 'free', argErrorHints: ARG_ERROR_HINTS,
44
78
  install: {
45
79
  manager: 'r',
46
80
  userArgv: ['<exe>', '-e', "install.packages('__PKG__',lib=Sys.getenv('R_LIBS_USER'),repos='https://cloud.r-project.org')"],
47
81
  uninstallArgv: ['<exe>', '-e', "remove.packages('__PKG__',lib=Sys.getenv('R_LIBS_USER'))"],
82
+ // Round-6 (C): user-only BY DESIGN, and the refusal now says why per engine.
83
+ systemUnsupportedReason: 'R 的用户库是 R_LIBS_USER;系统级安装要写发行版的包目录(需 root 或发行版包管理器),本工具只出用户级计划',
48
84
  },
49
85
  userInstall: { windows: 'winget install --id RProject.R', macos: 'brew install r', linux: 'apt install r-base' },
50
86
  },
@@ -54,13 +90,15 @@ export const MATH_ENGINES = {
54
90
  versionArgv: ['--version'], versionRe: '(\\d+\\.\\d+\\.\\d+)',
55
91
  scriptArgv: ['--no-gui', '--quiet', '<script>'], evalArgv: ['--no-gui', '--quiet', '--eval', '<expr>'],
56
92
  stdinArgv: ['--no-gui', '--quiet'], ext: '.m',
57
- probeCode: "s=pkg('list'); n={'__QPKGS__'}; for i=1:numel(n); printf('%s:%s|',n{i},merge(any(cellfun(@(x) strcmp(x.name,n{i}),s)),'ok','missing')); end",
93
+ // round-7 (live): line-per-package via disp, no `|` and no `%` in the argv.
94
+ probeCode: "s=pkg('list'); n={'__QPKGS__'}; for i=1:numel(n); if any(cellfun(@(x) strcmp(x.name,n{i}),s)); disp([n{i} ' ok']); else; disp([n{i} ' missing']); end; end",
58
95
  packageProbe: { argv: ['--no-gui', '--quiet', '--eval', '<probeCode>'], parse: 'pairs' },
59
96
  license: 'free', argErrorHints: ARG_ERROR_HINTS,
60
97
  install: {
61
98
  manager: 'octave-pkg',
62
99
  userArgv: ['<exe>', '--no-gui', '--quiet', '--eval', "pkg install -forge __PKG__"],
63
100
  uninstallArgv: ['<exe>', '--no-gui', '--quiet', '--eval', 'pkg uninstall __PKG__'],
101
+ systemUnsupportedReason: 'Octave 的 pkg install 装进用户包目录;系统级要写 Octave 的 share/packages(需 root),本工具只出用户级计划',
64
102
  },
65
103
  userInstall: { windows: 'winget install --id GNU.Octave', macos: 'brew install octave', linux: 'apt install octave' },
66
104
  },
@@ -76,6 +114,7 @@ export const MATH_ENGINES = {
76
114
  manager: 'julia-pkg',
77
115
  userArgv: ['<exe>', '-e', 'using Pkg; Pkg.add("__PKG__")'],
78
116
  uninstallArgv: ['<exe>', '-e', 'using Pkg; Pkg.rm("__PKG__")'],
117
+ systemUnsupportedReason: 'Julia 的 Pkg.add 装进当前活动环境 / 用户 depot(JULIA_DEPOT_PATH);系统级不是 Julia 的概念,本工具只出用户级计划',
79
118
  },
80
119
  userInstall: { windows: 'winget install --id Julialang.Julia', macos: 'brew install julia', linux: 'apt install julia' },
81
120
  },
@@ -84,7 +123,8 @@ export const MATH_ENGINES = {
84
123
  candidates: ['matlab'],
85
124
  versionArgv: ['-batch', 'disp(version)'], versionRe: '(\\d+\\.\\d+)',
86
125
  scriptArgv: ['-batch', "run('<script>')"], evalArgv: ['-batch', '<expr>'], stdinArgv: null, ext: '.m',
87
- probeCode: "t={'__QPKGS__'}; for i=1:numel(t); printf('%s:%d|',t{i},license('test',t{i})); end",
126
+ // round-7 (live): no `|`/`%` in any probe argv (a real host rejected such argv with a null spawn).
127
+ probeCode: "t={'__QPKGS__'}; for i=1:numel(t); if license('test',t{i}); disp([t{i} ' ok']); else; disp([t{i} ' missing']); end; end",
88
128
  packageProbe: { argv: ['-batch', '<probeCode>'], parse: 'pairs' },
89
129
  license: 'commercial', argErrorHints: ARG_ERROR_HINTS,
90
130
  licenseProbe: { argv: ['-batch', "disp(license('test','MATLAB'))"], okWhen: 'trim-1' },
@@ -96,7 +136,8 @@ export const MATH_ENGINES = {
96
136
  candidates: ['maple'],
97
137
  versionArgv: ['--version'], versionRe: '(\\d+\\.\\d+)',
98
138
  scriptArgv: ['-q', '<script>'], evalArgv: ['-q', '-c', '<expr>'], stdinArgv: null, ext: '.mpl',
99
- probeCode: 'for p in ["__PKGS__"] do try with(p) catch: printf("%s:missing|", p); next end try; printf("%s:ok|", p) end do',
139
+ // round-7 (live): `print` instead of printf so the argv carries no `|`/`%`.
140
+ probeCode: 'for p in ["__PKGS__"] do try with(p) catch: print(p, " missing"); next end try; print(p, " ok") end do',
100
141
  packageProbe: { argv: ['-q', '-c', '<probeCode>'], parse: 'pairs' },
101
142
  license: 'commercial', argErrorHints: ARG_ERROR_HINTS,
102
143
  licenseProbe: { argv: ['-q', '-c', 'printf("1")'], okWhen: 'exit-0' },
@@ -67,6 +67,8 @@ import {
67
67
  MATH_RULE_LINES_EN,
68
68
  MATH_ARCHIVE_WORKFLOW_LINE,
69
69
  MATH_ARCHIVE_WORKFLOW_LINE_EN,
70
+ MATH_SUBSTITUTION_RULE_LINE,
71
+ MATH_SUBSTITUTION_RULE_LINE_EN,
70
72
  normalizeMathParams,
71
73
  probeMathEngines,
72
74
  registerMathComputation,
@@ -2902,6 +2904,11 @@ export function apply(ctx) {
2902
2904
  // reports MATH_NO_SUBPROCESS before engine detection), and let it check the retention cap.
2903
2905
  hasSubprocess: () => { const sub = subprocessOf(); return !!(sub && typeof sub.spawn === 'function') },
2904
2906
  listDir: (rel) => mathListDirRel(rel),
2907
+ // round-7 (fix 2): DSH's own bundled runtimes (`<home>/.dsh/dsh-runtimes/*/dependencies/<engine>/`)
2908
+ // as a LAST resort after PATH. Generic roots only; the module globs the tree name and accepts
2909
+ // only the descriptor's own candidate names.
2910
+ runtimeRoots: () => { const env = process.env.DSH_HOME; if (env) return [String(env)]; const home = String(process.env.HOME || process.env.USERPROFILE || ''); return home ? [home.replace(/[\\/]+$/, '') + '/.dsh'] : [] },
2911
+ listDirAbs: async (abs) => { try { const t = await fs.resolve(String(abs)); const st = await fs.stat(t); if (!st) return []; return (await fs.listDir(t)) || [] } catch (e) { return [] } },
2905
2912
  log: (kind, msg) => mathLog(kind, msg),
2906
2913
  }
2907
2914
  // The DYNAMIC per-round availability line: computed from a (cached) probe when the prompt is
@@ -2923,6 +2930,10 @@ export function apply(ctx) {
2923
2930
  // `scriptChanged` actionable for a member).
2924
2931
  if (mathLineZh.indexOf(MATH_ARCHIVE_WORKFLOW_LINE) === -1) console.error('vibe-math-v5: the math availability line lost the archive workflow rule')
2925
2932
  if (mathLineEn.indexOf(MATH_ARCHIVE_WORKFLOW_LINE_EN) === -1) console.error('vibe-math-v5: the EN math availability line lost the archive workflow rule')
2933
+ // Round-6 (A): an undeclared SUBSTITUTION must never read like the exact result — the
2934
+ // honesty rule has to reach the prompt in both languages.
2935
+ if (mathLineZh.indexOf(MATH_SUBSTITUTION_RULE_LINE) === -1) console.error('vibe-math-v5: the math availability line lost the substitution-honesty rule')
2936
+ if (mathLineEn.indexOf(MATH_SUBSTITUTION_RULE_LINE_EN) === -1) console.error('vibe-math-v5: the EN math availability line lost the substitution-honesty rule')
2926
2937
  return mathLineZh
2927
2938
  } catch (e) {
2928
2939
  // A probe failure must never break prompt construction: keep whatever we had.
@@ -2935,11 +2946,12 @@ export function apply(ctx) {
2935
2946
  const line = lang === 'en' ? mathLineEn : mathLineZh
2936
2947
  if (line) return '\n' + line
2937
2948
  // Fallback: when the dynamic line could not be built, the member still needs to know the
2938
- // tool exists, how to cite it, and (P2a) that an edited script needs a NEW receipt.
2949
+ // tool exists, how to cite it, that an edited script needs a NEW receipt, and (round 6) that
2950
+ // a substitution weakening exactness must be declared.
2939
2951
  if (String(params.mathComputation) === 'off') return ''
2940
2952
  return lang === 'en'
2941
- ? '\n' + MATH_PERSONA_TOOL_LINE + '\n' + MATH_ARCHIVE_WORKFLOW_LINE_EN
2942
- : '\n' + MATH_PERSONA_TOOL_LINE + '\n' + MATH_ARCHIVE_WORKFLOW_LINE
2953
+ ? '\n' + MATH_PERSONA_TOOL_LINE + '\n' + MATH_ARCHIVE_WORKFLOW_LINE_EN + '\n' + MATH_SUBSTITUTION_RULE_LINE_EN
2954
+ : '\n' + MATH_PERSONA_TOOL_LINE + '\n' + MATH_ARCHIVE_WORKFLOW_LINE + '\n' + MATH_SUBSTITUTION_RULE_LINE
2943
2955
  }
2944
2956
  // Push the tool section into a prompt under construction (a no-op in the 'off' mode, which
2945
2957
  // is the "off means zero mention" discipline).