Skip to content

test(web): pin agent-status-changed and session-ingested narrowing to the shared types - #1

Merged
IvanBBaev merged 10 commits into
mainfrom
claude/fervent-maxwell-2hmdro
Sep 26, 2026
Merged

IvanBBaev merged 10 commits into
mainfrom
claude/fervent-maxwell-2hmdro

Conversation

@IvanBBaev

Copy link
Copy Markdown
Owner

The two sibling realtime arms were still narrowed by hand with no type pin
(L4 follow-up, found-not-taken 2026-09-09). An exhaustive
satisfies Record<keyof AgentStatusChangedEvent, true> field list makes a
shared-schema field change a compile error in apps/web, a drop-one-field sweep
proves the guard reads every field, and a SessionIngestedEvent-typed frame pins
ingestedSessionId. Mutation-checked: all three mutations went red.

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01FXNMQzi7tUcVA65eSi6mPp

… the shared types

The two sibling realtime arms were still narrowed by hand with no type pin
(L4 follow-up, found-not-taken 2026-09-09). An exhaustive
`satisfies Record<keyof AgentStatusChangedEvent, true>` field list makes a
shared-schema field change a compile error in apps/web, a drop-one-field sweep
proves the guard reads every field, and a SessionIngestedEvent-typed frame pins
ingestedSessionId. Mutation-checked: all three mutations went red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXNMQzi7tUcVA65eSi6mPp
… 10 (D10)

The seed carried Sonnet 5 at 3 / 15 with derived cache rates. The platform
pricing page (re-read 2026-09-26) says the $2 / $10 launch price is now the
standard price and the scheduled increase to $3 / $15 will not occur, so every
Sonnet 5 dollar shown was 1.5x too high. Migration 20 rewrites the five seeded
floor rows in place (ON CONFLICT DO UPDATE) instead of adding a later-dated row,
so the cancelled price never becomes history; no row is added and operator rows
at other instants are untouched. Stored usage re-prices at read time.

Checksum identical under tsx, vitest and node strip-types. Four new migration
tests; dollar expectations that read the seeded Sonnet rate re-derived by hand;
migration 19's tests bounded to <= 19. Docs: data-model ledger gains rows 19 and
20, migration counts corrected to twenty. WP-C1 ratification stays the owner's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXNMQzi7tUcVA65eSi6mPp
…t race

- DONE.md: a 2026-09-26 milestone entry (D10 / migration 20, the realtime
  pins, the test race, the migration-count drift), plus a note that the
  2026-09-04..09-25 entry is still the Wave-4 R2 item
- Code comments: PRICING_SEED's sonnet row points at migration 20;
  queries.ts counts migrations 18-20; isAgentStatusChangedEvent and
  ingestedSessionId name the test that pins them
- api.md: all three realtime frames are narrowed by hand and pinned
- apps/web/test/app.test.tsx: the 401 test waited for nothing before asserting
  the SSE stream closed, but React 19 runs that cleanup after the commit when
  the 401 arrives outside act; it failed ~1 in 17 coverage runs. It now waits
  for the eventual close and asserts a stream existed. Proved with the close
  deferred (old 3/3 red, new 3/3 green) and removed (new red).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXNMQzi7tUcVA65eSi6mPp
…5..09-26 DONE milestone

- R1 (Wave 4) rehearsed on a clean tree: all seven CI commands plus gate:node
  exit 0 at 167 test files / 3060 tests, 100% in all five packages; spawner 313
  files, policy file the only allowlisted one; licences 406 packages / 428
  installed versions, one documented exception; RELEASE §2 greps clean; P0 4/19;
  backup.test 4/4; the live-drill command proven on a scratch schema-20 database
  only. No box ticked. Recorded in RELEASE.md, TODO Wave 4 and the analysis README.
- R2: the 2026-09-23 "140 / 2621" reading was already stale on main; the dated
  2026-09-26 figure now sits beside it on every page that quotes the suite size,
  and the gate outputs are re-dated in testing.md and licensing.md. Historical
  readings are kept, not overwritten.
- DONE.md: the milestone entry for 40f1524, 39e565a, closing-board Waves 0-2,
  docs sweeps #3-#6 and 4b3cd2d, with commit attribution checked against git.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXNMQzi7tUcVA65eSi6mPp
…e other four packages

apps/web guarded only the coverage-ignore pragma. Lowering a web threshold or
adding a file to the web coverage `exclude` passed CI; RELEASE.md §1 told the
release reader to diff vitest.config.ts by hand for that reason. The web
honesty block now reads the config as text and pins the exact thresholds
object (four keys at 100, no extras), include 'src/**' and the exact
two-entry exclude list, each entry required to exist. Mutations killed:
branches 99, a third exclude, an extra perFile key, exclude via a variable.

Docs: RELEASE.md §1, testing.md "Three asymmetries", CONTRIBUTING.md (also
"raising" -> "lowering"), PROJECT-STATE, CHANGELOG, TODO, DONE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXNMQzi7tUcVA65eSi6mPp
testing.md's "Third" asymmetry still said check-no-spawner.mjs and
check-licenses.mjs have no unit tests and are exercised only by CI.
apps/server/test/scripts-gates.test.ts drives each gate's pure core (and the
Node-major guard's) against throwaway fixture trees. Dated note added; the
part that still holds - scripts outside every coverage denominator, CLI
wrappers deliberately unexecuted - is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXNMQzi7tUcVA65eSi6mPp
WP-F5 was always "static no-spawner + no-SSRF gate" and CD-7 makes no-SSRF
CI-blocking, but check-no-spawner.mjs never carried an outbound pattern: the
invariant rested on RELEASE.md §2's grep and on review, and a fetch() added to
the server passed CI. The Phase-1 row was ticked with only the spawner half.

The gate now applies an outbound-network family to server-process source
(apps/server/src/, packages/*/src/): fetch(, the node http/https/http2/net/
tls/dgram/dns modules, 13 HTTP client packages matched as specifiers only,
WebSocket/EventSource clients and XMLHttpRequest; and refuses an HTTP client
package in the server and library manifests. Browser code and tests are out
of scope by path, not by exemption. The OK line reports the file count (93,
all clean). v2.0's dispatcher line will need a visible inline marker.

scripts-gates.test.ts 41 -> 60: every pattern, scope in and out, look-alike
words, the inline hatch, manifests. Six gate mutations each killed.

Docs: RELEASE.md §1/§2, SECURITY.md §9, security model rule 6 and summary,
threat model, ADR CD-7, telegram.md (two "planned" / "upheld by review"
passages), roadmap guide, licensing.md, testing.md, CHANGELOG, TODO, DONE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXNMQzi7tUcVA65eSi6mPp
… IN9, X8)

A read-only audit of every ticked v1.0 work package against its
development-plan Done-when found clauses the code met but no test proved:

- WP-D10: redaction determinism/idempotence, and a redelivered or
  re-ingested secret-bearing hook event storing one row with unchanged
  bytes (SQLite-backed route test).
- WP-IN9: every token_usage row attributed to exactly one agent of its own
  session, over the whole fixture registry, in the P0 reconciliation suite.
- WP-X8: new hooks-end-to-end.test.ts replays the request read out of the
  installer-generated command against the real loopback server into
  events_raw, including the per-firing delivery id.

Each new test was shown to fail on a matching regression (key over the
unredacted body; main usage left unattributed; installer path, content type
and delivery-id header drift). Stale api.md readSince claim and a rows.ts
reference corrected. TODO gains the audit section; CHANGELOG updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXNMQzi7tUcVA65eSi6mPp
…(IN8 #10)

Two Done-when clauses the WP audit found ticked but never built.

WP-U1 "resumable": RealtimeHub keeps the last 256 frames (replayCapacity,
0 disables) and /api/stream replays every buffered frame after the
request's Last-Event-ID - which EventSource sends on its own reconnect, so
the SPA needs no change - before live fan-out, in one synchronous step.
Non-decimal headers are ignored. Fixed while writing it: replay writes
through the route's write(), which can reap the stream, and close() read
`unsubscribe` and `heartbeat` from their temporal dead zone; both hoisted,
a writer throwing during replay is dropped and counted, and a stream reaped
by its own replay is unsubscribed at once. A guard for "ids from an earlier
process" was dead code (survived mutation) and is replaced by a written-down
restart limit. Nine tests; replay off-by-one, empty buffer and the
reaped-during-replay check each killed by mutation.

IN8 parser-gate #10: parseSession returns claudeCodeVersions (sorted
distinct per-record `version` strings) for provenance only; parsing still
branches on directory shape. Not persisted. Three tests, core 100%.

Docs: api.md (three places), ADR CD-5 addendum and index, parser-spec #10,
web comments that said "no replay buffer", TODO audit section, CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXNMQzi7tUcVA65eSi6mPp
…ilestone

Nine audit findings are product or process calls rather than code, so they go
to the board with a recommended default each: Q5 dashboard reader (D11), U7
live/force layout (D12), C6 staleness gate vs synthetic fixtures (D13), X1
real-session corpus (D14), X5 coverage-block demonstration (D15), X10
WORKLOG check (D16), C1 pricing refresh cadence (D17), C2 PricingProvider
port (D18), the dead is_compaction_baseline column (D19). Each was
re-verified against the code before being written down. DONE.md records
the audit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXNMQzi7tUcVA65eSi6mPp
@IvanBBaev
IvanBBaev merged commit a5265ab into main Sep 26, 2026
1 check passed
@IvanBBaev
IvanBBaev deleted the claude/fervent-maxwell-2hmdro branch October 5, 2026 11:55
IvanBBaev added a commit that referenced this pull request Oct 5, 2026
test(web): pin agent-status-changed and session-ingested narrowing to the shared types
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.

2 participants