This page mirrors the canonical CHANGELOG.md at the repo root via¶
pymdownx.snippets. Edit the root file, not this page.¶
Changelog¶
All notable changes to activegraph are documented here.
The format follows Keep a Changelog; versioning follows Semantic Versioning. Per-version migration notes reference the Migration from v0.7 cookbook, the canonical runbook for upgrading runs and code across milestones.
The doc site mirrors this file at
Changelog via the
mkdocs snippet plugin — edit CHANGELOG.md at the repo root.
[Unreleased]¶
Nothing yet. v1.1 scope is tracked in CONTRACT.md § v1.1.
[v1.0] — 2026-05-18¶
v1.0 final. The lighter-weight verification pass against v1.0-rc3 ran the same seven-check shape as the rc2 lighter pass and produced six clean passes plus one partial finding on Check 6 (the tutorial's step 7 fork-and-diff snippet undersold its own output). The B2 fix's core promise — fork-and-diff runs without an API key against bundled fixtures — held intact. Scope = v1.0-rc3 + the Check 6 tutorial fix + a README "Concepts at a glance" section bridging the README and the doc site for evaluators.
No runtime capability changes; no public-API renames; no CONTRACT amendment.
Changed¶
- Tutorial step 7 fork-and-diff snippet emits its own next-step
guidance instead of a bare
forked: <run-id>line. The shipped rc3 snippet ran cleanly end-to-end but its terminal output was one anticlimactic line, leaving a first-time reader to scroll past it and notice the "Then diff:" CLI block on their own. The snippet now prints the exactactivegraph diffcommand for the fork it just created (parameterized from the same constants defined at the top of the snippet), and the transition prose before the CLI block names it explicitly. The diff itself produces 61 divergent objects and 49 divergent relations — a substantive output that the rc3 snippet was hiding behind a prose-only handoff. The voice test: a first-time reader runningpython fork_and_diff.pycold now sees both the fork creation and the exact next command, with no ambiguity about whether they need to do something else. - README adds a "Concepts at a glance" section between
"What you get" and "A small example." Twelve primitives — graph,
events, behaviors, relations, patches, views, frames, policies,
patterns, replay, forking, failure model — each with a one-line
"what + why" and a link to the concept page. The section is
evaluator-facing: it lets a reader scan the framework's
conceptual primitives from the GitHub repo page without first
clicking through to the doc site. Mirrors the
docs/concepts/*.mdnavigation 1:1; complements but does not duplicate "What you get" (which is feature-oriented; the new section is primitive-oriented). - Deploy-verification workflow gains a
pull_requesttrigger. Discovered at v1.0 final merge time: the gate (CONTRACT v1.1 #9) ran on push-to-main and cron but not on PR events, so the required-status-check rule on branch protection had nothing to match against on the PR. Aworkflow_dispatchrun reported under a different context name and didn't satisfy the rule. Addingpull_request:to the workflow'son:triggers lets the check report alongside the other CI gates on every PR; the existing push and cron triggers continue to run unchanged. Config-only change; the gate's logic is untouched.
Fixed¶
- Check 6 user-test finding (rc3 lighter pass). See the Tutorial step 7 entry above. The runtime artifact didn't change; the tutorial prose and the snippet's terminal output changed.
Migration from v1.0-rc3¶
Additive. No code changes required. Existing v1.0-rc3 installs should:
[v1.0-rc3 amendment — docs-build fix] — 2026-05-18¶
Post-rc3-merge, pre-rc3-tag follow-on. The v1.1 #9 deploy-
verification gate's first run on main after the rc3 merge caught
a silent failure that had been dwelling since the doc-site phase:
mkdocs.yml declared the mkdocstrings plugin for API-reference
auto-generation (added in commit b533dd4 during the doc-site
phase), but .github/workflows/docs.yml's hardcoded install step
only pulled mkdocs + mkdocs-material. Every docs build through
every doc-site PR failed with Config value 'plugins': The
"mkdocstrings" plugin is not installed, the deploy job never had
an artifact to upload, and the has_pages: false finding from the
rc3 #2 investigation was an effect of this — not just the
externally-owned Pages-enable step. No version bump; this is a
follow-on to v1.0-rc3, not a new rc.
The gate did its job¶
CONTRACT v1.1 #9 (deploy-verification) was designed to catch the
class "internal CI ships green, the external artifact is broken,
nobody notices for months." On its first real run, it caught the
build failure that v1.0 had been carrying silently since the doc-
site phase. The gate's red signal on main post-rc3-merge was
correctly the discipline call to action, not noise.
Fixed¶
mkdocstrings[python]now installed by the docs workflow. Root cause: hardcodedpip install mkdocs mkdocs-materialin.github/workflows/docs.ymldrifted frommkdocs.yml'splugins:block. Audit-then-fix discipline (same shape as rc3's wheel-completeness audit): enumerated every plugin and every markdown extension inmkdocs.yml, cross-checked against the workflow install. Single gap:mkdocstrings(+ its[python]handler). Thepymdownx.*extensions are covered transitively bymkdocs-material(verified via fresh-venv install).
Changed¶
pyproject.tomlgains adocsoptional-dependency extra. Listsmkdocs,mkdocs-material,mkdocstrings[python]. The docs workflow now installs from this extra (pip install -e ".[docs]") instead of hardcoding the dep list. Adding a new mkdocs plugin in the future updates one place — the same pattern every other workflow already follows (types.yml,docstrings.yml,wheel-completeness.yml, anddeploy-verification.ymlall install from pyproject).
Audit-decision: no CONTRACT v1.1 #10¶
Considered: a generalized "declared-but-not-installed" audit gate
in the same shape as v1.1 #8 and v1.1 #9. Cross-checked all six
workflows' install steps. docs.yml was the only workflow
whose install step hardcoded deps that could drift from a separate
config file (mkdocs.yml). Every other workflow installs from
pyproject extras (auto-synced) or installs only its own tool, so
the failure mode "config declares X, install doesn't include X" is
structurally impossible for them. Joining docs.yml to that
pattern institutes the prevention; an audit gate would be
mechanism without a target. Filed as a one-off, not a class.
Externally owned (unchanged from rc3)¶
The two operational steps named in the rc3 entry above still
gate the v1.1 #9 deploy-verification check from passing: enable
GitHub Pages on the repo, configure DNS for docs.activegraph.ai.
With this build-fix landed, the docs workflow can now produce a
deployable artifact for the first time since the doc-site phase
shipped — the artifact is the precondition that the externally-
owned Pages-enable step then publishes.
[v1.0-rc3] — 2026-05-18¶
The lighter-user-test-findings milestone. Two findings from the CONTRACT v1.0 #C4 lighter pass against rc2 addressed; both surfaced discipline gaps that ship with new v1.1 CI gates institutionalizing the verification layer that caught them. No runtime capability changes; no public-API renames.
Added¶
- Wheel-completeness CI gate
(
.github/workflows/wheel-completeness.yml+tests/test_wheel_completeness.py). CONTRACT v1.1 #8. Builds the wheel viapython -m build, installs it into a fresh venv (NOT editable), runsactivegraph quickstartagainst the installed wheel, fails if any runtime data file is missing. Catches the class of bug that's structurally invisible to source-tree tests and editable installs. Markedslow; CI invokes viapytest -m slow tests/test_wheel_completeness.py. To be configured as a required status check on main per CONTRACT v1.1 #8 implementation scope. - Deploy-verification CI gate
(
.github/workflows/deploy-verification.yml+tests/test_doc_site_reachable.py). CONTRACT v1.1 #9. FetchesDOCS_BASE_URL+ 4 known-good page paths, asserts HTTP 200 and that the response body containsActive Graph(the mkdocssite_name). Failure-mode design distinguishes DNS failure, HTTP 404, and content mismatch — each fails with a message that names the operational step to fix it. The HTTP-reachability complement totests/test_doc_links.py, which is source-tree- scoped only. Runs on push to main + daily cron (catches drift if the site goes down without a code change). Required for merge once GitHub Pages is enabled.
Changed¶
- B3 fix:
prompts/*.mdship in the wheel. The v1.0-rc2 user- test gate surfaced thatpip install activegraph==1.0.0rc2followed byactivegraph quickstartcrashed withPackPromptLoadError: prompts directory does not exist. Root cause:pyproject.tomldeclared no[tool.setuptools.package-data]block, so setuptools' default behavior (ship only.pyfiles) omitted the 4.mdprompt files. Audit confirmed exactly 4 non-.pyfiles inactivegraph/, all inpacks/diligence/prompts/. Fix is a single key/glob; rc3 #1 commit. The wheel-completeness gate above is the enforcement layer that prevents this class from recurring. - Domain cutover:
docs.activegraph.dev→docs.activegraph.ai. CONTRACT v1.0 #C6 amended (rc3 amendment block in CONTRACT.md). Primary domain switched to the already-owneddocs.activegraph.ai..devbecomes a redirect-source the maintainer registers and configures separately (externally owned). The codebase holds exactly one primary; the constantDOCS_BASE_URLis the single swap point. Affected files:activegraph/errors.py(constant),docs/CNAME,mkdocs.yml(site_url),README.md(5 link refs),CHANGELOG.md(11 link refs),HANDOFF.md,docs/about/publishing.md,examples/quickstart_session.txt,.github/workflows/docs.yml(comments). Error snapshots rebaselined viaUPDATE_SNAPSHOTS=1— 58 files. The cutover pattern worked as designed: one constant change propagates to every URL throughf"{DOCS_BASE_URL}/..."interpolation.tests/test_doc_links.pycontinues to recognize the .dev URL form so historical CHANGELOG entries linking to .dev still pass the source-presence check.
Externally owned (B4 findings; the gate is shipped, the¶
operational steps are yours):
- GitHub Pages must be enabled on the repo. Per rc3 step-4
investigation:
has_pages: falseis the smoking-gun finding; the doc site at any URL 404s because there's nothing to serve. Fix: Settings → Pages → Source: GitHub Actions. Precondition: the repo must be public (free plan) or on GitHub Pro/Team /Enterprise (paid). Until this lands, the v1.1 #9 deploy- verification gate is red on every CI run; that's the correct signal. - DNS for
docs.activegraph.aimust be configured. CNAME record pointing atyoheinakajima.github.io(the GitHub Pages default subdomain). The v1.1 #9 gate's failure message names this when DNS is the missing piece. docs.activegraph.devredirect. Register the .dev domain and configure it to 301/302-redirect todocs.activegraph.ai. Not strictly required for the v1.1 #9 gate to pass (gate only checks .ai), but needed for historical CHANGELOG entries' .dev links to keep resolving for users.
Boundary shift (CONTRACT v1.1 framing):¶
The two new gates each move the user-test boundary outward by one layer.
- v1.1 #8 (wheel-completeness): after this gate lands, the lighter user-test verifies the PyPI artifact (CDN, upload, distribution) — not the wheel itself.
- v1.1 #9 (deploy-verification): after this gate lands, the lighter user-test verifies the published-domain experience (does the README link land on a page that reads well? does navigation feel right?) — not the basic reachability question of "does this URL return 200."
Same rc1-vs-rc2 discipline pattern noted in the CONTRACT entries: each rc surfaces a finding that's structurally invisible to the prior layer's CI; each rc institutionalizes the verification layer that caught it.
[v1.0-rc2] — 2026-05-18¶
The user-test-findings milestone. Five findings from the CONTRACT v1.0 #C4 gate addressed; one was a latent runtime state-machine bug since v0.5. No new runtime capability; no public-API renames.
Added¶
- PyPI publish workflow (
.github/workflows/publish.yml). Tag-push trigger matchingv*triggerspython -m buildthen upload via PyPI trusted publishing (OIDC-based). Documented in Publishing a release. Externally owned per CONTRACT v1.0 #C8 — the agent ships the workflow, the maintainer runs the publish. - Tutorial-snippet CI test (
tests/test_tutorial_snippets.py). Subprocess-runs the tutorial's step 7 fork snippet end-to-end against the bundled fixtures; asserts exit 0 and idempotency on re-run. Tactical down-payment on CONTRACT v1.1 #2 expansion (spec-vs-impl drift gate for Python doc snippets). _requeue_unfiredregression test (tests/test_requeue_unfired.py). Locks the C3 regression vector:Runtime.loadon a cleanly-drained saved run producesqueue_depth == 0.
Changed¶
_requeue_unfiredusesruntime.idleas the high-water mark. Latent bug since CONTRACT v0.5 #8: the function relied on the false reverse-implication "nobehavior.startedreferences this event id ⟹ event was still in the queue." Events with zero subscribed behaviors are popped-and-discarded with nobehavior.startedemitted, so they were falsely requeued on everyRuntime.load. The fix uses the lastruntime.idleevent as the high-water mark (the runtime emitsruntime.idleonly after the queue empties); only events after the last idle are candidates for requeue.runtime.budget_exhaustedis explicitly NOT a drain marker — using it would break budget-bounded pause-and-resume.- Tutorial step 3 and quickstart prose distinguish the provider
layer (where the fixture provider produces responses) from the
runtime's replay cache layer (where
cache_hit=truelegitimately appears under strict-replay loads orRuntime.fork()in-process). Pre-rc2 prose conflated the two. The conflation was originally in the v1.0 spec atexamples/quickstart_session.txt; the spec is updated with a header drift-note documenting the two-layer reality. - Tutorial step 7 fork snippet uses
RecordedDiligenceProvider(companies=THREE_COMPANIES)as the fork'sllm_provider=. Matches the parent run's provider; preserves the "no API key required" tutorial pitch. The snippet also includes a tutorial-only cleanup-on-collision branch so it's re-runnable without manual DB surgery. _prepare_interactive_subdircollision prompt re-prompts on unrecognized input. Pre-rc2 behavior fell through to the suffix branch on any input that wasn'toorq, which swallowed typeahead from the next prompt. Mirrors the existing iteration-loop pattern atrun_interactive_mode.
Deprecated¶
Nothing. Backward compatibility holds — all v0–v1.0-rc1 tests pass.
Removed¶
Nothing user-facing.
Fixed¶
Runtime.load(...).status().queue_depthreads 0 on a freshly loaded cleanly-drained run. Was a non-zero false count of events that had been popped-and-discarded during the original run. See the Changed entry for_requeue_unfiredabove.activegraph --versionreports the correct version. Was stuck at0.9.1through v1.0-rc1's release (the version-sync gate validated internal consistency but not correspondence with the git tag). The v1.1 #6 version-tag-correspondence gate closes this gap in v1.1.- Tutorial step 7 fork snippet runs end-to-end against bundled fixtures with no API key, matching the rest of the quickstart's "no API key required" pitch.
cache_hit=trueclaim in the tutorial and quickstart "what just happened" prose: the claim was wrong for initial fixture-mode runs (the runtime's replay cache only fires on strict-replay or in-process fork). Prose corrected; two-layer vocabulary lands cleanly for first-time readers.
Migration from v1.0-rc1¶
Additive. No code changes required. Existing v1.0-rc1 installs should:
Existing saved runs (*.db files) load with queue_depth == 0
correctly post-upgrade — the C3 fix is in the load path, not the
storage format.
Known follow-ons (v1.1 scope)¶
In addition to the v1.0-rc1 v1.1 backlog (carried forward):
- CONTRACT v1.1 #2 expansion — spec-vs-impl drift gate covers executable Python snippets in docs, not just CLI flags. v1.0-rc2 ships the tactical step 7 test; v1.1 generalizes.
- CONTRACT v1.1 #5 —
Runtime.loadauto-provider ergonomics. The rc2 fix for B2 passesRecordedDiligenceProviderexplicitly; the v1.1 design question is whetherRuntime.loadshould infer a provider from the run's recorded events or from a pack-manifest declaration. New runtime capability, banned in v1.0. - CONTRACT v1.1 #6 — version-tag-correspondence CI gate.
Existing version-sync gate validates
__version__matchespyproject.toml; the v1.1 gate adds correspondence with the current annotated tag in tagged-release CI runs. - CONTRACT v1.1 #7 backlog item: fork cache pre-population
symmetry.
Runtime.fork(at_event=...)in-process pre-populates the LLM cache from the parent's events; the persistent shape (SQLiteEventStore.fork_runthenRuntime.load) does not. The two paths should be symmetric. New runtime behavior, banned in v1.0.
[v1.0-rc1] — 2026-05-18¶
The adoption-surface milestone. No new runtime capability; the contract is "a new user can install, run, understand, debug, and extend the framework without reading source code."
Added¶
- Error hierarchy rewrite. Every exception now inherits from
ActiveGraphErrorand carries structuredwhat_failed,how_to_fix, andcontextfields. Seven category bases (ConfigurationError,RegistrationError,ExecutionError,ReplayError,StorageError,PatternError,PackError) with 33 leaves. Built-in lineage preserved via multi-inheritance —except ValueError/except KeyErrorclauses still work. - Per-error reference catalog. Every error message ends with a
More:link to a dedicated page documenting when it fires, why, how to diagnose, and how to fix. Catalog at docs.activegraph.ai/reference/errors. - Documentation site at docs.activegraph.ai: concepts pages for every primitive (graph, events, behaviors, relations, patches, views, frames, policies, patterns, replay, forking, failure model); guides; cookbook (common patterns, debugging, migration); CLI reference; API reference via mkdocstrings.
activegraph quickstartCLI command. Bundled Diligence demo in fixture mode (byte-deterministic, no API key, ~20 seconds);--interactivemode walks the user through writing their first behavior.- 10-minute tutorial at docs.activegraph.ai/quickstart. Install → run → write a behavior → save and inspect → fork and diff. Seven steps; every example runs.
- CI gates on the public surface. Version-sync gate
(
pyproject.toml↔activegraph.__version__), broken-link gate for the doc site, mypy--strictgate on the__all__allowlist (22/38 modules clean at baseline), docstring coverage gate (Ring 0 92/100 not-missing, Ring 1 at 84.7%; exemption list indocstring_gaps.toml). - CLI follow-on flags (referenced from error messages' recovery
prose):
inspect --event <id>,inspect --behaviors,inspect --pack-version,migrate --skip-corrupted,fork --record.
Changed¶
- README trimmed from 1275 lines to ~190. The doc site is now
the canonical reference; the README is the conversion funnel
(30-second pitch → install →
activegraph quickstart→ tutorial). - Error messages structured. Every framework-raised exception
exposes
what_failed(one line),how_to_fix(actionable prose), andcontext(structured detail) on the exception instance. Plainstr(exc)renders all three. - Trace printer formats
pack.loaded(was previously falling through to the generic event renderer).
Deprecated¶
Nothing. Backward compatibility holds — all v0–v0.9 tests pass.
Removed¶
Nothing user-facing. Internal: a handful of dead code paths surfaced during the error-rewrite audits were removed.
Fixed¶
pack.loadedtrace formatting (was missing despite being spec'd in CONTRACT v0.9 #25).- Several inconsistent error categories — see CONTRACT v1.0 PR-F audit findings for the cross-category reclassifications.
Migration from v0.9.1¶
Additive. See Migration from v0.7 § 5–6:
# v1.0 — broader catches with structured context:
try:
rt = Runtime.load(url, run_id=rid)
except activegraph.StorageError as e:
log(e.what_failed, e.how_to_fix, e.context)
except activegraph.ActiveGraphError as e:
log(e.what_failed, e.how_to_fix)
Existing except ValueError/except KeyError/except TypeError
clauses keep working — multi-inheritance preserves builtin
lineage.
Known follow-ons (v1.1 scope)¶
fork --set <pack>.<key>=<value>for cheap fork-with-override experiments (CONTRACT v1.1 #1; canonical Python-API recipe at Cookbook § Fork with a pack-setting override).inspect --memoandinspect --search(CONTRACT v1.1 #1).- Type-completeness burndown — close the 16 dirty allowlist
modules (CONTRACT v1.1 #3,
TYPE_REPORT.md). - Docstring-completeness burndown — close the 8 missing Ring 0
exemptions and upgrade one-liners to full
(CONTRACT v1.1 #4,
COVERAGE_REPORT.md). - Spec-vs-impl drift gate for CLI flags (CONTRACT v1.1 #2).
[v0.9.1] — 2026-05-17¶
Operator-visible quality-of-life fixes between v0.9 and v1.0.
Added¶
[trace.flags]rollup header at the top of every trace block withprompt_normalized=true|falseso operators can see at a glance whether a run used the v0.7+ normalized-prompt format.
Changed¶
- Approval-demo output is now granular (per-object) rather than batched, so operators can see which approval the runtime is waiting on.
Migration from v0.9¶
None — additive trace and demo improvements; no API changes.
[v0.9] — 2026-05-16¶
The pack format milestone. A pack bundles object types, behaviors, tools, prompts, and policies for a specific domain.
Added¶
Packdataclass: frozen, equality by(name, version).- Pack-aware decorators (
activegraph.packs.behavior,llm_behavior,relation_behavior,tool) with no global registry side effects. runtime.load_pack(pack, settings=...)— idempotent; conflicts (object type, relation type, behavior name, tool name, policy name) raisePackConflictErrorbefore any state mutation; version mismatch raisesPackVersionConflictError.- Object type schemas enforced via Pydantic at
graph.add_object; relation type validation atgraph.add_relation. - Namespace prefixing: canonical strict
(
diligence.claim_extractor); short-name lookups lenient. - Three settings access forms: typed parameter injection
(primary),
ctx.settings,ctx.pack_settings(name). - Prompt loader: TOML frontmatter; content-hashed via SHA-256 truncated to 16 hex chars; hash (not version) is the replay contract.
- Discovery via Python entry points
(
activegraph.packs);discover(),load_by_name(),clear_discovery_cache(). activegraph pack new <name>scaffolding command.activegraph pack listto enumerate installed packs.activegraph.packs.diligence— production-quality reference pack: 8 object types, 6 relation types, 7 behaviors, 3 tools, 2 policies, 4 prompts, recorded fixtures for 3 companies, end-to-end demo atexamples/diligence_real_run.py.- Pack authoring guide at Authoring packs.
Changed¶
- Python floor raised to 3.11 (uses stdlib
tomllib). pydantic>=2is now a hard dependency (was opt-in via[llm]). The pack format's object-type schemas and settings models require it.click>=8,<9becomes a hard dependency (CLI is always available).
Migration from v0.8¶
Additive. See
Migration from v0.7 § 4.
Global decorators (@behavior, @tool) keep working alongside
loaded packs; the pack format is opt-in for new code.
Python 3.10 users must upgrade to 3.11+ before installing v0.9.
[v0.8] — 2026-05-16¶
The operator surface milestone. Hardens the boundary between the framework and the world it runs in.
Added¶
PostgresEventStorebehind the sameEventStoreprotocol as SQLite (Postgres 16+;pip install activegraph[postgres]).- Connection-URL addressing everywhere (
sqlite:///relative,sqlite:////absolute,postgres://...). activegraph migrate --from <url> --to <url>— transaction-per-run, idempotent, one-directional.- Structured JSON logging via
configure_logging(json_output=True)with a documented schema (the operator contract). Metricsprotocol (three methods: counter, histogram, gauge) withNoOpMetricsdefault and referencePrometheusMetricsbackend.runtime.status(recent=N)— frozenRuntimeStatusdataclass for introspection.activegraphCLI:inspect,replay,fork,diff,export-trace,migrate. CLI exit codes documented as contract.- Operator guide at Operating in production.
Migration from v0.7¶
Additive. See
Migration from v0.7 § 3, 7, 8.
Old SQLite path arguments (persist_to="/path/to.db") keep
working; URLs are required for CLI and cross-store operations.
[v0.7] — 2026-05-16¶
The tools and advanced matching milestone.
Added¶
@tooldecorator: tools as first-class primitives with input schema, output schema, determinism flag, cost, timeout.- LLM ↔ tool turn loop owned by the runtime; multi-turn until
the model returns a non-tool response or
max_tool_turnshits. tool.requested/tool.respondedevent pair; replay cache separate from the LLM cache.RecordedToolProvider+RecordingToolProviderfor tests.- Two reference tools:
web_fetch,graph_query(factory-based for graph read access). - Cypher-subset pattern subscriptions via
pattern=on@behavior/@llm_behavior. Compile-time strict; the unsupported tokens raiseUnsupportedPatternErrornaming the offending token. - Negation via
NOT EXISTS { ... }. - Temporal predicates:
activate_after=Nevents (event-count, not wall-clock — keeps replay deterministic). - Tool budgets (
max_tool_calls) + cost-sharing with LLM (max_cost_usdcovers both). - Causal-chain walk crosses tool boundaries via
tool_request_event_idprovenance.
Changed¶
- Prompt assembly normalized — every prompt is content-hashed
via the canonical form; the
prompt_normalized=trueflag appears in the v0.9.1 trace rollup for runs using this format.
Migration from v0.6¶
Additive. v0.6 LLM behaviors continue to work without tools=
declarations.
[v0.6] — 2026-05-16¶
The LLM integration milestone.
Added¶
@llm_behaviordecorator with structured output parsing (Pydantic schema).- Frame-aware prompt construction: system prompt assembled from frame goal + constraints + behavior description + output-schema reminder, in a fixed order.
llm.requested/llm.respondedevent pair with model, full prompt+params, prompt hash, estimated cost, deterministic flag, cache-hit flag.AnthropicProviderreference implementation (readsANTHROPIC_API_KEY; never from code).RecordedLLMProvider+RecordingLLMProviderfor tests (fixtures keyed by SHA-256 of prompt+params canonical form).- Cost accounting: Decimal-precise
max_cost_usdbudget; pre-call estimate viacount_tokens; post-call actual cost from provider'susage. - Structured failure reasons (
llm.network_error,llm.rate_limited,llm.parse_error,llm.schema_violation,llm.fixture_missing,budget.cost_exhausted).
Migration from v0.5¶
Additive. LLM behaviors are opt-in; non-LLM runs unaffected. New
optional dependency activegraph[llm] (anthropic SDK).
[v0.5] — 2026-05-16¶
The resumability milestone. The event log becomes the source of truth.
Added¶
- Full event log persistence via the
EventStoreprotocol; SQLite reference backend with schema version pinned from day one in ametatable. Runtime.load(url, run_id=...)— open, pick a run, replay, return runtime ready to continue.- Strict-replay mode (
replay_strict=True) — re-executes behaviors and firesReplayDivergenceErroron mismatch. - Fork (
runtime.fork(at_event=...)) — new run, copies parent's event log up to the cutoff (inclusive), independent log thereafter. - Structural diff (
parent.diff(other)) — shared / parent-only / fork-only event partitions; divergent objects and relations. - Multiple runs per file; ULID
run_ids; provenance carriesrun_id. - Unfired-event re-queue on load (events emitted but never popped return to the queue on resume).
Migration from v0¶
Additive. v0 in-memory runs continue to work without
persist_to=. New optional dependency
activegraph[sqlite] (stdlib — no extra packages needed).
[v0] — 2026-05-16¶
The core runtime.
Added¶
- In-memory
Graphwith typed objects, typed relations, and an append-only event log. - Function-based (
@behavior) and class-based (subclassBehavior) behaviors. - Relation behaviors (
@relation_behavior) — coordination logic on edges. - Event-type subscriptions with predicate filters (
where=). - Patch system with optimistic concurrency (version-keyed apply;
rejected patches surface as
patch.rejectedevents). - Views with type/depth/recent-events scoping.
- Frames (mission context per run) and policies (per-behavior capability declarations).
- Trace printer (
runtime.print_trace()); causal-chain query (runtime.trace.causal_chain(object_id=...)). - Budgets (
max_events,max_behavior_calls,max_seconds,max_depth, etc.) — runtime stops cleanly when hit; resumable.
Migration from before v0¶
There is no before-v0.
The graph is the world. Behaviors are physics. The trace is the proof.