Skip to content

Release v0.23.0 - #699

Merged
samrusani merged 6 commits into
mainfrom
release/v0.23.0
Oct 30, 2026
Merged

samrusani merged 6 commits into
mainfrom
release/v0.23.0

Conversation

@samrusani

@samrusani samrusani commented Oct 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

Release prep for v0.23.0, a minor release on v0.22.0. It moves every version site to 0.23.0, dates the seven changelog entries that sit under Unreleased, adds the notes in their pending state and records the release candidate in the control documents. v0.22.0 stays the latest published release, and nothing here tags, publishes or dispatches anything.

What v0.23.0 contains (git log --first-parent v0.22.0..origin/main, merged at 739507ed):

25 files under apps/api/src differ from v0.22.0 (all modified, none added) and 13 under apps/api/alembic. No tool is added (default 3, full 12, legacy 74 and 77), no setting is added (no new ALICE_ name anywhere under apps/api/src), the only new command is alice-memory keys with create, list and revoke, and no migration is added: the head is 20261011_0097 as in v0.22.0. Thirteen migration files changed in place.

What moved

  • Version 0.23.0 at the six sites scripts/release_check.py requires: pyproject.toml, apps/web/package.json, packaging/mcpb/manifest.json, plugins/alice-memory/.claude-plugin/plugin.json, and the two command pins in plugins/alice-memory/.mcp.json and plugins/alice-memory/hooks/hooks.json. Every other 0.22.0 stays, because it names the latest published release, the baseline, the checksums or the marketplace pin (ref v0.22.0, commit a6a5f49e).
  • CHANGELOG. The seven Unreleased (on main, not in v0.22.0): entries lose the prefix (the first word is capitalised) and move under the dated v0.23.0 heading (2026-10-30, in the form release_check.py requires), with an empty ## Unreleased above it. Three wording edits beyond the prefix: the keys entry called an event by a word the repository keeps out of its text and now says "the revocation event"; the malformed id entry named a legacy tool whose name carries that word and now says "the legacy tool that returns a memory's history"; and a sentence break in the malformed id entry ("error. and the write actions") is now a comma. The import entry is as merged, including its measurement conditions.
  • Markers converted, every one. A grep over the whole tree (every file type, three spellings: Unreleased (on main, not in v0.22.0), On main, not in v0.22.0, not in v0.22.0) finds only CHANGELOG.md: the seven entries at lines 5 to 11 of main, listed here by their first words: "the SQLite vault gets agent keys", "the MCP tool alice_recall returns ten", "a vNext door that reads a row id", "POST /v0/vnext/open-loops/extract", "POST /v0/vnext/context-packs and the MCP tool", "the Alembic migrations 20260510_0067", "alice-memory import-markdown on a SQLite vault". No document carried the form without the word Unreleased this time, so none moved to a "From v0.23.0" wording.
  • Notes. docs/release/v0.23.0-release-notes.md, 14.6 KB, state pending and pending, no checksums file. Sections: What to do after upgrading, Agent keys on the SQLite vault, Server errors that are now answers, Migrations for the self-hosted database owner, Recall and import on SQLite, Other changes in the package, Behaviour changes an integrator will notice, Security, What this release does not claim, Install.
    • The keys section carries the sentence "keys tell Alice which agent is asking and limit what Alice returns to it; they do not stop a process that runs as your OS user from reading the vault file." once, and the notes use none of the words isolation, boundary, tenant, sandbox or vulnerability.
    • Security keeps the two sentences of the last notes, says the keyless refusal is a change of behaviour and that no advisory is planned, and gives the reason (v0.22.0 had no command that mints a key on the SQLite vault). See the claim check: no door of v0.22.0 minted one.
    • The vectors sentence of the v0.22.0 notes ("No measurement of them is published") is not repeated, because the results pages of Name the run commit and the measured speed before the passage vectors answers #690 to Add the Claude results of the passage vectors comparison #692 are on main now. The last section summarises their "Both families" section and links it.
  • Control documents. README, ARCHITECTURE, PRODUCT_BRIEF, ROADMAP, RELEASING and docs/vnext/README.md gain "v0.23.0 is the current release candidate. It is not published." and keep v0.22.0 as the latest published release. CURRENT_STATE.md gets a "What v0.23.0 Targets" section above "What v0.22.0 Shipped".
  • docs/alpha/known-limitations.md is unchanged, as it was in the v0.22.0 release PR (its header says v0.22.0, which is right until the post-publication change).

Tests

  • New tests/unit/test_v0230_release_notes.py, 29 tests, modelled on the v0.22.0 notes test at the release PR. It imports nothing that CI's environment lacks (no setuptools; the package walk is written out, and the file passes with setuptools, pkg_resources and wheel hidden), and it starts the hook with python -m, because a test file that imports a host module has to be listed in the real-host workflow's path filter (unit shard 1 failed on that in the first run; the second commit fixes it). Each test names its mutations in its docstring. Guards:
    • identity, pending state, size ceiling and section order; the six version sites and the marketplace pin; the candidate lines and the Targets section; the dated heading and the empty Unreleased section; no marker left;
    • the dash and security wording, no advisory identifier and one "no advisory is planned" sentence; the exact keys sentence and the words kept out of the notes;
    • the eight upgrade steps in order; the limits section; the published comparison page says what the notes take from it;
    • the numbers that drift (tool counts 3, 12, 74 and 77 from the code; the head 20261011_0097; the budget 10 and the limit 8; the import numbers equal in the changelog entry and the notes; no hardware in the notes);
    • the thirteen changed migration files, byte for byte against the tag export (nothing added, nothing else changed, each gained NO FORCE ROW LEVEL SECURITY); the settings (no new ALICE_ name) and the flags of every command (only keys and its three sub-commands, flag by flag); install writes the same environment values; the package holds nothing from scripts/ or apps/web;
    • run, against this tree and the v0.22.0 export: keys create, list, revoke and their refusals; the keyless refusal (core and legacy tools, revoked keys, a bad key, an unreadable key table); the brief and the hook; the commands you run yourself; the export and the file copy; the known difference; ten note passages; the memory id spellings on SQLite;
    • the eight PostgreSQL integration files exist and the notes' sentences about them; each headline change has its changelog entry; the release check accepts the tree.
  • The seven older tests that index the changelog by position move down one section (test_v0200_release_notes.py, test_v0202_release_notes.py, test_v0210_release_notes.py, test_v0211_release_notes.py, test_data_dir_guard.py, test_mcp_readonly_hints.py, test_claude_code_plugin.py), and test_v0220_release_notes.py moves its heading test and no longer reads the version sites, which belong to the new test (its version test is renamed test_the_marketplace_pins_the_published_release_and_the_notes_carry_its_install_lines, and its release check test runs the pre-tag rule for 0.22.0 explicitly), as Release v0.22.0 #681 did for v0.21.1.
  • Mutations: 80, every one fails the test it names (clone of the head be9b0f33, an exact single-match replace or a created or deleted file, the named test green first, the file written back from saved bytes). 74 on test_v0230_release_notes.py (one of them fails two tests), and 6 on the edited older tests: three changelog shape mutations (the v0.23.0 heading redated, the v0.22.0 heading renamed, a section inserted between them), each failing all 8 position tests, and three on the edited v0.22.0 tests (marketplace ref back to v0.21.1, the install line in its notes, its status set to pending). The 74 cover: title, state, checksums file, section list; plugin pin, package version, marketplace ref and sha, the install line; a candidate line gone from ROADMAP and README, v0.23.0 named latest published, the Targets section renamed; an entry under Unreleased, the heading redated, the old marker in an entry and in a doc; a dash, the disclosure verb, the review clause, an advisory identifier; the keys sentence reworded twice, a tenant word, the refusal called a fix; an upgrade step renamed, the hook environment clause, a limits clause, the known-difference sentence; two numbers of the notes, a hardware word, the budget, the limit, a tool added to the default surface, a migration file added, an unlisted migration changed, NO FORCE taken out of 0067, a revision renamed; a new ALICE_ name, a flag added to keys list, keys revoke renamed, scripts added to the packages and to MANIFEST.in, an install key reference; the raw key printed twice, a hash in the list record, the not-shown-again line dropped, --project binding nothing, the reserved name, a blank project and a blank agent id allowed; the keyless call let through, revoked keys counted, a legacy tool let through, an unreadable key table let through, the brief and the hook without a key (three), import-chatgpt asking for a key, a hash in the creation event, an archived source let through to a key; the budget back to 8, an explicit limit ignored, the budget in document mode, alice_explain reading the id as sent; the integration file deleted, a sentence of the errors section, the comparison page, the comparison link; four changelog entry mutations; a published status.
  • scripts/derived_label_mutations.json: line and sha256 refreshed on the 45 edits that name CHANGELOG.md (43) and CURRENT_STATE.md (2); no before text failed to resolve. All 45 cases were replayed with scripts/verify_derived_label_mutations.py --only NAME --output DIR against head be9b0f33 (45 names, 45 results): 45 of 45 killed by the test they name, baseline exit 0 and mutant exit 1 for each. test_derived_label_mutation_manifest_matches_tree.py passes.

Claim checks

Every sentence of the notes that states a behaviour was run against this branch and against an export of the v0.22.0 tag (git archive v0.22.0), each with its own PYTHONPATH, through the real entry points: alice-memory commands, alice-memory mcp over stdio (JSON-RPC tools/call), the session-start hook with echo '{}' on stdin and a timeout, and, for the PostgreSQL doors, the mounted ASGI application against the local PostgreSQL 16 (a fresh database per test). No other host was contacted. Verdicts below are v0.22.0 then this branch.

Sentence of the notes Check v0.22.0 This branch
keys create prints the raw key once keys create --agent-id claude-code --profile admin_agent --label "Claude Code host" on a fresh vault exit 2, invalid_request, no output exit 0; line 1 the key (alice_sk_...), line 2 "Store this key now; it is not shown again, and only its sha256 hash is stored.", line 3 agent, profile, label
--project binds; same refusals as the PostgreSQL command --project acme; ~global; blank; blank agent id; profile nonsense exit 2 key bound (project=acme); the other four exit 2 with "the project name ~global is reserved by Alice ...", "project_scope must not be blank", "agent_id is required", and the generic invalid request for the profile (argparse choices)
keys list shows no hash and no raw key list, human and --json, grep for the key and its sha256 exit 2 2 lines, then none of either in 2 outputs; 10 fields (agent_id, created_at, id, key_prefix, label, last_used_at, permission_profile, project_scope, revoked, revoked_at); the stored hash equals the sha256 of the key
keys revoke one of two keys, then the last; again; a name that matches none exit 2 "Revoked alice_sk_... (openclaw); its next call is refused."; a revoked key presented is refused; already revoked and no match exit 2 with their messages
A vault with an active key refuses a keyless MCP call alice_recall and alice_capture (full tools) with no ALICE_AGENT_API_KEY, a key minted recall and capture answered (a key minted with the tag's own create_agent_key) not_permitted, "The tool request could not be processed", for both
... the legacy tools too a legacy tool with ALICE_MCP_LEGACY_TOOLS=1 and ALICE_MCP_FULL_TOOLS=1 read as the owner (not_found for an unknown id) not_permitted; the repository test uses alice_open_loop_extract and alice_graph_neighborhood, which resolve no identity of their own
A bad or revoked key answers as before; only active keys count bad key; revoked key; one of two revoked not_permitted for a bad key the same not_permitted; revoking the last active key makes a keyless call answer again
If the count of keys cannot be read, the call is refused rename the revoked_at column of the key table, call keyless not_permitted
The brief prints nothing without the key alice-memory brief on the keyed vault, no key 528 bytes, exit 0 0 bytes, exit 0; with the admin key 528 bytes; with a bad key 0 bytes
The hook prints nothing without the key alice-memory-session-start, {} on stdin, JSON and markdown 1,187 and 528 bytes, exit 0 0 and 0 bytes, exit 0; with the key 1,187 bytes; with a bad key 0
A vault with no key prints the brief after the last revoke brief 639 bytes, hook 1,403 bytes (same rule as before keys)
The commands you run yourself take no key doctor, export, sleep, sleep-proposals, import-markdown, import-chatgpt, import, keys list on the keyed vault, no key exit 0 exit 0 each
The export drops keys; mint again after an import export of the keyed vault; import it; list; keyless recall no key record, no hash, no raw key in 39 lines; the two creation events (prefix, agent id, profile) are in it and make no key; after the import "No agent keys on this vault." and a keyless recall is answered
A file copy after a checkpoint keeps keys PRAGMA wal_checkpoint(TRUNCATE), copy memory.db the copy lists both keys; keyless recall refused; the admin key answers
Known difference memory citing a source, sources delete, then alice_explain, alice_memory_review, alice_context_pack as the keyless owner and as an unbound admin_agent key key: alice_explain refused ("requested explanation is unavailable"), review and pack carry no source id; owner: all three carry it (explain 11,088 bytes, review 5,187, pack 2,175 against 4,637 and 1,859 for the key) the same, byte for byte
No door of v0.22.0 mints a key on the SQLite vault alicebot agent keys create with sqlite:/// and sqlite://// URLs on a vault with 2 keys; callers of create_agent_key; the record types import accepts invalid_request, key count 2 before and after n/a: the one caller of create_agent_key is cli/agents.py; import takes no key record; no MCP tool mints. No advisory, as the brief said
alice_recall returns ten passages, not eight 15 one-passage notes, alice_recall with no limit 8 (3,774 bytes) 10 (4,655 bytes, +23%)
... an explicit limit is honoured; document mode unchanged limit 8, 5, 12; ALICE_SEARCH_QUALITY=off 8, 5, 12; 8 8, 5, 12; 8
... in vectors mode ALICE_SEARCH_QUALITY=vectors, opt-in on, loopback endpoint that records every text, 15 chunks embedded 8 (stage vectors) 10 (stage vectors); with limit 8 it is 8
alice_explain finds a memory by another spelling of its id (SQLite) upper case, urn:uuid:, braces, no hyphens; no-such-id not_found for all five; not_found the memory for the first four; not_found
Four vNext routes (PostgreSQL) GET /v0/vnext/beliefs/no-such-id/state, POST .../open-loops/no-such-id/review, GET .../projects/no-such-id/dashboard, POST .../projects/update-candidates/no-such-id/review 500 (InvalidTextRepresentation), 500, 500, 409 404 for all four, the body of an unknown id
open-loops/extract scope.person_id of no row; no-such-person 500 (ForeignKeyViolation on open_loops_person_fkey); 500 (InvalidTextRepresentation) 404 not_found; 404 not_found
context-packs a memory whose source_id is urn:uuid:, URN:UUID:, source:, uuid: or alice://sources/ 500 (InvalidTextRepresentation) for all five 201 and a pack for all five
MCP tools and the duplicate loop (PostgreSQL) tests/integration/test_malformed_id_doors_postgres.py, test_open_loop_person_not_found_postgres.py, test_source_id_spelling_context_pack_postgres.py copied into the tag export 74 + 9 + 12 failed pass
Thirteen migrations complete for the owner the four owner migration files and the residual backfills file; test_migrations_forced_flags_restore.py 2 + 2 + 2 + 7 failed (NotNullViolation on revision_number of memory_revisions at 0067, on config_fingerprint_sha256 of model_providers at 0088); the flags file fails on collection: 5 of 13 bracketed pass; the eight integration files together: 179 passed, 0 failed (v0.22.0: 108 failed, 53 passed in the seven files that collect)
The head did not move; the thirteen files ScriptDirectory.get_heads(); a byte comparison of both Alembic folders 20261011_0097, 98 revisions 20261011_0097, 98 revisions; 13 files differ, none added or removed, each gained NO FORCE ROW LEVEL SECURITY
A database at the head needs nothing v0.22.0 code upgraded a database to head, then this code ran upgrade head; and a fresh upgrade with this code revision 20261011_0097 before and after; schema fingerprint (columns, row-level security flags, 156 policies, indexes, triggers) 02abcaaacffe54b6 before and after, and the same after a fresh upgrade: 105 tables, 96 forced
Same stored result for import-markdown 203 files (200 from scripts/generate_markdown_perf_corpus.py --seed 5, one credential file, two duplicates), fresh vaults, 17 tables compared with ids and timestamps set aside receipts equal (202 imported, 1 duplicate, 1 skipped credential); 9 non-empty tables equal; only embedding_stamp.token (random) and event_log.integrity_hash (covers ids and timestamps) differ; 202 sources, 1,570 chunks; dry run receipts equal
Content hash lookup uses its own index EXPLAIN QUERY PLAN of the lookup sources_user_captured_idx sources_user_content_hash_idx
213 s against 321 s, 535 MB to 480 MB not re-run the changelog's own numbers and conditions; the notes add no hardware, machine or measurement (the 203 file run above was 3.8 s and 3.9 s and is not a timing claim)
install takes the same flags and writes the same values install --help md5; _own_env on 5 payloads equal equal; --agent-key-env is not a flag
No tool or setting added; only keys is new tool counts under the four flag sets; every ALICE_ name; the parser of every command 3, 12, 74, 77 3, 12, 74, 77; no new name; new commands keys, keys create, keys list, keys revoke only
Package scope python -m build --no-isolation of the head, git archive copy wheel 392 files, sdist 400 files plus 22 folders wheel 392 files, sdist 400 files plus 22 folders (422 entries; #681 reported the 422); no file from scripts/ or apps/web in either

Findings of the check, handled in the notes or left alone:

  • The known difference is in PR Agent keys on the SQLite vault #698 and not in the documents. The brief for this release said the docs state it. docs/alpha/mcp-tools.md says only that an archived source's quote is withheld from every key. The notes state it in the words above and the checks above reproduce it, and v0.22.0 gives a key the same answers. Adding it to known-limitations.md would be its own change (five tests pin that page).
  • PR Agent keys on the SQLite vault #698's body says alice-memory install --agent-key-env VARNAME exists. It does not on main. No parser has the flag, and _own_env in host_install.py carries a docstring about "the agent key's environment reference" with no code behind it. The changelog and the notes say only that install writes no key and no flag takes one. The docstring is stale and was left alone (a source change).
  • docs/alpha/agent-integration.md names the command proposals. It is sleep-proposals. The notes use the real name.
  • The changelog's import entry still carries its measurement conditions (a hardware description and "main's about 321 s"). It is as merged.
  • The export keeps the two key creation events (prefix, agent id, profile). "The export drops keys" is true of the keys and their hashes; the notes do not say the events are gone.
  • v0.5.1-vnext-preview also ships revision 0067. The changelog says v0.6.0 is the first release that ships it, which holds for releases; the preview tag is not one.

Validation

Run on head be9b0f33 in a worktree of the repository, with the repository's own Python 3.12.11 and PYTHONPATH set to the worktree's apps/api/src and root.

  • python scripts/release_check.py and with --require-finalized-release-docs: Release check: PASS (alice-memory 0.23.0) for both.
  • python scripts/check_control_doc_truth.py: PASS (16 documents verified).
  • python scripts/check_commit_authors.py --base origin/main --head HEAD: PASS (3 commits).
  • scripts/check_protected_paths.py categorization of the changed files (25 at be9b0f33, 27 at e65e67a6): no protected area is touched.
  • python -m ruff check apps/api/src/alicebot_api scripts tests eval/longmemeval: all checks passed. python -m mypy --ignore-missing-imports with the file list of the CI step: no issues in 295 source files. python -m compileall -q on the three folders of the CI step: clean.
  • Unit tests, the five shard selections of tests.yml, each as python -m pytest <selection> -q -p no:cacheprovider, the five in parallel, from a clean tree with the logs outside it:
    • shard 1 (test_[p-r]*, test_saved_p*, test_[t-w]*): 6,028 passed, 0 failed, 2 skipped
    • shard 2 (test_[0-9a-c]*, test_s[!aoq]*, test_saved_quotes_*): 4,249 passed, 0 failed, 11 skipped
    • shard 3 (test_[j-o]*, test_s[oq]*): 15,038 passed, 0 failed, 23 skipped
    • shard 4 (test_saved_quote_*): 488 passed, 0 failed
    • shard 5 (test_[d-i]*): 2,736 passed, 0 failed, 4 skipped
    • Total 28,539 passed, 0 failed, 40 skipped (v0.22.0 had 28,400 passed, 40 skipped). The host home guard refused 0 path checks in each. The counts are from the run on the final head. A first run, before any test edit, failed 10 tests: the seven that index the changelog by position, the two tests of the v0.22.0 notes that this PR updates, and the manifest test before the re-pin. A run on the first commit failed one, the real-host path list test, which the second commit fixes.
  • pytest eval/longmemeval -q: 218 passed.
  • PostgreSQL 16 (local): the eight integration files of the four fix entries, 179 passed on this tree; see the claim check for the v0.22.0 side.
  • Mutations: 80 of 80 killed. Manifest: 45 of 45 replayed cases killed with a green baseline, from be9b0f33.
  • The added lines hold no em or en dash except the required CHANGELOG heading, no home path, machine name or personal detail, and none of the words the repository keeps out of its text, apart from the one verb of the pinned disclosure sentence of the Security section (the second sentence, copied from the last notes; the new test assembles the word from parts). The tests that assert the absence of the other words assemble them from parts too.
  • Not run here: the performance suites, the integration suites other than the eight files, make release-check, the web tests, the real-host jobs and the publish-recheck-rehearsal.yml run itself. CI runs the required ones, and the rehearsal is dispatched on the merge commit before the tag.

Not fixed here

  • docs/alpha/known-limitations.md still says v0.22.0 as the release it describes; it moves in the post-publication change.
  • The documents that describe keys (agent-integration.md, mcp-tools.md, backup-and-restore.md, known-limitations.md, SECURITY.md) carry no "From v0.23.0" marker.
  • The stale _own_env docstring and the --agent-key-env sentence of Agent keys on the SQLite vault #698, above.
  • unit shard 1 has one live-server test, test_request_body_limits.py::test_a_live_server_refuses_a_flood_closes_the_connection_and_keeps_serving[chunked], that failed once with "Connection reset by peer" while mutation runs shared the machine; it passed alone three times and in the final shard run.

What is left for after publication

The same mechanical change as after v0.22.0: add docs/release/v0.23.0-checksums.txt and set the notes state to published and recorded; move the statements that name the latest published release, the baseline and the checksums to v0.23.0 (README, ARCHITECTURE, PRODUCT_BRIEF, ROADMAP, RELEASING, CURRENT_STATE, docs/vnext/README.md) and drop the candidate lines; move the marketplace ref and sha to the v0.23.0 tag commit and the sentences that name the v0.22.0 pin; move the install and checkout lines; add the v0.23.0 notes and changelog section to test_published_release_notes_stay_immutable.py; turn the pending-state tests of test_v0230_release_notes.py into the published form; refresh line and sha256 in the manifest.

Commits after be9b0f3

3ef3a7f9 Complete the owner command list and state the admin key difference in the docs:

  • The upgrade step on commands that run as the owner now names labels, sources and project too. Run on a keyed vault with no ALICE_AGENT_API_KEY: labels check, sources list, project report and project show exit 0, while brief prints 0 bytes.
  • docs/alpha/agent-integration.md names sleep-proposals (it said proposals, which is not a command), lists the same owner commands, and states the known difference next to the advice to mint an unbound admin_agent key for the owner's hosts. The notes' "What this release does not claim" calls it one exception rather than the only one, since a keyed explain also carries policy decision rows.
  • The malformed id entry keeps the tool name alice_vnext_memory_audit as it is on main; the test that keeps the word out of the entry now looks only at text outside code spans.
  • The notes' cost line says the keyless recall was measured against the code before the change (the changelog entry measured against main at that time, which already returned ten passages), not against v0.22.0.
  • The import paragraph drops the sentence about a file that changes between its check and its read, which no test covers.

5d277e9f Re-pin the mutation cases whose files changed: 44 edits (43 citing CHANGELOG.md for its digest, 1 citing docs/alpha/agent-integration.md, line 404 to 408). Replayed all 44 against local PostgreSQL 16: 44 killed, 44 baselines green.

Checks on 5d277e9f: release_check.py plain and --require-finalized-release-docs PASS; check_commit_authors.py --base main PASS (5 commits); ruff check clean; test_v0230_release_notes.py, test_phase5_enterprise_handoff_truth.py and the manifest test 50 passed, 1 skipped; the 15 doc test files that read agent-integration.md plus test_sqlite_agent_keys.py passed. Mutations of the edited tests, each alone: drop labels from the step (the upgrade steps test fails), restore "the exception above" (the limits test fails), put the word in the entry's prose (the changelog entry test fails).

e65e67a6 Move the showcase bench tests out of unit shard 2. CI on 5d277e9f cancelled "Unit tests, shard 2 of 5" at its 20 minute limit with 98 percent of the shard run, and main's own run on 739507ed did the same. Shard 2 took 16 minutes as a job before the agent keys change and 19 to 20 after it (it passed at 19:14 and 19:48 on that change's heads), past the 17 minute split line in gates.json. Run locally on 3e95d082 and 739507ed, shard 2 went from 413 s to 496 s of tests, almost all in three files: test_showcase_bench_vectors.py 16 to 72 s, test_showcase_bench.py 51 to 68 s and test_alice_bench_ranking_mode.py 5 to 15 s, because the bench now starts one alice-memory keys create process per team key. Local shard totals on 739507ed: 1 317 s, 2 496 s, 3 351 s, 4 337 s, 5 205 s. The vectors bench file moves to shard 1 and the bench file to shard 5; shard 2 drops test_sh* from its s pattern and keeps the other showcase files with test_showcase_[!b]*.py. test_ci_unit_job_split.py and every unit test that reads the workflow pass (352 passed, 1 skipped); dropping the bench file from shard 5, or giving shard 2 back its old s pattern, fails the split test. The seven mutation cases that cite the workflow were re-pinned and replayed: 7 killed, 7 baselines green.

Upgrade Overview

Protected Areas

  • memory schema
  • evidence pipeline
  • trust rules
  • promotion logic
  • continuity APIs

None is touched. scripts/check_protected_paths.py categorizes none of the 27 changed files. The changes are version strings, documentation, tests, the mutation manifest and the unit shard selection in .github/workflows/tests.yml.

Compatibility Impact

No code change in this PR. The code v0.23.0 ships is the code on main. The package version moves from 0.22.0 to 0.23.0, and the MCPB manifest and the Claude Code plugin pins move with it. The marketplace file still pins the v0.22.0 tag commit until the post-publication change.

Migration / Rollout

No migration is added. PostgreSQL stays at revision 20261011_0097; thirteen existing migration files changed in place (see the notes) and a database already at or past them is not touched. A SQLite vault with no key behaves as in v0.22.0; once a key is minted, each agent host needs ALICE_AGENT_API_KEY in its MCP server environment and in the launch environment of the session-start hook. Tagging, the release gate, the rehearsal run and publication are not part of this PR.

Operator Action

None for this PR. Before the tag, dispatch publish-recheck-rehearsal.yml on the merge commit and confirm its run is on the SHA to be tagged.

Validation

scripts/release_check.py (with and without --require-finalized-release-docs), scripts/check_control_doc_truth.py, scripts/check_commit_authors.py, the protected-path categorization, ruff check, the CI mypy step, the five unit shard selections of tests.yml, pytest eval/longmemeval, the eight PostgreSQL integration files, the 80 mutations and the manifest replays above.

Rollback

Revert the merge commit. Nothing is tagged or published by this PR, so there is no external state to undo.

Moves the six version sites to 0.23.0, dates the seven changelog entries that sat under Unreleased, adds the release notes in their pending state and records the release candidate in the control documents. v0.22.0 stays the latest published release. Nothing here tags, publishes or dispatches anything.

The changelog entries lose the "Unreleased (on main, not in v0.22.0)" prefix and move under the dated v0.23.0 heading. Two wordings change beyond the prefix: the revocation event of the keys entry and the legacy memory history tool of the malformed id entry no longer carry the word the repository keeps out of its text, and a sentence break in the malformed id entry is fixed.

The new test file test_v0230_release_notes.py pins the notes and runs their claims against this tree and against an export of the v0.22.0 tag. The tests that index the changelog by position move down one section, and the v0.22.0 notes test no longer reads the version sites, which belong to the new test. Forty-five cases of the mutation manifest are re-pinned (43 on CHANGELOG.md, 2 on CURRENT_STATE.md).
The real-host workflow test lists every test file that imports one of the host modules among the paths that start the heavy job. The notes test started the hook with a line that imported the hook module, so unit shard 1 failed on that list. The test now runs the hook with python -m, as a host's hook command does, and imports nothing from the host modules.
…e v0.23.0 notes test

The flags test now names the flags of keys, keys create, keys list and keys revoke instead of checking only that those four commands are the ones that changed. The keyless refusal of the legacy tools is tested with the two legacy tools that resolve no agent identity of their own, so the refusal in call_mcp_tool is the only thing that stops them. A new test runs the helper that decides the environment values install writes on five payloads, in the v0.22.0 export and in this tree, and finds them equal.
… the docs

Name labels, sources and project among the commands that run as the owner, fix
the sleep-proposals name in the agent guide, and say there that an unbound
admin_agent key does not get the evidence of an archived source. Keep the legacy
tool name in the malformed id entry, say the recall cost was measured against the
code before the change, and drop an import sentence no test covers.
Shard 2 reached 19 to 20 minutes as a job against its 20 minute limit, past
the 17 minute split line, after the bench began minting each team key with its
own alice-memory keys create process. The vectors bench file moves to shard 1
and the bench file to shard 5. Re-pin the seven mutation cases that cite the
workflow file.
@samrusani
samrusani marked this pull request as ready for review October 30, 2026 15:54
@samrusani
samrusani merged commit 116d217 into main Oct 30, 2026
43 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant