audrey 1.0.0 → 1.0.2

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 (234) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +30 -6
  3. package/benchmarks/adapter-self-test.mjs +6 -2
  4. package/benchmarks/adapters/example-allow.mjs +5 -2
  5. package/benchmarks/adapters/mem0-platform.mjs +19 -12
  6. package/benchmarks/adapters/zep-cloud.mjs +51 -27
  7. package/benchmarks/baselines.js +11 -6
  8. package/benchmarks/build-leaderboard.mjs +36 -23
  9. package/benchmarks/cases.js +24 -12
  10. package/benchmarks/create-conformance-card.mjs +12 -3
  11. package/benchmarks/create-submission-bundle.mjs +22 -8
  12. package/benchmarks/dry-run-external-adapters.mjs +24 -12
  13. package/benchmarks/guardbench.js +354 -124
  14. package/benchmarks/output/adapter-self-test/guardbench-adapter-self-test.json +7 -7
  15. package/benchmarks/output/external/guardbench-external-dry-run.json +1 -1
  16. package/benchmarks/output/external/guardbench-external-evidence.json +1 -1
  17. package/benchmarks/output/guardbench-conformance-card.json +12 -12
  18. package/benchmarks/output/guardbench-raw.json +243 -144
  19. package/benchmarks/output/guardbench-summary.json +354 -230
  20. package/benchmarks/output/leaderboard/guardbench-leaderboard.json +5 -5
  21. package/benchmarks/output/leaderboard/guardbench-leaderboard.md +2 -2
  22. package/benchmarks/output/submission-bundle/guardbench-conformance-card.json +12 -12
  23. package/benchmarks/output/submission-bundle/guardbench-raw.json +243 -144
  24. package/benchmarks/output/submission-bundle/guardbench-summary.json +354 -230
  25. package/benchmarks/output/submission-bundle/schemas/guardbench-raw.schema.json +21 -1
  26. package/benchmarks/output/submission-bundle/schemas/guardbench-summary.schema.json +23 -2
  27. package/benchmarks/output/submission-bundle/submission-manifest.json +15 -15
  28. package/benchmarks/output/submission-bundle/validation-report.json +1 -1
  29. package/benchmarks/output/summary.json +58 -58
  30. package/benchmarks/perf-snapshot.js +12 -9
  31. package/benchmarks/perf.bench.js +14 -6
  32. package/benchmarks/public-paths.mjs +11 -5
  33. package/benchmarks/reference-results.js +10 -5
  34. package/benchmarks/report.js +48 -27
  35. package/benchmarks/run-external-guardbench.mjs +47 -25
  36. package/benchmarks/run.js +112 -59
  37. package/benchmarks/schemas/guardbench-raw.schema.json +21 -1
  38. package/benchmarks/schemas/guardbench-summary.schema.json +23 -2
  39. package/benchmarks/validate-adapter-module.mjs +13 -10
  40. package/benchmarks/validate-adapter-registry.mjs +16 -5
  41. package/benchmarks/validate-guardbench-artifacts.mjs +76 -19
  42. package/benchmarks/verify-external-evidence.mjs +86 -31
  43. package/benchmarks/verify-publication-artifacts.mjs +34 -11
  44. package/benchmarks/verify-submission-bundle.mjs +9 -4
  45. package/dist/mcp-server/config.d.ts +1 -1
  46. package/dist/mcp-server/config.d.ts.map +1 -1
  47. package/dist/mcp-server/config.js +5 -3
  48. package/dist/mcp-server/config.js.map +1 -1
  49. package/dist/mcp-server/index.d.ts +4 -3
  50. package/dist/mcp-server/index.d.ts.map +1 -1
  51. package/dist/mcp-server/index.js +479 -172
  52. package/dist/mcp-server/index.js.map +1 -1
  53. package/dist/src/action-key.d.ts.map +1 -1
  54. package/dist/src/action-key.js +6 -2
  55. package/dist/src/action-key.js.map +1 -1
  56. package/dist/src/adaptive.d.ts.map +1 -1
  57. package/dist/src/adaptive.js +4 -2
  58. package/dist/src/adaptive.js.map +1 -1
  59. package/dist/src/affect.d.ts.map +1 -1
  60. package/dist/src/affect.js +8 -5
  61. package/dist/src/affect.js.map +1 -1
  62. package/dist/src/audrey.d.ts +11 -1
  63. package/dist/src/audrey.d.ts.map +1 -1
  64. package/dist/src/audrey.js +110 -53
  65. package/dist/src/audrey.js.map +1 -1
  66. package/dist/src/capsule.d.ts.map +1 -1
  67. package/dist/src/capsule.js +37 -15
  68. package/dist/src/capsule.js.map +1 -1
  69. package/dist/src/causal.d.ts +1 -1
  70. package/dist/src/causal.d.ts.map +1 -1
  71. package/dist/src/causal.js +4 -2
  72. package/dist/src/causal.js.map +1 -1
  73. package/dist/src/confidence.d.ts.map +1 -1
  74. package/dist/src/confidence.js +5 -5
  75. package/dist/src/confidence.js.map +1 -1
  76. package/dist/src/consolidate.d.ts.map +1 -1
  77. package/dist/src/consolidate.js +17 -9
  78. package/dist/src/consolidate.js.map +1 -1
  79. package/dist/src/context.js +1 -1
  80. package/dist/src/context.js.map +1 -1
  81. package/dist/src/controller.d.ts +17 -1
  82. package/dist/src/controller.d.ts.map +1 -1
  83. package/dist/src/controller.js +73 -23
  84. package/dist/src/controller.js.map +1 -1
  85. package/dist/src/db.d.ts.map +1 -1
  86. package/dist/src/db.js +78 -27
  87. package/dist/src/db.js.map +1 -1
  88. package/dist/src/decay.d.ts +1 -1
  89. package/dist/src/decay.d.ts.map +1 -1
  90. package/dist/src/decay.js +1 -1
  91. package/dist/src/decay.js.map +1 -1
  92. package/dist/src/embedding.d.ts +12 -4
  93. package/dist/src/embedding.d.ts.map +1 -1
  94. package/dist/src/embedding.js +18 -16
  95. package/dist/src/embedding.js.map +1 -1
  96. package/dist/src/encode.d.ts.map +1 -1
  97. package/dist/src/encode.js +5 -4
  98. package/dist/src/encode.js.map +1 -1
  99. package/dist/src/events.d.ts +3 -2
  100. package/dist/src/events.d.ts.map +1 -1
  101. package/dist/src/events.js +7 -3
  102. package/dist/src/events.js.map +1 -1
  103. package/dist/src/export.d.ts.map +1 -1
  104. package/dist/src/export.js +21 -7
  105. package/dist/src/export.js.map +1 -1
  106. package/dist/src/feedback.d.ts.map +1 -1
  107. package/dist/src/feedback.js +1 -1
  108. package/dist/src/feedback.js.map +1 -1
  109. package/dist/src/forget.d.ts.map +1 -1
  110. package/dist/src/forget.js +12 -6
  111. package/dist/src/forget.js.map +1 -1
  112. package/dist/src/fts.d.ts.map +1 -1
  113. package/dist/src/fts.js +20 -8
  114. package/dist/src/fts.js.map +1 -1
  115. package/dist/src/hybrid-recall.d.ts.map +1 -1
  116. package/dist/src/hybrid-recall.js +12 -6
  117. package/dist/src/hybrid-recall.js.map +1 -1
  118. package/dist/src/impact.d.ts.map +1 -1
  119. package/dist/src/impact.js +26 -10
  120. package/dist/src/impact.js.map +1 -1
  121. package/dist/src/import.d.ts.map +1 -1
  122. package/dist/src/import.js +11 -6
  123. package/dist/src/import.js.map +1 -1
  124. package/dist/src/index.d.ts +5 -4
  125. package/dist/src/index.d.ts.map +1 -1
  126. package/dist/src/index.js +4 -4
  127. package/dist/src/index.js.map +1 -1
  128. package/dist/src/interference.d.ts.map +1 -1
  129. package/dist/src/interference.js +10 -5
  130. package/dist/src/interference.js.map +1 -1
  131. package/dist/src/introspect.d.ts.map +1 -1
  132. package/dist/src/introspect.js +12 -6
  133. package/dist/src/introspect.js.map +1 -1
  134. package/dist/src/llm.d.ts +2 -2
  135. package/dist/src/llm.d.ts.map +1 -1
  136. package/dist/src/llm.js +6 -6
  137. package/dist/src/llm.js.map +1 -1
  138. package/dist/src/migrate.d.ts.map +1 -1
  139. package/dist/src/migrate.js +10 -4
  140. package/dist/src/migrate.js.map +1 -1
  141. package/dist/src/preflight.d.ts.map +1 -1
  142. package/dist/src/preflight.js +6 -8
  143. package/dist/src/preflight.js.map +1 -1
  144. package/dist/src/profile.d.ts.map +1 -1
  145. package/dist/src/profile.js.map +1 -1
  146. package/dist/src/promote.d.ts.map +1 -1
  147. package/dist/src/promote.js +16 -7
  148. package/dist/src/promote.js.map +1 -1
  149. package/dist/src/prompts.d.ts.map +1 -1
  150. package/dist/src/prompts.js +1 -2
  151. package/dist/src/prompts.js.map +1 -1
  152. package/dist/src/recall.d.ts.map +1 -1
  153. package/dist/src/recall.js +85 -18
  154. package/dist/src/recall.js.map +1 -1
  155. package/dist/src/redact.d.ts.map +1 -1
  156. package/dist/src/redact.js +9 -4
  157. package/dist/src/redact.js.map +1 -1
  158. package/dist/src/reflexes.d.ts.map +1 -1
  159. package/dist/src/reflexes.js +1 -7
  160. package/dist/src/reflexes.js.map +1 -1
  161. package/dist/src/rollback.d.ts.map +1 -1
  162. package/dist/src/rollback.js +4 -2
  163. package/dist/src/rollback.js.map +1 -1
  164. package/dist/src/routes.d.ts.map +1 -1
  165. package/dist/src/routes.js +37 -14
  166. package/dist/src/routes.js.map +1 -1
  167. package/dist/src/rules-compiler.d.ts.map +1 -1
  168. package/dist/src/rules-compiler.js +24 -2
  169. package/dist/src/rules-compiler.js.map +1 -1
  170. package/dist/src/server.js +2 -2
  171. package/dist/src/server.js.map +1 -1
  172. package/dist/src/tool-trace.d.ts +2 -2
  173. package/dist/src/tool-trace.d.ts.map +1 -1
  174. package/dist/src/tool-trace.js +12 -4
  175. package/dist/src/tool-trace.js.map +1 -1
  176. package/dist/src/types.d.ts.map +1 -1
  177. package/dist/src/ulid.js +1 -1
  178. package/dist/src/ulid.js.map +1 -1
  179. package/dist/src/utils.d.ts.map +1 -1
  180. package/dist/src/utils.js.map +1 -1
  181. package/dist/src/validate.d.ts.map +1 -1
  182. package/dist/src/validate.js +20 -10
  183. package/dist/src/validate.js.map +1 -1
  184. package/docs/paper/07-evaluation.md +5 -5
  185. package/docs/paper/audrey-paper-v1.md +6 -6
  186. package/docs/paper/evidence-ledger.md +1 -1
  187. package/docs/paper/output/arxiv/arxiv-manifest.json +4 -4
  188. package/docs/paper/output/arxiv/main.tex +6 -6
  189. package/docs/paper/output/arxiv-compile-report.json +3 -3
  190. package/docs/paper/output/submission-bundle/README.md +30 -6
  191. package/docs/paper/output/submission-bundle/benchmarks/output/adapter-self-test/guardbench-adapter-self-test.json +7 -7
  192. package/docs/paper/output/submission-bundle/benchmarks/output/external/guardbench-external-dry-run.json +1 -1
  193. package/docs/paper/output/submission-bundle/benchmarks/output/external/guardbench-external-evidence.json +1 -1
  194. package/docs/paper/output/submission-bundle/benchmarks/output/guardbench-conformance-card.json +12 -12
  195. package/docs/paper/output/submission-bundle/benchmarks/output/guardbench-raw.json +243 -144
  196. package/docs/paper/output/submission-bundle/benchmarks/output/guardbench-summary.json +354 -230
  197. package/docs/paper/output/submission-bundle/benchmarks/output/leaderboard/guardbench-leaderboard.json +5 -5
  198. package/docs/paper/output/submission-bundle/benchmarks/output/leaderboard/guardbench-leaderboard.md +2 -2
  199. package/docs/paper/output/submission-bundle/benchmarks/output/submission-bundle/submission-manifest.json +15 -15
  200. package/docs/paper/output/submission-bundle/benchmarks/output/submission-bundle/validation-report.json +1 -1
  201. package/docs/paper/output/submission-bundle/benchmarks/output/summary.json +52 -52
  202. package/docs/paper/output/submission-bundle/benchmarks/schemas/guardbench-raw.schema.json +21 -1
  203. package/docs/paper/output/submission-bundle/benchmarks/schemas/guardbench-summary.schema.json +23 -2
  204. package/docs/paper/output/submission-bundle/docs/paper/07-evaluation.md +5 -5
  205. package/docs/paper/output/submission-bundle/docs/paper/audrey-paper-v1.md +6 -6
  206. package/docs/paper/output/submission-bundle/docs/paper/evidence-ledger.md +1 -1
  207. package/docs/paper/output/submission-bundle/docs/paper/output/arxiv/arxiv-manifest.json +4 -4
  208. package/docs/paper/output/submission-bundle/docs/paper/output/arxiv/main.tex +6 -6
  209. package/docs/paper/output/submission-bundle/docs/paper/output/arxiv-compile-report.json +3 -3
  210. package/docs/paper/output/submission-bundle/package.json +18 -5
  211. package/docs/paper/output/submission-bundle/paper-submission-manifest.json +40 -40
  212. package/examples/fintech-ops-demo.js +12 -5
  213. package/examples/healthcare-ops-demo.js +8 -4
  214. package/examples/ollama-memory-agent.js +41 -13
  215. package/examples/stripe-demo.js +12 -5
  216. package/package.json +18 -5
  217. package/scripts/audit-release-completion.mjs +179 -101
  218. package/scripts/create-arxiv-source.mjs +20 -14
  219. package/scripts/create-paper-submission-bundle.mjs +6 -2
  220. package/scripts/finalize-release.mjs +111 -36
  221. package/scripts/prepare-release-cut.mjs +14 -6
  222. package/scripts/publish-release-bundle.mjs +62 -23
  223. package/scripts/publish-release-github-api.mjs +89 -24
  224. package/scripts/smoke-cli.js +26 -6
  225. package/scripts/sync-paper-artifacts.mjs +5 -1
  226. package/scripts/verify-arxiv-compile.mjs +52 -16
  227. package/scripts/verify-arxiv-source.mjs +45 -15
  228. package/scripts/verify-browser-launch-plan.mjs +28 -11
  229. package/scripts/verify-browser-launch-results.mjs +32 -14
  230. package/scripts/verify-paper-artifacts.mjs +539 -79
  231. package/scripts/verify-paper-claims.mjs +48 -20
  232. package/scripts/verify-paper-submission-bundle.mjs +22 -11
  233. package/scripts/verify-publication-pack.mjs +23 -9
  234. package/scripts/verify-release-readiness.mjs +250 -71
@@ -1,6 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { cpSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
3
- import { dirname, join, relative, resolve } from 'node:path';
3
+ import { dirname, join, resolve } from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
 
6
6
  const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
@@ -60,9 +60,11 @@ function protectInline(text) {
60
60
  };
61
61
 
62
62
  let next = text.replace(/\[([^\]]+)\]\((https?:\/\/[^)]+)\)/g, (_, label, url) =>
63
- protect(`\\href{${latexEscape(url)}}{${latexEscape(label)}}`));
63
+ protect(`\\href{${latexEscape(url)}}{${latexEscape(label)}}`),
64
+ );
64
65
  next = next.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, label, url) =>
65
- protect(`\\texttt{${latexEscape(label)}} (${latexEscape(url)})`));
66
+ protect(`\\texttt{${latexEscape(label)}} (${latexEscape(url)})`),
67
+ );
66
68
  next = next.replace(/\[@([^\]]+)\]/g, (_, rawIds) => {
67
69
  const ids = rawIds
68
70
  .split(/;\s*@?|\s*,\s*@?/)
@@ -288,17 +290,21 @@ export function writeArxivSourcePackage(options = {}) {
288
290
 
289
291
  writeFileSync(join(outDir, 'main.tex'), built.tex, 'utf-8');
290
292
  cpSync(fromRoot(SOURCE_BIB), join(outDir, 'references.bib'));
291
- writeFileSync(join(outDir, 'README-arxiv.txt'), [
292
- 'Audrey arXiv source package',
293
- '',
294
- 'Main file: main.tex',
295
- 'Bibliography: references.bib',
296
- '',
297
- 'Generated from docs/paper/audrey-paper-v1.md and docs/paper/publication-pack.json.',
298
- 'This host did not require a local TeX compiler to generate the source package.',
299
- 'Before final arXiv upload, compile with a TeX toolchain and preview the PDF in arXiv.',
300
- '',
301
- ].join('\n'), 'utf-8');
293
+ writeFileSync(
294
+ join(outDir, 'README-arxiv.txt'),
295
+ [
296
+ 'Audrey arXiv source package',
297
+ '',
298
+ 'Main file: main.tex',
299
+ 'Bibliography: references.bib',
300
+ '',
301
+ 'Generated from docs/paper/audrey-paper-v1.md and docs/paper/publication-pack.json.',
302
+ 'This host did not require a local TeX compiler to generate the source package.',
303
+ 'Before final arXiv upload, compile with a TeX toolchain and preview the PDF in arXiv.',
304
+ '',
305
+ ].join('\n'),
306
+ 'utf-8',
307
+ );
302
308
 
303
309
  const files = [
304
310
  fileRecord(outDir, 'main.tex', SOURCE_MARKDOWN),
@@ -138,10 +138,14 @@ export async function writePaperSubmissionBundle(options = {}) {
138
138
  const claimVerification = await verifyPaperClaims();
139
139
  const publicationPackVerification = await verifyPublicationPack();
140
140
  if (!claimVerification.ok) {
141
- throw new Error(`Cannot create paper submission bundle with invalid claims: ${claimVerification.failures.join('; ')}`);
141
+ throw new Error(
142
+ `Cannot create paper submission bundle with invalid claims: ${claimVerification.failures.join('; ')}`,
143
+ );
142
144
  }
143
145
  if (!publicationPackVerification.ok) {
144
- throw new Error(`Cannot create paper submission bundle with invalid publication pack: ${publicationPackVerification.failures.join('; ')}`);
146
+ throw new Error(
147
+ `Cannot create paper submission bundle with invalid publication pack: ${publicationPackVerification.failures.join('; ')}`,
148
+ );
145
149
  }
146
150
 
147
151
  rmSync(outDir, { recursive: true, force: true });
@@ -67,7 +67,8 @@ function safeRepoRelativePath(value, label) {
67
67
  function normalizeArgs(args) {
68
68
  args.version = safeVersion(args.version);
69
69
  args.artifactDir = safeRepoRelativePath(args.artifactDir, '--artifact-dir');
70
- if (args.commitMessage !== null) args.commitMessage = safeString(args.commitMessage, '--commit-message');
70
+ if (args.commitMessage !== null)
71
+ args.commitMessage = safeString(args.commitMessage, '--commit-message');
71
72
  if (args.npmOtp !== null) args.npmOtp = safeString(args.npmOtp, '--npm-otp');
72
73
  return args;
73
74
  }
@@ -109,7 +110,8 @@ function parseArgs(argv = process.argv.slice(2)) {
109
110
 
110
111
  for (let i = 0; i < argv.length; i++) {
111
112
  const token = argv[i];
112
- if ((token === '--version' || token === '--target-version') && argv[i + 1]) args.version = argv[++i];
113
+ if ((token === '--version' || token === '--target-version') && argv[i + 1])
114
+ args.version = argv[++i];
113
115
  else if (token === '--artifact-dir' && argv[i + 1]) args.artifactDir = argv[++i];
114
116
  else if (token === '--commit-message' && argv[i + 1]) args.commitMessage = argv[++i];
115
117
  else if (token === '--npm-otp' && argv[i + 1]) args.npmOtp = argv[++i];
@@ -162,7 +164,9 @@ function commandFor(command, args) {
162
164
  if (!RELEASE_COMMANDS.has(command)) {
163
165
  throw new Error(`Unsupported release command: ${command}`);
164
166
  }
165
- const safeArgs = args.map((arg, index) => safeString(String(arg), `${command} argument ${index + 1}`));
167
+ const safeArgs = args.map((arg, index) =>
168
+ safeString(String(arg), `${command} argument ${index + 1}`),
169
+ );
166
170
  if (process.platform === 'win32' && command === 'npm') {
167
171
  return { command: 'cmd.exe', args: ['/d', '/c', 'npm', ...safeArgs] };
168
172
  }
@@ -218,7 +222,9 @@ function listArtifacts(artifactDir, version) {
218
222
  }
219
223
 
220
224
  return files.map(path => ({
221
- path: path.startsWith(ROOT) ? path.slice(ROOT.length + 1).replaceAll('\\', '/') : path.replaceAll('\\', '/'),
225
+ path: path.startsWith(ROOT)
226
+ ? path.slice(ROOT.length + 1).replaceAll('\\', '/')
227
+ : path.replaceAll('\\', '/'),
222
228
  sha256: sha256(path),
223
229
  bytes: readFileSync(path).byteLength,
224
230
  }));
@@ -280,15 +286,23 @@ function buildPlan(args) {
280
286
  if (args.tag) commands.push(`git tag -a ${tagName} -m "Audrey ${args.version}"`);
281
287
  if (args.push) commands.push(`git push origin HEAD:master --follow-tags`);
282
288
  if (args.pack) commands.push(`npm pack --pack-destination ${args.artifactDir}`);
283
- if (args.sourceBundle) commands.push(`git bundle create ${args.artifactDir}/audrey-${args.version}.git.bundle refs/heads/master refs/tags/v${args.version}`);
289
+ if (args.sourceBundle)
290
+ commands.push(
291
+ `git bundle create ${args.artifactDir}/audrey-${args.version}.git.bundle refs/heads/master refs/tags/v${args.version}`,
292
+ );
284
293
  if (args.publishNpm) {
285
294
  const otp = args.npmOtp ? ' --otp <provided>' : '';
286
- commands.push(`npm publish ${args.artifactDir}/audrey-${args.version}.tgz --access public --registry ${NPM_REGISTRY}${otp}`);
295
+ commands.push(
296
+ `npm publish ${args.artifactDir}/audrey-${args.version}.tgz --access public --registry ${NPM_REGISTRY}${otp}`,
297
+ );
287
298
  }
288
- if (args.publishPypi) commands.push(`python -m twine upload python/dist/audrey_memory-${args.version}*`);
299
+ if (args.publishPypi)
300
+ commands.push(`python -m twine upload python/dist/audrey_memory-${args.version}*`);
289
301
 
290
302
  if (actions.length === 0) {
291
- blockers.push('Select at least one action such as --pack, --source-bundle, --commit, --tag, --push, --publish-npm, or --publish-pypi');
303
+ blockers.push(
304
+ 'Select at least one action such as --pack, --source-bundle, --commit, --tag, --push, --publish-npm, or --publish-pypi',
305
+ );
292
306
  }
293
307
  if (args.publishPypi && !pypiCredentialEnv()) {
294
308
  blockers.push('Set TWINE_PASSWORD, PYPI_API_TOKEN, or UV_PUBLISH_TOKEN before --publish-pypi');
@@ -312,12 +326,18 @@ function buildPlan(args) {
312
326
  }
313
327
 
314
328
  function runReadiness(plan) {
315
- const readiness = run('node', ['scripts/verify-release-readiness.mjs', '--allow-pending', '--json'], { timeout: 180_000 });
329
+ const readiness = run(
330
+ 'node',
331
+ ['scripts/verify-release-readiness.mjs', '--allow-pending', '--json'],
332
+ { timeout: 180_000 },
333
+ );
316
334
  plan.results.push(readiness);
317
335
  assertOk(readiness);
318
336
  const report = JSON.parse(readiness.stdout);
319
337
  if (!report.ok) {
320
- throw new Error(`release readiness failed: ${report.failures?.join('; ') || 'unknown failure'}`);
338
+ throw new Error(
339
+ `release readiness failed: ${report.failures?.join('; ') || 'unknown failure'}`,
340
+ );
321
341
  }
322
342
  plan.readiness = {
323
343
  ok: report.ok,
@@ -367,7 +387,20 @@ function createSourceBundle(args, plan) {
367
387
  }
368
388
 
369
389
  const tree = assertOk(run('git', ['write-tree'], { env })).stdout;
370
- const commit = assertOk(run('git', ['commit-tree', tree, '-p', 'HEAD', '-m', args.commitMessage ?? `Release Audrey ${args.version}`], { env })).stdout;
390
+ const commit = assertOk(
391
+ run(
392
+ 'git',
393
+ [
394
+ 'commit-tree',
395
+ tree,
396
+ '-p',
397
+ 'HEAD',
398
+ '-m',
399
+ args.commitMessage ?? `Release Audrey ${args.version}`,
400
+ ],
401
+ { env },
402
+ ),
403
+ ).stdout;
371
404
  const tagContent = [
372
405
  `object ${commit}`,
373
406
  'type commit',
@@ -384,17 +417,33 @@ function createSourceBundle(args, plan) {
384
417
  mkdirSync(join(gitDir, 'refs', 'heads'), { recursive: true });
385
418
  mkdirSync(join(gitDir, 'refs', 'tags'), { recursive: true });
386
419
  writeFileSync(join(gitDir, 'HEAD'), 'ref: refs/heads/master\n', 'utf-8');
387
- writeFileSync(join(gitDir, 'config'), '[core]\n\trepositoryformatversion = 0\n\tfilemode = false\n\tbare = true\n', 'utf-8');
420
+ writeFileSync(
421
+ join(gitDir, 'config'),
422
+ '[core]\n\trepositoryformatversion = 0\n\tfilemode = false\n\tbare = true\n',
423
+ 'utf-8',
424
+ );
388
425
  writeFileSync(join(gitDir, 'refs', 'heads', 'master'), `${commit}\n`, 'utf-8');
389
426
  writeFileSync(join(gitDir, 'refs', 'tags', `v${args.version}`), `${tag}\n`, 'utf-8');
390
427
 
391
- const bundle = run('git', ['--git-dir', gitDir, 'bundle', 'create', bundlePath, 'refs/heads/master', `refs/tags/v${args.version}`], {
392
- env: {
393
- GIT_OBJECT_DIRECTORY: objectDir,
394
- GIT_ALTERNATE_OBJECT_DIRECTORIES: fromRoot('.git/objects'),
428
+ const bundle = run(
429
+ 'git',
430
+ [
431
+ '--git-dir',
432
+ gitDir,
433
+ 'bundle',
434
+ 'create',
435
+ bundlePath,
436
+ 'refs/heads/master',
437
+ `refs/tags/v${args.version}`,
438
+ ],
439
+ {
440
+ env: {
441
+ GIT_OBJECT_DIRECTORY: objectDir,
442
+ GIT_ALTERNATE_OBJECT_DIRECTORIES: fromRoot('.git/objects'),
443
+ },
444
+ timeout: 180_000,
395
445
  },
396
- timeout: 180_000,
397
- });
446
+ );
398
447
  plan.results.push(bundle);
399
448
  assertOk(bundle);
400
449
 
@@ -410,7 +459,11 @@ function createSourceBundle(args, plan) {
410
459
  indexFile: '.tmp/release.index',
411
460
  bundle: args.artifactDir.replaceAll('\\', '/') + `/audrey-${args.version}.git.bundle`,
412
461
  };
413
- writeFileSync(fromRoot('.tmp/release-git-object-report.json'), `${JSON.stringify(objectReport, null, 2)}\n`, 'utf-8');
462
+ writeFileSync(
463
+ fromRoot('.tmp/release-git-object-report.json'),
464
+ `${JSON.stringify(objectReport, null, 2)}\n`,
465
+ 'utf-8',
466
+ );
414
467
  plan.sourceControl = objectReport;
415
468
  }
416
469
 
@@ -434,18 +487,22 @@ function execute(args, plan) {
434
487
  }
435
488
 
436
489
  if (args.push) {
437
- const push = run('git', [
438
- '-c',
439
- 'http.sslBackend=openssl',
440
- '-c',
441
- 'credential.helper=',
442
- '-c',
443
- 'core.askPass=',
444
- 'push',
445
- 'origin',
446
- 'HEAD:master',
447
- '--follow-tags',
448
- ], { timeout: 45_000 });
490
+ const push = run(
491
+ 'git',
492
+ [
493
+ '-c',
494
+ 'http.sslBackend=openssl',
495
+ '-c',
496
+ 'credential.helper=',
497
+ '-c',
498
+ 'core.askPass=',
499
+ 'push',
500
+ 'origin',
501
+ 'HEAD:master',
502
+ '--follow-tags',
503
+ ],
504
+ { timeout: 45_000 },
505
+ );
449
506
  plan.results.push(push);
450
507
  assertOk(push);
451
508
  }
@@ -464,7 +521,14 @@ function execute(args, plan) {
464
521
  const whoami = run('npm', ['whoami', '--registry', NPM_REGISTRY]);
465
522
  plan.results.push(whoami);
466
523
  assertOk(whoami);
467
- const publishArgs = ['publish', npmTarballPath(args.artifactDir, args.version), '--access', 'public', '--registry', NPM_REGISTRY];
524
+ const publishArgs = [
525
+ 'publish',
526
+ npmTarballPath(args.artifactDir, args.version),
527
+ '--access',
528
+ 'public',
529
+ '--registry',
530
+ NPM_REGISTRY,
531
+ ];
468
532
  if (args.npmOtp) publishArgs.push('--otp', args.npmOtp);
469
533
  const publish = run('npm', publishArgs, { timeout: 180_000 });
470
534
  plan.results.push(publish);
@@ -473,19 +537,29 @@ function execute(args, plan) {
473
537
 
474
538
  if (args.publishPypi) {
475
539
  const uploadEnv = pypiCredentialEnv();
476
- if (!uploadEnv) throw new Error('Missing PyPI credentials: set TWINE_PASSWORD, PYPI_API_TOKEN, or UV_PUBLISH_TOKEN');
540
+ if (!uploadEnv)
541
+ throw new Error(
542
+ 'Missing PyPI credentials: set TWINE_PASSWORD, PYPI_API_TOKEN, or UV_PUBLISH_TOKEN',
543
+ );
477
544
  const build = run('npm', ['run', 'python:release:check'], { timeout: 180_000 });
478
545
  plan.results.push(build);
479
546
  assertOk(build);
480
547
  const artifacts = pythonArtifactPaths(args.version);
481
548
  if (artifacts.length === 0) throw new Error(`No Python artifacts found for ${args.version}`);
482
- const upload = run('python', ['-m', 'twine', 'upload', ...artifacts], { timeout: 180_000, env: uploadEnv });
549
+ const upload = run('python', ['-m', 'twine', 'upload', ...artifacts], {
550
+ timeout: 180_000,
551
+ env: uploadEnv,
552
+ });
483
553
  plan.results.push(upload);
484
554
  assertOk(upload);
485
555
  }
486
556
 
487
557
  plan.artifacts = listArtifacts(artifactDir, args.version);
488
- writeFileSync(join(artifactDir, 'release-finalize-report.json'), `${JSON.stringify(plan, null, 2)}\n`, 'utf-8');
558
+ writeFileSync(
559
+ join(artifactDir, 'release-finalize-report.json'),
560
+ `${JSON.stringify(plan, null, 2)}\n`,
561
+ 'utf-8',
562
+ );
489
563
  }
490
564
 
491
565
  function printPlan(plan, json) {
@@ -503,7 +577,8 @@ function printPlan(plan, json) {
503
577
  }
504
578
  if (plan.artifacts.length) {
505
579
  console.log('Artifacts:');
506
- for (const artifact of plan.artifacts) console.log(`- ${artifact.path} sha256=${artifact.sha256}`);
580
+ for (const artifact of plan.artifacts)
581
+ console.log(`- ${artifact.path} sha256=${artifact.sha256}`);
507
582
  }
508
583
  }
509
584
 
@@ -4,7 +4,8 @@ import { fileURLToPath } from 'node:url';
4
4
 
5
5
  const ROOT = process.cwd();
6
6
  const DEFAULT_TARGET_VERSION = '1.0.0';
7
- const VERSION_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
7
+ const VERSION_RE =
8
+ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
8
9
 
9
10
  function fromRoot(path) {
10
11
  return resolve(ROOT, path);
@@ -34,7 +35,8 @@ function parseArgs(argv = process.argv.slice(2)) {
34
35
 
35
36
  for (let i = 0; i < argv.length; i++) {
36
37
  const token = argv[i];
37
- if ((token === '--target-version' || token === '--version') && argv[i + 1]) args.targetVersion = argv[++i];
38
+ if ((token === '--target-version' || token === '--version') && argv[i + 1])
39
+ args.targetVersion = argv[++i];
38
40
  else if (token === '--date' && argv[i + 1]) args.date = argv[++i];
39
41
  else if (token === '--apply') args.apply = true;
40
42
  else if (token === '--json') args.json = true;
@@ -203,10 +205,14 @@ export function prepareReleaseCut(options = {}) {
203
205
  const versions = currentVersionSnapshot();
204
206
  const versionValues = Object.values(versions);
205
207
  const failures = [];
206
- if (versionValues.some(value => !value)) failures.push('One or more release version surfaces are missing');
207
- if (new Set(versionValues).size !== 1) failures.push(`Release version surfaces are not aligned: ${JSON.stringify(versions)}`);
208
+ if (versionValues.some(value => !value))
209
+ failures.push('One or more release version surfaces are missing');
210
+ if (new Set(versionValues).size !== 1)
211
+ failures.push(`Release version surfaces are not aligned: ${JSON.stringify(versions)}`);
208
212
  if (versions.packageJson && compareCoreVersions(targetVersion, versions.packageJson) < 0) {
209
- failures.push(`Target version ${targetVersion} is lower than current package version ${versions.packageJson}`);
213
+ failures.push(
214
+ `Target version ${targetVersion} is lower than current package version ${versions.packageJson}`,
215
+ );
210
216
  }
211
217
 
212
218
  const files = plannedFiles(targetVersion, date).map(([path, after]) => {
@@ -251,7 +257,9 @@ async function main() {
251
257
  console.log(JSON.stringify(report, null, 2));
252
258
  } else if (report.ok) {
253
259
  const changed = report.files.filter(file => file.changed).map(file => file.path);
254
- console.log(`${report.apply ? 'Applied' : 'Planned'} Audrey ${report.targetVersion} release cut: ${changed.length} file(s)`);
260
+ console.log(
261
+ `${report.apply ? 'Applied' : 'Planned'} Audrey ${report.targetVersion} release cut: ${changed.length} file(s)`,
262
+ );
255
263
  for (const file of changed) console.log(`- ${file}`);
256
264
  } else {
257
265
  console.error('Release cut preparation failed:');
@@ -22,7 +22,8 @@ function parseArgs(argv = process.argv.slice(2)) {
22
22
 
23
23
  for (let i = 0; i < argv.length; i++) {
24
24
  const token = argv[i];
25
- if ((token === '--version' || token === '--target-version') && argv[i + 1]) args.version = argv[++i];
25
+ if ((token === '--version' || token === '--target-version') && argv[i + 1])
26
+ args.version = argv[++i];
26
27
  else if (token === '--bundle' && argv[i + 1]) args.bundle = argv[++i];
27
28
  else if (token === '--remote' && argv[i + 1]) args.remote = argv[++i];
28
29
  else if (token === '--apply') args.apply = true;
@@ -72,7 +73,12 @@ function run(command, args, options = {}) {
72
73
  }
73
74
 
74
75
  function firstLine(result) {
75
- return `${result.stderr}\n${result.stdout}`.split(/\r?\n/).map(line => line.trim()).find(Boolean) ?? '';
76
+ return (
77
+ `${result.stderr}\n${result.stdout}`
78
+ .split(/\r?\n/)
79
+ .map(line => line.trim())
80
+ .find(Boolean) ?? ''
81
+ );
76
82
  }
77
83
 
78
84
  function parseBundleRefs(output, version) {
@@ -101,9 +107,27 @@ function parseRemoteRefs(output, version) {
101
107
  }
102
108
 
103
109
  function remoteHead(args) {
104
- let result = run('git', ['ls-remote', args.remote, 'refs/heads/master', `refs/tags/v${args.version}`], { timeout: 60_000 });
105
- if (!result.ok && /schannel|AcquireCredentialsHandle|SEC_E_NO_CREDENTIALS/i.test(firstLine(result))) {
106
- result = run('git', ['-c', 'http.sslBackend=openssl', 'ls-remote', args.remote, 'refs/heads/master', `refs/tags/v${args.version}`], { timeout: 60_000 });
110
+ let result = run(
111
+ 'git',
112
+ ['ls-remote', args.remote, 'refs/heads/master', `refs/tags/v${args.version}`],
113
+ { timeout: 60_000 },
114
+ );
115
+ if (
116
+ !result.ok &&
117
+ /schannel|AcquireCredentialsHandle|SEC_E_NO_CREDENTIALS/i.test(firstLine(result))
118
+ ) {
119
+ result = run(
120
+ 'git',
121
+ [
122
+ '-c',
123
+ 'http.sslBackend=openssl',
124
+ 'ls-remote',
125
+ args.remote,
126
+ 'refs/heads/master',
127
+ `refs/tags/v${args.version}`,
128
+ ],
129
+ { timeout: 60_000 },
130
+ );
107
131
  result.fallback = 'openssl';
108
132
  }
109
133
  return result;
@@ -112,20 +136,26 @@ function remoteHead(args) {
112
136
  function publishFromBundle(args, refs) {
113
137
  const temp = mkdtempSync(join(tmpdir(), 'audrey-release-push-'));
114
138
  try {
115
- const clone = run('git', ['clone', '--bare', resolve(ROOT, args.bundle), temp], { timeout: 120_000 });
139
+ const clone = run('git', ['clone', '--bare', resolve(ROOT, args.bundle), temp], {
140
+ timeout: 120_000,
141
+ });
116
142
  if (!clone.ok) return [clone];
117
- const push = run('git', [
118
- '-c',
119
- 'http.sslBackend=openssl',
120
- '-c',
121
- 'credential.helper=',
122
- '-c',
123
- 'core.askPass=',
124
- 'push',
125
- args.remote,
126
- `${refs.master}:refs/heads/master`,
127
- `${refs.tag}:refs/tags/v${args.version}`,
128
- ], { cwd: temp, timeout: 45_000 });
143
+ const push = run(
144
+ 'git',
145
+ [
146
+ '-c',
147
+ 'http.sslBackend=openssl',
148
+ '-c',
149
+ 'credential.helper=',
150
+ '-c',
151
+ 'core.askPass=',
152
+ 'push',
153
+ args.remote,
154
+ `${refs.master}:refs/heads/master`,
155
+ `${refs.tag}:refs/tags/v${args.version}`,
156
+ ],
157
+ { cwd: temp, timeout: 45_000 },
158
+ );
129
159
  return [clone, push];
130
160
  } finally {
131
161
  rmSync(temp, { recursive: true, force: true });
@@ -135,16 +165,22 @@ function publishFromBundle(args, refs) {
135
165
  export function planPublish(args) {
136
166
  const verify = run('git', ['bundle', 'verify', args.bundle], { timeout: 60_000 });
137
167
  const remote = remoteHead(args);
138
- const bundleRefs = verify.ok ? parseBundleRefs(verify.stdout, args.version) : { master: null, tag: null };
139
- const remoteRefs = remote.ok ? parseRemoteRefs(remote.stdout, args.version) : { master: null, tag: null };
168
+ const bundleRefs = verify.ok
169
+ ? parseBundleRefs(verify.stdout, args.version)
170
+ : { master: null, tag: null };
171
+ const remoteRefs = remote.ok
172
+ ? parseRemoteRefs(remote.stdout, args.version)
173
+ : { master: null, tag: null };
140
174
  const blockers = [];
141
175
 
142
176
  if (!verify.ok) blockers.push(`Bundle verification failed: ${firstLine(verify)}`);
143
177
  if (!bundleRefs.master) blockers.push('Bundle is missing refs/heads/master');
144
178
  if (!bundleRefs.tag) blockers.push(`Bundle is missing refs/tags/v${args.version}`);
145
179
  if (!remote.ok) blockers.push(`Remote check failed: ${firstLine(remote)}`);
146
- if (remoteRefs.tag && remoteRefs.tag !== bundleRefs.tag) blockers.push(`Remote v${args.version} already points at ${remoteRefs.tag}`);
147
- if (remoteRefs.master === bundleRefs.master && remoteRefs.tag === bundleRefs.tag) blockers.push('Remote already matches the release bundle');
180
+ if (remoteRefs.tag && remoteRefs.tag !== bundleRefs.tag)
181
+ blockers.push(`Remote v${args.version} already points at ${remoteRefs.tag}`);
182
+ if (remoteRefs.master === bundleRefs.master && remoteRefs.tag === bundleRefs.tag)
183
+ blockers.push('Remote already matches the release bundle');
148
184
 
149
185
  return {
150
186
  schemaVersion: '1.0.0',
@@ -198,7 +234,10 @@ async function main() {
198
234
  }
199
235
 
200
236
  function isDirectRun() {
201
- return Boolean(process.argv[1]) && resolve(process.argv[1]).toLowerCase() === fileURLToPath(import.meta.url).toLowerCase();
237
+ return (
238
+ Boolean(process.argv[1]) &&
239
+ resolve(process.argv[1]).toLowerCase() === fileURLToPath(import.meta.url).toLowerCase()
240
+ );
202
241
  }
203
242
 
204
243
  if (isDirectRun()) {