Wave 48 tick#2 — STATE: x402 endpoint prod seed (entrypoint runner)¶
- Date: 2026-05-12
- Branch:
feat/jpcite_2026_05_12_wave48_x402_prod_seed - Base SHA:
81eacab9334523edee6b59d534a432e37824bc97(main) - PR: filled at open time
- Lane:
/tmp/jpcite-w48-x402-seed-entrypoint.lane(mkdir-exclusive)
Symptom (prod)¶
am_x402_endpoint_config(created by migration 282, Wave 47) is empty on the Fly volume. As a result,/v1/audit_workpaper,/v1/cases,/v1/programs,/v1/search,/v1/semantic_searchreturn HTTP 404 (no x402 config row) instead of the contracted HTTP 402 (Payment Required).- Wave 47 tick#2 had only run the seeder against a local DB during dev, never inside the prod container.
Root cause¶
scripts/etl/seed_x402_endpoints.py exists and is idempotent, but nothing in
the container boot path invokes it. Migrations create the table; the seeder
is the ONLY mechanism that populates the 5 canonical rows.
Fix¶
entrypoint.sh §4.x (new): post schema_guard, pre exec "$@", invoke
python /app/scripts/etl/seed_x402_endpoints.py --db "$DB_PATH" when both
the seeder file and an autonomath DB are present. Idempotent (no --force).
Failure is logged via err but does NOT exit 1 — boot stays alive.
Memory invariants honored:
- feedback_no_quick_check_on_huge_sqlite: zero PRAGMA probes added.
Seeder is O(5 SELECT + ≤5 INSERT) and well under Fly 60s grace.
- feedback_destruction_free_organization: additive only, no rm/mv,
no --force. Operator-set repricing is preserved across boots.
- feedback_dual_cli_lane_atomic: lane claimed via mkdir.
Diff¶
entrypoint.sh | 26 ++++++++++++++++++++++++++
tests/test_entrypoint_vec0_boot_gate.py | 8 ++++++++
tests/test_x402_prod_seed_entrypoint.py | NEW ~180 LOC
docs/research/wave48/STATE_w48_x402_seed_pr.md | NEW
entrypoint.shdiff = 26 LOC inserted (§4.x block before §5 exec).tests/test_entrypoint_vec0_boot_gate.pydiff = 8 LOC (replacement-order fix: hoist the seed path rewrite ABOVE the/seedsubstitution because/seedsubstring exists inside/seed_x402_endpoints.pyand would otherwise corrupt the test-rewritten path).tests/test_x402_prod_seed_entrypoint.py= NEW, ~180 LOC, 6 tests.
Test verdict¶
$ bash -n entrypoint.sh
OK
$ python -m pytest tests/test_x402_prod_seed_entrypoint.py tests/test_entrypoint_vec0_boot_gate.py \
--deselect "...::test_autonomath_boot_manifest_exists_and_is_empty_allowlist_by_default" -q
20 passed, 1 deselected in 2.99s
The 1 deselected test (test_autonomath_boot_manifest_exists_and_is_empty_allowlist_by_default)
is a pre-existing failure on main (manifest now carries 43 entries from
Wave 43-47, asserts empty) and unrelated to this PR. Confirmed by re-running
on main HEAD: same failure, same line.
Live entrypoint exec sanity (AUTONOMATH_ENABLED=true, tmp paths, seed
script absent dev-build path):
[entrypoint] [W48.x402] seed_x402_endpoints.py absent — skipping x402 prod seed (dev build?)
[entrypoint] starting server: true
rc=0
New test file structure (6 tests, ~180 LOC)¶
test_entrypoint_invokes_seed_x402_endpoints_after_schema_guard— order: schema_guard < seed invocation < exectest_entrypoint_seed_block_is_best_effort_not_boot_fatal— block contains noexit 1, has|| err ...chaintest_entrypoint_seed_block_skips_when_db_absent— guards on[ -s "$DB_PATH" ]test_entrypoint_seed_block_omits_pragma_quick_check— zero PRAGMA in EXECUTED shell (comment-stripped before scan)test_entrypoint_seed_block_does_not_pass_force_flag— no--forcearg (operator repricing preserved)test_seed_script_idempotent_against_fresh_schema— live exec the seeder twice against an inline schema, assert 2nd run is{noop: 5}
Post-merge expected impact¶
- Fly redeploy after merge: §4.x kicks in on next boot, seeds 5 rows.
/v1/{audit_workpaper,cases,programs,search,semantic_search}flip from 404 → 402 Payment Required per x402 contract.- Subsequent boots: idempotent noop.
Out of scope (deferred)¶
- Live x402 settlement flow (Coinbase Base L2 callback) — separate tick.
- CF Pages
functions/x402_handler.tsparity verify — already deployed per Wave 47 tick#2 STATE. - Per-endpoint repricing telemetry — Dim V monthly snapshot already in place.