Skip to content

feat: anton_state SDK + artifact lifecycle integration for stateful artifacts#259

Open
StpMax wants to merge 6 commits into
stagingfrom
feat/ENG-704
Open

feat: anton_state SDK + artifact lifecycle integration for stateful artifacts#259
StpMax wants to merge 6 commits into
stagingfrom
feat/ENG-704

Conversation

@StpMax

@StpMax StpMax commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

What

Adds durable state support for fullstack-stateful-app artifacts on the anton side
(ENG-704): a STATE SDK with two
interchangeable drivers, and its integration into the artifact lifecycle
(backend template, generation rules, publish bundle, local runs).

1. anton_state — the STATE SDK (new top-level package)

One async Store API (get / put / delete / query, TTL, conditional writes /
optimistic locking) over two drivers behind a common Driver protocol:

  • SQLite driver (local dev): stdlib sqlite3, WAL mode, items stored as JSON.
  • DynamoDB driver (published runtime): boto3 with per-invocation STS creds
    passed via backend.STATE; capped retries, throttle → StateThrottled.
    boto3 is imported lazily — the local SQLite path needs no boto3 at all.

Parity by construction — the API is the intersection of both backends, and
known divergences are eliminated in driver code rather than left to generation
prompts:

  • strict cloud-grade validation on both sides (key types, empty keys, 400 KB item
    cap, TTL must be an epoch-seconds number);
  • ConsistentRead=True by default on base-table reads → read-after-write behaves
    the same locally and in the cloud;
  • lazy TTL on both sides: expired items are filtered on read; conditional writes
    see expired "zombies" identically;
  • float ↔ Decimal conversion in the DynamoDB driver (numbers round-trip as plain
    Python numbers on both drivers);
  • remaining documented divergences are minimal: GSI reads are always eventual;
    don't combine TTL with conditional writes on the same key.

Schema is a single source of truth: state_manifest.json (declarative,
pydantic-validated) is read both by backend code (open_store() /
StateSchema.from_manifest) and by the publish/provisioning pipeline — code and
provisioned table cannot drift by construction. Migrations are out of scope for
v1 (key-schema must match on republish; enforced by the provisioning gate in
mindshub_services).

Driver selection mirrors SECRETS: backend.STATE is None → SQLite;
{table, region, credentials} dict (overlaid by the cloud runner) → DynamoDB.

2. Lifecycle integration

  • Publisher: vendors the anton_state package into every fullstack bundle
    (version-locked, no package index needed at runtime); ships
    state_manifest.json in the bundle and duplicates it in the publish payload
    for the provisioning pipeline; defensively excludes .anton_state.db
    (+ -wal/-shm) from bundles.
  • Backend launcher: local backends run in a scratchpad venv where
    anton_state isn't installed — the launcher injects an isolated PYTHONPATH
    dir exposing only the anton_state package (symlink, copy fallback), so
    anton's own dependencies never shadow the backend venv's. Covers
    cowork-server too (it calls launch_artifact_backend).
  • Backend template (prompts.py): module-level STATE = None slot symmetric
    to SECRETS, a get_store() pattern with __file__-relative paths; included
    only for fullstack-stateful-app.
  • Generation rules: STATE is positioned for light state (counters,
    settings, sessions, simple keyed documents); heavy/relational needs go to an
    external connected database — not forced into KV.

Packaging note

anton_state is added to [tool.hatch.build.targets.wheel].packages — not to
publish it standalone, but because anton itself imports it at runtime
(publisher._vendor_anton_state, backend_launcher._anton_state_pythonpath_dir):
the wheel is the source both vendoring and local injection copy from. New deps
(boto3, moto) are dev-only; anton's runtime dependencies are unchanged.

Out of scope (follow-ups in other repos)

  • Cloud data-plane — gateway STS mint (variant A′, dedicated permission
    boundaries), runner backend.STATE overlay, table provisioning at publish:
    mindshub_services + terraform PRs.

Until those land, published stateful artifacts get STATE = None in the cloud;
local behavior is fully functional.

Testing

pytest tests/test_anton_state/ tests/test_publisher_state.py tests/test_backend_launcher_env.py tests/test_prompts_state.py

  • driver parity suites (SQLite + DynamoDB via moto): roundtrip, conditional
    writes, optimistic locking, TTL zombies, GSI queries, number round-trips;
  • single-source manifest seam test (publish side and backend side read the same
    schema);
  • vendoring/bundle content, isolated PYTHONPATH injection, template/rules smoke
    checks;
  • lazy-import guard: the SQLite path never imports boto3.

@StpMax
StpMax changed the base branch from main to staging July 17, 2026 15:43
@StpMax StpMax changed the title (WIP) ENG-704 feat: anton_state SDK + artifact lifecycle integration for stateful artifacts Jul 20, 2026
@StpMax
StpMax marked this pull request as ready for review July 20, 2026 11:16
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