Skip to content

Release v0.1.0 prep - #1

Merged
zzjc1234 merged 60 commits into
mainfrom
dev
Jul 6, 2026
Merged

zzjc1234 merged 60 commits into
mainfrom
dev

Conversation

@zzjc1234

@zzjc1234 zzjc1234 commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • Prepare current dev branch for v0.1.0 release
  • Include GitHub Actions updates and cleanup commits

Validation

  • Not run; release PR only

zzjc1234 and others added 30 commits May 11, 2026 20:31
- queue.ts: ix_outbox_session was in SCHEMA_STATEMENTS, so on a legacy
  queue.db (created before session_id existed) the index DDL fired
  before migrateSchema() got a chance to ALTER ADD the column —
  constructor threw "no such column: session_id" and the upgrade path
  the migration was designed to support never ran. Moved the index
  creation into migrateSchema(), after the column is guaranteed.
  New test seeds a legacy DB and asserts the constructor auto-migrates.

- ingest.py: UNIQUE(session_id, turn_count) raised IntegrityError up
  the stack as a 500. Wrapped session.commit() in try/except, return
  409 with a descriptive detail instead. New route-level test that
  pre-empts a second record on the same session/turn.

- ingest-worker.test.ts: replaced a tautological JSON.parse("{}")
  assertion with a real round-trip check that body_json preserves the
  shared session_id and per-turn turn_count via pickReady.

Tests: llm-client 124 pass (+1 legacy migration test), backend 52
pass (+1 duplicate-turn test). Agent smoke against real Tbox PASS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- util.ts: new sessionBlobPath(cacheDir, session_id) helper shared by
  main.ts (write + sync read) and eviction.ts (unlink). Three call
  sites used to hand-roll the same path; now they can't drift.
- session.ts: canonicalize uses Object.create(null) for the output
  map, so a "__proto__" key in a message writes a regular property
  instead of mutating the prototype chain.
- queue.ts findEvictableSessions: group_concat separator is ASCII
  unit-separator (0x1F) instead of comma. Can't appear in a UUID
  record_id, so future-proofs against id-format changes.
- backend conftest.py: after create_all, manually creates the partial
  unique index (active token per user) that Alembic 0001 owns but
  SQLModel.metadata can't express. Tests now see the same constraints
  as production. New test_student_token_active_per_user_partial_unique
  proves the constraint actually fires.

Tests: llm-client 124 pass, backend 53 pass (+1). Agent smoke PASS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three domain subdirs that name real architectural seams, not
descriptive groupings:

- http/     — HTTP server boundary (server, handler, net, proxy).
              "http" because that's the actual current protocol
              edge; not "transport/http/" (over-abstraction for a
              hypothetical second protocol).
- recording/— per-call capture + session correlation. Name
              borrowed from rrweb / OpenTelemetry / Sentry Replay,
              which use the same term for the same concept.
- outbox/   — the transactional outbox pattern (Chris Richardson,
              Microservices Patterns). Was already the right
              vocabulary; just promoting it to a directory.

Two file renames inside outbox/ to drop now-redundant prefixes:

- ingest-worker.ts → relay.ts          (the outbox-relay role)
- ingest.ts        → ingest-client.ts  (HTTP client to backend)

main.ts / config.ts / util.ts stay at src/ root (entry + shared).
Tests stay co-located with their source files.

Cross-directory imports are absolute-from-src (./outbox/relay,
../recording/capture, ../http/proxy etc.); same-dir imports keep
their plain ./name form.

Pure rename + path-fix; no behaviour change. typecheck clean,
124 llm-client tests pass, real-Tbox agent smoke still PASS.
Auto-MKCOL was added to the router's sync stage when real Tbox
integration landed (commit 85ca416). The fake WebDAV in
smoke_e2e.sh wasn't updated: it returned 200 with DAV header for
everything non-PUT, but webdav-client's recursive createDirectory
expects 201 on MKCOL. So MKCOL hung / errored, sync never advanced,
and the record stayed pending.

Also bumped sleep 3 → sleep 8 to match the other two smokes
(3 stages × ~1s worker poll = 3-5s typical, 8s headroom).

Now: 1/3 fake-everything, 2/3 real-Tbox single, 3/3 real-Tbox
agent — all PASS.
Hands-on tests against models.sjtu.edu.cn/api/v1 driving the router
through opencode (with oh-my-opencode plugins, Sisyphus orchestrator,
deepseek-chat / deepseek-reasoner / qwen). 50 captures across 5
scenarios; all `verified=true`.

Highlights:

  test 1 (small task):  17 captures from 1 trivial user prompt —
                        Sisyphus loops + N "What did we do so far?"
                        sub-agents + title gen + summarizers.
  test 2 (multimodal):  router preserves `content: [text|image_url]`
                        end-to-end; opencode's Read tool strips images
                        for unknown-capability custom providers.
  test 3 (skill):       opencode injects `<skill>` metadata into the
                        system prompt; agent uses descriptions, rarely
                        loads SKILL.md content.
  test 4 (MCP):         registered fs MCP; agent never reached it —
                        context overflow loop from plugin + tool
                        schemas exceeding deepseek-chat's 65k window.
                        Exposed router gap: `tools` not preserved
                        (fixed in commit 509a670).
  test 5 (compression): each opencode-internal sub-task (summary,
                        title-gen) inherits the FULL previous
                        assistant output — title gen alone produced
                        a 371KB blob.

Net router verdict: works correctly on every capture across all 5
tests. The router is unaffected by upstream/client choices; what
varies is how the agent platform chunks its work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two test files exercise the capture / blob / sync paths at realistic
agent-platform sizes (1-5 MB), so a future "let's add a size cap"
refactor can't silently regress the audit promise.

src/recording/large-payload.test.ts (5 new unit tests):
  - 1 MB user message → blob preserves verbatim, sha256 valid, <500ms
  - 1 MB+ tools array (200 × 8 KB schemas) → all 200 survive round-trip
  - 1 MB SSE response → preserved as raw string including [DONE]
  - SessionTracker prefix-extends a 1 MB conversation across two turns
    in <1s (catches an O(N²) regression in messagesEqual)
  - 10 concurrent 1 MB sessions in the LRU → 10th classify <2s

src/main-sync.test.ts (+1 integration test):
  - 2 MB cache file → sync stage reads + uploads byte-identical to fake
    WebDAV; deterministic sha match.

Realistic upper bound: at ~5 MB we're beyond a single 1M-token
context window, so the upstream itself would reject before we see it.
These tests cover the band of inputs we'd actually receive.

Total: llm-client 134 tests pass (was 128).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
zzjc1234 and others added 29 commits May 16, 2026 19:34
The handler `_cmd_record_list` was already filtering on args.assignment
since the assignment-dimension commit (6de0a61), but the argparse
`add_argument("--assignment", ...)` had been dropped in a rebase along
the way — every `record list` call crashed with AttributeError.

Caught while walking through a live demo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zzjc1234
zzjc1234 merged commit b786a15 into main Jul 6, 2026
8 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