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.
- package/CHANGELOG.md +54 -0
- package/README.md +30 -6
- package/benchmarks/adapter-self-test.mjs +6 -2
- package/benchmarks/adapters/example-allow.mjs +5 -2
- package/benchmarks/adapters/mem0-platform.mjs +19 -12
- package/benchmarks/adapters/zep-cloud.mjs +51 -27
- package/benchmarks/baselines.js +11 -6
- package/benchmarks/build-leaderboard.mjs +36 -23
- package/benchmarks/cases.js +24 -12
- package/benchmarks/create-conformance-card.mjs +12 -3
- package/benchmarks/create-submission-bundle.mjs +22 -8
- package/benchmarks/dry-run-external-adapters.mjs +24 -12
- package/benchmarks/guardbench.js +354 -124
- package/benchmarks/output/adapter-self-test/guardbench-adapter-self-test.json +7 -7
- package/benchmarks/output/external/guardbench-external-dry-run.json +1 -1
- package/benchmarks/output/external/guardbench-external-evidence.json +1 -1
- package/benchmarks/output/guardbench-conformance-card.json +12 -12
- package/benchmarks/output/guardbench-raw.json +243 -144
- package/benchmarks/output/guardbench-summary.json +354 -230
- package/benchmarks/output/leaderboard/guardbench-leaderboard.json +5 -5
- package/benchmarks/output/leaderboard/guardbench-leaderboard.md +2 -2
- package/benchmarks/output/submission-bundle/guardbench-conformance-card.json +12 -12
- package/benchmarks/output/submission-bundle/guardbench-raw.json +243 -144
- package/benchmarks/output/submission-bundle/guardbench-summary.json +354 -230
- package/benchmarks/output/submission-bundle/schemas/guardbench-raw.schema.json +21 -1
- package/benchmarks/output/submission-bundle/schemas/guardbench-summary.schema.json +23 -2
- package/benchmarks/output/submission-bundle/submission-manifest.json +15 -15
- package/benchmarks/output/submission-bundle/validation-report.json +1 -1
- package/benchmarks/output/summary.json +58 -58
- package/benchmarks/perf-snapshot.js +12 -9
- package/benchmarks/perf.bench.js +14 -6
- package/benchmarks/public-paths.mjs +11 -5
- package/benchmarks/reference-results.js +10 -5
- package/benchmarks/report.js +48 -27
- package/benchmarks/run-external-guardbench.mjs +47 -25
- package/benchmarks/run.js +112 -59
- package/benchmarks/schemas/guardbench-raw.schema.json +21 -1
- package/benchmarks/schemas/guardbench-summary.schema.json +23 -2
- package/benchmarks/validate-adapter-module.mjs +13 -10
- package/benchmarks/validate-adapter-registry.mjs +16 -5
- package/benchmarks/validate-guardbench-artifacts.mjs +76 -19
- package/benchmarks/verify-external-evidence.mjs +86 -31
- package/benchmarks/verify-publication-artifacts.mjs +34 -11
- package/benchmarks/verify-submission-bundle.mjs +9 -4
- package/dist/mcp-server/config.d.ts +1 -1
- package/dist/mcp-server/config.d.ts.map +1 -1
- package/dist/mcp-server/config.js +5 -3
- package/dist/mcp-server/config.js.map +1 -1
- package/dist/mcp-server/index.d.ts +4 -3
- package/dist/mcp-server/index.d.ts.map +1 -1
- package/dist/mcp-server/index.js +479 -172
- package/dist/mcp-server/index.js.map +1 -1
- package/dist/src/action-key.d.ts.map +1 -1
- package/dist/src/action-key.js +6 -2
- package/dist/src/action-key.js.map +1 -1
- package/dist/src/adaptive.d.ts.map +1 -1
- package/dist/src/adaptive.js +4 -2
- package/dist/src/adaptive.js.map +1 -1
- package/dist/src/affect.d.ts.map +1 -1
- package/dist/src/affect.js +8 -5
- package/dist/src/affect.js.map +1 -1
- package/dist/src/audrey.d.ts +11 -1
- package/dist/src/audrey.d.ts.map +1 -1
- package/dist/src/audrey.js +110 -53
- package/dist/src/audrey.js.map +1 -1
- package/dist/src/capsule.d.ts.map +1 -1
- package/dist/src/capsule.js +37 -15
- package/dist/src/capsule.js.map +1 -1
- package/dist/src/causal.d.ts +1 -1
- package/dist/src/causal.d.ts.map +1 -1
- package/dist/src/causal.js +4 -2
- package/dist/src/causal.js.map +1 -1
- package/dist/src/confidence.d.ts.map +1 -1
- package/dist/src/confidence.js +5 -5
- package/dist/src/confidence.js.map +1 -1
- package/dist/src/consolidate.d.ts.map +1 -1
- package/dist/src/consolidate.js +17 -9
- package/dist/src/consolidate.js.map +1 -1
- package/dist/src/context.js +1 -1
- package/dist/src/context.js.map +1 -1
- package/dist/src/controller.d.ts +17 -1
- package/dist/src/controller.d.ts.map +1 -1
- package/dist/src/controller.js +73 -23
- package/dist/src/controller.js.map +1 -1
- package/dist/src/db.d.ts.map +1 -1
- package/dist/src/db.js +78 -27
- package/dist/src/db.js.map +1 -1
- package/dist/src/decay.d.ts +1 -1
- package/dist/src/decay.d.ts.map +1 -1
- package/dist/src/decay.js +1 -1
- package/dist/src/decay.js.map +1 -1
- package/dist/src/embedding.d.ts +12 -4
- package/dist/src/embedding.d.ts.map +1 -1
- package/dist/src/embedding.js +18 -16
- package/dist/src/embedding.js.map +1 -1
- package/dist/src/encode.d.ts.map +1 -1
- package/dist/src/encode.js +5 -4
- package/dist/src/encode.js.map +1 -1
- package/dist/src/events.d.ts +3 -2
- package/dist/src/events.d.ts.map +1 -1
- package/dist/src/events.js +7 -3
- package/dist/src/events.js.map +1 -1
- package/dist/src/export.d.ts.map +1 -1
- package/dist/src/export.js +21 -7
- package/dist/src/export.js.map +1 -1
- package/dist/src/feedback.d.ts.map +1 -1
- package/dist/src/feedback.js +1 -1
- package/dist/src/feedback.js.map +1 -1
- package/dist/src/forget.d.ts.map +1 -1
- package/dist/src/forget.js +12 -6
- package/dist/src/forget.js.map +1 -1
- package/dist/src/fts.d.ts.map +1 -1
- package/dist/src/fts.js +20 -8
- package/dist/src/fts.js.map +1 -1
- package/dist/src/hybrid-recall.d.ts.map +1 -1
- package/dist/src/hybrid-recall.js +12 -6
- package/dist/src/hybrid-recall.js.map +1 -1
- package/dist/src/impact.d.ts.map +1 -1
- package/dist/src/impact.js +26 -10
- package/dist/src/impact.js.map +1 -1
- package/dist/src/import.d.ts.map +1 -1
- package/dist/src/import.js +11 -6
- package/dist/src/import.js.map +1 -1
- package/dist/src/index.d.ts +5 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/interference.d.ts.map +1 -1
- package/dist/src/interference.js +10 -5
- package/dist/src/interference.js.map +1 -1
- package/dist/src/introspect.d.ts.map +1 -1
- package/dist/src/introspect.js +12 -6
- package/dist/src/introspect.js.map +1 -1
- package/dist/src/llm.d.ts +2 -2
- package/dist/src/llm.d.ts.map +1 -1
- package/dist/src/llm.js +6 -6
- package/dist/src/llm.js.map +1 -1
- package/dist/src/migrate.d.ts.map +1 -1
- package/dist/src/migrate.js +10 -4
- package/dist/src/migrate.js.map +1 -1
- package/dist/src/preflight.d.ts.map +1 -1
- package/dist/src/preflight.js +6 -8
- package/dist/src/preflight.js.map +1 -1
- package/dist/src/profile.d.ts.map +1 -1
- package/dist/src/profile.js.map +1 -1
- package/dist/src/promote.d.ts.map +1 -1
- package/dist/src/promote.js +16 -7
- package/dist/src/promote.js.map +1 -1
- package/dist/src/prompts.d.ts.map +1 -1
- package/dist/src/prompts.js +1 -2
- package/dist/src/prompts.js.map +1 -1
- package/dist/src/recall.d.ts.map +1 -1
- package/dist/src/recall.js +85 -18
- package/dist/src/recall.js.map +1 -1
- package/dist/src/redact.d.ts.map +1 -1
- package/dist/src/redact.js +9 -4
- package/dist/src/redact.js.map +1 -1
- package/dist/src/reflexes.d.ts.map +1 -1
- package/dist/src/reflexes.js +1 -7
- package/dist/src/reflexes.js.map +1 -1
- package/dist/src/rollback.d.ts.map +1 -1
- package/dist/src/rollback.js +4 -2
- package/dist/src/rollback.js.map +1 -1
- package/dist/src/routes.d.ts.map +1 -1
- package/dist/src/routes.js +37 -14
- package/dist/src/routes.js.map +1 -1
- package/dist/src/rules-compiler.d.ts.map +1 -1
- package/dist/src/rules-compiler.js +24 -2
- package/dist/src/rules-compiler.js.map +1 -1
- package/dist/src/server.js +2 -2
- package/dist/src/server.js.map +1 -1
- package/dist/src/tool-trace.d.ts +2 -2
- package/dist/src/tool-trace.d.ts.map +1 -1
- package/dist/src/tool-trace.js +12 -4
- package/dist/src/tool-trace.js.map +1 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/ulid.js +1 -1
- package/dist/src/ulid.js.map +1 -1
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js.map +1 -1
- package/dist/src/validate.d.ts.map +1 -1
- package/dist/src/validate.js +20 -10
- package/dist/src/validate.js.map +1 -1
- package/docs/paper/07-evaluation.md +5 -5
- package/docs/paper/audrey-paper-v1.md +6 -6
- package/docs/paper/evidence-ledger.md +1 -1
- package/docs/paper/output/arxiv/arxiv-manifest.json +4 -4
- package/docs/paper/output/arxiv/main.tex +6 -6
- package/docs/paper/output/arxiv-compile-report.json +3 -3
- package/docs/paper/output/submission-bundle/README.md +30 -6
- package/docs/paper/output/submission-bundle/benchmarks/output/adapter-self-test/guardbench-adapter-self-test.json +7 -7
- package/docs/paper/output/submission-bundle/benchmarks/output/external/guardbench-external-dry-run.json +1 -1
- package/docs/paper/output/submission-bundle/benchmarks/output/external/guardbench-external-evidence.json +1 -1
- package/docs/paper/output/submission-bundle/benchmarks/output/guardbench-conformance-card.json +12 -12
- package/docs/paper/output/submission-bundle/benchmarks/output/guardbench-raw.json +243 -144
- package/docs/paper/output/submission-bundle/benchmarks/output/guardbench-summary.json +354 -230
- package/docs/paper/output/submission-bundle/benchmarks/output/leaderboard/guardbench-leaderboard.json +5 -5
- package/docs/paper/output/submission-bundle/benchmarks/output/leaderboard/guardbench-leaderboard.md +2 -2
- package/docs/paper/output/submission-bundle/benchmarks/output/submission-bundle/submission-manifest.json +15 -15
- package/docs/paper/output/submission-bundle/benchmarks/output/submission-bundle/validation-report.json +1 -1
- package/docs/paper/output/submission-bundle/benchmarks/output/summary.json +52 -52
- package/docs/paper/output/submission-bundle/benchmarks/schemas/guardbench-raw.schema.json +21 -1
- package/docs/paper/output/submission-bundle/benchmarks/schemas/guardbench-summary.schema.json +23 -2
- package/docs/paper/output/submission-bundle/docs/paper/07-evaluation.md +5 -5
- package/docs/paper/output/submission-bundle/docs/paper/audrey-paper-v1.md +6 -6
- package/docs/paper/output/submission-bundle/docs/paper/evidence-ledger.md +1 -1
- package/docs/paper/output/submission-bundle/docs/paper/output/arxiv/arxiv-manifest.json +4 -4
- package/docs/paper/output/submission-bundle/docs/paper/output/arxiv/main.tex +6 -6
- package/docs/paper/output/submission-bundle/docs/paper/output/arxiv-compile-report.json +3 -3
- package/docs/paper/output/submission-bundle/package.json +18 -5
- package/docs/paper/output/submission-bundle/paper-submission-manifest.json +40 -40
- package/examples/fintech-ops-demo.js +12 -5
- package/examples/healthcare-ops-demo.js +8 -4
- package/examples/ollama-memory-agent.js +41 -13
- package/examples/stripe-demo.js +12 -5
- package/package.json +18 -5
- package/scripts/audit-release-completion.mjs +179 -101
- package/scripts/create-arxiv-source.mjs +20 -14
- package/scripts/create-paper-submission-bundle.mjs +6 -2
- package/scripts/finalize-release.mjs +111 -36
- package/scripts/prepare-release-cut.mjs +14 -6
- package/scripts/publish-release-bundle.mjs +62 -23
- package/scripts/publish-release-github-api.mjs +89 -24
- package/scripts/smoke-cli.js +26 -6
- package/scripts/sync-paper-artifacts.mjs +5 -1
- package/scripts/verify-arxiv-compile.mjs +52 -16
- package/scripts/verify-arxiv-source.mjs +45 -15
- package/scripts/verify-browser-launch-plan.mjs +28 -11
- package/scripts/verify-browser-launch-results.mjs +32 -14
- package/scripts/verify-paper-artifacts.mjs +539 -79
- package/scripts/verify-paper-claims.mjs +48 -20
- package/scripts/verify-paper-submission-bundle.mjs +22 -11
- package/scripts/verify-publication-pack.mjs +23 -9
- package/scripts/verify-release-readiness.mjs +250 -71
|
@@ -16,6 +16,7 @@ const ROOT = process.cwd();
|
|
|
16
16
|
const DEFAULT_TARGET_VERSION = '1.0.0';
|
|
17
17
|
const PYPI_CREDENTIAL_ENVS = ['TWINE_PASSWORD', 'PYPI_API_TOKEN', 'UV_PUBLISH_TOKEN'];
|
|
18
18
|
const NPM_REGISTRY = 'https://registry.npmjs.org/';
|
|
19
|
+
const PYPI_JSON_BASE = 'https://pypi.org/pypi';
|
|
19
20
|
|
|
20
21
|
function fromRoot(path) {
|
|
21
22
|
return resolve(ROOT, path);
|
|
@@ -35,13 +36,16 @@ function parseArgs(argv = process.argv.slice(2)) {
|
|
|
35
36
|
const args = {
|
|
36
37
|
targetVersion: DEFAULT_TARGET_VERSION,
|
|
37
38
|
allowPending: false,
|
|
39
|
+
checkPypiRegistry: true,
|
|
38
40
|
json: false,
|
|
39
41
|
};
|
|
40
42
|
|
|
41
43
|
for (let i = 0; i < argv.length; i++) {
|
|
42
44
|
const token = argv[i];
|
|
43
|
-
if ((token === '--target-version' || token === '--version') && argv[i + 1])
|
|
45
|
+
if ((token === '--target-version' || token === '--version') && argv[i + 1])
|
|
46
|
+
args.targetVersion = argv[++i];
|
|
44
47
|
else if (token === '--allow-pending') args.allowPending = true;
|
|
48
|
+
else if (token === '--skip-pypi-registry') args.checkPypiRegistry = false;
|
|
45
49
|
else if (token === '--json') args.json = true;
|
|
46
50
|
else if (token === '--help' || token === '-h') args.help = true;
|
|
47
51
|
else throw new Error(`Unknown argument: ${token}`);
|
|
@@ -56,6 +60,7 @@ function usage() {
|
|
|
56
60
|
Options:
|
|
57
61
|
--target-version <version> Target release version. Default: ${DEFAULT_TARGET_VERSION}.
|
|
58
62
|
--allow-pending Exit 0 when only publish/account/credential blockers remain.
|
|
63
|
+
--skip-pypi-registry Do not check whether the target PyPI version is already public.
|
|
59
64
|
--json Print the machine-readable readiness report.
|
|
60
65
|
`;
|
|
61
66
|
}
|
|
@@ -177,7 +182,10 @@ export function remoteBranchFreshnessStatus({ branch, upstream, upstreamSha }, r
|
|
|
177
182
|
const remoteRef = `refs/heads/${branch}`;
|
|
178
183
|
let result = run(['ls-remote', 'origin', remoteRef]);
|
|
179
184
|
const fallbackEvidence = [];
|
|
180
|
-
if (
|
|
185
|
+
if (
|
|
186
|
+
result.status !== 0 &&
|
|
187
|
+
/schannel|AcquireCredentialsHandle|SEC_E_NO_CREDENTIALS/i.test(commandSummary(result))
|
|
188
|
+
) {
|
|
181
189
|
const fallback = run(['-c', 'http.sslBackend=openssl', 'ls-remote', 'origin', remoteRef]);
|
|
182
190
|
if (fallback.status === 0) {
|
|
183
191
|
result = fallback;
|
|
@@ -187,11 +195,16 @@ export function remoteBranchFreshnessStatus({ branch, upstream, upstreamSha }, r
|
|
|
187
195
|
if (result.status !== 0) {
|
|
188
196
|
return {
|
|
189
197
|
evidence: ['remoteHead=unverified', ...fallbackEvidence],
|
|
190
|
-
blockers: [
|
|
198
|
+
blockers: [
|
|
199
|
+
`Verify live remote origin/${branch} before final release (${commandSummary(result)})`,
|
|
200
|
+
],
|
|
191
201
|
};
|
|
192
202
|
}
|
|
193
203
|
|
|
194
|
-
const remoteLine = result.stdout
|
|
204
|
+
const remoteLine = result.stdout
|
|
205
|
+
.trim()
|
|
206
|
+
.split(/\r?\n/)
|
|
207
|
+
.find(line => line.endsWith(remoteRef));
|
|
195
208
|
const remoteSha = remoteLine?.split(/\s+/)[0];
|
|
196
209
|
if (!remoteSha) {
|
|
197
210
|
return {
|
|
@@ -203,7 +216,9 @@ export function remoteBranchFreshnessStatus({ branch, upstream, upstreamSha }, r
|
|
|
203
216
|
const evidence = [...fallbackEvidence, `remoteHead=origin/${branch}:${shortSha(remoteSha)}`];
|
|
204
217
|
const blockers = [];
|
|
205
218
|
if (upstream && upstreamSha && upstreamSha !== remoteSha) {
|
|
206
|
-
blockers.push(
|
|
219
|
+
blockers.push(
|
|
220
|
+
`Fetch/reconcile origin/${branch}: local ${upstream} is ${shortSha(upstreamSha)} but live remote is ${shortSha(remoteSha)}`,
|
|
221
|
+
);
|
|
207
222
|
}
|
|
208
223
|
|
|
209
224
|
return { evidence, blockers };
|
|
@@ -214,8 +229,19 @@ function remoteReleaseRefs(branch, targetVersion, run = runGit) {
|
|
|
214
229
|
const tagRef = `refs/tags/v${targetVersion}`;
|
|
215
230
|
let result = run(['ls-remote', 'origin', branchRef, tagRef, `${tagRef}^{}`]);
|
|
216
231
|
const evidence = [];
|
|
217
|
-
if (
|
|
218
|
-
|
|
232
|
+
if (
|
|
233
|
+
result.status !== 0 &&
|
|
234
|
+
/schannel|AcquireCredentialsHandle|SEC_E_NO_CREDENTIALS/i.test(commandSummary(result))
|
|
235
|
+
) {
|
|
236
|
+
const fallback = run([
|
|
237
|
+
'-c',
|
|
238
|
+
'http.sslBackend=openssl',
|
|
239
|
+
'ls-remote',
|
|
240
|
+
'origin',
|
|
241
|
+
branchRef,
|
|
242
|
+
tagRef,
|
|
243
|
+
`${tagRef}^{}`,
|
|
244
|
+
]);
|
|
219
245
|
if (fallback.status === 0) {
|
|
220
246
|
result = fallback;
|
|
221
247
|
evidence.push('releaseRemoteTlsFallback=openssl');
|
|
@@ -249,7 +275,10 @@ function currentWorkingReleaseTree() {
|
|
|
249
275
|
};
|
|
250
276
|
|
|
251
277
|
try {
|
|
252
|
-
for (const args of [
|
|
278
|
+
for (const args of [
|
|
279
|
+
['read-tree', 'HEAD'],
|
|
280
|
+
['add', '--all'],
|
|
281
|
+
]) {
|
|
253
282
|
const result = runGit(args, { env, timeout: 120000 });
|
|
254
283
|
if (result.status !== 0) return { ok: false, error: commandSummary(result) };
|
|
255
284
|
}
|
|
@@ -288,7 +317,9 @@ function releaseSourceHandoffStatus(targetVersion, branch) {
|
|
|
288
317
|
} else {
|
|
289
318
|
evidence.push(`currentReleaseTree=${shortSha(currentTree.tree)}`);
|
|
290
319
|
if (report.tree && currentTree.tree !== report.tree) {
|
|
291
|
-
blockers.push(
|
|
320
|
+
blockers.push(
|
|
321
|
+
`Regenerate release artifacts: current release tree ${currentTree.tree} differs from source handoff tree ${report.tree}`,
|
|
322
|
+
);
|
|
292
323
|
}
|
|
293
324
|
}
|
|
294
325
|
|
|
@@ -300,10 +331,14 @@ function releaseSourceHandoffStatus(targetVersion, branch) {
|
|
|
300
331
|
evidence.push('sourceBundleVerify=passed');
|
|
301
332
|
const refs = parseBundleRefs(bundleVerify.stdout, targetVersion);
|
|
302
333
|
if (refs.branch !== report.commit) {
|
|
303
|
-
blockers.push(
|
|
334
|
+
blockers.push(
|
|
335
|
+
`Release source bundle master is ${refs.branch ?? 'missing'}, expected ${report.commit}`,
|
|
336
|
+
);
|
|
304
337
|
}
|
|
305
338
|
if (refs.tag !== report.tag) {
|
|
306
|
-
blockers.push(
|
|
339
|
+
blockers.push(
|
|
340
|
+
`Release source bundle tag is ${refs.tag ?? 'missing'}, expected ${report.tag}`,
|
|
341
|
+
);
|
|
307
342
|
}
|
|
308
343
|
}
|
|
309
344
|
|
|
@@ -316,13 +351,19 @@ function releaseSourceHandoffStatus(targetVersion, branch) {
|
|
|
316
351
|
evidence.push(`releaseRemoteMaster=${shortSha(remoteMaster)}`);
|
|
317
352
|
evidence.push(`releaseRemoteTag=${shortSha(remoteTagObject)}`);
|
|
318
353
|
if (report.commit && remoteMaster !== report.commit) {
|
|
319
|
-
blockers.push(
|
|
354
|
+
blockers.push(
|
|
355
|
+
`Publish source bundle commit ${report.commit} to origin/${branch} (remote is ${remoteMaster ?? 'missing'})`,
|
|
356
|
+
);
|
|
320
357
|
}
|
|
321
358
|
if (report.tag && remoteTagObject !== report.tag) {
|
|
322
|
-
blockers.push(
|
|
359
|
+
blockers.push(
|
|
360
|
+
`Publish source bundle tag object ${report.tag} to refs/tags/v${targetVersion} (remote is ${remoteTagObject ?? 'missing'})`,
|
|
361
|
+
);
|
|
323
362
|
}
|
|
324
363
|
if (remoteTagCommit && report.commit && remoteTagCommit !== report.commit) {
|
|
325
|
-
blockers.push(
|
|
364
|
+
blockers.push(
|
|
365
|
+
`Remote v${targetVersion} dereferences to ${remoteTagCommit}, not release commit ${report.commit}`,
|
|
366
|
+
);
|
|
326
367
|
}
|
|
327
368
|
|
|
328
369
|
const stalePrefixes = [
|
|
@@ -360,18 +401,19 @@ function versionChecks(targetVersion) {
|
|
|
360
401
|
const evidence = values.map(([name, value]) => `${name}=${value ?? 'missing'}`);
|
|
361
402
|
|
|
362
403
|
if (values.some(([, value]) => !value)) {
|
|
363
|
-
return failed('version-surfaces', 'Version surfaces are present', evidence, [
|
|
404
|
+
return failed('version-surfaces', 'Version surfaces are present', evidence, [
|
|
405
|
+
'One or more version surfaces are missing',
|
|
406
|
+
]);
|
|
364
407
|
}
|
|
365
408
|
if (uniqueVersions.size !== 1) {
|
|
366
|
-
return failed('version-surfaces', 'Version surfaces are aligned', evidence, [
|
|
409
|
+
return failed('version-surfaces', 'Version surfaces are aligned', evidence, [
|
|
410
|
+
'package.json, package-lock.json, and Python version are not aligned',
|
|
411
|
+
]);
|
|
367
412
|
}
|
|
368
413
|
if (!uniqueVersions.has(targetVersion)) {
|
|
369
|
-
return pending(
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
evidence,
|
|
373
|
-
[`Local version is ${versions.packageJson}; bump all release surfaces to ${targetVersion} only when 1.0 publish is being cut`],
|
|
374
|
-
);
|
|
414
|
+
return pending('target-version', `Target release version is ${targetVersion}`, evidence, [
|
|
415
|
+
`Local version is ${versions.packageJson}; bump all release surfaces to ${targetVersion} only when 1.0 publish is being cut`,
|
|
416
|
+
]);
|
|
375
417
|
}
|
|
376
418
|
return ok('target-version', `Target release version is ${targetVersion}`, evidence);
|
|
377
419
|
}
|
|
@@ -379,7 +421,8 @@ function versionChecks(targetVersion) {
|
|
|
379
421
|
function sourceControlCheck(targetVersion) {
|
|
380
422
|
const status = runGit(['status', '--short', '--branch', '--untracked-files=all']);
|
|
381
423
|
if (status.status !== 0) {
|
|
382
|
-
const detail =
|
|
424
|
+
const detail =
|
|
425
|
+
status.stderr.trim() || status.stdout.trim() || `git status exited ${status.status}`;
|
|
383
426
|
return failed('source-control', 'Source control is ready for release', [], [detail]);
|
|
384
427
|
}
|
|
385
428
|
|
|
@@ -393,10 +436,16 @@ function sourceControlCheck(targetVersion) {
|
|
|
393
436
|
const originPush = gitOutput(['remote', 'get-url', '--push', 'origin']);
|
|
394
437
|
const tagName = `v${targetVersion}`;
|
|
395
438
|
const tagExists = Boolean(gitOutput(['tag', '--list', tagName]));
|
|
396
|
-
const tagsAtHead = (gitOutput(['tag', '--points-at', 'HEAD']) ?? '')
|
|
439
|
+
const tagsAtHead = (gitOutput(['tag', '--points-at', 'HEAD']) ?? '')
|
|
440
|
+
.split(/\r?\n/)
|
|
441
|
+
.filter(Boolean);
|
|
397
442
|
const metadataWritable = gitMetadataWritableCheck();
|
|
398
|
-
const remoteFreshness = originPush
|
|
399
|
-
|
|
443
|
+
const remoteFreshness = originPush
|
|
444
|
+
? remoteBranchFreshnessStatus({ branch, upstream, upstreamSha })
|
|
445
|
+
: { evidence: [], blockers: [] };
|
|
446
|
+
const sourceHandoff = originPush
|
|
447
|
+
? releaseSourceHandoffStatus(targetVersion, branch)
|
|
448
|
+
: { usable: false, evidence: [], blockers: [] };
|
|
400
449
|
const evidence = [
|
|
401
450
|
`branch=${branch}`,
|
|
402
451
|
`head=${head}`,
|
|
@@ -415,7 +464,8 @@ function sourceControlCheck(targetVersion) {
|
|
|
415
464
|
blockers.push(...sourceHandoff.blockers);
|
|
416
465
|
evidence.push('sourceControlLane=external-source-bundle');
|
|
417
466
|
} else {
|
|
418
|
-
if (!metadataWritable.writable && metadataWritable.blocker)
|
|
467
|
+
if (!metadataWritable.writable && metadataWritable.blocker)
|
|
468
|
+
blockers.push(metadataWritable.blocker);
|
|
419
469
|
blockers.push(...remoteFreshness.blockers, ...sourceHandoff.blockers);
|
|
420
470
|
if (!upstream) blockers.push('Configure an upstream branch before final release');
|
|
421
471
|
if (upstream) {
|
|
@@ -424,18 +474,26 @@ function sourceControlCheck(targetVersion) {
|
|
|
424
474
|
const [ahead, behind] = counts.split(/\s+/).map(Number);
|
|
425
475
|
evidence.push(`ahead=${ahead}`, `behind=${behind}`);
|
|
426
476
|
if (ahead > 0) blockers.push(`Push ${ahead} release commit(s) to ${upstream}`);
|
|
427
|
-
if (behind > 0)
|
|
477
|
+
if (behind > 0)
|
|
478
|
+
blockers.push(`Pull or reconcile ${behind} upstream commit(s) before final release`);
|
|
428
479
|
}
|
|
429
480
|
}
|
|
430
|
-
if (changedLines.length > 0)
|
|
481
|
+
if (changedLines.length > 0)
|
|
482
|
+
blockers.push(
|
|
483
|
+
`Commit or stash ${changedLines.length} working-tree change(s) before final release`,
|
|
484
|
+
);
|
|
431
485
|
if (!tagExists) blockers.push(`Create release tag ${tagName} on the final release commit`);
|
|
432
|
-
if (tagExists && !tagsAtHead.includes(tagName))
|
|
486
|
+
if (tagExists && !tagsAtHead.includes(tagName))
|
|
487
|
+
blockers.push(`Move or recreate ${tagName} so it points at the final release commit`);
|
|
433
488
|
}
|
|
434
489
|
|
|
435
490
|
if (blockers.length > 0) {
|
|
436
491
|
return pending('source-control', 'Source control is ready for release', evidence, blockers);
|
|
437
492
|
}
|
|
438
|
-
return ok('source-control', 'Source control is ready for release', [
|
|
493
|
+
return ok('source-control', 'Source control is ready for release', [
|
|
494
|
+
...evidence,
|
|
495
|
+
`${tagName} points at HEAD`,
|
|
496
|
+
]);
|
|
439
497
|
}
|
|
440
498
|
|
|
441
499
|
function escapeRegex(value) {
|
|
@@ -452,7 +510,8 @@ export function targetChangelogStatus(changelog, targetVersion) {
|
|
|
452
510
|
const section = nextSection === -1 ? rest : rest.slice(0, nextSection);
|
|
453
511
|
const placeholderMarkers = [];
|
|
454
512
|
if (/\bTODO\b/i.test(section)) placeholderMarkers.push('TODO marker');
|
|
455
|
-
if (/Release Cut Checklist/i.test(section))
|
|
513
|
+
if (/Release Cut Checklist/i.test(section))
|
|
514
|
+
placeholderMarkers.push('release-cut checklist scaffold');
|
|
456
515
|
|
|
457
516
|
return { found: true, placeholderMarkers };
|
|
458
517
|
}
|
|
@@ -461,14 +520,18 @@ function changelogCheck(targetVersion) {
|
|
|
461
520
|
const changelog = readText('CHANGELOG.md');
|
|
462
521
|
const status = targetChangelogStatus(changelog, targetVersion);
|
|
463
522
|
if (status.found && status.placeholderMarkers.length === 0) {
|
|
464
|
-
return ok('changelog-target', `CHANGELOG has a final ${targetVersion} section`, [
|
|
523
|
+
return ok('changelog-target', `CHANGELOG has a final ${targetVersion} section`, [
|
|
524
|
+
'CHANGELOG.md',
|
|
525
|
+
]);
|
|
465
526
|
}
|
|
466
527
|
if (status.found) {
|
|
467
528
|
return failed(
|
|
468
529
|
'changelog-target',
|
|
469
530
|
`CHANGELOG has a final ${targetVersion} section`,
|
|
470
531
|
['CHANGELOG.md'],
|
|
471
|
-
[
|
|
532
|
+
[
|
|
533
|
+
`Replace placeholder ${targetVersion} changelog scaffold before strict readiness: ${status.placeholderMarkers.join(', ')}`,
|
|
534
|
+
],
|
|
472
535
|
);
|
|
473
536
|
}
|
|
474
537
|
return pending(
|
|
@@ -483,15 +546,31 @@ function pythonDistCheck(targetVersion) {
|
|
|
483
546
|
const wheel = `python/dist/audrey_memory-${targetVersion}-py3-none-any.whl`;
|
|
484
547
|
const sdist = `python/dist/audrey_memory-${targetVersion}.tar.gz`;
|
|
485
548
|
if (existsSync(fromRoot(wheel)) && existsSync(fromRoot(sdist))) {
|
|
486
|
-
const verification = spawnSync(
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
549
|
+
const verification = spawnSync(
|
|
550
|
+
'python',
|
|
551
|
+
['scripts/verify-python-package.py', '--version', targetVersion, '--json'],
|
|
552
|
+
{
|
|
553
|
+
cwd: ROOT,
|
|
554
|
+
encoding: 'utf-8',
|
|
555
|
+
},
|
|
556
|
+
);
|
|
490
557
|
if (verification.status !== 0) {
|
|
491
|
-
const detail =
|
|
492
|
-
|
|
558
|
+
const detail =
|
|
559
|
+
verification.stderr.trim() ||
|
|
560
|
+
verification.stdout.trim() ||
|
|
561
|
+
`python verifier exited ${verification.status}`;
|
|
562
|
+
return failed(
|
|
563
|
+
'python-dist',
|
|
564
|
+
`Python ${targetVersion} artifacts verify`,
|
|
565
|
+
[wheel, sdist],
|
|
566
|
+
[detail],
|
|
567
|
+
);
|
|
493
568
|
}
|
|
494
|
-
return ok('python-dist', `Python ${targetVersion} artifacts verify`, [
|
|
569
|
+
return ok('python-dist', `Python ${targetVersion} artifacts verify`, [
|
|
570
|
+
wheel,
|
|
571
|
+
sdist,
|
|
572
|
+
'python package verifier passed',
|
|
573
|
+
]);
|
|
495
574
|
}
|
|
496
575
|
return pending(
|
|
497
576
|
'python-dist',
|
|
@@ -501,10 +580,33 @@ function pythonDistCheck(targetVersion) {
|
|
|
501
580
|
);
|
|
502
581
|
}
|
|
503
582
|
|
|
504
|
-
function
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
583
|
+
async function pypiRegistryVersionStatus(packageName, targetVersion, fetchImpl = fetch) {
|
|
584
|
+
try {
|
|
585
|
+
const response = await fetchImpl(
|
|
586
|
+
`${PYPI_JSON_BASE}/${encodeURIComponent(packageName)}/${encodeURIComponent(targetVersion)}/json`,
|
|
587
|
+
{
|
|
588
|
+
headers: { accept: 'application/json' },
|
|
589
|
+
},
|
|
590
|
+
);
|
|
591
|
+
if (response.ok) return { ok: true, published: true, status: response.status };
|
|
592
|
+
if (response.status === 404) return { ok: true, published: false, status: response.status };
|
|
593
|
+
return {
|
|
594
|
+
ok: false,
|
|
595
|
+
published: false,
|
|
596
|
+
status: response.status,
|
|
597
|
+
error: `PyPI returned HTTP ${response.status}`,
|
|
598
|
+
};
|
|
599
|
+
} catch (error) {
|
|
600
|
+
return { ok: false, published: false, status: 'network-error', error: error.message };
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export async function pypiPackageTargetStatus(
|
|
605
|
+
{ packageName, version },
|
|
606
|
+
targetVersion,
|
|
607
|
+
options = {},
|
|
608
|
+
) {
|
|
609
|
+
const env = options.env ?? process.env;
|
|
508
610
|
const evidence = [`python package=${packageName}`, `python version=${version ?? 'missing'}`];
|
|
509
611
|
|
|
510
612
|
if (version !== targetVersion) {
|
|
@@ -516,17 +618,51 @@ function pypiPublishCheck(targetVersion) {
|
|
|
516
618
|
);
|
|
517
619
|
}
|
|
518
620
|
|
|
519
|
-
|
|
621
|
+
if (options.checkRegistry === true) {
|
|
622
|
+
const registry = await pypiRegistryVersionStatus(packageName, targetVersion, options.fetchImpl);
|
|
623
|
+
if (registry.ok && registry.published) {
|
|
624
|
+
return ok('pypi-package-target', `PyPI package is already published as ${targetVersion}`, [
|
|
625
|
+
...evidence,
|
|
626
|
+
`registry=${packageName}==${targetVersion}`,
|
|
627
|
+
]);
|
|
628
|
+
}
|
|
629
|
+
if (!registry.ok) {
|
|
630
|
+
return pending(
|
|
631
|
+
'pypi-package-target',
|
|
632
|
+
`PyPI package is ready to publish as ${targetVersion}`,
|
|
633
|
+
evidence,
|
|
634
|
+
[
|
|
635
|
+
`Verify PyPI registry availability before publishing (${registry.error ?? `status=${registry.status}`})`,
|
|
636
|
+
],
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
evidence.push(`registry=${packageName}==${targetVersion}:unpublished`);
|
|
641
|
+
}
|
|
642
|
+
const credentialEnv = PYPI_CREDENTIAL_ENVS.find(name => Boolean(env[name]));
|
|
520
643
|
if (!credentialEnv) {
|
|
521
644
|
return pending(
|
|
522
645
|
'pypi-package-target',
|
|
523
646
|
`PyPI package is ready to publish as ${targetVersion}`,
|
|
524
647
|
evidence,
|
|
525
|
-
[
|
|
648
|
+
[
|
|
649
|
+
`Provide runtime PyPI publish credentials (${PYPI_CREDENTIAL_ENVS.join(', ')}) or trusted-publisher evidence before publishing`,
|
|
650
|
+
],
|
|
526
651
|
);
|
|
527
652
|
}
|
|
528
653
|
|
|
529
|
-
return ok('pypi-package-target', `PyPI package is ready to publish as ${targetVersion}`, [
|
|
654
|
+
return ok('pypi-package-target', `PyPI package is ready to publish as ${targetVersion}`, [
|
|
655
|
+
...evidence,
|
|
656
|
+
`credentialEnv=${credentialEnv}`,
|
|
657
|
+
]);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
async function pypiPublishCheck(targetVersion, options = {}) {
|
|
661
|
+
const pyproject = readText('python/pyproject.toml');
|
|
662
|
+
const packageName = pyproject.match(/^name\s*=\s*"([^"]+)"/m)?.[1] ?? 'unknown';
|
|
663
|
+
return pypiPackageTargetStatus({ packageName, version: pythonVersion() }, targetVersion, {
|
|
664
|
+
checkRegistry: options.checkPypiRegistry === true,
|
|
665
|
+
});
|
|
530
666
|
}
|
|
531
667
|
|
|
532
668
|
async function paperChecks() {
|
|
@@ -547,14 +683,19 @@ async function paperChecks() {
|
|
|
547
683
|
];
|
|
548
684
|
|
|
549
685
|
if (failures.length > 0) {
|
|
550
|
-
return failed(
|
|
551
|
-
'paper
|
|
552
|
-
'
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
686
|
+
return failed(
|
|
687
|
+
'paper-artifacts',
|
|
688
|
+
'Paper artifacts verify locally',
|
|
689
|
+
[
|
|
690
|
+
'paper:claims',
|
|
691
|
+
'paper:publication-pack',
|
|
692
|
+
'paper:arxiv:verify',
|
|
693
|
+
'paper:launch-plan',
|
|
694
|
+
'paper:launch-results',
|
|
695
|
+
'paper:bundle:verify',
|
|
696
|
+
],
|
|
697
|
+
failures,
|
|
698
|
+
);
|
|
558
699
|
}
|
|
559
700
|
return ok('paper-artifacts', 'Paper artifacts verify locally', [
|
|
560
701
|
`${claimReport.claims.length} claim(s)`,
|
|
@@ -569,17 +710,28 @@ async function paperChecks() {
|
|
|
569
710
|
async function browserPublicationCheck() {
|
|
570
711
|
const report = await verifyBrowserLaunchResults();
|
|
571
712
|
if (!report.ok) {
|
|
572
|
-
return failed(
|
|
713
|
+
return failed(
|
|
714
|
+
'browser-publication',
|
|
715
|
+
'Browser publication results are valid',
|
|
716
|
+
[report.results],
|
|
717
|
+
report.failures,
|
|
718
|
+
);
|
|
573
719
|
}
|
|
574
720
|
if (!report.ready) {
|
|
575
721
|
return pending(
|
|
576
722
|
'browser-publication',
|
|
577
723
|
'Paper/browser launch targets are submitted',
|
|
578
|
-
[
|
|
724
|
+
[
|
|
725
|
+
`${report.targets.filter(target => target.status === 'submitted').length}/${report.targets.length} submitted`,
|
|
726
|
+
],
|
|
579
727
|
report.blockers,
|
|
580
728
|
);
|
|
581
729
|
}
|
|
582
|
-
return ok(
|
|
730
|
+
return ok(
|
|
731
|
+
'browser-publication',
|
|
732
|
+
'Paper/browser launch targets are submitted',
|
|
733
|
+
report.targets.map(target => `${target.id}: ${target.publicUrl}`),
|
|
734
|
+
);
|
|
583
735
|
}
|
|
584
736
|
|
|
585
737
|
function arxivCompileCheck() {
|
|
@@ -601,7 +753,12 @@ function arxivCompileCheck() {
|
|
|
601
753
|
async function externalEvidenceCheck() {
|
|
602
754
|
const report = await verifyExternalGuardBenchEvidence({ allowPending: true, write: false });
|
|
603
755
|
if (!report.ok) {
|
|
604
|
-
return failed(
|
|
756
|
+
return failed(
|
|
757
|
+
'external-evidence',
|
|
758
|
+
'External GuardBench evidence verifies',
|
|
759
|
+
[report.outRoot],
|
|
760
|
+
report.failures,
|
|
761
|
+
);
|
|
605
762
|
}
|
|
606
763
|
const pendingRows = report.adapters.filter(adapter => adapter.status !== 'verified');
|
|
607
764
|
if (pendingRows.length > 0) {
|
|
@@ -609,10 +766,17 @@ async function externalEvidenceCheck() {
|
|
|
609
766
|
'external-evidence',
|
|
610
767
|
'External Mem0/Zep GuardBench evidence is live-verified',
|
|
611
768
|
report.adapters.map(adapter => `${adapter.id}: ${adapter.status}/${adapter.evidenceKind}`),
|
|
612
|
-
pendingRows.map(
|
|
769
|
+
pendingRows.map(
|
|
770
|
+
adapter =>
|
|
771
|
+
`${adapter.id}: ${adapter.missingEnv?.length ? `missing ${adapter.missingEnv.join(', ')}` : adapter.evidenceKind}`,
|
|
772
|
+
),
|
|
613
773
|
);
|
|
614
774
|
}
|
|
615
|
-
return ok(
|
|
775
|
+
return ok(
|
|
776
|
+
'external-evidence',
|
|
777
|
+
'External Mem0/Zep GuardBench evidence is live-verified',
|
|
778
|
+
report.adapters.map(adapter => `${adapter.id}: verified`),
|
|
779
|
+
);
|
|
616
780
|
}
|
|
617
781
|
|
|
618
782
|
function npmVersionMissing(result) {
|
|
@@ -626,7 +790,9 @@ export function npmPackageTargetStatus(pkg, targetVersion, run = runNpm) {
|
|
|
626
790
|
'npm-package-target',
|
|
627
791
|
`npm package is ready to publish as ${targetVersion}`,
|
|
628
792
|
[`package.json version=${pkg.version}`],
|
|
629
|
-
[
|
|
793
|
+
[
|
|
794
|
+
`Cut the npm package only after version is bumped to ${targetVersion} and npm OTP/auth is available`,
|
|
795
|
+
],
|
|
630
796
|
);
|
|
631
797
|
}
|
|
632
798
|
|
|
@@ -641,9 +807,14 @@ export function npmPackageTargetStatus(pkg, targetVersion, run = runNpm) {
|
|
|
641
807
|
`registry=${packageSpec}`,
|
|
642
808
|
]);
|
|
643
809
|
}
|
|
644
|
-
return failed(
|
|
645
|
-
|
|
646
|
-
|
|
810
|
+
return failed(
|
|
811
|
+
'npm-package-target',
|
|
812
|
+
`npm package registry state is coherent for ${targetVersion}`,
|
|
813
|
+
evidence,
|
|
814
|
+
[
|
|
815
|
+
`npm registry returned unexpected version for ${packageSpec}: ${registryVersion || 'empty'}`,
|
|
816
|
+
],
|
|
817
|
+
);
|
|
647
818
|
}
|
|
648
819
|
|
|
649
820
|
if (!npmVersionMissing(registryStatus)) {
|
|
@@ -662,7 +833,9 @@ export function npmPackageTargetStatus(pkg, targetVersion, run = runNpm) {
|
|
|
662
833
|
'npm-package-target',
|
|
663
834
|
`npm package is ready to publish as ${targetVersion}`,
|
|
664
835
|
evidence,
|
|
665
|
-
[
|
|
836
|
+
[
|
|
837
|
+
`Authenticate npm CLI for ${NPM_REGISTRY} before publishing (${commandSummary(authStatus)})`,
|
|
838
|
+
],
|
|
666
839
|
);
|
|
667
840
|
}
|
|
668
841
|
|
|
@@ -688,12 +861,13 @@ export async function verifyReleaseReadiness(options = {}) {
|
|
|
688
861
|
await browserPublicationCheck(),
|
|
689
862
|
await externalEvidenceCheck(),
|
|
690
863
|
packageDryRunCheck(targetVersion),
|
|
691
|
-
pypiPublishCheck(targetVersion),
|
|
864
|
+
await pypiPublishCheck(targetVersion, options),
|
|
692
865
|
];
|
|
693
866
|
const failures = checks.flatMap(row => row.failures.map(failure => `${row.id}: ${failure}`));
|
|
694
867
|
const blockers = checks.flatMap(row => row.blockers.map(blocker => `${row.id}: ${blocker}`));
|
|
695
868
|
const ready = failures.length === 0 && blockers.length === 0;
|
|
696
|
-
const okStatus =
|
|
869
|
+
const okStatus =
|
|
870
|
+
failures.length === 0 && (options.allowPending === true || blockers.length === 0);
|
|
697
871
|
|
|
698
872
|
return {
|
|
699
873
|
schemaVersion: '1.0.0',
|
|
@@ -722,7 +896,9 @@ async function main() {
|
|
|
722
896
|
} else if (report.ready) {
|
|
723
897
|
console.log(`Audrey ${report.targetVersion} release readiness passed.`);
|
|
724
898
|
} else if (report.ok) {
|
|
725
|
-
console.log(
|
|
899
|
+
console.log(
|
|
900
|
+
`Audrey ${report.targetVersion} release readiness has ${report.blockers.length} pending blocker(s).`,
|
|
901
|
+
);
|
|
726
902
|
for (const blocker of report.blockers) console.log(`- ${blocker}`);
|
|
727
903
|
} else {
|
|
728
904
|
console.error(`Audrey ${report.targetVersion} release readiness failed.`);
|
|
@@ -733,7 +909,10 @@ async function main() {
|
|
|
733
909
|
if (!report.ok) process.exit(1);
|
|
734
910
|
}
|
|
735
911
|
|
|
736
|
-
if (
|
|
912
|
+
if (
|
|
913
|
+
process.argv[1] &&
|
|
914
|
+
resolve(process.argv[1]).toLowerCase() === fileURLToPath(import.meta.url).toLowerCase()
|
|
915
|
+
) {
|
|
737
916
|
main().catch(error => {
|
|
738
917
|
console.error(error.stack ?? error.message);
|
|
739
918
|
process.exit(1);
|