Note
This chronological ledger preserves the state and verification claims recorded by each delivery phase. Earlier statements are historical, not current capability declarations. Use the documentation map, current module contracts, and runtime capability catalog before publishing a support claim.
- Configured
products/desktop/build.gradle.ktswith essential JPMS runtime modules (jdk.unsupported,jdk.crypto.ec,jdk.crypto.cryptoki,java.sql,java.naming,java.management,java.scripting,java.compiler,java.instrument,java.security.jgss) to resolve Netty bootstrap (sun.misc.Unsafe), SQLite JDBC, and SSL provider dependencies in nativejlinkpackaged distributions.
- Implemented
TrafficErrorBannerin:ui:desktop:trafficand wiredTrafficIntent.DismissEngineErrorandTrafficState.engineErrorMessageto present clear, dismissible visual error feedback whenever port binding fails or proxy engine errors occur.
- Executed full multi-module
./gradlew test checktest suite (232 tasks passed). - Executed
./gradlew :products:desktop:createDistributableto verify nativejlinkruntime image generation and distribution assembly.
- Designed mathematically centered master SVG logos, symbols, and wordmarks with balanced 70.92px horizontal and 81.60px vertical margins in
../desktopBrand/svg/. - Generated brand kit via LogoLoom MCP (
export_brand_kit,optimize_svg) with 25 web and social assets in../desktopBrand/kit/. - Compiled native platform desktop icons: macOS
.icns(315 KB), Windows 7-layer.ico(27 KB), and Linux FreeDesktop.pngsuite in../desktopBrand/. - Documented brand standards in
docs/brand_guidelines.md.
- Replaced legacy application resources in
products/desktop/src/jvmMain/resources/icons/with the official centered icons (KNet.icns,KNet.ico,KNet.png,KNet.svg). - Verified Compose Desktop window icon (
DesktopBootstrap.kt) and sidebar branding badge (NavigationOverlay.kt). - Verified native packaging builds with
./gradlew :products:desktop:createDistributableand./gradlew :products:desktop:packageDmg(products/desktop/build/compose/binaries/main/dmg/KNet-1.0.0.dmg).
- Configured
TargetFormat.ExealongsideTargetFormat.Msiinproducts/desktop/build.gradle.ktswith consistentupgradeUuid,perUserInstall, andshortcutoptions so Windows setup executables embedKNet.icodirectly into the PE header. - Designed high-DPI Retina installer window background (
../desktopBrand/dmg/knet-dmg-background.png,../desktopBrand/dmg/knet-dmg-background@2x.png) with KNet dark theme, logo, and drag-to-Applications layout. - Configured
.github/workflows/release-desktop.ymlwithcreate-dmgpost-processing andfileiconstamping for macOS branded DMG packaging (KNet-${VERSION}-mac.dmg). - Added
Package macOS Portable Zipstep (KNet-${VERSION}-mac.zip) using Apple'sdittoutility to preserve native.appbundle icon attributes and permissions directly in Finder upon extraction. - Added
Package Windows Portable Zipstep (KNet-${VERSION}-windows-x64.zip) using PowerShellCompress-Archiveto provide a zero-installation, non-admin direct-run package for Windows users. - Embedded
knet.desktopFreeDesktop launcher entry andknet.pngapplication icon into the root of Linux universal portable tarballs (knet-${VERSION}-linux-x64.tar.gz,knet-${VERSION}-linux-arm64.tar.gz) for single-click GUI execution. - Added
ubuntu-24.04-armnative GitHub runner matrix target in.github/workflows/release-desktop.ymlto build Linux ARM64 packages (.deb,.rpm, andknet-${VERSION}-linux-arm64.tar.gz). - Restructured
.github/workflows/release-desktop.ymlinto a two-stage pipeline (build-packagesmatrix + singlepublish-releaseaggregator job) generating a structured Markdown distribution table and publishing all multi-platform assets atomically with a single clean changelog. - Verified with
./gradlew check :products:desktop:createDistributable(236 tasks passed).
Started on 2026-08-18 from the approved target architecture in docs/target_architecture_and_implementation_plan.md.
Completed on 2026-08-18:
- Added the stable
:core:traffic,:core:connectivity,:application:desktop, and:connectivity:desktopmodule boundaries without moving current runtime behavior. - Established canonical shared
HttpRequestSnapshot,HttpResponseSnapshot, andHttpExchangeSnapshotcontracts for API Studio, Traffic, Breakpoints, collections/replay, inspectors, and export. - Kept body bytes out of shared snapshots through
BodyRef, boundedBodyRange/BodyChunkaccess, and explicit capture outcomes. - Added UI-neutral proxy runtime, paged traffic query, connectivity context, setup descriptor, and managed mechanism contracts.
- Added a
MODULE.mdresponsibility contract at all 41 Gradle project roots and the centraldocs/module_responsibility_index.mdindex. - Added configuration-cache-compatible
verifyArchitectureFoundationGradle checks for module documentation coverage and new inner-layer dependency rules. Every modulecheckdepends on these guardrails. - Preserved existing production paths for later compatibility-adapter migrations; no proxy, storage, or UI runtime was switched in this phase.
Verification passed with ./gradlew check :products:desktop:createDistributable: 258 actionable tasks, 55 executed and 203 up-to-date.
Completed on 2026-08-18:
- Added explicit desktop compatibility mapping from current
HttpTransactionEntity/domain values toHttpRequestSnapshot,HttpResponseSnapshot, andHttpExchangeSnapshotwithout introducing a reverse dependency into:core:traffic. - Added opaque versioned legacy
BodyIdand cursor codecs; neither filesystem paths nor cursor internals cross the data adapter boundary. - Added
BodyAccess, boundedBodyRange/BodyChunkreads, andLoadTrafficExchangeDetailsUseCasewith a one-mebibyte preview limit per request or response. - Implemented
LegacyTrafficQueryAdapterover the existing Room table with newest/oldest keyset paging, database-side method/status filtering, parsed-host filtering, and compact monotonic invalidation signals. - Added schema v10 with composite time, method, and response-status traffic indexes plus a non-destructive v9-to-v10 migration.
- Migrated the Traffic inspector detail-loading path to the canonical application use case while leaving the existing live-list and proxy write paths operational.
- Added compatibility parity, paging, filtering, invalidation, bounded-range, and payload-root containment tests.
- Updated affected module ownership contracts and the central responsibility index.
Verification passed with ./gradlew check :products:desktop:createDistributable: 258 actionable tasks, 67 executed and 191 up-to-date.
The architecture program did not stop at Phase 8: those phases established only the additive foundation and one canonical Traffic detail vertical slice. The board below records the later completed mandatory phases and explicitly gated optional product/protocol increments.
The source of truth for boundaries, invariants, future-feature isolation, and detailed exit criteria is docs/target_architecture_and_implementation_plan.md. This board tracks implementation status against that target.
| Target architecture phase | Repository delivery phase | Current state |
|---|---|---|
| Target 0: contracts, baselines, guardrails | Phase 7 and Phase 9 | Complete: module/dependency guardrails, ADRs, deterministic fixtures, and measured proxy/storage resource baselines are present |
| Target 1: P0 security/correctness containment | Phase 9 | Complete: listener/trust/authority/lifecycle/ordering/reference/migration/connection-policy containment and measured resource recovery gates pass |
| Target 2: stable core/application seams | Phases 7, 8, 9, and 10 | Traffic query/detail, proxy control, capture ingress, body maintenance, direct HTTP recording, and clear/session-rotation seams are present; remaining UI and breakpoint seams remain |
| Target 3: canonical session writer/store/query | Phase 10 | Complete: canonical contracts, schema v12, body store, bounded writer, indexed query, gaps, retention/recovery, finalized-orphan reconciliation, migrating reads, bounded live compatibility, active clear rotation, direct recording, restart-boundary recovery, legacy-writer removal, and the 100,000-row gate are present |
| Target 4: streaming proxy/bounded capture | Phase 11 | Complete: request/response streaming, bidirectional backpressure, bounded canonical capture, typed cancellation, compatibility gates, runtime metrics, and capacity/churn gates pass |
| Target 5: breakpoints/UI/dependency migration | Phase 12 | Complete |
| Target 6: semantic inspector architecture | Phases 13 and 106 | Complete; GraphQL and bounded SSE preview are supported, while live SSE is an additive experimental contribution |
| Target 7: connectivity and portal isolation | Phase 14 | Complete for manual/PAC/Apple/ADB and the isolated setup listener |
| Target 8: pairing/mobile-ready ingress | Phase 15 | Complete |
| Target 9: companion/relay product | Phase 16 | Optional product scope not activated; foundations complete and capability unavailable |
| Target 10: protocol increments | Phases 17 and 106 | HTTP/2, native gRPC, HTTP/1.1 WebSocket, modern GraphQL WebSocket, and live SSE are additive experimental increments; HTTP/3 remains pending |
| Target 11: performance/production gates | Phase 18 | Standard gate complete; extended-duration soak is a release operation |
This is the next mandatory phase. It completes the unimplemented parts of target architecture Phases 0–2 before deeper capture and proxy replacement.
Started on 2026-08-18.
Completed in the first containment slice:
- Added focused accepted ADRs for dependency direction, traffic/body ownership, listener access, connectivity/companion isolation, and protocol capability truth.
- Made loopback and strict upstream TLS the default production path; application startup rejects unauthenticated LAN/wildcard exposure before binding.
- Added strict authority parsing for CONNECT/Host and prevented upstream hosts or unknown local routes from invoking the setup portal.
- Made proxy start atomic and retryable, made stop await listener/event-loop termination, and registered process-owned proxy/writer shutdown before database close.
- Enforced configured TCP-connect, TLS-handshake, read-idle, write-idle, graceful-shutdown, total/per-client downstream, and total upstream limits inside Netty.
- Fixed breakpoint request/response reference and promise ownership across forward, drop, timeout, disconnect, error, and handler-removal paths.
- Preserved HTTP/1 response ordering with a bounded compatibility queue until the streaming transport replaces aggregation.
- Replaced racing callback persistence with one bounded ordered compatibility writer; late pending callbacks cannot regress complete rows and orphan responses cannot fabricate requests or bodies.
- Removed destructive Room fallback, supplied missing historical migrations, and proved v1-to-current-schema data preservation.
- Secured certificate and payload directories/files, made writes atomic and filenames opaque/contained, and made clear-traffic await both file and database removal.
- Routed the production Traffic start/stop/state path through
:application:desktopuse cases andProxyRuntime. - Added executable resource gates for 24 concurrent loopback clients, an 8 MiB aggregated response, slow upstream peers, abrupt downstream disconnects, ten listener lifecycle repetitions, heap/direct-memory peaks, file-descriptor recovery, and canonical metadata storage growth.
- Added a 100,000-row schema-v11 fixture proving database-side host/method/status filtering returns a bounded 100-item keyset page without full-session materialization.
Measured on 2026-08-18 using a Macmini9,1 (Apple M1, 8 GiB), macOS Darwin 24.6.0, and OpenJDK 21.0.8:
- 24 clients × 256 KiB: 31 ms measured transfer window, 202,950,193 bytes/second, 10,336,088-byte peak heap delta, zero-byte measured pooled-direct delta, 118 peak descriptor delta, and descriptors recovered within the declared allowance.
- 8 MiB response: 29 ms, 8,725,912-byte peak heap delta, and 16,777,216-byte pooled-direct delta.
- Six slow upstream peers plus 24 abrupt disconnects: 1,583 ms with descriptor recovery; ten start/stop repetitions: 2,145 ms with descriptor recovery.
- 100,000 canonical exchanges: fixture creation 1,201 ms, filtered 100-row page 2 ms, and 46,242,224 bytes across SQLite database/WAL/sidecars.
Verification checkpoint on 2026-08-18: ./gradlew check :products:desktop:createDistributable passed after the in-progress Phase 10 additions with 258 actionable tasks (59 executed, 199 up-to-date). The desktop distribution was produced successfully.
At the Phase 9 checkpoint the existing capture path remained authoritative. Phase 10 subsequently switched proxy callbacks to one exclusively selected canonical writer while preserving legacy rows through read compatibility.
Exit criteria: the target Phase 0–2 security, lifecycle, ordering, leak, and dependency tests pass; fresh runtime exposure is safe by default; one application-owned proxy-control path is in production use.
Started on 2026-08-18. Implemented additively with production registration delayed until its safety gates passed:
- Added portable monotonic connection/exchange/body/gap capture events and application
CaptureIngress/BodyStorecontracts. - Added pre-allocation body-byte reservations, a bounded metadata channel, explicit degraded health, compact durable saturation gaps, and one ordered writer per test session.
- Added
FileBodyStorewith opaque hashed paths, owner-only permissions, bounded writes, SHA-256 digesting, explicit truncation, fsync/atomic finalize, range reads, delete, abandoned-temp reconciliation, and bounded opaque finalized-object inventory. - Added non-destructive schema v11 for sessions, connections, exchanges, body objects, duplex messages, inspection annotations, capture gaps, and deletion outbox with target query indexes. Schema v12 adds nullable/backfillable opaque object keys for safe finalized-orphan reconciliation.
- Added monotonic conditional DAO transitions so late response/body events cannot change a terminal exchange.
- Added a canonical indexed query adapter with database-side host/method/status filtering, keyset cursors, page-batched body metadata, and bounded body access.
- Added deletion-outbox reconciliation and isolated tests for writer ordering, body ownership/truncation, saturation gaps, query mapping, and file/database convergence.
- Added crash-safe closed-session clear: one Room transaction queues body deletions before removing metadata, followed by bounded retryable file reconciliation.
- Added a temporary
LegacyCallbackCaptureAdapterthat maps full request/response callbacks into canonical heads, bounded reservation-before-copy body chunks, explicit orphan/saturation gaps, and monotonic terminal events. - Cut production composition directly to the canonical writer; integration tests prove current-schema metadata and opaque bodies are written while the legacy table and payload directory remain untouched.
- Added the 100,000-row indexed query/storage regression gate described in Phase 9.
- Added oldest-first global retention with independently enforced terminal-session count and stored-byte limits, bounded eviction passes, and deletion-outbox convergence. Active sessions are never evicted.
- Added bounded startup recovery for interrupted sessions, connections, and exchanges; abandoned temporary objects; pending deletions; and finalized-body metadata whose object is missing.
- Added storage-key backfill plus bounded finalized-object inventory so a body file that survives a crash before metadata attachment is deleted without exposing paths or loading the entire object store.
- Added a migration-period query adapter that keeps legacy schema-v10 rows readable while routing arbitrary schema-v11 sessions, canonical-first exchange lookup, body identifiers, and change generations through the canonical store.
- Migrated the compatibility live repository to a bounded 1,000-row metadata merge of legacy traffic and the newest canonical session. Direct lookup and lazy body loading prefer canonical records, export inherits those repository paths, and clear converges legacy data plus closed canonical sessions.
- Added application-owned traffic clear orchestration. A running proxy swaps a stable capture sink to a fresh canonical session, terminalizes unfinished old capture state without closing client transport channels, and only then deletes closed traffic metadata and body files; focused tests prove an existing connection captures its next exchange in the replacement session.
- Added
TrafficRecordPort/RecordHttpExchangeUseCasewith sharedRequestHead/ResponseHeadmetadata and defensive-copy body ownership. Direct API Studio executions now use this boundary and reuse the active proxy session or one lifecycle-owned direct session without duplicate proxied records. - Added direct-to-proxy session handoff tests proving exactly one canonical session remains active, and a reopened-database restart-boundary integration proving interrupted session/connection/exchange ownership is recovered before a new writer admits capture.
- Removed
CaptureWriterSelection, the proxy repository's pending/replace legacy persistence queue, its payload writer, and the dormantrecordTransaction(HttpTransaction)feature path. Legacy schema rows remain read-only migration input for query/export/clear compatibility.
Final Phase 10 verification on 2026-08-18 passed git diff --check && ./gradlew check :products:desktop:createDistributable with 258 actionable tasks (119 executed, 139 up-to-date). The desktop distributable was produced successfully after direct recording, restart recovery, and legacy-writer removal.
Exit criteria: one monotonic writer owns every new session; saturation and gaps are explicit; clear/retention/recovery converge; 100,000-row paging stays bounded.
Completed in the first Phase 11 slice on 2026-08-18:
- Removed default upstream
HttpObjectAggregator; response heads/content/trailers now flow incrementally through the HTTP/1 transport. - Coupled upstream reads to completion of downstream writes with manual Netty read advancement, bounding queued data for slow clients.
- Preserved response-breakpoint behavior behind an explicit composition predicate: only an enabled response rule installs the bounded compatibility aggregator, while the proxy engine remains independent from rule types.
- Added an engine-owned, persistence-neutral streaming capture sink with real connection/exchange identities and reservation-before-copy body allocations.
- Cut desktop production capture directly to the canonical ingress/writer and removed
LegacyCallbackCaptureAdapter; direct API Studio records share the same streaming session owner. - Added explicit streaming-body completion so canonical
BodyRefmetadata preserves full observed bytes and a typed complete/truncated outcome after copying stops. - Removed process-global pipeline initializers; each proxy runtime now owns an immutable extension list.
- Replaced clear-all certificate caching with single-flight asynchronous generation, LRU/idle/weight bounds, and a runtime-owned bounded crypto executor.
- Removed the unused competing upstream connection-pool implementation while retaining one-shot ownership as the single current path.
- Added a 500 MiB generated-response qualification that retains no test payload, uses the new capture sink, and asserts bounded heap/direct memory plus a 10 MiB capture limit.
- Replaced default downstream aggregation with incremental request-head/content forwarding and explicit downstream-read-to-upstream-write/writability coupling.
- Kept existing breakpoint behavior behind bounded request/response aggregation predicates supplied by desktop composition; portal routing now consumes request heads without forcing aggregation.
- Added provisional
100 Continue, request/response trailer, downstream half-close, early-response, and typed source-cancellation handling. - Added constant-time event-loop lag metrics and removed the proxy engine's final
ProxyTrafficListenercallback surface, leavingProxyCaptureSinkas its only capture boundary. - Added a 128 MiB generated-upload qualification, the declared 100 concurrent × 10 MiB generated-response workload, and a configurable connection-churn soak gate.
Measured qualification: 524,288,000 bytes forwarded in 746 ms, 10,485,760 bytes admitted to capture, 27,557,120-byte peak heap delta, and zero-byte measured pooled-direct delta.
Additional measured gates on 2026-08-18:
- 128 MiB upload: 593 ms, 10 MiB captured, zero-byte measured heap delta, and 4 MiB pooled-direct delta.
- 100 concurrent × 10 MiB responses: 1,704 ms, 59,391,344-byte peak heap delta, and 67,108,864-byte pooled-direct delta.
- 1,000 connection-churn requests across 20 workers: 760 ms with descriptors converging to 142 (inside the declared allowance);
knet.proxy.soak.cyclesscales the same gate for release soak runs.
Current Phase 11 checkpoint on 2026-08-18 passed git diff --check && ./gradlew check :products:desktop:createDistributable with 258 actionable tasks (57 executed, 201 up-to-date). The desktop distributable was produced successfully after the response-breakpoint compatibility gate was added.
Exit criteria: a 500 MiB response forwards with bounded memory; capture truncation never breaks forwarding; ordering, slow-peer, disconnect, keep-alive, direct-memory, and soak tests pass.
- Add application-owned breakpoint coordination with compiled rule snapshots and bounded pause time, bytes, and connection count.
- Migrate the Traffic list from
Flow<List<HttpTransaction>>to canonical keyset pages and generation-based refresh. - Split list/detail/runtime status ownership and keep only bounded detail previews in UI state.
- Migrate Traffic-to-API-Studio, replay, collections, breakpoints, and export to the shared
HttpRequestSnapshot/HttpResponseSnapshot/HttpExchangeSnapshotcontracts and boundedBodyAccess. - Move presentation models out of core and migrate every desktop ViewModel away from concrete engines, storage, and desktop adapters.
- Consolidate
:engine:trafficrewrite behavior and retire superseded session/simulator paths only after their callers are gone.
Completed on 2026-08-18: Traffic uses canonical keyset pages with a 1,000-row retained window and bounded detail previews; 100,000-row storage and UI tests pass. PrepareTrafficRequestUseCase supplies the common HttpRequestSnapshot to replay/export/API Studio and rejects silent body truncation. BreakpointCoordinator owns bounded rules, pauses, byte/connection budgets, decisions, patches, cancellation, and deadlines. Presentation-only traffic models moved to UI; legacy live presentation/repositories and the dormant :engine:traffic module were removed. Certificate, settings, traffic, and API Studio runtime calls now cross application contracts. An executable UI isolation rule prevents concrete runtime/storage imports; the pure formatter library is the narrow documented exception.
Exit criteria: shared canonical HTTP models serve all applicable features; no desktop UI module depends on concrete runtime/storage; Traffic memory follows page and preview limits at 100,000 rows.
- Add the budgeted asynchronous inspector scheduler, bounded body access, versioned annotations, persistence/query adapters, and generic UI renderer.
- Adapt GraphQL to the inspector contract without putting parsing on forwarding or capture paths.
- Classify unsupported/dormant WebSocket and gRPC code honestly until their transport prerequisites are delivered.
- Publish a runtime capability catalog backed by production end-to-end tests.
Completed on 2026-08-18: a bounded concurrency/body/deadline scheduler runs after capture, persists generic versioned annotations, isolates cancellation/timeout/failure, and renders generic results in Traffic detail. GraphQL and a bounded post-capture SSE preview are registered inspectors with production-path end-to-end tests. Live SSE capture, API Studio execution, event persistence, and breakpoints are not delivered by this phase. Dormant WebSocket/protobuf transport/parser stubs were removed, and unsupported capabilities remain UNAVAILABLE.
Exit criteria: inspector failure or timeout cannot affect forwarding/capture; annotations are rerunnable; every Supported claim has an end-to-end test.
- Implement the desktop network snapshot monitor and independent manual, PAC, Apple profile, and ADB packages behind
:core:connectivity/:application:desktopcontracts. - Add descriptor-driven setup UI, versioned artifact caching, deterministic PAC generation, and golden tests.
- Move portal delivery to a strict-authority separate adapter/listener and remove portal routing from the proxy pipeline.
- Reconcile IPv4, IPv6, Wi-Fi, Ethernet, hotspot, and VPN network changes without unnecessary proxy restarts.
Completed on 2026-08-18: manual proxy, deterministic PAC, deterministic Apple profile, ADB reverse, versioned artifacts, and the IPv4/IPv6/default-route/VPN network monitor register independently. Setup delivery runs on a separate strict-authority loopback listener. The obsolete :engine:portal proxy-handler module was removed. Network transitions republish connectivity state without restarting the proxy or rotating capture.
Exit criteria: mechanisms register additively; arbitrary upstream setup-like paths are forwarded normally; network transitions update descriptors/health independently.
- Expand portable pairing invitation, handshake, device, credential, revocation, expiry, replay, and scope state.
- Add application pairing coordination and secure trusted-device storage.
- Add loopback-only internal gateway binding, typed ingress identity, device-scoped access policy, and QR/deep-link onboarding descriptors.
- Prove an authenticated standard proxy byte bridge under backpressure and network reconnection without restarting the proxy or capture session.
Completed on 2026-08-18: one-shot expiring invitations, Ed25519 device proof, scoped credentials, replay defense, revocation, and durable trusted-device storage are implemented. The initial standalone encrypted-file adapter was consolidated into the schema-v15 Room registered-device source of truth during Phase 22; only public keys and one-way credential/invitation digests are persisted. A bounded loopback standard-proxy gateway authenticates and strips local credentials, bridges under stream backpressure, attributes canonical traffic through neutral ingress identity, rejects admission overflow, and terminates active sockets on revocation. QR/deep-link onboarding contains the one-time invitation material without changing proxy, traffic, PAC, or manual-proxy contracts.
Exit criteria: a test device can pair, bridge a scoped proxy stream, appear with the correct ingress identity, and be revoked without changing ordinary PAC/manual/proxy/traffic behavior.
The application layer is split into explicit siblings: JVM-only desktop orchestration lives in
:application:desktop, while Android/iOS companion workflows live in :application:companion. The parent
application/ directory is documentation and Gradle namespace only; neither sibling depends on the other.
- Add Android/iOS companion applications and platform VPN adapters only after product scope is approved.
- Add desktop companion connectivity plus direct tunnel transport; add an end-to-end encrypted relay carrier only if required.
- Reuse the authenticated internal proxy binding, canonical traffic/session architecture, pairing identity, and application queries.
- Do not modify the proxy forwarding contract, canonical traffic/store contracts, or existing PAC/manual/Apple implementations.
Exit criteria: direct and relay paths pass the same proxy conformance suite; revocation and network transition behavior remain bounded and deterministic.
The Android-first shared foundation was activated on 2026-08-26. Portable companion domain models, application
contracts/use cases, versioned persistence/control protocol, shared presentation state/ViewModel, Android Keystore
identity/credential adapters, Android network/VPN-consent lifecycle boundaries, and Android/iOS compile gates now
exist as additive modules. See
android_companion_foundation_plan.md. No Android product UI, concrete
VPN/TUN packet backend, authenticated direct tunnel, desktop companion control/tunnel server, or relay carrier has
been added yet. Runtime capability status therefore remains UNAVAILABLE for Mobile Companion, VPN, and Relay
until those real implementations and physical-device gates pass.
Deliver independently after Phases 11 and 13 establish the transport and inspector seams:
- WebSocket upgrade/frame transport and duplex storage/UI.
- SSE streaming inspector. [COMPLETED — EXPERIMENTAL]
- HTTP/2 ALPN and multiplexed stream transport.
- gRPC inspector over supported HTTP/2.
- HTTP/3/QUIC transport after an explicit library/platform decision.
Each increment must satisfy conformance, failure, backpressure, body-limit, lifecycle, and long-run tests before being marked Supported.
The bounded post-capture SSE semantic preview remains independently supported. Live Traffic event capture,
API Studio streaming, generic message persistence, bounded parsing, and event breakpoints are implemented as the
experimental Phase 106 increment specified in
sse_target_and_implementation_plan.md. GraphQL HTTP semantics were
completed in Phase 13.
HTTP/2 is implemented end to end as an EXPERIMENTAL capability with local real-socket tests; its remaining
cross-platform/device and release-soak gates are tracked in docs/http2_target_and_implementation_plan.md.
Native gRPC capture, message breakpoints, descriptor-driven inspection, and API Studio are now implemented as an
independent :engine:grpc increment. The WebSocket increment completed its local JVM gate on 2026-08-25 with a
generic post-upgrade duplex proxy seam, RFC 6455 framing/capture, message breakpoints, Traffic presentation, and an
additive API Studio workspace. HTTP/3 remains an independent future increment. Experimental transports are not
marked SUPPORTED until their external qualification matrices pass.
Implementation started on 2026-08-25 from the approved architecture and gates in
sse_target_and_implementation_plan.md. The increment keeps SSE inside
the canonical HTTP exchange and HTTP API Studio workspace while adding bounded live event records, Traffic
presentation, streaming execution, and event breakpoints through existing extension seams. Local implementation
and deterministic JVM evidence are complete. Identity/gzip/deflate streaming is implemented through one bounded
codec registry; cross-platform execution, real-device evidence, the default release soak, and remaining lifecycle
rows remain before SUPPORTED promotion.
- [COMPLETED] Add protocol-neutral post-
101 Switching Protocolsduplex observation/transformation hooks to:engine:proxywithout adding WebSocket parsing to the proxy. - [COMPLETED] Add
:engine:websocketwith bounded incremental RFC 6455 framing, canonical child-message capture, payload presentation, request descriptors, message breakpoints, API Studio execution, and module documentation. - [COMPLETED] Add
:ui:desktop:apiStudio:websocketwith transient blank authoring, shared saved/unsaved collections, full-duplex message controls, and bounded event presentation. - [COMPLETED] Register product DI, truthful runtime capabilities, protocol-lab coverage, and the root
webSocketQualificationverification gate. - [COMPLETED] Locally qualify masking, fragmentation, control frames, close/cancel/error lifecycle, backpressure,
capture limits, replacement framing,
ws, versioned persistence, and API Studio lifecycle without launching the desktop app.wssuses the already-qualified CONNECT/TLS path but remains in the external device matrix.
Detailed evidence, limits, and explicit exclusions are recorded in
websocket_qualification.md.
This additive semantic increment targets the modern graphql-transport-ws protocol over KNet's existing HTTP/1.1
WebSocket transport. It keeps one canonical WebSocket parent exchange and child-message stream while adding
operation-aware Traffic presentation, layered message breakpoints, and a contributed GraphQL subscription API
Studio editor. The proxy remains unaware of GraphQL semantics, and the existing raw WebSocket tooling remains the
fallback.
The modern graphql-transport-ws semantic increment is implemented and has a dedicated local qualification gate.
It reuses one canonical WebSocket parent/message stream, adds bounded operation-aware presentation and message
breakpoints, and contributes a saved/unsaved GraphQL subscription editor to the shared API Studio workspace.
External wss, browser/mobile, network-transition, and soak evidence still gates promotion beyond
EXPERIMENTAL. Architecture, limits, and exact evidence are recorded in
graphql_websocket_target_and_implementation_plan.md and
graphql_websocket_qualification.md.
Performance and security tests are added during every preceding phase; this phase closes the overall capacity program.
- Enforce repeatable 10/100/1,000-connection, churn, 500 MiB, concurrent-body, slow-peer/disk, and capture-saturation workloads.
- Enforce 1,000/10,000/100,000-row storage and UI workloads.
- Run multi-hour heap, direct-memory, thread, file-descriptor, database, and body-directory soak tests.
- Cover disk-full, corrupt body, schema initialization/reset policy, network transitions, pairing/tunnel failure, and shutdown deadlines.
- Publish the supported capacity envelope and align security/protocol capability claims with test evidence.
Exit criteria: no unbounded production path remains and resource use stabilizes under configured retention.
Completed engineering gate on 2026-08-18: phase18ReleaseGate aggregates architecture checks, every included module's check task, and desktop packaging. Its final run passed all 254 actionable tasks and produced the desktop distributable. Tests cover 500 MiB response streaming, 128 MiB upload, 100 concurrent 10 MiB responses, 1,000-connection default churn, slow peers, admission saturation, lifecycle/descriptor recovery, 100,000-row indexed paging, the 1,000-row UI window, retention, crash recovery, schema-v13 persistence, disk-exhaustion degradation, corrupt-body integrity marking, network transitions, pairing expiry/replay/scope/revocation, active gateway revocation, and shutdown ordering. Earlier development schemas now reset by policy. The extended release soak remains a deliberately parameterized release operation (-Dknet.proxy.soak.cycles=...); no claim is made that a multi-hour run occurred in this implementation session.
Post-phase architecture cleanup on 2026-08-18 moved every Koin binding declaration into :products:desktop, organized by product feature. :data:desktop and UI feature modules no longer define composition modules; they expose adapters, use cases, ViewModels, and screens for the product root to assemble. verifyCompositionOwnership now prevents binding declarations from drifting back into reusable modules.
Post-phase development cleanup on 2026-08-18 removed backward-compatibility code that was no longer justified for an unreleased product. The old transaction table and schema migrations, old payload-path reader, certificate pipe-format importer, duplicate domain HttpRequest/HttpResponse/HttpTransaction/HttpTimings, callback traffic listener/internal correlation header, old proxy repository API, interception-session API, unused HTTP executor facade, and dormant session/export implementations are gone. Schema v13 is canonical-only and older local databases intentionally reset. Proxy, breakpoint, Traffic, API Studio, and persistence now share :core:traffic snapshots and application contracts directly. The cleanup was verified by phase18ReleaseGate: all 254 actionable tasks passed and the desktop distributable was produced.
Started on 2026-08-18 after the Kotlin/JVM usage audit. This phase keeps JVM APIs where Netty, JCA/JCE, Room, sockets, filesystem permissions, desktop integration, or blocking transport adapters genuinely require them while removing avoidable Java usage and false portability from shared source sets.
Completed on 2026-08-18:
- Replaced the authenticated gateway's
runBlocking, latches, and private executors with one owned coroutine scope, suspend authentication, a bounded elastic IO view, active-socket cancellation, and structured duplex copying. - Moved clipboard operations to an asynchronous Compose
Clipboardfoundation API. The current Compose Desktop transfer-object adaptation is confined to one:ui:corejvmMainfile; feature modules contain no AWT clipboard code. - Isolated common/JVM boundaries for HTTP exception classification, proxy-client cache synchronization, pointer cursors, and editor pointer input. Desktop host-platform detection moved out of the domain source set.
- Replaced Java UUID, Base64, standard charset, URL/form decoding, deque, linked-map imports, wall-clock duration measurement, and timestamp-derived identity generation with Kotlin APIs where a portable equivalent exists.
- Replaced direct settings AWT/filesystem access with an injected feature-owned platform-action contract implemented only by the desktop product root.
- Replaced synchronized certificate collection wrappers with an explicit manager state lock covering compound mutations, snapshots, rule resolution, and persistence ordering.
- Added
verifyKotlinFirstSourcesto the architecture and release gates. It rejects JVM references incommonMain, productionrunBlocking, Java UUID, avoidable Java utility imports, and AWT clipboard use outside the approved platform adapter. - Updated affected module ownership documents and added regression tests for Unicode form decoding, settings platform delegation, and concurrent certificate-rule snapshots.
Required JVM APIs remain intentionally isolated where Netty, blocking sockets, JCA/JCE, Room and filesystem operations, desktop shell/trust-store integration, JSR-223, compression streams, or the Compose Desktop clipboard entry implementation require them. These are implementation details, not portable contracts.
Final verification on 2026-08-18 passed git diff --check, targeted tests (139 actionable tasks),
and phase18ReleaseGate (255 actionable tasks). All included module checks passed and the desktop
distributable was produced successfully.
Exit criteria: all designated portable source sets are JVM-import-free, required JVM integrations stay
isolated in implementation modules, no production runBlocking or feature-level AWT clipboard path
remains, and phase18ReleaseGate passes with the Kotlin-first verification enabled.
Started on 2026-08-18 to close IDE/compiler hygiene after the Kotlin-first boundary work.
Completed on 2026-08-18:
- Retained explicit
publicvisibility in:application:desktop,:core:traffic,:core:connectivity, and:connectivity:desktop, whereexplicitApi()makes the modifier part of the enforced API contract. - Removed 1,021 redundant
publicmodifiers from implementation, persistence, product, presentation, and test sources without changing declaration visibility or behavior. The generated application-metadata template now follows the same convention. - Replaced deprecated Compose preview, classpath painter-resource, and non-auto-mirrored directional
icon APIs. The shared application logo is now owned by
:ui:coreand loaded through Compose Multiplatform Resources by both desktop bootstrap and navigation UI. - Removed every
java.timeimport and qualified reference from repository Kotlin source.kotlin.time.Clockandkotlin.time.Instantnow own wall-clock acquisition, instant conversion, and duration arithmetic.kotlinx-datetime0.8.0 supplies the multiplatform local calendar and system-time-zone conversion that deliberately does not belong to the Kotlin standard library. - Added the shared
KNetDateTimepresentation formatter in:ui:coreand deterministic UTC tests for ISO date keys, local time rendering, compact date rendering, and millisecond padding. - Extended
verifyKotlinFirstSourcesto reject redundant visibility outside explicit-API modules, deprecated Compose resource/preview APIs, non-auto-mirrored directional icons, legacy date formatting, and anyjava.timeuse in production or test Kotlin sources. - Opted the two intentional
expect/actualclass boundaries into Kotlin's documented compiler flag so clean compilation does not rely on per-source warning suppression.
Required Java/JVM APIs remain in JVM implementation source sets for Netty, sockets, JCA/JCE and Bouncy Castle certificates, filesystem permissions and atomic replacement, Room/SQLite, desktop shell/AWT adapters, JavaScript engines, and compression streams. They have no equivalent Kotlin standard-library implementation that would improve portability or correctness.
Final verification passed git diff --check, the extended verifyKotlinFirstSources policy,
targeted warning-free affected-module compilations, every included module check and test, desktop
runtime-image creation, and phase18ReleaseGate (258 actionable tasks). The desktop distributable
was produced successfully.
Exit criteria: redundant visibility warnings are removed outside explicit-API modules, explicit-API
contracts still compile, Kotlin-first guards pass, deprecated production usages found by the audit are
resolved or documented as platform requirements, and phase18ReleaseGate succeeds.
Started on 2026-08-18 after the repository-wide duplicate-model audit. This phase removes semantic translation chains while retaining boundary types that add real transport, persistence, editor, or rendering behavior.
Implemented:
- Replaced the HTTP client's body-kind/body/form-parameter tuple with one
OutboundRequestBodyhierarchy;ApiRequestAuth,ExecutionResult, and canonicalExchangeTimingsnow cross the outbound execution boundary without client-owned duplicates. - Removed duplicate response/timing specifications. Traffic, API Studio response rendering, and the
reusable HTTP panel consume canonical
ResponseHeadandExchangeTimings; UI projections add only presentation lifecycle, logs, assertions, selection, or formatting. - Added the evidence-driven leaf
:core:scriptingmodule and moved shared language, phase, snippet, and immutable assertion values there. Collections, application contracts, UI editors, and the script engine consume those contracts directly. - Replaced application/UI/interceptor breakpoint copies with the single
BreakpointRuleandBreakpointPhasein:core:domain. Method matching remains typed as canonicalHttpMethod, and protocol criteria now survive repository-to-coordinator flow. - Consolidated content encoding in
:core:traffic; capture, storage, proxy, and body decoders use the same extensible value. - Made
StructuredPayloadState.GraphQLthe GraphQL data owner.GraphQlStatenow composes that payload and adds only active-tab UI state. - Removed duplicate Traffic inspector sub-tabs, code-editor context menu items, application menu items, unused explorer state, and duplicate API Studio network-error details.
- Removed certificate UI copies.
CertificateAuthoritySummary,ClientCertificateSummary, typedClientCertificateFormat, andMtlsRuleSpeccrossCertificateManagementdirectly. - Extended dependency-boundary verification for
:core:scripting,:core:domain, and the application module, and updated affected module responsibility contracts.
Intentionally retained:
- Room entities, Netty/Ktor transport objects, immutable engine observations, mutable editor drafts, script sandbox host objects, and UI projections where they add behavior rather than duplicate a semantic contract.
ResponseInspectorStatefor execution/loading/error/assertion presentation, andGraphQlStatefor active editor-tab state; neither is accepted by core traffic, persistence, or proxy APIs.
Exit criteria: duplicate-declaration audit finds one owner for every audited semantic cluster; architecture/Kotlin-first checks pass; all module tests and the packaged desktop release gate pass.
Final verification on 2026-08-18 passed git diff --check, the residual duplicate-declaration scan,
targeted migrated-module tests, verifyArchitectureFoundation, and phase18ReleaseGate (261
actionable tasks). Every included module check passed and the desktop distributable was produced.
Phase 22: Primary Wi-Fi Device Connectivity [IN PROGRESS — OPEN WI-FI SETUP IMPLEMENTED, DEVICE GATES PENDING]
Wi-Fi sharing will become the primary stock-phone connection path while the production proxy remains
loopback-only. The approved direction is an automatically managed, exact-interface LAN gateway in
:connectivity:desktop that accepts any reachable local-network client and forwards attributed byte streams
to the unchanged internal proxy. It will not introduce LAN behavior into :engine:proxy, traffic storage,
body handling, PAC generation, ADB, breakpoints, or inspectors.
The revised delivery includes truthful endpoint availability, a stable QR setup URL, an open LAN setup page,
Android CA and Apple profile downloads, CA/manual/PAC setup behavior, automatic proxy-lifecycle activation,
network-change recovery, a single-card Connect Device UI, real Android/iPhone conformance, and bounded
resource gates. No invitation, confirmation, or source approval is required for manual Wi-Fi proxy clients.
Future companion/VPN connectivity remains the authenticated option for remote networks and apps that ignore
system proxy settings.
Detailed architecture, phases, security limitations, module changes, and exit criteria are defined in
docs/wifi_connectivity_implementation_plan.md.
Superseded approval prototype checkpoint completed on 2026-08-18 and removed on 2026-08-19:
- Added canonical Wi-Fi sharing models, the application contract/use cases, and feature-grouped desktop DI.
- The prototype proved exact-interface LAN bridging, source attribution, quotas, and listener rollback. Its approved-source registry, invitations, token routes, and revocation controls were later removed when the product requirement changed to open local-client admission.
- Added network/proxy invalidation and atomic listener-start rollback without restarting the loopback proxy or clearing captured traffic.
- Corrected setup-provider availability so a loopback address is never advertised as phone-reachable.
- The isolated
:ui:desktop:connectivitymodule andConnect Devicenavigation were retained; the prototype device-management presentation was replaced by the focused single-card setup flow. - Added feature-grouped desktop composition bindings and focused UI state/QR tests.
- Passed the Kotlin-first/architecture foundation gate and focused application, connectivity, traffic, and persistence tests.
Companion identity persistence checkpoint completed on 2026-08-19. Room schema 15 stores registered companion identities, trusted-device public keys and credential digests, and one-time pairing invitation digests; its explicit 14-to-15 auto-migration preserves existing traffic and API Studio records. The temporary association between those identities and manual Wi-Fi sources was removed. Room identity now remains exclusively behind the authenticated pairing/companion boundary and is not consulted by the open Wi-Fi gateway.
Open Wi-Fi setup UX checkpoint completed on 2026-08-19. The Connect Device screen was reduced to one
Wi-Fi Proxy Setup card whose setup drawer owns the QR code and manual Android/iPhone instructions.
The exact-interface setup listener now uses one stable setup URL and a
resource-backed responsive HTML page with Android DER certificate and Apple configuration-profile downloads.
The obsolete manual Wi-Fi invitation, approval, registration, and known-device presentation were removed;
Room pairing identity remains reserved for the future authenticated companion path. Starting/stopping the
proxy now automatically starts/stops the LAN gateway, and any reachable local source is admitted under global
and per-source connection quotas.
Automated verification on 2026-08-19 passed the focused core-connectivity, application, desktop-connectivity, desktop-connectivity UI, desktop product, desktop-app, and architecture-foundation test/build gates. The resource-backed setup page, Android certificate route, Apple profile route, open-client forwarding, automatic proxy stop/restart recovery, and stale approval-symbol scan were verified without launching the desktop app.
Real Apple profile installation, Android/iPhone testing, IPv6 validation, and the final packaged capacity/security gate remain pending. These checks intentionally do not change the stable proxy, traffic, or connectivity application boundaries.
Completed on 2026-08-19: Traffic remains sorted newest-first, while its visible sequence column now numbers
the oldest retained interception as 1 and the newest interception with the highest number. Each newly
observed interception appears at the top with the next number. The presentation property was renamed from
the ambiguous id to sequenceNumber, and Traffic-to-API-Studio forwarding now uses the canonical exchange
identifier rather than the visible sequence number.
Verification passed :ui:desktop:traffic:jvmTest, verifyArchitectureFoundation, and git diff --check
without launching the desktop app.
Started on 2026-08-19: extract the right-edge animated drawer shell from the breakpoint feature into
:ui:core, migrate Live Intercept and Wi-Fi Proxy Setup to that shared primitive, and place connectivity
method cards in a top-left wrapping grid. Feature state and content remain owned by their feature modules;
no global drawer ViewModel or business-state coordinator is introduced.
Completed on 2026-08-19: KNetSideDrawer now owns non-modal right-edge placement, responsive standard and
expanded widths, slide animation, surface, and border. Live Intercept retains its breakpoint-specific queue
and editor behavior in :ui:desktop:breakpointManager; Wi-Fi retains its QR, endpoint, instructions, and
proxy actions in :ui:desktop:connectivity. The former Wi-Fi Dialog was removed, and the Wi-Fi card is the
first top-left item in a wrapping connectivity-method grid ready for additive cards.
Verification passed the :ui:core, breakpoint-manager, connectivity, desktop-app, and desktop-product test
suites plus verifyArchitectureFoundation (158 actionable tasks) and git diff --check, without launching
the desktop app.
Started on 2026-08-19 after identifying that request aggregation and the streaming/full proxy-handler choice were frozen when a downstream TCP connection was accepted. Rules added, enabled, disabled, or restored after that point could update the application coordinator while existing streaming connections continued bypassing the full-message breakpoint adapter. This phase will add a bounded runtime refresh boundary for breakpoint requirement changes, preserve streaming when no breakpoint requires aggregation, and add regression coverage for rule activation after a client connection already exists. The desktop application will not be launched during implementation verification.
Completed on 2026-08-19: ProxyRuntimeRepository now reduces application breakpoint state to distinct
request/response aggregation requirements and observes that state for its process lifetime. A requirement
change closes only active downstream child connections through the neutral engine boundary; it does not stop
the listener, rotate or clear traffic, replace the canonical capture session, or introduce rule knowledge
into :engine:proxy. Reconnected clients select the current streaming or bounded full-message pipeline.
Repository shutdown cancels the observer before stopping Netty, and repeated start/stop remains supported
until terminal close.
Two real loopback regression tests start with an already-connected streaming client, enable either a request
or response breakpoint, verify the stale connection is refreshed, reconnect, and prove the corresponding
phase is published as a pending application breakpoint before forwarding resumes. Focused and wider
verification passed :application:desktop:test, :engine:proxy:test, :engine:interceptor:test,
:data:desktop:jvmTest, :products:desktop:test, verifyArchitectureFoundation, and git diff --check
(149 actionable tasks in the wider gate). The desktop application was not launched.
Superseded on 2026-08-20 by Phase 75: rule changes are now evaluated per message through bounded selective aggregation. They no longer close established client connections, and the connection-refresh behavior above is retained only as historical migration context.
Started on 2026-08-19 after the live breakpoint path was found to evaluate only phase, method, and URL while the domain, Room mapper, and desktop editor each contained separate hardcoded GraphQL/gRPC/WebSocket branches. This phase replaces those closed branches with an application-owned protocol breakpoint extension registry. Each extension will own its typed criteria, bounded inspection, compiled matching, and persistence codec; the coordinator, proxy engine, canonical HTTP request/response models, and Room schema will remain protocol-neutral. GraphQL will become the first real extension, with its compact request observation retained by exchange identity for response-phase matching. Missing, invalid, or unavailable extensions will fail closed instead of matching unrelated traffic. Verification will cover operation-specific request and response breakpoints, generic HTTP behavior, persistence round trips, unavailable extensions, bounded ownership, and architecture dependency direction without launching the desktop application.
Completed on 2026-08-19: Breakpoint matching is now split into a stable transport matcher and an
application-owned BreakpointProtocolExtension registry. The coordinator, canonical HTTP exchange models,
proxy engine, persistence mapper, and desktop editor no longer branch on GraphQL, gRPC, WebSocket, or other
protocol names. An extension owns its protocol identifier, UI-neutral criteria schema, versioned persistence
payload, bounded inspection, compiled criteria, and semantic matcher. Unknown, unavailable, malformed, and
duplicate extensions fail closed.
GraphQL is the first installed extension. A shared Kotlin-serialization parser serves both traffic semantic inspection and live breakpoint matching, including bounded single and batch requests. Request observations contain only compact operation metadata and are retained by canonical exchange identity only when a response rule needs them; raw bodies are not cached and observations are removed after response evaluation. Both the Breakpoint Manager and Traffic quick-add flow use the same schema-driven application use case, so adding a new protocol does not require protocol-specific UI branches or proxy-engine changes. Existing generic HTTP rules continue through the built-in HTTP extension, while the unchanged Room columns store the open protocol identifier and opaque versioned payload.
Verification passed focused domain, application, protocol, interceptor, breakpoint-manager, traffic,
persistence, and desktop-composition tests, including a synthetic third-party protocol, GraphQL operation and
batch matching, response correlation and cleanup, missing-extension behavior, Room round trips, and a live
Netty interception test. The final check verifyArchitectureFoundation gate passed with 272 actionable tasks,
and git diff --check passed. The desktop application was not launched.
Started on 2026-08-19 after request-phase breakpoint suspension was confirmed to occur before the canonical
proxy handler admitted the exchange to capture. The live drawer therefore received a pending breakpoint while
Traffic had no row, and the migrated isIntercepted presentation fields had no canonical producer. This phase
moved protocol-neutral exchange admission ahead of the forwarding gate, reuses one exchange identity and
capture owner through resume, projects active breakpoint state onto Traffic, and reveals the drawer only after
the corresponding highlighted In Progress row is present. Active paused rows remain visible despite ordinary
Traffic filters, and resolution restores the durable response state while retaining a bounded, process-session
matched marker. The provisional request row carries metadata only; breakpoint body ownership remains bounded
and no body copy was added to the Traffic projection.
Request/response models, protocol extensions, Room ownership, and the UI-independent breakpoint coordinator
remain unchanged. Focused proxy, interceptor, data, Traffic, application-shell, and product-composition tests
passed with 157 actionable tasks, including live request/response pauses, exactly-once capture admission, and
pre-forward cancellation on breakpoint drop or disconnect.
The final check verifyArchitectureFoundation gate passed with 272 actionable tasks, and git diff --check
passed. The desktop application was not launched.
Completed on 2026-08-19. Removed the breakpoint warning icon from the Traffic method cell while retaining the paused and matched row background highlights as the single interception indicator. No capture, breakpoint, drawer, or traffic-state behavior changed. The desktop application was not launched.
Started on 2026-08-19 after comparing the reusable Timeline panel with repository history. The original
waterfall used one 130dp label column, but per-label intrinsic widthIn sizing later allowed every timing
track to begin at a different horizontal position. This phase restores one shared responsive column:
130dp at normal inspector widths and one bounded width shared by every row when the inspector is narrow.
Canonical ExchangeTimings, Traffic ownership, and the reusable HTTP-panel boundary remain unchanged.
Focused HTTP-panel and Traffic tests passed with 74 actionable tasks, including normal and narrow inspector
width coverage. The final check verifyArchitectureFoundation gate passed with 272 actionable tasks, and
git diff --check passed. The desktop application was not launched.
Started on 2026-08-19 after auditing :ui:desktop:codeEditor as the shared payload and script editing
surface for Traffic, API Studio, GraphQL, and scripting. This phase will retain the independent editor module
and its KNet-facing facade while replacing closed language selection, full-document edit snapshots, parallel
syntax/folding paths, filtered-line search, and fragmented editor state with a reusable versioned document
and session foundation.
The target provides additive language registration with independent optional tokenization, folding, indentation, bracket, and comment capabilities; stateful cross-line tokenization; language-aware folding; operation-based undo/redo; a command dispatcher; real find/replace state; shared viewport behavior; and a cohesive Compose API. Autocomplete and completion providers are explicitly outside the requested scope. Language services remain independent from Compose rendering and KNet HTTP semantics so the editor can later be extracted into a standalone Kotlin code-editor repository without migrating its consumers or core model.
Completed on 2026-08-19. The editor now has one versioned, chunk-sharing document model; one UI-neutral session for document, directional selection, caret, history, and exact synchronous change events; bounded delta undo/redo; real find/replace; strongly typed commands; and a cohesive Compose State/Actions/Configuration API. The viewport composes visible lines only, gives one active line ownership of text input, shares horizontal scrolling, and avoids document-sized mapping arrays on the normal unfolded path. Full-string serialization is explicit and optional.
The closed language/highlighter implementation was replaced by an immutable contribution registry with independent stateful tokenization, folding, indentation, bracket, and comment capabilities. Built-in JSON, GraphQL, XML, HTML, JavaScript, CSS, and plain-text support use the same public extension boundary as future languages. Incremental syntax processing retains immutable token chunks, observes multiline lexical state, and falls back to a correct full pass whenever delta versions are not contiguous. Syntax, folding, and search run against immutable snapshots with cooperative coroutine cancellation and stale-version rejection.
The built-in Compose surface now provides highlighted literal/regex/case/whole-word search, editable
replace/replace-all, language-driven indentation, bracket closing, comment toggling, folds, modern clipboard
actions, and configurable labels and semantic colors. Autocomplete/completion remains intentionally absent.
All six HTTP-panel consumers were migrated to the new API, unknown valid language identifiers are preserved
as custom contributions, obsolete duplicate buffers/history/highlighters/facades were removed, and the editor
module no longer depends on KNet domain models or Java/AWT APIs. Module responsibility and standalone
extraction guidance are documented in :ui:desktop:codeEditor/MODULE.md and
docs/code_editor_architecture.md.
Focused code-editor and HTTP-panel suites passed with 47 and 32 tests respectively. The final
check verifyArchitectureFoundation gate passed with 269 actionable tasks; Kotlin-first, module boundary,
module documentation, UI runtime-isolation, and composition-ownership checks all passed. git diff --check
passed. The desktop application was not launched.
Started on 2026-08-19 after downward drag selection stopped when the pointer entered the horizontal scrollbar hit zone, while upward drag selection continued normally. This phase will make pointer drag ownership stable for the complete gesture: a drag that begins in the editor remains a text-selection drag when it crosses a scrollbar boundary, while a drag that begins on a scrollbar remains scrollbar-owned. Regression coverage will verify downward and upward ownership behavior. The desktop application will not be launched.
Completed on 2026-08-19. Pointer ownership is now selected once at primary-button press and retained until
release. Text drags continue selection and auto-scroll after crossing the bottom or side scrollbar hit zone,
while gestures beginning on a scrollbar remain scrollbar-owned. Three ownership regression tests cover
downward boundary crossing, scrollbar departure, and release/reacquisition; the complete code-editor suite
passed with 50 tests. The affected HTTP-panel consumer compiled, verifyArchitectureFoundation passed, and
git diff --check passed. The desktop application was not launched.
Started on 2026-08-19 after full-width blue selection rows flashed while virtualized lines were composed during downward drag auto-scroll. This phase will make selection painting identical before and after text layout becomes available, represent a selected newline with one character cell instead of the viewport width, suppress zero-width end-line paint, and prevent active-line focus synchronization from clearing an ongoing viewport drag selection. The desktop application will not be launched.
Completed on 2026-08-19. Empty intermediate lines now represent their selected newline with one character
cell rather than painting the viewport width; zero-column exclusive end lines produce no selection paint;
and fallback geometry matches the native-layout geometry used after a virtualized row is composed. Active
line inputs no longer request focus or publish selection/caret changes while viewport drag selection is
active, preventing the canonical selection from being cleared between pointer frames. Five focused
regression tests were added, the complete code-editor suite passed with 55 tests, the affected HTTP-panel
consumer compiled, verifyArchitectureFoundation passed, and git diff --check passed. The desktop
application was not launched.
Started on 2026-08-19 after Traffic correctly classified a Datadog newline-delimited JSON payload as
BodyFormat.JsonStream but discarded its formatted frames before rendering. This phase will retain one JSON
language/editor implementation while distinguishing the multi-record transport shape in the formatter.
Detection will prefer a valid complete JSON value, recognize explicit NDJSON/JSONL media types, and otherwise
require every non-empty line to be an independently valid JSON value. The HTTP-panel presentation bridge will
render formatted frames with visible record separation through the existing read-only JSON editor. The desktop
application will not be launched.
Completed on 2026-08-19. JSON format resolution now validates a complete JSON value before considering
multi-record framing, so pretty-printed objects and arrays remain single documents. Explicit NDJSON/JSONL
media types and implicit payloads whose every non-empty line is independently valid JSON resolve to the
existing BodyFormat.JsonStream; each record is formatted by the same JSON formatter. Invalid mixed text
does not become an implicit stream.
The HTTP-panel presentation bridge now joins formatted stream records with a visible blank-line boundary and
passes the result to the existing read-only CodeLanguage.JSON editor. No NDJSON language, tokenizer, folding,
search, editor, request model, or response model was added. Module documentation records this syntax-versus-
framing rule so future JSON stream conventions extend formatter detection instead of duplicating JSON support.
The formatter, HTTP-panel, and Traffic suites passed with 46, 33, and 11 tests respectively. The final
check verifyArchitectureFoundation gate passed with 269 actionable tasks, and git diff --check passed. The
desktop application was not launched.
Started on 2026-08-19 after multi-line selection exposed the unpainted leading between the text-sized selection surface and the taller virtualized row. This phase will retain the existing row height, text line height, and baseline spacing while making selection paint own the complete visual-line slot. Adjacent selected lines will therefore meet without dark seams. Horizontal selection bounds, trailing-newline width, wrapping, fallback geometry, document content, and selection semantics remain unchanged. Regression coverage will exercise the geometry independently, and the desktop application will not be launched.
Completed on 2026-08-19. Both read-only and editable line content now place selection paint on a full-height visual-line surface while keeping the text content centred with its existing line height and baseline. Native text layout still supplies horizontal character bounds. The vertical paint projection assigns outer leading to the first and final visual slots and splits internal leading at one shared boundary, so ordinary and wrapped selected lines meet without dark seams. The fallback path, trailing-newline cell width, row height, typography, document text, and selection coordinates were not changed.
Three focused geometry regressions cover complete single-row paint, shared wrapped-line boundaries, and outer
leading ownership. The code-editor and HTTP-panel suites passed with 58 and 33 tests respectively. The final
check verifyArchitectureFoundation gate passed with 269 actionable tasks, and git diff --check passed. The
desktop application was not launched.
Started on 2026-08-19 after comparing the migrated proxy lifecycle with commit 6b9fe3c. The legacy Traffic
buttons appeared fast because one wildcard listener served LAN clients directly and stop returned before
active channels and Netty event loops finished closing. The migrated implementation correctly awaits complete
resource ownership but currently couples frequent capture controls to full loopback proxy, Wi-Fi gateway,
setup portal, connection, and canonical-writer teardown.
This phase will separate the stable forwarding plane from the capture plane. Traffic Start/Stop will attach or detach versioned canonical capture targets through the existing switchable sink while Netty and Wi-Fi remain available. A detached session will drain through one bounded retirement owner, allowing a new session to begin without waiting for old persistence cleanup. Exchanges remain bound to exactly one capture generation; traffic is never split between sessions. Rapid commands are serialized, Stop Capture never deletes stored traffic, and breakpoints will not suspend traffic while capture is paused because their required Traffic row would not exist. Full proxy shutdown remains synchronous and is reserved for application shutdown, explicit connectivity shutdown, or configuration rebinding. The desktop application will not be launched.
Completed on 2026-08-19. ProxyRuntimeState and the new typed CaptureSessionState now represent
independent lifecycles. Traffic Stop disables breakpoint admission, atomically replaces the switchable
capture target with a paused generation, and queues the detached canonical writer on one bounded IO
retirement owner. The Netty listener, Wi-Fi gateway, setup portal, downstream connections, and forwarding
path remain active. Traffic Start on the same configured port opens a strictly ordered fresh canonical
session and swaps only the capture target; a port change still performs the required full configuration
shutdown/rebind.
The switchable connection wrapper now survives a paused target, begins capturing its next exchange after
resume, and keeps an already-created exchange attached to its original generation. Breakpoint capture
availability is separate from the user's breakpoint enablement and aggregation requirements: pause continues
pending decisions unchanged and future uncaptured exchanges bypass interception without triggering pipeline
refresh or client disconnects. Repeated UI commands are serialized as revisioned desired state, stored rows
survive pause/resume, and the toolbar reports Forwarding · Capture paused while Start/Stop enablement follows
capture state rather than listener state. Full proxy cleanup remains process/configuration owned and drains
both active and asynchronously retired writers before Room closes.
Focused application, data, Traffic, and product composition suites passed, including listener-identity,
generation ownership, paused-connection resume, breakpoint release, and toolbar lifecycle regressions. The
final check verifyArchitectureFoundation gate passed with 269 actionable tasks, git diff --check passed,
and the desktop application was not launched.
Started on 2026-08-19 from the repository-backed Traffic module audit. This phase keeps the canonical
:core:traffic snapshots, application contracts, Room storage, proxy/capture ownership, typed breakpoint
projection, and product DI boundaries. It incrementally corrects selected-detail identity, repeated
header/query preservation, captured-request URL ownership, decoded-body memory limits, persisted-session
visibility, bounded viewport paging, non-starving live refresh, transport/protocol classification, clear
lifecycle serialization, capture failure presentation, and remaining dead or inconsistent presentation
state. The 1,000-row bound remains a UI memory bound rather than becoming a stored-history limit.
Verification will add focused regressions for rapid selection, empty-body caching, repeated HTTP fields, captured-query replay, compressed-body expansion limits, cross-session history, continuous generations, filtered paging, typed HTTPS/HTTP-version classification, clear races, and filtered footer statistics. The desktop application will not be launched.
Completed on 2026-08-19. Inspector preparation and its bounded cache are now keyed by canonical exchange ID, so rapid selection cannot publish stale details and empty bodies are cached without sentinel ambiguity. One application-owned captured-request converter now preserves ordered repeated headers and query parameters for API Studio replay. Traffic rows retain only table data while the inspector reads the canonical exchange, removing duplicate header, query, and response projections.
Decoded payloads now have an enforced output-byte ceiling across gzip, deflate, Brotli, and Zstandard paths, and the inspector cache is bounded by both entry count and estimated retained bytes. Room history queries can span all retained sessions, use typed scheme and application-protocol criteria, and search host, path, method, and status. Schema 16 adds the global newest-first timestamp/ID index. The Traffic viewport remains capped at 1,000 rows while older pages continue to be reachable through a rolling window, and conflated generation refresh prevents a continuous capture stream from starving the UI.
Traffic-specific filters now live in the Traffic presentation module and expose only classifications backed by canonical data: HTTP/HTTPS scheme and HTTP/1.x, HTTP/2, or HTTP/3 protocol. Unsupported WebSocket, gRPC, GraphQL, and path-name guesses were removed. Clear History is serialized, clears only persisted traffic, resets the active viewport/cache, and reloads any surviving history. Automatic startup retention cleanup is owned once by the desktop process rather than by a screen ViewModel, while capture failures are surfaced independently from proxy-listener state.
Focused domain, application, data, Traffic, HTTP-panel, and product composition regressions passed. The final
check verifyArchitectureFoundation gate passed with 269 actionable tasks, git diff --check passed, and the
desktop application was not launched. Module responsibility documents were updated alongside the code and
Room schema migration.
Started on 2026-08-19 after the Traffic table showed its Status header offset from every status value. The header reserves 64 dp while data rows reserve 84 dp; because the preceding Path column is weighted, this causes its allocation to differ between the header and rows and moves row status cells 20 dp to the left. This phase will give both surfaces one shared status-column width without changing table density, status content, highlighting, colors, or column visibility behavior. The desktop application will not be launched.
Completed on 2026-08-19. The Status header and row cells now consume the same shared 84 dp width, giving the
weighted Path column identical remaining space in both table surfaces. The header, numeric statuses, and
in-progress/error labels therefore share one left edge, and later width adjustments have a single owner. The
Traffic JVM suite and verifyArchitectureFoundation passed with 66 actionable tasks, git diff --check
passed, and the desktop application was not launched.
Started on 2026-08-19 from a repository-wide audit of :ui:core and its active desktop consumers. This
phase keeps the existing KMP design-system boundary and reusable primitives, while correcting theme-system
resolution, token adoption, interaction semantics, dialog and split-pane correctness, input behavior,
dropdown presentation, and accessibility. The KNet dropdown family will receive one consistent anchored
field/menu design with selected, hover, disabled, searchable, and keyboard-accessible states rather than
maintaining two visually divergent implementations.
The phase will also remove only repository-proven dead aliases, no-op helpers, sample/catalog production sources, and abandoned component-framework scaffolding; active consumers will be migrated before an API is removed. Feature-specific table sizing will gain one Traffic-owned column specification, while protocol- specific presentation will be kept out of generic UI foundations. Focused common/JVM tests, module responsibility documentation, architecture verification, and whitespace validation will be run. The desktop application will not be launched.
Completed on 2026-08-19. :ui:core now provides a system-aware Material-backed theme, reduced-motion-aware
animation tokens, native selection/toggle/button semantics, controlled split panes, selection-preserving text
inputs, responsive dialogs, and one visually consistent dropdown family. Both regular and searchable dropdowns
now share compact sizing, matched anchor/menu widths, clear hover/focus/disabled/selected states, truncation,
selected checkmarks, scrolling bounds, and keyboard navigation. Traffic owns its complete table metrics, while
HTTP method colors and status badges moved to :ui:desktop:httpPanel instead of leaking protocol concepts into
the generic design system.
Repository-proven dead aliases, duplicate wrappers, no-op helpers, production catalogs/samples, and abandoned
component-framework scaffolding were removed after migrating active consumers. :ui:core and HTTP-panel module
responsibility documents now describe the resulting ownership rules. :ui:core:jvmTest, the desktop product
compile, the full check verifyArchitectureFoundation gate (269 actionable tasks), and git diff --check
passed. The desktop application was not launched.
Started on 2026-08-19 after opening the searchable scripting-language dropdown raised Compose's
SubcomposeLayout intrinsic-measurement exception. The redesigned searchable dropdown placed a lazy list
inside Material DropdownMenu; Material measures menu content intrinsically, while lazy layouts deliberately
do not support intrinsic measurement. This phase replaces that incompatible nesting with a KNet-owned anchored
popup that gives both regular and searchable dropdown content explicit bounded constraints, preserves lazy
search results, handles below/above viewport placement, and keeps anchor focus for keyboard input. The desktop
application will not be launched.
Completed on 2026-08-19. Regular and searchable dropdowns now share a KNet-owned popup with an explicit anchor
width, bounded height, viewport-clamped left/right placement, and automatic below/above placement. The regular
menu retains bounded scrolling, while searchable results remain lazy without being measured intrinsically.
The input retains focus so filtering and arrow/Enter/Escape handling continue through the anchor. UI-core tests,
Settings compilation, desktop product compilation, and the full check verifyArchitectureFoundation gate
passed with 269 actionable tasks. git diff --check passed, and the desktop application was not launched.
Started on 2026-08-19 after the shared dropdown anchor was observed in both constraint extremes. Inside the
horizontally scrollable Traffic filter bar, infinite horizontal constraints collapsed the weighted label and
left only the chevron visible. Inside API Studio's bounded request row, fillMaxWidth allowed the unweighted
dropdown to consume the URL field's available width. This phase gives regular and searchable dropdowns a finite
design-system default width while preserving normal caller overrides through Modifier.width, widthIn,
weight, and fillMaxWidth. Every active consumer will be checked so full-width dialog fields remain explicit
and compact toolbar/filter fields remain self-contained. The desktop application will not be launched.
Completed on 2026-08-19. Both dropdown variants now start from a finite 120 dp anchor width, making their inner
weighted label measurement deterministic in bounded and unbounded parent layouts. Because the caller modifier
precedes the default sizing modifier, explicit widths, minimum widths, weights, and full-width fields continue
to override the compact default normally. Settings' 160 dp searchable fields now express that width directly,
and all active regular/searchable dropdown consumers were reviewed. UI-core tests, all dropdown-consuming UI
module compilations, desktop product compilation, and the full check verifyArchitectureFoundation gate
passed with 269 actionable tasks. git diff --check passed, and the desktop application was not launched.
Started on 2026-08-19 after fixing the request method dropdown exposed additional empty blocks across API Studio's request, body-format, and GraphQL tab strips. This phase audits every API Studio surface that consumes the changed design-system primitives, compares it with the pre-remediation implementation, and corrects shared component behavior at its owner rather than adding screen-specific visual patches. The scope includes the URL bar, request tabs, parameter/header/body/auth/script editors, GraphQL controls, collection sidebar, dialogs, response pane, split layout, empty/loading states, and keyboard/resize behavior. The desktop application will not be launched.
Completed on 2026-08-19. The empty rectangles across API Studio were one design-system regression rather than
separate screen failures: KNetTab gave its label weight inside KNetTabRow, whose horizontal scrolling
measures content with unbounded width, so Compose reduced every weighted label to zero. Tab labels now retain
their natural width up to a finite design-system maximum and remain single-line/ellipsized. This restores the
request inspector, request/response body-mode, GraphQL authoring/viewing, Traffic inspector, certificate, and
response-inspector tab labels from the shared owner. GraphQL authoring also gives its tab strip the toolbar
space remaining beside the operation-name field, so narrow split positions scroll instead of overlapping.
The API Studio URL bar, open-request tabs, collection sidebar, key/value editors, auth and script editors,
dialogs, response facade, loading/empty/error states, and controlled split pane were reviewed against their
pre-remediation implementations and current design-system constraints. Stale imports from the response facade
were removed, and the UI-core/HTTP-panel module responsibility documents now record the constraint contract.
Focused UI-core, HTTP-panel, and API Studio suites plus desktop product compilation passed with 138 actionable
tasks. The full check verifyArchitectureFoundation gate passed with 269 actionable tasks, git diff --check
passed, and the desktop application was not launched.
Started on 2026-08-19 after API Studio's empty parameter editor showed the shared Add Param button reduced
to a thin clipped strip. KNetButton applied its fixed height before the caller modifier, which placed caller
padding inside the fixed-height measurement and left insufficient height for button content. This phase restores
standard Compose modifier ownership: caller layout modifiers remain outermost while the design-system height
acts as the overridable inner default. The desktop application was not launched.
Completed on 2026-08-19. KNetButton now applies the caller modifier before its design-system height. Outer
padding therefore contributes to the component's total layout size instead of consuming the button's content
height, restoring the complete Add Param, Add Header, and Add Cookie buttons. Explicit caller heights,
including API Studio's 40 dp request-bar actions, continue to override the compact default normally. All active
API Studio, HTTP-panel, and UI-core button consumers were reviewed, and no second fixed-height-before-caller
pattern was found.
Focused UI-core, HTTP-panel, and API Studio suites plus desktop product compilation passed with 138 actionable
tasks. The full check verifyArchitectureFoundation gate passed with 269 actionable tasks, git diff --check
passed, and the desktop application was not launched.
Started on 2026-08-19 after editable code-editor content visibly flashed on every character mutation. The document snapshot advances synchronously, while syntax tokenization correctly runs on a background dispatcher; the viewport currently rejects the complete previous token model during that interval and briefly renders all visible lines without semantic colors. This phase adds a current-version presentation projection that synchronously retokenizes only the directly changed lines and structurally reuses the previous prefix and suffix until authoritative background tokenization converges. Background cancellation and stale-result guards remain intact, and the desktop application will not be launched.
Completed on 2026-08-19. The editor now keeps separate completed and presentation token models. A normal session edit synchronously projects the changed line onto the new document version and structurally reuses unchanged token chunks, so visible content never falls back wholesale to plain text while the worker tokenizer is running. Consecutive keystrokes chain from the latest presentation model even when earlier background jobs are cancelled. The completed worker result remains authoritative and replaces the presentation only when its snapshot version is still current.
Immediate work is bounded to 32 directly changed lines and 32 KiB of changed text. Oversized edited lines are
temporarily unstyled instead of blocking the UI thread, while unaffected lines remain stable. Regression tests
cover ordinary character replacement, structural line splitting, oversized single-line payloads, and rapid
edits before background convergence. The focused editor/HTTP-panel/API-Studio/product verification passed with
139 actionable tasks; the full check verifyArchitectureFoundation gate passed with 269 actionable tasks.
git diff --check passed, and the desktop application was not launched.
Started on 2026-08-19 after confirming that every active KNet editor inherits the reusable editor's disabled word-wrap default. This phase makes visual wrapping the default so long request bodies, responses, GraphQL documents, and scripts remain inside the viewport without a visible horizontal scrollbar. Wrapping remains a presentation concern and never inserts document newlines. Wrapped-row keyboard navigation, pointer hit testing, selection painting, variable-height virtualization, gutter behavior, and vertical scrolling will be verified. The optional non-wrapped capability remains available for a future standalone editor consumer, and the desktop application will not be launched.
Completed on 2026-08-19. CodeEditorConfiguration now enables word wrapping by default, so all current KNet
request, response, GraphQL, script, and Traffic-inspection editors stay inside their viewport and omit the
horizontal scrollbar without per-feature overrides. Wrapping changes only Compose layout: stored text, logical
line coordinates, gutter numbering, copy operations, and request serialization remain unchanged. Consumers of
a future standalone editor may still explicitly disable wrapping when horizontal navigation is desired.
Up/Down navigation now remains inside an active logical line while another wrapped visual row exists and crosses
logical lines only at the first or final visual row. Pointer ownership now reserves the bottom hit zone only
when a horizontal scrollbar is actually rendered, preserving bottom-edge selection and downward auto-scroll in
wrapped viewports. Regression coverage verifies the wrap default, wrapped-row navigation boundaries, and
conditional scrollbar hit zones. The focused editor/HTTP-panel/API-Studio/product verification passed with
139 actionable tasks; the full check verifyArchitectureFoundation gate passed with 269 actionable tasks.
git diff --check passed, and the desktop application was not launched.
Started on 2026-08-19 after pointer selection across trailing or empty line space briefly painted the complete active row before converging to the exact selected characters. Two viewport ownership transitions cause the flash: pointer-down moves the caret before a non-empty selection exists, so the active-line background is temporarily eligible; and activating a row swaps its lightweight text renderer for the editable renderer, discarding measured text geometry until the replacement layout completes. This phase makes pointer gesture ownership observable from the initial press, retains compatible measured geometry at the keyed logical-row boundary, and verifies that real whitespace remains selectable while unused viewport space never paints as selection. The desktop application will not be launched.
Completed on 2026-08-19. SelectionGestureHandler now exposes Compose-observable gesture ownership as soon as
the initial text press establishes its anchor. The viewport uses that state together with the canonical
selection to suppress active-line background and native caret/focus behavior throughout the gesture, including
the zero-length interval before the pointer first moves. A normal click restores active-line paint on release.
Each keyed logical row now owns its latest compatible TextLayoutResult; the read-only Text and active
BasicTextField are stateless layout producers. Moving the caret to a row therefore retains exact measured
selection geometry across the renderer swap instead of briefly falling back to estimated character cells.
Compatibility is guarded by the current logical text, so an actual edit never applies geometry from stale
content. Regression coverage verifies press/release ownership, active-row paint policy, and exact document
columns through trailing whitespace. The focused editor/HTTP-panel/API-Studio/product verification passed with
139 actionable tasks; the full check verifyArchitectureFoundation gate passed with 269 actionable tasks.
git diff --check passed, and the desktop application was not launched.
Started on 2026-08-19 after the wrapped editor exposed vertical gaps between selection rectangles on adjacent logical lines. Phase 44 correctly removed the fixed row height to permit wrapping, but the wrapped text-content surface then became shorter than the gutter-owned minimum row height on single-visual-line content. Phase 45's exact selection painter fills its content surface, not the taller sibling-owned row, so the remaining pixels appeared as gaps. This phase gives both read-only and editable content the shared logical-line minimum while preserving natural multi-line expansion, typography, baselines, and document semantics. The desktop application will not be launched.
Completed on 2026-08-19. Editable and read-only line content now use one shared viewport sizing contract. The
content surface has the same minimum logical-line height as the gutter in both wrapped and unwrapped modes;
unwrapped content still fills its fixed parent, while wrapped content remains unconstrained above the minimum.
The selection painter therefore covers the sibling-owned remainder that previously appeared as a seam, without
changing TextStyle, line height, baseline placement, wrapping, or serialized content.
The focused editor/HTTP-panel/API-Studio/product verification passed with 139 actionable tasks; the full
check verifyArchitectureFoundation gate passed with 269 actionable tasks. git diff --check passed, and the
desktop application was not launched.
Started on 2026-08-19 after clearing a selection by clicking its existing caret line caused the active-line background to disappear on press and reappear on release. The caret never left the line; the visual transition was created solely because active-line paint incorrectly depended on selection and gesture state. This phase separates the layers: caret ownership alone controls active-line paint, while selection gesture state continues to control only selection geometry, native caret visibility, and focus publication. The desktop application will not be launched.
Completed on 2026-08-19. LazyCodeLineRow now applies the ambient background directly from isActiveLine and
does not consult selection length or pointer-gesture ownership. Selecting text, clicking to collapse it, or
releasing the pointer on the same caret line therefore leaves the background continuously mounted. Moving the
caret to a different logical line remains the only operation that transfers active-line paint.
Selection gesture ownership remains intact for the concerns it actually owns: deterministic range painting,
transparent native selection/caret presentation, and protection from focus-driven caret publication. The
obsolete combined active-line/selection paint policy and its regression assertions were removed, and the module
contract now documents the independent layers. The focused editor/HTTP-panel/API-Studio/product verification
passed with 139 actionable tasks; the full check verifyArchitectureFoundation gate passed with 269 actionable
tasks. git diff --check passed, and the desktop application was not launched.
Started on 2026-08-19 after reviewing the Traffic filter toolbar's oversized dropdown anchors, click-through close behavior, and selection-dependent width concern. The shared popup is non-focusable, so clicking its open anchor first dismisses the popup as an outside click and then lets the same pointer event toggle the anchor open again. The shared anchor already has a finite width, but the contract needs to make density and width stability explicit across selected values. This phase adds a compact density used consistently by Traffic chips and filters, consumes outside dismissal at the popup boundary, and retains the popup through a short reduced-motion- aware exit transition. The desktop application will not be launched.
Completed on 2026-08-19. Traffic's count chips and Method, Status, and Protocol anchors now use the same 26 dp compact-control height. The shared dropdown keeps its finite anchor width outside content measurement, so a placeholder or newly selected value can truncate but cannot resize the field or popup. Traffic also passes its typed filter values directly rather than maintaining duplicate label lists and reverse string lookup.
The shared popup now remains composed through a short fade/98%-scale exit and uses the design system's fast
duration and reduced-motion policy. Ordinary selection popups are focusable, so an open-anchor click is consumed
as one outside dismissal instead of reaching the anchor and reopening it. Searchable dropdowns explicitly retain
their non-focusable popup policy so the results window does not steal keyboard focus from the search field.
Regression coverage verifies both density presets, the fixed-width default, popup exit composition, and the two
focus policies. Focused UI-core, Traffic, Settings, Certificate, API Studio, and desktop composition verification
passed with 148 actionable tasks. The full check verifyArchitectureFoundation gate passed with 269 actionable
tasks, and the desktop application was not launched.
Started on 2026-08-20 to move the existing Connect Device destination from the primary navigation group into the setup/security group. The route, destination identity, icon, and workspace behavior remain unchanged; only its sidebar placement changes so it appears immediately after the primary-group divider and immediately before Certificates. Navigation configuration coverage will assert the real section order, and the desktop application will not be launched.
Completed on 2026-08-20. The navigation overlay now renders Traffic, API Studio, and Intercepts in the primary group, followed by the divider, Connect Device, and Certificates. Settings and branding retain their existing bottom placement. The destination route, icon, selection handling, and workspace host were not changed.
Navigation section metadata now has one shared owner used by both composition and regression coverage, so the
test asserts the actual Connect Device-to-Certificates ordering instead of recreating a separate expected list.
The focused app test, desktop product compilation, and verifyArchitectureFoundation passed with 133 actionable
tasks. git diff --check passed, and the desktop application was not launched.
Started on 2026-08-20 after confirming that Traffic's Columns control still bypasses the KNet dropdown family
and directly composes a Material menu. This produces different anchor height, surface styling, motion, width,
and dismissal behavior beside the Method, Status, and Protocol controls. This phase adds one reusable generic
multi-select dropdown to :ui:core, backed by the existing KNet anchor and popup mechanics, and migrates the
active Traffic column selector to it. Multi-selection remains explicit: toggling an item does not close the
menu, and each row owns exactly one toggle action. The desktop application will not be launched.
Completed on 2026-08-20. KNetDropdown and the new generic KNetMultiSelectDropdown now share one internal
anchor owner for compact/standard height, hover/focus borders, keyboard toggling, stable label measurement, and
chevron motion. Multi-select uses the same bounded animated popup and outside-click ownership as single-select,
but intentionally remains open after a value is toggled. Its 148 dp design-system default accommodates a compact
checkbox indicator and Traffic's longer column labels without allowing content to resize the control.
Traffic's feature-local Material menu, duplicate anchor styling, nested checkbox click handler, and supporting
imports were removed. Traffic now supplies only typed optional TrafficColumn values, visibility lookup, toggle
callback, and display labels. The option row owns checkbox semantics and exactly one toggleable interaction while
reusing the shared KNet checkbox indicator, selected surface, hover transition, typography, and ellipsis policy.
UI-core and Traffic module contracts document the new ownership, and component coverage locks both dropdown
width presets. Focused UI-core, Traffic, and desktop product verification passed with 133 actionable tasks. The
full check verifyArchitectureFoundation gate passed with 269 actionable tasks, and the desktop application was
not launched.
Started on 2026-08-20 after a repository-backed audit found that API Studio document hydration, autosave, promotion, startup restoration, and request cancellation were coordinated by two ViewModels plus the screen. That ownership permitted partial or duplicate writes, stale execution results, successful no-op dependency fallbacks, and lossy request persistence. This phase establishes one active-document owner, one ordered latest- state autosave path, atomic draft-to-saved transitions, cancellation-safe execution identity, lossless request round trips, transactional promotions, explicit loading/failure presentation state, and production Koin verification. Application orchestration will move out of presentation where the existing boundaries support it; shared mutable editor state will remain a UI projection of canonical authored and observed HTTP values. The desktop application will not be launched.
Completed on 2026-08-20. ApiStudioViewModel is now the sole owner of the active request document while
CollectionsViewModel owns only persisted sidebar CRUD. SavedApiRequest is the canonical authored-request
model across API Studio and persistence, with typed HTTP methods and body formats plus lossless query-parameter,
header, cookie, body-field, authentication, and script state. Room schema 17 persists that complete model, and
draft promotion is transactional instead of a delete-then-save sequence.
Autosave and workspace selection now pass through ordered, cancellation-aware coordinators, startup restores the exact saved request, stale executions cannot replace newer editor results, and persistence failures are visible without falsely updating the UI. Request execution and direct traffic recording moved to the application layer; the desktop product supplies explicit production bindings for dispatchers and scripting. Dead request tabs, environment UI, duplicate API Studio theme/sidebar models, and obsolete presentation execution use cases were removed. Module responsibility documents were updated for each affected boundary.
Focused domain, application, data, storage, API Studio, and desktop-product verification passed. The complete
check verifyArchitectureFoundation gate passed with 269 actionable tasks (136 executed, 133 up-to-date), and
the desktop application was not launched.
Started on 2026-08-20 to give the request method and URL distinct visual ownership. The method selector will be a fixed-width standalone dropdown on the left with a centered method label, while the URL remains the flexible middle field with vertically centered content and a concise empty-state hint. Existing send, cancel, save, keyboard, overflow, and responsive behavior will remain unchanged. The desktop application will not be launched.
Completed on 2026-08-20. The method dropdown is now a standalone, fixed-width control before the independently
bordered URL field. Its selected method is centered without moving the trailing chevron, and method colors are
applied consistently for every method rather than treating GET as a placeholder selection. The URL field retains
the flexible width, Enter-to-send behavior, overflow preview, and vertically centered single-line text while
showing the compact Enter request URL hint only when empty.
The shared dropdown gained opt-in selected-label alignment with start alignment preserved as the default, so no
other KNet dropdown changed visually. UI-core and API Studio module contracts document the ownership. Focused
UI-core tests, API Studio tests, desktop product compilation, and verifyArchitectureFoundation passed with 139
actionable tasks. git diff --check passed, and the desktop application was not launched.
Started on 2026-08-20 after visual verification showed the standalone method dropdown using the shared 36 dp standard height beside 40 dp URL and action controls. This correction adds an explicit 40 dp dropdown density, uses it for the request method, and restores normal start alignment so the method retains compact left padding while remaining vertically centered. The desktop application will not be launched.
Completed on 2026-08-20. API Studio now selects the shared 40 dp large dropdown density, matching the URL, Save, and Send control heights exactly. The method label again uses the standard 10 dp leading inset and remains vertically centered; the earlier horizontal-centering option was removed because it no longer had a real caller. Compact and standard dropdowns remain unchanged. UI-core coverage now locks all three density heights.
Focused UI-core tests, API Studio tests, desktop product compilation, and verifyArchitectureFoundation passed
with 139 actionable tasks. git diff --check passed, and the desktop application was not launched.
Started on 2026-08-20 to replace the single-select dropdown's hardcoded 120 dp default width with a measured, content-responsive width. The default anchor and popup will size to the widest option plus their required visual chrome, bounded by design-system minimum and maximum widths. Width will remain stable across selection changes, and explicit caller sizing will continue to override the calculated default. Verification will be deferred while the user-owned KNet process is running so its live classpath is not overwritten.
Completed on 2026-08-20. KNetDropdown now measures every option label using the active design-system text style
and derives one stable anchor width from the widest result. Anchor and selected-menu chrome are included in the
calculation, with a 72 dp minimum and 280 dp maximum. This removes the former 120 dp hardcoded single-select
width without allowing the control to jump when selection changes or grow without a responsive bound. Explicit
feature widths still win through the caller modifier; searchable and multi-select controls retain their distinct
120 dp and 148 dp defaults because their content and interaction contracts differ.
Pure sizing coverage locks the lower bound, calculated content width, upper bound, density chrome, and specialized
dropdown defaults. git diff --check passed. Gradle verification was intentionally not run because the user-owned
KNet process remained active, preventing another live-classpath JAR replacement failure.
Started on 2026-08-20 to replace URL-only and ViewModel-owned API Studio document naming with an extensible request-naming pipeline. This phase applies only to session/request titles; collection names remain entirely user-controlled. The canonical saved-request model will persist whether a title is generated or user-defined, HTTP naming will use a meaningful path/host fallback, and GraphQL naming will reuse the existing formatter to resolve explicit or document operation names. Product DI will compose ordered protocol strategies so future formats can add naming support without modifying the API Studio ViewModel or stable naming use case.
Completed on 2026-08-20. API Studio session/request titles now resolve from the canonical SavedApiRequest
through an ordered contribution pipeline. The terminal HTTP strategy returns a query/fragment-free path or root
host; the GraphQL contribution reuses GraphQLBodyFormatter to resolve explicit envelope and named AST
operations, falling back cleanly for anonymous operations. Product DI owns strategy precedence, so another
protocol adds one contribution and one binding without adding protocol branches to the ViewModel. Collection
names remain entirely user-controlled. Phase 56 subsequently widened this same contribution boundary to resolve
the sidebar protocol badge alongside the generated title.
Generated-versus-user-defined ownership is now part of the canonical request and Room schema v18. Generated
titles use a 250 ms latest-wins debounce and perform canonical conversion plus protocol parsing off the UI
dispatcher. Save-dialog changes and sidebar renames become user-defined and cannot be overwritten later; legacy
rows migrate as USER_DEFINED. Ordered auto-save snapshots retain this ownership across draft/saved promotion,
proxy/app restarts, and direct request restoration. Domain, formatter, mapper, auto-save, ViewModel, and sidebar
coverage was added. git diff --check passed. Gradle execution and the generated schema-v18 export were
intentionally deferred because the user-owned KNet process remained active on the build JAR classpath; the
desktop application was not launched or restarted.
Started on 2026-08-20 to evolve the new request-name-only contribution into one extensible descriptor pipeline.
The same protocol recognition will now provide both the generated session/request title and the compact sidebar
badge, preventing duplicate GraphQL/future-protocol parsing. Normal HTTP requests retain their method badge;
GraphQL requests use GQL while preserving their actual HTTP method as transport metadata. API Studio's request
bar continues to edit the real HTTP method, and collection names remain outside this feature.
Completed on 2026-08-20. DescribeRequestUseCase now resolves a generated title, open semantic kind, compact
badge, and actual HTTP transport method from one canonical SavedApiRequest. Ordered product composition installs
the GraphQL contribution before the terminal HTTP contribution. Named GraphQL documents therefore use their
operation name and GQL; anonymous GraphQL documents retain GQL while borrowing only /graphql as the HTTP
name fallback. Ordinary requests continue to show GET, POST, or their real method.
Both unsaved sessions and saved collection rows receive the descriptor in the Room-backed sidebar projection,
which already runs on the injected I/O dispatcher. The request bar remains unchanged and continues to author the
transport method. Future protocols can contribute a new kind, badge, and optional name through one strategy plus
one product binding; the sidebar renders unknown kinds with its neutral accent fallback without requiring a core
change. Domain, formatter, and sidebar ViewModel coverage locks priority, anonymous-name fallback, parser reuse,
badge identity, and method retention. git diff --check passed. Gradle verification was intentionally deferred
because the user-owned KNet process remains active on the build-JAR classpath; the application was not launched,
stopped, or restarted.
Started on 2026-08-20 after visual review found that the stable method-selector width correctly prevents request- bar movement but its edge-separated label and chevron create excessive empty space for short methods. The shared dropdown will gain an opt-in centered anchor-content arrangement. API Studio alone will use it to keep the method and chevron as one compact group with fixed spacing while preserving the existing widest-option width, popup animation, keyboard behavior, and unchanged URL/action positions. The desktop application will not be launched.
Completed on 2026-08-20. KNetDropdown now offers an opt-in centered anchor-content arrangement while retaining
its existing edge-separated default for Traffic filters, forms, and multi-select controls. API Studio enables the
option only for the HTTP method selector. Its label and rotating chevron now render as one centered group with a
design-system-owned 8 dp gap, while the anchor and popup remain sized from the widest method option. Selecting
POST, OPTIONS, or another method therefore cannot resize the selector or move the URL, Save, and Send controls.
The existing reduced-motion-aware popup and chevron animations are unchanged. UI-core sizing coverage locks the
new spacing token, and module responsibility documents record the opt-in ownership. git diff --check passed.
Gradle verification was intentionally deferred because the user-owned KNet process remains active on the build-
JAR classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after runtime verification showed that API Studio correctly changes Send into a loading Cancel control, but the shared button's default loading policy disables pointer input and the hand cursor. The button primitive will retain that safe default for ordinary submissions and gain an explicit opt-in for controls whose loading state represents a valid cancellation action. API Studio will enable the opt-in only while a cancel callback is available. Existing execution cancellation and keyboard routing remain unchanged, and the desktop application will not be launched.
Completed on 2026-08-20. KNetButton retains its default enabled && !loading interaction policy and now exposes
an explicit clickableWhileLoading override for genuine cancellation controls. The override feeds the same
resolved interaction state into Compose click handling and the desktop hand cursor, so visual and pointer states
cannot disagree. API Studio opts in only for its Send/Cancel action when a cancellation callback exists; its
spinner and Cancel label remain visible while clicks now invoke the existing revision-safe cancelExecution().
All other loading buttons remain protected from duplicate submission. UI-core policy coverage locks enabled,
disabled, loading, and cancellable-loading combinations, and module documents record the ownership.
git diff --check passed. Gradle verification was intentionally deferred because the user-owned KNet process remains
active on the build-JAR classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after desktop verification showed that opening a focusable dropdown transfers pointer ownership to the popup layer, causing the still-visible anchor to fall back from the hand cursor to the system default. The shared popup will include a transparent, anchor-sized interaction proxy only for focusable selection dropdowns. That proxy will retain the hand cursor and close the dropdown directly, while the same focusable popup continues to consume the click so the former close-then-reopen defect cannot return. Searchable comboboxes will retain their non-focusable popup and text cursor contract. The desktop application will not be launched.
Completed on 2026-08-20. Focusable single-select and multi-select dropdowns now measure the complete anchor size
and host a transparent anchor interaction proxy in the same popup layer as the animated menu. The proxy exposes
the hand cursor and directly dismisses the popup, so clicking an expanded header closes exactly once and cannot
reach the underlying anchor. Popup placement accounts for the proxy whether the menu opens above or below and
prefers the side with enough space, while outside-click dismissal and the existing focusable input policy remain
unchanged. Searchable comboboxes continue to use their non-focusable menu-only popup and text cursor. Pure
placement coverage locks below, above, and constrained-side behavior. git diff --check passed. Gradle
verification was intentionally deferred because the user-owned KNet process remains active on the build-JAR
classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after API Studio visual verification found that the primary Params/Auth/Headers/Body tab strip remained edge-to-edge while the surrounding request-authoring controls use the shared medium horizontal inset. The request editor will apply that existing spacing token at its call site without imposing fixed tab widths or changing shared Traffic/response inspector layouts. Code-editor verification also found that Ctrl/Cmd+A moves the logical caret to the full selection's active document-end boundary, after which the viewport's generic caret-reveal effect scrolls to the final line. The session will retain that correct directional selection and caret model, while the viewport will recognize a whole-document selection as a keep-viewport operation. Search, ordinary navigation, editing, and drag-selection auto-scroll behavior will remain unchanged. The desktop application will not be launched.
Completed on 2026-08-20. The reusable request-authoring panel now applies the existing medium horizontal spacing token to its primary Params/Auth/Headers/Body/Cookies/Scripts tab strip. Individual tabs remain content-sized and the shared row retains horizontal overflow, so counts, future labels, and narrow split panes do not require fixed widths. Read-only Traffic and response inspector call sites were not changed.
The virtualized code-editor viewport now distinguishes complete-document selection from navigation before its
caret-reveal effect runs. Ctrl/Cmd+A and the shared Select All action therefore preserve the current scroll
position while EditorSession continues to own the correct full directional selection and document-end active
caret. Partial selections still reveal their endpoint, preserving search and ordinary selection behavior; pointer
drag auto-scroll remains independently owned by its existing controller. Pure policy coverage locks caret-only,
partial, forward whole-document, and reverse whole-document cases. git diff --check passed. Gradle verification
was intentionally deferred because the user-owned KNet process remains active on the build-JAR classpath; the
application was not launched, stopped, or restarted.
Started on 2026-08-20 after visual verification of Phase 60 showed that the request tab surface is correctly
inset but the separate, full-width divider below it remains visible across the authoring pane. That divider will
be removed only from RequestEditorPanel; the tab surface and spacing already provide the required grouping.
Traffic and response inspector separators will remain unchanged. The desktop application will not be launched.
Completed on 2026-08-20. The standalone HorizontalDivider immediately below the request-authoring primary tab
strip was removed along with its now-unused import. The inset tab surface remains the sole visual grouping, while
the URL-bar divider above and all Traffic/response inspector separators remain unchanged. git diff --check
passed. Gradle verification was intentionally deferred because the user-owned KNet process remains active on the
build-JAR classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after runtime verification showed the editor toolbar flashing when switching among GraphQL
Query, Variables, and Extensions. The active tab currently changes both text and language on one controlled editor
session: external replacement occurs after composition, language changes reset fold regions, and the debounced fold
analysis temporarily removes Expand All/Collapse All, shifting Prettify. GraphQL will retain one CodeEditorState
per logical sub-document so undo, caret, selection, and document identity do not leak across tabs. The shared editor
toolbar will reserve its fold-action slot from configured language capability and disable actions while no fold
regions exist, rather than conditionally removing the slot based on transient asynchronous results. The desktop
application will not be launched.
Completed on 2026-08-20. GraphQlEditor now unconditionally retains independent CodeEditorState instances for
Query, Variables, and Extensions and presents the active state through the existing single editor call site.
User-originated text is marked before updating the controlling GraphQL model, while genuine external changes such
as request restoration, operation-name synchronization, and Prettify results synchronize only the matching
session. Switching tabs no longer performs an asynchronous full-document replacement, clears another tab's undo
history, or shares its caret and selection.
The editor header now reserves Expand All/Collapse All from header configuration plus the registered language's
folding capability. Fold analysis results only control whether those actions are enabled and use a hand cursor;
they never remove the action container or shift Prettify. GraphQL and JSON both contribute folding providers, so
the toolbar structure remains identical throughout GraphQL sub-tab switches. Pure policy coverage locks supported,
disabled-by-configuration, and unsupported-language cases. Module contracts and the code-editor architecture
guide now record per-document state ownership and stable toolbar rules. git diff --check passed. Gradle
verification was intentionally deferred because the user-owned KNet process remains active on the build-JAR
classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after confirming that the editor session and folding architecture is extensible but the
header still exposes a format-specific onPrettify callback. The code-editor API will replace that callback with
an ordered list of strongly identified, declarative header actions plus one generic action dispatcher. Existing
HTTP-panel formatting integrations will contribute Prettify through this contract. Folding will remain an
editor-owned capability. The renderer will use stable action identities and preserve disabled action slots, so
future JSON, GraphQL, XML, gRPC, WebSocket, or other format actions can be added without modifying editor core.
The desktop application will not be launched.
Completed on 2026-08-20. CodeEditorHeaderConfiguration now accepts an ordered list of callback-free
CodeEditorHeaderAction declarations. Each action reuses the existing validated EditorCommandId.Custom
identity, and CodeEditorActions.onCommand is the single generic interaction boundary. The toolbar renders
contributions with stable Compose keys, preserves declared disabled actions, rejects duplicate identities, and
remains unaware of format semantics. The dedicated onPrettify callback and editor-owned Prettify label were
removed rather than retained as compatibility APIs.
The HTTP panel now owns one namespaced Prettify contribution and routes it to the active request, response, or
GraphQL formatter. Future format actions can add declarations and command handling without modifying code-editor
configuration, action callbacks, or rendering. Folding remains editor-owned and continues to reserve its stable
capability-based slot. Pure tests cover duplicate command identities and namespaced Prettify dispatch. Module
contracts and the architecture guide document the extension boundary. git diff --check passed. Gradle
verification was intentionally deferred because the user-owned KNet process remains active on the build-JAR
classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after response-cookie inspection showed long values being ellipsized despite available
vertical space. The shared KNetReadOnlyKeyValueViewer already contains an opt-in multiline path, but its default
is single-line and no network-inspection caller enables it. Read-only values will wrap by default and grow their
row naturally, while key labels and table headers remain stable single-line columns and the copy action stays at
the row's top edge. Editable key-value tables will remain single-line. Compact read-only consumers may still opt
out explicitly. The desktop application will not be launched.
Completed on 2026-08-20. KNetReadOnlyKeyValueViewer now wraps value content by default and uses the resulting
multi-line measurement to grow each row naturally. Key labels and both column headers remain single-line and
ellipsized, while multiline rows top-align the key, value, and existing copy action. The explicit wrapValues
parameter retains a compact single-line opt-out and replaces the less precise allowMultiLine name. Because all
request-header, response-header, cookie, parameter, and form-data inspection paths already consume this shared
viewer, they inherit the behavior without feature-specific changes. The editable KNetKeyValueEditor remains
single-line. The UI-core module contract records the shared policy. git diff --check passed. Gradle verification
was intentionally deferred because the user-owned KNet process remains active on the build-JAR classpath; the
application was not launched, stopped, or restarted.
Started on 2026-08-20 after choosing the API Studio URL field's measured-overflow preview for compact editable
key/value rows. The existing hover measurement, stationary-pointer delay, popup placement, and styling are
currently private implementation inside KNetTextField; copying that behavior into the key/value editor would
create two divergent interaction paths. UI core will extract one internal overflow-popup host and compose it from
both KNetTextField and the editable key/value key/value cells. Rows and stored values remain single-line, and a
popup is composed only when the actual rendered text width exceeds its cell. Read-only wrapped values remain
unchanged. The desktop application will not be launched.
Completed on 2026-08-20. UI core now owns one internal OverflowTextPopupHost that measures complete text with
the caller's exact inline style, subtracts caller-declared unavailable horizontal space, waits for stationary
hover, and displays the complete value through the existing bounded non-focusable popup placement. The original
KNetTextField now composes this host instead of owning a private duplicate implementation, preserving API Studio
URL and other text-field behavior.
Both editable key and value cells now compose the same host around their existing single-line
BasicTextField. The table's appearance, row height, editing callbacks, checkbox/delete controls, and stored
values remain unchanged; only genuinely clipped text receives the full-value preview. Password fields continue
to suppress previews, and Phase 64's read-only wrapping remains independent. Pure coverage locks unmeasured,
exact-fit, and overflowing width decisions. The UI-core module contract records the shared ownership.
git diff --check passed. Gradle verification was intentionally deferred because the user-owned KNet process
remains active on the build-JAR classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after the remaining separator above API Studio's primary request tabs was shown extending
past the inset tab surface. The separator is owned by ApiStudioScreen, not the reusable HTTP request panel. It
will retain the URL-bar/request-editor boundary while adopting the same shared horizontal spacing token as the
primary tabs. Traffic inspection, response inspection, and the already-removed divider below the tabs will remain
unchanged. The desktop application will not be launched.
Completed on 2026-08-20. The URL-bar separator now uses the shared medium horizontal spacing token already used
by API Studio's primary request-tab surface. The line therefore retains the intended structural separation but
terminates at the same left and right bounds as the tabs instead of reaching the pane edges. The change is local
to ApiStudioScreen; Traffic inspection, response inspection, and the reusable HTTP request panel are unchanged.
The API Studio module contract records ownership of this boundary. git diff --check passed. Gradle verification
was intentionally deferred because the user-owned KNet process remains active on the build-JAR classpath; the
application was not launched, stopped, or restarted.
Started on 2026-08-20 after API Studio's inset primary request-tab surface remained square beside rounded inputs,
buttons, and dropdowns. The existing shared KNetTabRow will clip its background and scrollable content with the
same small theme shape already used by individual tabs. This keeps feature call sites free of duplicated shaping
and gives all shared tab rows one consistent design-system treatment without changing their sizing, overflow, or
selection behavior. The desktop application will not be launched.
Completed on 2026-08-20. KNetTabRow now clips its surface and scrollable children with the design-system small
shape before painting its background. API Studio's primary request tabs therefore receive matching rounded
container corners through the existing shared component, with no feature-specific shape or duplicate wrapper.
Tab height, insets, content-responsive widths, horizontal overflow, and selection behavior are unchanged. The
UI-core module contract records the shared styling policy. git diff --check passed. Gradle verification was
intentionally deferred because the user-owned KNet process remains active on the build-JAR classpath; the
application was not launched, stopped, or restarted.
Started on 2026-08-20 after visual verification showed that the shared 2 dp small shape is effectively
imperceptible on API Studio's wide dark tab surface. KNetTabRow will use the design-system medium shape already
used by dropdown surfaces and apply that shape to both clipping and background painting. Tab dimensions, insets,
scrolling, and selection behavior will remain unchanged. The desktop application will not be launched.
Completed on 2026-08-20. The shared tab-row surface now clips with the 4 dp medium theme shape and paints its
background with that same shape, matching KNet dropdown containers and making the outer corners visibly rounded
on wide dark surfaces. The previous 2 dp radius was valid but visually negligible at this scale. No dimensions,
spacing, scrolling, or interaction behavior changed. The UI-core module contract now records the medium-corner
policy. git diff --check passed. Gradle verification was intentionally deferred because the user-owned KNet
process remains active on the build-JAR classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after confirming that API Studio still renders an explicit separator between the URL bar and its rounded primary request-tab surface. That screen-owned divider and its unused import will be removed so the inset rounded tab container provides the grouping without a competing line. Traffic and response inspector dividers will remain unchanged. The desktop application will not be launched.
Completed on 2026-08-20. ApiStudioScreen no longer renders the horizontal separator after RequestUrlBar, and
the now-unused divider import was removed. The rounded, inset primary request-tab surface is now the only visual
grouping between request actions and request content. Traffic, response inspection, and split-pane dividers were
not changed. The obsolete separator ownership entry was removed from the API Studio module contract.
git diff --check passed. Gradle verification was intentionally deferred because the user-owned KNet process
remains active on the build-JAR classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after Params, Headers, and Cookies showed their editable table header and divider extending
to the request-pane edges beneath the inset rounded primary tabs. RequestEditorPanel will reuse one local
modifier that applies the existing medium horizontal/vertical spacing and medium clipping shape to those three
key-value editors. The domain-agnostic UI-core editor will remain unchanged so scripting, breakpoint, response,
and body-format layouts keep control of their own placement. The desktop application will not be launched.
Completed on 2026-08-20. RequestEditorPanel now builds one request-specific key-value editor modifier from the
shared medium spacing and shape tokens and reuses it for Headers, Params, and Cookies. Their table headers, row
dividers, empty states, and controls now sit within the same inset bounds as the primary request tabs, and the
clipped table surface exposes matching rounded corners. Body, Auth, Scripts, and unrelated UI-core editor callers
retain their previous layout. Static call-site inspection confirmed exactly the three intended branches use the
modifier. The HTTP-panel module contract records this placement policy. git diff --check passed. Gradle
verification was intentionally deferred because the user-owned KNet process remains active on the build-JAR
classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after the Auth selector truncated “Inherit auth from parent” even though its measured content-responsive width should accommodate the label. The shared single-select dropdown will separate stable anchor width from preferred menu width, derive both from the complete option set, animate width only when that set changes, and allow the menu to grow beyond the anchor while its popup layout clamps to window constraints. Anchor and menu labels will reuse the existing overflow-preview host only when their rendered allocation still clips the complete text. The selected-row chrome will remove its duplicate spacing so measurement and rendering use the same contract. Searchable and multi-select dropdown behavior will remain unchanged unless using the existing default popup width. The desktop application will not be launched.
Completed on 2026-08-20. Standard single-select dropdowns now measure their complete option label set with the exact anchor and menu typography, derive independent anchor and menu width targets, and animate those targets through the shared reduced-motion-aware duration. Selection changes do not participate in the width target. The anchor remains bounded by its design maximum and incoming layout constraints; the menu may request the complete widest-row width and the focusable popup layout clamps it to window constraints while keeping its transparent dismissal proxy aligned over the real anchor, including when the wider menu shifts away from a window edge.
Both anchor labels and ordinary menu labels now use the existing measured overflow-preview host, which remains
dormant unless the rendered text actually exceeds its allocation. The redundant selected-row spacer was removed,
so the menu chrome rendered beside the checkmark now exactly matches the width calculation and “Inherit auth from
parent” no longer truncates unnecessarily. Searchable, multi-select, and custom-rendered menu content retain their
existing contracts. Pure coverage records independent anchor/menu chrome and menu growth, anchor-flooring, and
window clamping. The UI-core module contract records the policy. git diff --check passed. Gradle verification
was intentionally deferred because the user-owned KNet process remains active on the build-JAR classpath; the
application was not launched, stopped, or restarted.
Started on 2026-08-20 after visual verification showed non-centered dropdown labels sitting directly against the chevron's independently highlighted region. The standard anchor will apply the existing 8 dp shared content gap as trailing label padding and include it in its content-responsive width calculation. Centered anchors already use that token and will remain unchanged. Menu sizing, viewport clamping, and selection behavior will remain unchanged. The desktop application will not be launched.
Completed on 2026-08-20. Non-centered KNetDropdownAnchor labels now retain the shared 8 dp trailing gap before
the chevron region, matching the spacing already used by centered label-and-chevron groups. The anchor width
calculator includes that gap, so adding the visual separation does not steal space from the measured label or
introduce new truncation. Menu width, checkmark spacing, viewport clamping, and selection-stable animation remain
unchanged. The sizing assertion and UI-core module contract were updated. git diff --check passed. Gradle
verification was intentionally deferred because the user-owned KNet process remains active on the build-JAR
classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after multiline and full-document selections failed to clear with Backspace even though
ordinary active-line deletion worked. The viewport currently gates selection deletion on a presentation-derived
selected-text string before asking the session to mutate, allowing a selection transition and the next key event
to fall through to the focused per-line text field. The editor foundation will add one UI-neutral
EditorSession.deleteSelection mutation and a typed EditorCommand.DeleteSelection. The editable viewport will
dispatch that operation first for Backspace/Delete and consume the key only when the authoritative live session
actually deleted a selection. Select All will use the same built-in dispatcher rather than a duplicated Compose
range calculation. Tests will cover full multiline, reverse partial, no-selection, command dispatch, caret,
selection clearing, and undo restoration. The desktop application will not be launched.
Completed on 2026-08-20. EditorSession.deleteSelection() now owns the complete selection-deletion transaction:
it reads the live directional selection, applies one typed deletion edit, clears selection, places the caret at
the normalized range start, preserves the editor's one-empty-line document invariant, and records the operation
for undo. EditorCommand.DeleteSelection exposes that behavior through the existing UI-neutral dispatcher, and
Select All now uses the same dispatcher rather than a Compose-local range calculation.
The editable viewport dispatches selection deletion for both Backspace and Delete and consumes the key only when
the session reports that a non-empty selection was removed. With no selection, the event continues to the focused
line input, preserving normal character and line-boundary deletion. Session and dispatcher coverage locks full-
document clearing, reverse multiline ranges, caret and selection state, undo restoration, and no-selection
fall-through semantics. Module and architecture documentation record the reusable ownership boundary.
git diff --check passed. Gradle verification was intentionally deferred because the user-owned KNet process
remains active on the build-JAR classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after repository history and current event-flow inspection confirmed two editing regressions
introduced when the former full-document BasicTextField was replaced by virtualized per-line inputs. A custom
viewport double-click can currently establish a word range and then lose it to a native line-field caret callback
later in the same pointer event. Once a viewport range does survive, focus is intentionally withheld from the line
field, but the focusable viewport has no text-input/IME connection; printable input therefore cannot replace a
single-line, multiline, reverse, or whole-document selection.
This phase adds a Compose-only document-selection text-input bridge while retaining EditorSession and typed
editor commands as the mutation boundary. Committed keyboard or IME text will dispatch the existing insertion
command, which replaces the session's authoritative range as one undoable edit. Pointer gesture ownership will be
read live during native line callbacks so a same-event double-click cannot publish a competing caret transition.
The virtualized renderer, language SPI, HTTP consumers, and feature modules will remain unchanged. Focused tests
will cover live gesture suppression, committed/composing input policy, word selection persistence, and multiline
replacement semantics. The desktop application will not be launched.
Completed on 2026-08-20. Editable line callbacks now consult live viewport-gesture ownership before publishing a
caret transition, closing the same-pointer-event race that removed double-click word selection. A minimal hidden
Compose text input retains keyboard, dead-key, and IME composition while a document-level selection owns focus;
committed text is forwarded through EditorCommand.InsertText, so EditorSession replaces the authoritative
range as one undoable operation. The bridge remains focused through the first commit until the visible active line
safely retakes focus, avoiding dropped follow-up characters when the selection endpoint was outside the composed
viewport.
Regression coverage records live gesture suppression, Unicode and multiline committed input, retained IME
composition, empty-input no-op behavior, and reverse multiline replacement with caret, selection, and undo
restoration. Existing gesture tests continue to cover double-click word and triple-click line range calculation.
git diff --check passed. Gradle verification was intentionally deferred because the user-owned KNet process
remains active on the build-JAR classpath; the application was not launched, stopped, or restarted.
Started on 2026-08-20 after the interception audit found correctness risks in the edit contract, HTTP message rebuilding, informational-response correlation, disconnect cleanup, response capture ordering, and eager UI body preparation. This phase will make unchanged forwarding explicitly lossless, replace the nullable cross-phase resume payload with phase-specific decisions, normalize edited HTTP framing, validate decision phase and edit bounds at the application boundary, retain request correlation through provisional responses, and release all request observations when a channel terminates.
The breakpoint drawer will publish a pending interception before potentially expensive body decoding and prepare only the active payload with bounded retention. Rule evaluation and ordering will remain additive for future protocol matchers while avoiding transport/UI coupling. Focused tests will cover the new invariants. The desktop application will not be launched.
Completed on 2026-08-20. The application contract now distinguishes unchanged body ownership from explicit replacement and exposes phase-specific request/response decisions. It validates phase, body, header count, and header bytes before resolving a pending event. Rules use persisted deterministic priority, protocol observations have bounded eviction plus terminal cleanup, and provisional responses retain the request correlation needed by the final response.
Production forwarding now has one streaming proxy handler. A protocol-neutral selective HTTP aggregator buffers only transport candidates; messages crossing the edit limit are replayed and continue streaming instead of failing or imposing an all-traffic memory cost. Live rules are read per request, so existing Wi-Fi clients are not closed when rule state changes. Edited messages receive deterministic framing, body-forbidden response handling, custom reason phrases, and safe trailer preservation. Capture completes after downstream acceptance and releases ownership on premature channel failure. Response correlation tracks every forwarded request head, so mixed selected/unselected pipelining and provisional responses cannot consume a later exchange's identity. Absolute proxy targets and tunneled non-default ports retain the same scheme/authority used by forwarding.
The drawer publishes pending metadata immediately, resolves only the active payload off the Compose thread, and
retains at most one resolved payload. An untouched Forward action preserves original wire bytes. Module
responsibility documents were updated. Disabling global interception immediately continues existing pauses
unchanged and closes the admission race for candidates arriving with the toggle. Focused application, proxy,
interceptor, desktop-data, and breakpoint UI tests plus desktop-product compilation pass in an isolated build
directory. The complete check verifyArchitectureFoundation gate then passed with 269 actionable tasks. KNet
was not launched, stopped, or restarted.
Started on 2026-08-20 after captured GraphQL traffic still opened the breakpoint editor as a generic HTTP/REST rule with no operation criterion. This phase adds a bounded, protocol-neutral suggestion input to the existing breakpoint extension SPI, lets semantic extensions contribute validated editor criteria in a deterministic priority order, and introduces an application use case that prepares one immutable rule draft from canonical captured traffic. GraphQL will reuse its existing parser to select GraphQL and prefill a single operation name while batched or anonymous requests remain endpoint-scoped. Traffic presentation will pass only the resulting generic rule and field values to the existing editor. The desktop application will not be launched.
Completed on 2026-08-20. The breakpoint protocol SPI now accepts one bounded captured-rule suggestion input and validates extension output through the same compiled criteria contract used by live matching. Suggestions are evaluated by deterministic semantic priority; HTTP remains the safe application fallback. The new application use case loads no more than the existing one-mebibyte traffic preview, supports not-yet-durable pending candidates under the same bound, removes volatile query/fragment data from the endpoint pattern, and returns one canonical rule plus generic editor values.
GraphQL reuses its existing document parser for both live observations and captured-rule suggestions. A single
named operation preselects GraphQL and fills Operation Name; anonymous, batched, body-incomplete, or endpoint-
hint-only GraphQL remains GraphQL with an empty operation criterion. Traffic performs preparation off the UI
thread, opens the dialog only when the immutable draft is ready, and passes the values through the desktop
workspace without importing the GraphQL engine. Focused tests cover different operation names on the identical
/graphql endpoint, batch fallback, semantic suggestion transport defaults, HTTP fallback, and Traffic state
wiring. Application/protocol checks, Traffic JVM tests, desktop-product compilation, module documentation,
module boundaries, UI runtime isolation, Kotlin-first source verification, composition ownership, and the
complete architecture-foundation gate all pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-20 after the live-interception queue and Traffic method column continued to render the HTTP
transport verb (POST) for GraphQL requests even though API Studio already exposed a semantic GQL identity.
This phase will generalize the existing request-descriptor strategy input so authored, pending, and captured
requests use one ordered descriptor pipeline. Traffic rows will retain the real HTTP method for filtering and
transport behavior while rendering a separate semantic method label. Persisted semantic annotation kinds will
be observed in one bounded batch rather than rereading request bodies for every visible row, and pending
breakpoints will use bounded body previews plus the matched rule's protocol identity. New protocol formats will
therefore add a descriptor strategy and semantic inspector/extension without changing either UI renderer. The
desktop application will not be launched.
Completed on 2026-08-20. The request descriptor contract now lives in the neutral domain.request boundary and
accepts protocol-neutral request metadata, an owned bounded body preview, and an optional open semantic-kind hint.
API Studio, pending breakpoint cards, and Traffic rows all resolve through the same ordered descriptor strategies.
The canonical HTTP method remains unchanged for transport behavior and method filters, while displayMethod renders
the semantic badge (GQL for GraphQL today). Captured semantic annotations are observed in one bounded Room query,
and pending breakpoint descriptors are resolved asynchronously so neither list waits for protocol recognition. The
desktop composition root owns the descriptor multibindings, so another format adds a prioritized strategy and its
semantic inspector/extension without changing the Traffic table or intercept queue. Domain, formatter, Traffic,
breakpoint-manager, data-desktop, API Studio, application, product compilation, and all architecture-foundation gates
pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-20 to make scroll position and overflow discoverable in the Traffic table and every shared KNet
dropdown variant. This phase adds one theme-aware vertical scrollbar primitive in :ui:core, renders it only when
the attached scroll state can actually move, and reuses it for single-select, multi-select, searchable dropdowns,
and the virtualized Traffic table. Scrollbars overlay the trailing edge without changing table columns, popup width,
or list ownership. The desktop application will not be launched.
Completed on 2026-08-20. :ui:core now owns one theme-aware KNetVerticalScrollbar with adapters for finite
ScrollState and virtualized LazyListState content. Both adapters derive visibility from measured scrollability,
so no scrollbar is composed when content fits. Single-select, multi-select, and searchable KNet dropdowns reuse the
primitive at their popup trailing edge, and the Traffic table overlays the same primitive on its existing lazy list.
Shared UI tests cover the overflow visibility rules; :ui:core:jvmTest, :ui:desktop:traffic:jvmTest, Traffic
compilation, module boundaries, module documentation, UI runtime isolation, composition ownership, Kotlin-first
sources, and the complete architecture-foundation gate pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-20 after focus-owning dropdown popups required one click to dismiss the active menu and a second click to open a neighboring dropdown. This phase replaces per-popup pointer ownership with one composition-scoped dropdown expansion coordinator. Dropdown popups will retain keyboard and outside-click dismissal without stealing focus from another anchor; an anchor click will atomically close the previous owner and open the new owner. The same coordinator will cover single-select, multi-select, and searchable KNet dropdowns, enforce one expanded dropdown at a time, and preserve one-click closing on the currently active anchor. The desktop application will not be launched.
Completed on 2026-08-20. KNetTheme now provides one composition-scoped DropdownExpansionCoordinator, and each
single-select, multi-select, or searchable dropdown owns a disposable expansion token through the shared
DropdownExpansionState. Opening a token atomically closes the previous owner; toggling the active token closes it.
Dropdown popups are non-focus-stealing, allowing the same native pointer event to reach a neighboring anchor. Popup
outside dismissal defers only its identity-checked coordinator release until the next frame, preventing stale
dismissal from closing a newly opened owner while preserving the existing one-click active-anchor close behavior.
The obsolete focusable popup anchor proxy and its custom layout were removed. Shared UI tests cover ownership
handoff, active-owner toggle, and stale-release isolation; all dropdown-consuming desktop modules compile,
:ui:core:jvmTest, product compilation, and the complete architecture-foundation gate pass. KNet was not launched,
stopped, or restarted.
Started on 2026-08-20 after the non-focus-stealing popup correctly enabled one-click handoff but exposed a desktop
pointer timing edge case on the active header: outside dismissal occurs on press, while the underlying anchor click
arrives on release, after the one-frame ownership grace period, and reopens the same dropdown. This phase moves the
guard into DropdownExpansionCoordinator as an identity- and monotonic-time-based click-through dismissal marker.
The next toggle from the dismissed owner will be consumed as the close action, while a different owner can still open
immediately. All dropdown variants will use coordinator toggling for pointer activation. The desktop application will
not be launched.
Completed on 2026-08-20. Popup dismissal now records an identity-scoped monotonic marker for 500 ms in the shared
DropdownExpansionCoordinator. The matching owner's next pointer toggle consumes that marker and remains closed;
a different owner clears the marker and opens immediately. DropdownExpansionState no longer relies on a one-frame
coroutine delay, and searchable arrow activation now uses the same coordinator toggle as the standard and
multi-select anchors. Regression tests cover same-owner press/release suppression, different-owner immediate handoff,
active-owner closing, and stale-owner isolation. :ui:core:jvmTest, all product UI compilation, product compilation,
and the complete architecture-foundation gate pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-20 after the Settings audit found that application preferences and workspace layout share one whole-snapshot persistence contract. Independent writers can therefore overwrite unrelated fields, proxy-port edits can restart the active listener for intermediate keystrokes, and persistence/runtime failures can be displayed as a successful save. This phase separates application settings from workspace layout ownership, introduces atomic preference updates, and moves API-client and breakpoint runtime synchronization out of the persistence mapper.
The Settings presentation will gain validated committed inputs, typed feedback, cancellation-safe certificate operations, narrow-window category navigation, responsive rows, shared semantic components, and accurate capability copy. Persisted settings without a runtime consumer will be disabled until the corresponding body-retention policy exists. Dead settings search state and the unused legacy workspace-preferences data source will be removed. Focused tests will cover atomic updates, invalid input, failed persistence, concurrent actions, runtime propagation, and responsive state behavior. The desktop application will not be launched.
Completed on 2026-08-21. Process-level preferences now use validated ApplicationSettings, ProxyPort, and Kotlin
Duration values behind a dedicated atomic repository; WorkspaceLayoutSettings again contains only presentation
state and also updates atomically. The DataStore adapters own disjoint key sets and have no runtime collaborators.
One desktop lifecycle synchronizer applies distinct API Studio and breakpoint timeout changes, while startup policy,
Traffic, Connectivity, Workspace, and API Studio consume the focused settings/layout use cases they require.
Settings numeric fields now remain drafts until an explicit valid commit, persistence errors no longer appear as success, toggles revert after failure, reset requires confirmation, and certificate trust work is guarded and cancellation-safe with typed manual-action details. Dead search state and the obsolete map-based workspace datasource were removed. The body-retention limit and theme control are visibly disabled future capabilities instead of active settings without consumers. Shared semantic components, narrow-window category tabs, responsive setting rows, per-category scrolling, and typed footer notices preserve all existing information without engine coordination in Compose.
Focused domain, Settings, API Studio, Connectivity, Traffic, persistence-isolation, and runtime-propagation tests pass. Product compilation and the architecture-foundation gate pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-21. The scripting-language setting has a closed two-item value set, so search provides no value and makes the control behave like editable input. This phase replaces only that control with the shared non-searchable typed KNet dropdown while preserving its state, disabled-saving behavior, and styling. KNet will not be launched.
Completed on 2026-08-21. Appearance Settings now uses the shared typed KNetDropdown for JavaScript and Kotlin;
no search field or editable-query behavior remains. Settings and desktop-product compilation plus git diff --check
pass. KNet was not launched.
Started on 2026-08-21 after clarifying that Traffic must contain only exchanges that actually traverse the active KNet proxy capture pipeline. Direct API Studio execution while the proxy is stopped must continue to return its response in API Studio but must not synthesize a capture session, canonical exchange, Room row, or body object. This phase removes the direct-recording workflow, its unused application contracts, desktop direct-session lifecycle, and associated tests/bindings. Proxy capture, paused-forwarding semantics, breakpoints, canonical persistence, and Traffic paging remain unchanged. KNet will not be launched.
Completed on 2026-08-21. API Studio execution now owns only request execution, optional scripting, and response
formatting. The synthetic TrafficRecordPort, direct-record command/payload models, recording use case, command
factory, Koin bindings, and desktop direct-session lifecycle were removed. DesktopProxyRuntimeAdapter now exposes
only proxy runtime and capture-session control, while StreamingProxyCaptureSession accepts exchanges solely from
admitted proxy connections. Consequently, a direct API Studio request still returns normally but creates no capture
session, canonical exchange, Room row, or body object. When API Studio is routed through the running proxy, the
existing proxy callbacks remain the single capture source; paused capture continues forwarding without recording.
Direct-recording tests were removed or converted to production streaming-capture fixtures so tests cannot normalize
an API that production no longer supports. Focused application, data-desktop, API Studio, and desktop composition
verification, verifyArchitectureFoundation, and git diff --check pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-21 after real API Studio proxy routing exposed that the strict JVM HTTP client trusts only
platform roots and therefore rejects KNet's dynamically generated downstream certificates. This phase will add an
explicit DER certificate input to the reusable HTTP client, compose platform roots with that one certificate only
for proxy-configured clients, and inject the active process-owned KNet Root CA from the desktop composition root.
Direct HTTP clients and the proxy's independent upstream TLS verification remain strict and unchanged. The HTTP
module will not read certificate files or depend on :engine:certificate, and trust-all mode will not be used as a
workaround. Focused certificate/trust tests, HTTP tests, desktop compilation, and architecture checks will run
without launching KNet.
Completed on 2026-08-21. :core:http now accepts a typed, defensively copied DER trust input and applies it
only when the client is configured to use the local proxy. On JVM, strict proxy clients compose the platform
trust manager with an isolated trust manager containing the supplied KNet Root CA; direct clients continue to
use platform trust only. The DER input is validated as a current, self-signed CA certificate and invalid input
fails closed. Desktop composition injects the active process-owned Root CA through
CertificateRuntimeRepository.rootCertificateDer() without adding certificate-file knowledge or an
:engine:certificate dependency to :core:http. Proxy-to-origin TLS verification remains independent and
strict. Deterministic trust-chain regression tests cover proxy-scoped acceptance, direct-client rejection,
invalid DER rejection, and defensive memory ownership. :core:http:jvmTest, desktop compilation and tests,
verifyArchitectureFoundation, and git diff --check pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-21 to move the existing traffic search field from the runtime-control toolbar into the traffic
filter bar, immediately before the protocol count pills. Search state and filtering remain owned by the existing
traffic state/view-model pipeline; this phase changes only composable responsibility and layout hierarchy. The
search field will participate in the filter bar's constrained-width horizontal scrolling, while capture controls,
runtime status, clear, and auto-scroll remain in the top toolbar. Focused traffic compilation/tests, architecture
checks, and git diff --check will run without launching KNet.
Completed on 2026-08-21. TrafficFilterBar now owns the existing search presentation and renders it before a
visual divider and the All, HTTP, HTTPS, and HTTP/2 count pills. Search continues to dispatch the same
typed TrafficIntent.Search through TrafficViewModel; no filtering or persistence behavior was duplicated.
The field uses the shared KNetSearchField, has a stable 240 dp width, and participates in the existing
horizontally scrollable filter group when the window is constrained. TrafficToolbar is again limited to
capture/runtime controls, clear, and auto-scroll. The traffic module documentation records this ownership.
:ui:desktop:traffic:jvmTest, desktop compilation and tests, verifyArchitectureFoundation, and
git diff --check pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-21 after the Wi-Fi setup drawer's QR explanation was observed truncating most of its content
with an ellipsis. The explanatory prose will wrap inside its existing weighted column while the QR code,
endpoint, URL, and copy action retain their current layout. Focused connectivity compilation/tests and
git diff --check will run without launching KNet.
Completed on 2026-08-21. The QR explanation now uses Compose's natural wrapping inside the existing weighted
content column instead of forcing one line with TextOverflow.Ellipsis. The surrounding QR code, endpoint,
selectable setup URL, and copy action are unchanged. The connectivity module documentation records wrapping
setup guidance. :ui:desktop:connectivity:jvmTest, desktop compilation, verifyArchitectureFoundation, and
git diff --check pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-21 to align the Wi-Fi setup drawer's close action with the shared desktop interaction model.
The plain Material icon button will be replaced by the reusable KNet icon button so the existing close intent
gains theme-aware hover feedback, keyboard focus treatment, button semantics, and a hand cursor. Focused
connectivity compilation/tests and git diff --check will run without launching KNet.
Completed on 2026-08-21. The drawer header now uses KNetIconButton for its close action, preserving the same
intent while adding the shared theme-aware hover surface, hand cursor, keyboard focus ring, accessibility target,
and button semantics. Connectivity tests, desktop compilation, and git diff --check pass. KNet was not
launched, stopped, or restarted.
Started on 2026-08-21 after the intended target was clarified as the bottom MessageBanner rendered by
ConnectDeviceScreen. The screen-level banner and its transient success-message model will be removed. Existing
card/runtime state will continue to communicate success, while operation failures will be retained as typed error
state and shown inline by the Wi-Fi card/setup drawer rather than silently discarded. The drawer's local-network
guidance remains unchanged. Focused connectivity compilation/tests, architecture checks, and git diff --check
will run without launching KNet.
Completed on 2026-08-21. ConnectDeviceScreen no longer renders the bottom MessageBanner, and the obsolete
message tone/value models plus dismiss intent were removed. Successful startup is communicated by the existing
proxy/Wi-Fi runtime projection on the setup card. Operation failures remain typed as failureCode and are shown
inline by both the card and setup drawer, with regression coverage for failed proxy startup. The drawer's
local-network guidance remains intact. Connectivity tests, desktop compilation, verifyArchitectureFoundation,
and git diff --check pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-21 to add explicit visual separation between the copy icon and Copy setup URL label without
changing the shared button layout or other button call sites. The current platform instructions will be assessed
separately for first-time-user clarity. Focused connectivity compilation/tests and git diff --check will run
without launching KNet.
Completed on 2026-08-21. The copy action now places an explicit 6 dp spacer between its icon and label at the
feature call site, avoiding behavioral or visual changes to other shared KNetButton consumers. Connectivity
tests, desktop compilation, and git diff --check pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-21 to make the Wi-Fi setup drawer understandable without external documentation. The change
will remain isolated to private composables in the desktop connectivity feature: a prerequisite checklist,
platform-specific certificate and manual-proxy instructions, a verification step, and a concise certificate
compatibility note. Shared drawers, banners, and other connectivity mechanisms will remain unchanged. Focused
connectivity tests, desktop compilation, and git diff --check will run without launching KNet.
Completed on 2026-08-21. The active Wi-Fi drawer now explains the complete setup path in place: same-network and
proxy-running prerequisites, explicit Android and Apple certificate installation, manual proxy fields using the
live endpoint, and a browser-based verification step. It also explains that user-CA rejection or certificate
pinning can prevent individual apps from being inspected even when browser capture works. Long platform steps
wrap instead of truncating. The new panels and their copy are private to WifiProxySetupDrawer; no shared drawer,
banner, connectivity core, or other setup mechanism changed. Connectivity tests and desktop compilation pass.
KNet was not launched, stopped, or restarted.
Started on 2026-08-21 after the differently styled instruction number and body text were observed sitting at
slightly different vertical positions. The two texts will align by their first typographic baseline inside the
feature-private platform step row, preserving multiline wrapping and leaving shared list components unchanged.
Focused connectivity tests, desktop compilation, and git diff --check will run without launching KNet.
Completed on 2026-08-21. Each step number and the first line of its wrapping instruction now use Compose first- baseline alignment, eliminating the vertical offset caused by their different typography styles while preserving natural multiline layout. The change is private to the Wi-Fi platform-step rows. Connectivity tests and desktop compilation pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-21 after an IntelliJ rerun exposed a transient handover conflict between the terminated KNet
process and the new process's LAN proxy/setup listeners. This phase keeps the loopback proxy engine unchanged
and strengthens only the connectivity boundary: typed activation failures, an observable recovery state, safe
LAN listener rebinding, bounded fast retry with lifecycle cancellation, setup-portal fallback, transactional
resource publication, and precise UI messaging. Regression tests will cover transient release, persistent
conflict, alternate setup port selection, rapid lifecycle restart, and stop/close during recovery. Focused module
tests, desktop compilation, architecture verification, and git diff --check will run without launching KNet.
Completed on 2026-08-21. Wi-Fi listener startup now publishes a typed Recovering state for transient bind
ownership, attempts bounded fast recovery at 100/250/500/1000/2000 ms, then keeps a precise typed failure visible
while slower background recovery remains active. Recovery generations are cancelled by proxy stop, network
replacement, and runtime close, preventing stale listeners from publishing after lifecycle changes. The LAN
gateway enables safe address reuse for TCP teardown handover without enabling shared-port ownership. Setup-page
startup tries an ordered, validated port list and publishes the actual fallback URL while the phone proxy endpoint
stays stable. Gateway and portal publication is transactional and rolls back partial ownership on failure.
The reusable connectivity adapter remains independent from the logging backend: typed failure plus the original
platform exception are delivered to product-owned diagnostic callbacks, and the desktop composition root routes
them to KNetLogger. The Connect Device card/drawer distinguish active recovery from terminal attention and
identify the exact failing listener and endpoint without parsing error strings. Regression coverage now verifies
transient release, persistent ownership, setup-port fallback, ordinary proxy stop/restart, proxy stop during
recovery, runtime close during recovery, and typed-model validation. :core:connectivity:jvmTest,
:connectivity:desktop:jvmTest (nine Wi-Fi backend tests), :ui:desktop:connectivity:jvmTest,
:products:desktop:test, desktop product compilation, verifyArchitectureFoundation, and git diff --check
pass. KNet was not launched, stopped, or restarted by this phase.
Started on 2026-08-21 after the desktop composition root was found embedding its setup-portal HTML document in
a Kotlin lambda. This phase audits all production source sets for inline HTML documents, moves runtime templates
into the owning module's src/jvmMain/resources/templates directory, and loads them through focused,
resource-backed Kotlin components with missing/empty-resource validation. The existing resource-backed Wi-Fi
setup portal remains unchanged. Test-only HTML parser fixtures are classified separately because they are input
data rather than shipped page templates. Focused product and HTTP-panel tests, product compilation,
verifyArchitectureFoundation, a production inline-HTML scan, and git diff --check will run without launching
KNet.
Completed on 2026-08-21. The repository audit found two inline HTML documents in production Kotlin: the desktop
composition root's dedicated setup-portal index and the HTTP panel's default HTML response-editor document. Both
now live under the owning module's src/jvmMain/resources/templates directory and are loaded through focused,
lazy resource components that fail clearly when a required resource is missing or empty. Product composition now
injects the setup page through the existing SetupPortalContent.renderIndex contract, and the response body model
references its module-owned packaged template. The already resource-backed Wi-Fi setup portal remains unchanged.
The follow-up production scan finds zero inline HTML documents. Seven short HTML values remain only in JVM test
sources as formatter/detection inputs; MIME constants, text/html response headers, and formatter signature
tokens are not document templates and remain in Kotlin where they belong. Module responsibility documents now
record ownership of the new resources. Focused resource tests, :products:desktop:test,
:ui:desktop:httpPanel:jvmTest, desktop product compilation, verifyArchitectureFoundation, and
git diff --check pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-21 to remove redundant protocol-default ports from the Traffic table's Host presentation.
HTTP :80 and HTTPS :443 will be hidden, while non-default ports remain visible. Canonical authority, routing,
persistence, full-URL construction, inspection, and export remain unchanged. Focused Traffic presentation tests,
module tests, desktop compilation, architecture verification, and git diff --check will run without launching
KNet.
Completed on 2026-08-21. The Traffic table now derives a dedicated host label from the typed HttpScheme: HTTP
:80 and HTTPS :443 are omitted, while non-default and scheme-mismatched ports remain visible. The underlying
row authority remains unchanged, so search, full URLs, inspection, export, persistence, and proxy routing retain
the resolved port. Canonical IPv6 authorities are bracketed before presentation/full-URL construction, and the
compact label safely removes only a matching default port. Tests cover both defaults, non-default ports,
scheme mismatches, and bracketed IPv6. :ui:desktop:traffic:jvmTest, desktop product compilation,
verifyArchitectureFoundation, and git diff --check pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-21 after a 200-row first page was observed renumbering its newest row to 625 and jumping to
the top when older pages loaded. This phase adds exact filtered totals and durable capture-order metadata at the
storage/application paging boundary, separates loaded and available counts in Traffic state, keeps row numbers
stable across pagination and filtering, and makes auto-scroll react only to a genuinely new newest transaction.
Regression coverage will reproduce the multi-page numbering and load-older viewport trigger. Storage, data,
application, Traffic, desktop compilation, architecture verification, and git diff --check will run without
launching KNet.
Completed on 2026-08-21. Canonical exchange rows now receive an immutable SQLite-generated capture sequence,
and ExchangeId remains uniquely indexed for lifecycle updates and cross-feature identity. Room schema v19
uses that sequence for newest/oldest keyset queries and adds an exact filtered-count query. The application
page contract wraps the existing shared HttpExchangeSnapshot with typed capture-order metadata and carries
the exact first-page total through its opaque continuation cursor, so API Studio, breakpoints, inspectors, and
Traffic continue sharing the same request/response model rather than copying it.
Traffic now stores loaded and available counts separately, maps the durable sequence directly into each row,
and never derives numbering from the current list size. A provisional breakpoint row receives only a temporary
next number until its canonical row arrives. Page/filter merges sort by durable sequence, and the footer reports
loaded of total while more matching rows remain. Auto-scroll is no longer keyed to list size: older-page loads
and bounded-window eviction do not jump to the top, while a genuinely newer capture or explicit auto-scroll
enablement still does.
Regression coverage verifies a 625-record history remains numbered 625 through 1 after all four pages load,
exact totals survive continuation cursors, SQLite sequences remain stable, and older-page viewport changes do
not request auto-scroll. The affected application, storage, data, and Traffic suites pass; the 100,000-row
filtered-query baseline remains within its declared limit. Desktop product compilation and the full
check verifyArchitectureFoundation gate pass with 270 actionable tasks. git diff --check passes, and KNet
was not launched, stopped, or restarted.
Started on 2026-08-21 to replace the shallow and partially duplicated :testingServer routes with one
deterministic local protocol lab. The existing WebFlux application remains the launcher, but responsibilities
will be grouped by protocol rather than one handler per HTTP verb. The lab will expose a versioned discovery
manifest, HTTP diagnostics and representative payloads, SSE, raw WebSocket echo, GraphQL HTTP/subscription
operations, HTTP/2 clear-text negotiation, and a native grpc-java listener for unary and streaming RPCs.
Unsupported transports such as HTTP/3 and WebTransport will not be represented by fake WebFlux endpoints.
The duplicate authentication implementation and obsolete /api route surface will be removed because KNet is
still in development and no compatibility contract is required. Module and usage documentation plus real
WebFlux, GraphQL, WebSocket, and gRPC integration tests will define the supported fixture contract. Verification
will compile and test :testingServer without launching the KNet desktop product.
Completed on 2026-08-21. The duplicated handler/router tree and obsolete /api surface were removed and replaced
with a versioned /lab/v1 protocol contract organized by capability. Spring WebFlux now provides cohesive HTTP,
payload, streaming, and raw WebSocket fixtures; Spring GraphQL provides named queries, mutations, and real
WebSocket subscriptions; a lifecycle-managed grpc-java listener provides unary, server-streaming,
client-streaming, bidirectional, health, reflection, typed-status, and trailer scenarios. XML, SOAP, GraphQL,
Protobuf, and the browser dashboard are resource- or schema-backed rather than embedded Kotlin strings.
The discovery manifest distinguishes executable capabilities from PLANNED gRPC-Web, HTTP/3, and WebTransport
work, so unsupported transports are not simulated or misrepresented. testingServer/MODULE.md documents module
ownership and dependency direction, while docs/testing_server_protocol_lab.md is the endpoint and extension
guide for desktop, API Studio, proxy, and phone testing.
The real-listener integration suite passes nine scenarios covering HTTP metadata, H2C negotiation, NDJSON, SSE,
named GraphQL HTTP operations, GraphQL subscriptions, raw WebSocket, all native gRPC cardinalities, typed gRPC
failure status, and trailers. :testingServer:test, :testingServer:bootJar, verifyArchitectureFoundation, and
git diff --check pass. The KNet desktop application was not launched.
Started on 2026-08-21 to replace Traffic's duplicated hardcoded header/row widths with one typed column-layout
state. Header separators will provide constrained drag resizing, resize cursors, per-column reset, synchronized
header/row horizontal overflow, and persistence only after a gesture completes. :ui:core will own only the
reusable resize handle while :ui:desktop:traffic retains its column identities, defaults, constraints, and
layout policy. Width persistence will use the existing workspace preference use cases rather than writing to
DataStore from Compose or the ViewModel.
Completed on 2026-08-21. Traffic headers and virtualized rows now resolve one typed
TrafficTableColumnWidths snapshot, so column edges cannot drift between the two render paths. Path remains in
automatic fill mode until explicitly resized. Practical per-column bounds prevent unusable widths; once the
resolved table exceeds its viewport, header and rows share one horizontal position and the existing UI-core
horizontal scrollbar appears. The reusable UI-core separator provides a wide drag target, horizontal-resize
cursor, hover/drag feedback, and double-click reset without knowing Traffic column identities.
Drag updates are immediate in ViewModel presentation state, while the existing workspace update use case writes DataStore only after the gesture finishes. A separator double-click persists one-column reset, and the Columns menu exposes a full-width reset command. An absent Path key is preserved as automatic-fill state across restart; invalid persisted widths fall back at the adapter boundary. No Compose or DataStore type crosses the domain contract.
Regression coverage verifies default Path fill, explicit-width overflow, column-specific min/max constraints,
individual reset, full reset, commit-only persistence, DataStore round-trip, and invalid domain values.
:core:domain:jvmTest, :data:desktop:jvmTest, :ui:desktop:traffic:jvmTest, desktop product compilation, and
verifyArchitectureFoundation pass. KNet was not launched, stopped, or restarted.
Started on 2026-08-21 to improve the reusable table resize separator's visibility without changing table layout. The idle indicator will use a stronger theme-derived neutral color, while hover and drag use the accent color and slightly greater visual thickness. The existing eight-density-independent-pixel interaction target and caller-owned resize behavior remain unchanged. UI-core and Traffic compilation plus architecture verification will run without launching KNet.
Completed on 2026-08-21. The resize separator now uses the theme's muted-text color at stronger opacity while
idle, making it distinguishable from passive panel borders in both palettes. Hover and active drag states use the
accent color and a two-density-independent-pixel indicator; the indicator remains centered inside the unchanged
eight-density-independent-pixel interaction target, so table measurements and column widths do not move.
:ui:core:compileKotlinJvm, :ui:desktop:traffic:compileKotlinJvm, and verifyArchitectureFoundation pass.
KNet was not launched.
Started on 2026-08-21 to add breathing room between the centered resize tick and adjacent Traffic header text. One design-token-derived asymmetric cell inset will be shared by header labels and row values so alignment remains exact. Column widths, separator geometry, hit targets, scrolling, and persistence will remain unchanged. Traffic compilation and architecture verification will run without launching KNet.
Completed on 2026-08-21. Every Traffic header label and corresponding row value now uses the same asymmetric
design-system spacing: 4 dp before content and 12 dp after it. The larger trailing inset keeps text away from the
resize tick, while the smaller leading inset prevents the next column from feeling detached. Insets are applied
inside the existing fixed column widths, so separator positions, drag calculations, persisted widths, synchronized
scrolling, and header-to-row alignment remain unchanged. Traffic and desktop product compilation plus
verifyArchitectureFoundation pass. KNet was not launched.
Started on 2026-08-21 to remove the redundant idle divider after the final visible Traffic column without removing that column's resize capability. The reusable resize handle will gain an explicit idle-visibility option; Traffic will disable only the final visible handle's idle indicator while preserving its full hit target, resize cursor, hover/drag accent treatment, double-click reset, and persisted sizing. Interior boundaries and other consumers remain unchanged. UI-core and Traffic compilation plus architecture verification will run without launching KNet.
Completed on 2026-08-21. Traffic derives the terminal boundary from its current visible-column list and disables
only that handle's neutral idle indicator. The reusable handle keeps its existing eight-density-independent-pixel
hit target and now reveals the same animated accent tick on hover or drag, retaining last-column resizing and
double-click reset. All interior boundaries remain visible at rest, and optional-column visibility changes
automatically move the terminal treatment to the new last column. UI-core, Traffic, and desktop product
compilation plus verifyArchitectureFoundation pass. KNet was not launched.
Started on 2026-08-21 to qualify HTTP/1.0 as a real proxy capability rather than relying on incidental Netty codec
compatibility. The work remains localized to :engine:proxy: version-aware generated responses, downstream
persistence rules, safe HTTP/1.1-to-HTTP/1.0 response framing, version-specific hop-by-hop header normalization,
and deterministic failure behavior. Real socket-level integration coverage will exercise absolute-form requests
without Host, content-length uploads, default close, explicit keep-alive, chunked upstream translation, HTTPS
CONNECT, canonical capture identity, and generated errors. Shared traffic models, Room schema, application use
cases, inspectors, breakpoints, connectivity mechanisms, and UI contracts remain unchanged. The runtime capability
catalog and module documentation will be updated only after the qualification suite passes. KNet will not be
launched.
Completed on 2026-08-21. :engine:proxy now derives one downstream HTTP/1 policy at request admission and uses
it consistently for origin forwarding, generated errors, CONNECT establishment, response framing, connection
reuse, capture, and queued-request ownership. HTTP/1.0 defaults to close, supports explicit Connection and
legacy Proxy-Connection keep-alive, removes proxy-only headers before forwarding, and rejects unsupported
transfer-encoded HTTP/1.0 request bodies deterministically. Absolute-form requests remain routable without a
Host field while KNet supplies the resolved authority to the origin.
Origin responses are translated without buffering ordinary streams: HTTP/1.1 chunk markers and trailers are removed for HTTP/1.0, self-delimiting responses may retain explicit keep-alive, and otherwise EOF provides the message boundary. Complete aggregated responses receive a content length when safe. KNet-generated 400, 429, 502, and CONNECT responses use the downstream request version, and terminal close decisions release rather than drain already-decoded requests.
Focused semantics and real-listener tests qualify absolute-form GET, content-length POST, default close,
explicit and legacy keep-alive, chunked translation, trailer removal, canonical HTTP/1.0 capture metadata,
generated failures, and a real CONNECT plus TLS handshake and inner HTTPS request through KNet. The desktop
runtime capability catalog now truthfully advertises qualified HTTP/1.0 and HTTP/1.1 support, and
:engine:proxy/MODULE.md records the ownership boundary. The proxy module's unused testing-server and WebFlux
test dependencies were removed so its qualification classpath remains focused and independently resolvable.
KNet was not launched, stopped, or restarted.
Started on 2026-08-21 after the stronger full-height header separators proved visually too similar to a rigid spreadsheet grid. The full-height interaction target will remain, but its visible indicator will become a short, centered, rounded tick with restrained idle contrast and accent expansion during hover or drag. UI-core and Traffic compilation plus architecture verification will run without launching KNet.
Completed on 2026-08-21. The visible separator is now a centered, rounded 1-by-14 dp neutral tick rather than a
full-height rule. Hover or drag animates it to a 2-by-22 dp accent tick using the design system's fast motion and
reduced-motion policy. Its surrounding 8 dp full-height hit target, resize cursor, drag calculation, double-click
reset, and table measurements are unchanged. UI-core and Traffic JVM compilation plus
verifyArchitectureFoundation pass. KNet was not launched.
Completed on 2026-08-21. API Studio now stores one strongly typed per-request version preference: Auto, exact
HTTP/1.0, or exact HTTP/1.1. The value belongs to the canonical SavedApiRequest, crosses the shared
NetworkRequestSpec, survives Room schema v20 and editor auto-save/restore, and reaches the existing execution use
case without a UI-specific transport model. Captured HTTP/1.0 and HTTP/1.1 requests preserve their version when
opened in API Studio; unsupported future captured protocols use Auto rather than pretending they can be forced.
Auto and HTTP/1.1 retain the Ktor client. Exact HTTP/1.0 is isolated behind the :core:http platform transport
boundary because CIO emits HTTP/1.1 request lines. Its JVM adapter supports origin-form direct requests,
absolute-form HTTP proxy requests, HTTPS CONNECT plus TLS, content-length and close-delimited responses, chunked
response decoding, informational responses, bounded bodies/headers, existing auth/body/cookie policies, redirects,
timeouts, retries, cancellation, and direct fallback when the local proxy is unavailable. API Studio response
inspection reports the actual response protocol independently of the requested preference.
Wire-level tests assert the literal HTTP/1.0 request line, direct POST framing, proxy absolute-form routing, close-delimited response handling, and observed response version. Domain, application, mapper, ViewModel, restore, proxy semantics, real-listener HTTP/1.0, and real CONNECT/TLS tests cover the complete path. KNet was not launched.
Completed on 2026-08-24. The proxy integration suite now covers three previously deferred connection-resilience cases through real sockets: malformed HTTP/2 traffic receives GOAWAY while the shared listener remains usable, PING receives an acknowledgement and the same parent accepts a subsequent application stream, and 40 repeated HTTP/2 parent create/request/close cycles are followed by healthy forwarding. These tests extend the existing negotiation, multiplexing, translation, HPACK, reset, GOAWAY, breakpoint, persistence, API Studio, and Traffic coverage without introducing a second proxy path.
The root http2Qualification verification task is now the single cross-module gate for architecture rules,
canonical HTTP and traffic contracts, proxy transport, desktop capture/Room persistence, the protocol lab, API
Studio, Traffic, and desktop composition. CI invokes exactly this task on macOS, Windows, and Linux; the stale
desktop assemble path in the general CI job was corrected to :products:desktop:assemble. The local macOS gate
passed all 167 Gradle tasks in 2 minutes 45 seconds. Remote CI results, Android/iOS real-device Wi-Fi smoke tests,
and release soak remain future evidence, so HTTP/2 correctly stays EXPERIMENTAL. KNet was not launched.
Header-boundary hardening completed on 2026-08-25. Netty's x-http2-* object-bridge fields now remain private to
HTTP/2 codec conversion: canonical request/response headers exclude the complete Netty extension-header set,
HTTP/2-to-HTTP/1 forwarding strips them before the origin wire, and upstream HTTP/2 responses strip them before
downstream delivery. Scheme and stream identity continue through the typed request target and StreamId fields.
Focused canonical mapping, response relay, and real-socket downgrade regressions passed, followed by the complete
:engine:proxy:test and verifyArchitectureFoundation gates (27 actionable tasks). KNet was not launched.
Completed on 2026-08-24 without production-code changes. docs/grpc_target_and_implementation_plan.md now defines
the repository-specific path from KNet's qualified HTTP/2 transport and existing local grpc-java protocol lab to
native gRPC capture, durable message timelines, message-aware breakpoints, and API Studio execution. Canonical
HttpRequestSnapshot, HttpResponseSnapshot, and HttpExchangeSnapshot remain the single request/response
models; ordered gRPC payloads become additive children through a protocol-neutral message contract and the
existing dormant duplex_messages persistence direction.
The plan adds one justified JVM :engine:grpc boundary so protobuf descriptors, reflection, compression,
framing, and grpc-java client execution do not leak into :engine:proxy, :core:http, application contracts,
storage, or Compose. It preserves the current HTTP/GraphQL interceptor path, evolves the global breakpoint queue
and drawer around stable HTTP-exchange and protocol-message units, and makes Traffic/API Studio presentation
extension-driven. Delivery phases G0 through G9 remain pending and must progress through real through-proxy
cardinality, backpressure, persistence, UI, security, cross-platform, and device gates before any gRPC capability
is marked supported. KNet was not launched, stopped, or restarted.
Started on 2026-08-25. The implementation adds one isolated :engine:sse semantic module and preserves the
canonical HTTP exchange as the parent request/response model. Identity-encoded event records are incrementally
parsed and captured as generic child protocol messages; Room, body storage, Traffic paging, and the proxy remain
protocol-neutral. Historical formatting and inspection use the same parser, removing the old duplicate SSE logic.
API Studio now has an optional protocol-neutral HTTP response stream contract. HTTP/1.1 and AUTO/exact HTTP/2 publish owned response heads and chunks before completion using the same request preparation as terminal execution; collector cancellation releases the active transport response. A product-registered SSE interpreter switches the existing HTTP response pane to a bounded live timeline, while ordinary HTTP and encoded event streams retain the bounded terminal path. Response-record breakpoints use the generic message gate and can match event type, event ID, or data before continuing, replacing, or terminating the stream.
The local protocol lab supplies finite, endless, multiline, comment, fragmented, malformed, disconnect, resume,
gzip, burst, and real TLS/ALPN HTTP/2 fixtures. The completion gate covers parser limits, passive capture,
persistence, Traffic decoding, formatting, breakpoint decisions, first-event delivery, cancellation, request
pipeline preservation, and desktop composition. Capability maturity remains EXPERIMENTAL; incremental encoded
stream decoding, cross-platform/device evidence, complete concurrent HTTP/2 isolation, and multi-hour soak remain
the explicit SSE-5 promotion gates. KNet is not launched by this phase.
Completed on 2026-08-25. The complete affected-module gate passed 189 Gradle tasks across the SSE engine, formatter, proxy, protocol module, canonical traffic/domain/HTTP contracts, application orchestration, desktop persistence, protocol lab, API Studio UI, desktop composition, Kotlin-first source checks, and architecture verification. The desktop application was not launched, stopped, or restarted by this work.
Completed on 2026-08-25 without production-code changes. The repository-specific SSE-5 section in
docs/sse_target_and_implementation_plan.md now defines one continuous delivery from the current experimental
live core to evidence-backed supported capture, API Studio, and breakpoint capabilities. The plan keeps the
canonical HTTP exchange, generic protocol-message children, proxy inspector/transformer seams, Room/body store,
Traffic, HTTP API Studio workspace, and global breakpoint drawer. No new Gradle module or alternate SSE request,
response, traffic, or collection model is introduced.
The completion sequence covers a shared stream-confined identity/gzip/deflate decoder pipeline, bounded encoded
breakpoint transcoding, real HTTP/1.1 and concurrent HTTP/2 isolation, lifecycle cleanup, saturation and security
limits, short CI stress plus release soak, presentation evidence, a root sseQualification gate, desktop
cross-platform execution, and Android/iOS Wi-Fi proxy evidence. Brotli/Zstandard, HTTP/3, browser policy emulation,
and automatic reconnect remain explicit additive future capabilities and do not dilute the frozen Supported SSE
profile. Capability promotion remains independent and evidence-gated. KNet was not launched by this planning
phase.
Started on 2026-08-25. This phase executes SSE-5 as one continuous implementation increment: shared bounded
identity/gzip/deflate streaming codecs, passive capture and API Studio integration, encoded record breakpoint
transcoding, HTTP/1.1 and HTTP/2 lifecycle isolation, saturation/security/resource gates, presentation evidence,
and the aggregate sseQualification task. Existing canonical HTTP, protocol-message, persistence, Traffic,
connectivity, and API Studio collection boundaries remain authoritative. Capability maturity will change only for
gates backed by recorded evidence; unavailable operating-system or physical-device evidence will remain explicit.
Completed locally on 2026-08-26. One shared stream-confined codec registry now implements bounded incremental identity, gzip, zlib-wrapped deflate, raw deflate, and supported stacked encodings for passive capture, HTTP API Studio interpretation, and response-record breakpoints. Encoded breakpoint replacements are re-encoded using the supported original representation, while generic proxy head sanitation removes invalid length, digest, validator, and range metadata after any payload transformation. The canonical parent remains encoded evidence and decoded SSE records remain bounded generic child messages.
Deterministic fixtures and tests cover arbitrary chunk boundaries, gzip trailer validation, malformed and
expansion-abuse input, decoder cleanup, API Studio gap presentation, HTTP/1.1 streaming, TLS/ALPN HTTP/2 encoded
DATA frames, and a real multiplexed proxy case where a paused SSE stream does not delay an ordinary sibling. The
root sseQualification gate passed 207 Gradle tasks on macOS, and the configurable sseReleaseSoak task passed a
one-second infrastructure smoke run. The checked-in CI matrix targets macOS, Windows, and Linux.
The live capability entries intentionally remain EXPERIMENTAL: the default three-hour soak with resource
measurements, actual cross-platform CI results, physical Android/iOS Wi-Fi proxy evidence, and remaining
real-socket lifecycle rows are not locally complete. The desktop application was not launched, stopped, or
restarted by this phase.
Started on 2026-08-26. Move the SSE response-stream interpreter and its mirrored tests from the ambiguous
engine.sse.apistudio package to engine.sse.integration.apistudio. This is a naming-only boundary clarification:
the SSE engine continues to implement the protocol-neutral application contract, while API Studio UI, workspace,
collection, and presentation ownership remain outside :engine:sse. Update composition imports and documentation,
then verify the focused SSE tests, desktop composition, and architecture gates without launching KNet.
Completed on 2026-08-26. Production and mirrored test packages now use
engine.sse.integration.apistudio; desktop composition imports and SSE documentation point to the explicit
integration path. The class still implements the same protocol-neutral application contract, and no UI, workspace,
collection, proxy, persistence, or runtime behavior moved into the SSE engine. :engine:sse:test, the focused
DesktopModulesTest, and verifyArchitectureFoundation passed together across 163 Gradle tasks. KNet was not
launched.
Started on 2026-08-26. Replace the ambiguous hexagonal port package/type terminology in both
:application:desktop and :application:companion with explicit contract packages and capability-oriented
interface names. Split the former companion contract monolith by capability, separate breakpoint contracts from
the stateful coordinator, separate semantic-inspection contracts from scheduling/use-case behavior, and keep
outer adapters dependent inward on the renamed contracts. No runtime behavior or application UI is intended to
change. Completion requires downstream compilation, architecture verification, companion platform gates, and the
full release qualification without launching KNet.
Completed on 2026-08-26. Both application modules now expose capability-oriented contract packages rather than
the ambiguous port package/type vocabulary. Desktop stateful orchestration lives under coordinator, focused
commands and queries remain under usecase, and the former companion contract monolith is split into pairing,
registration, credential, connection, inspection, and certificate contracts. Breakpoint contracts, protocol
registry behavior, coordination, semantic inspection scheduling, annotation queries, body access, and pairing
coordination are separated by responsibility without changing their runtime behavior.
The companion Android connectivity adapter now also declares the normal ACCESS_NETWORK_STATE permission required
by its existing ConnectivityManager contract. Focused application tests, desktop product tests, architecture
verification, companionFoundationQualification, Android lint, and the complete phase18ReleaseGate passed. The
final release gate covered 524 tasks, including JVM, Android, iOS simulator, engine, Compose UI, packaging, and
architecture checks. KNet was not launched.
Phase 111: Android Companion Product Registration [COMPLETED — PRODUCT SHELL; CAPTURE RUNTIME PENDING]
Completed on 2026-08-26. Added the real :products:companion:androidApp Android application target with its manifest,
resource-owned minimal launcher, Android product composition root, lifecycle cleanup, and composition tests. The
product composes the implemented versioned registration/invitation adapters, protected Android Keystore credential
storage, non-exportable device identity/proof signing, and Android network observation. It deliberately does not
substitute successful stubs for the unavailable pinned transport, certificate flow, or VPN/TUN packet backend.
The root companionAndroidProductQualification gate covers the portable companion foundation, Android product
unit tests, lint, and debug APK assembly without installing or launching the application. The installable shell is
therefore an actual product target, while companion traffic capture, full product UI, certificate trust, physical
device evidence, and VPN remain explicit follow-up increments. The dedicated product gate passed 287 tasks and the
complete phase18ReleaseGate subsequently passed 589 tasks, including every module check and desktop packaging.
Neither product was launched.
Completed on 2026-08-26 following the current JetBrains Compose Multiplatform structure: the Android application
remains a thin executable host while reusable screens, theme, state rendering, and UI strings live in the new
:ui:companion:sharedUi Kotlin Multiplatform module. The module targets Android and iOS directly and retains a JVM
target for fast common UI mapping tests. Android's MainActivity now uses ComponentActivity.setContent, edge-to-edge
window handling, and lifecycle-aware collection; the former XML layout and duplicated Android screen strings were
removed. Android manifest, launcher/theme, icon, and backup XML remain product packaging resources rather than UI.
The architecture gate now rejects companion res/layout files plus setContentView/R.layout usage so later
features cannot accidentally create a parallel Android View implementation.
The shared UI JVM tests, Android compilation, iOS-simulator production compilation, Android product tests, lint,
and debug APK assembly passed together across 291 tasks. Pure state/resource mapping tests intentionally run on the
JVM; executable iOS UI tests require the supported Xcode 26.4 toolchain, while this workstation still has Xcode 16.4.
The complete phase18ReleaseGate then passed all 645 tasks, including every module check and desktop packaging. No
application was installed or launched.
Completed on 2026-08-26 without creating or registering an iOS product. The existing
:ui:companion:sharedUi iOS targets now include an iosMain UIKit bridge built with ComposeUIViewController.
It renders the same common Compose UI from an injected StateFlow<CompanionUiState> while leaving state ownership,
lifecycle composition, dependency injection, signing, and Xcode integration to a future iOS product target.
Started on 2026-08-26. Convert :ui:core from a JVM-only Compose module into KNet's complete Compose
Multiplatform UI foundation for JVM, Android, iOS ARM64, and iOS Simulator ARM64. Preserve one common API for
themes, colors, semantic tokens, typography, spacing, shapes, motion, resources, and reusable components while
confining unavoidable clipboard and pointer implementations to platform source sets. Migrate companion shared UI
to consume KNetTheme instead of owning a duplicate palette. No iOS product will be registered and Android
verification will compile and test without assembling an APK.
Completed on 2026-08-26. :ui:core now uses Kotlin Multiplatform and the Android Multiplatform Library plugin with
JVM, Android, iOS ARM64, and iOS Simulator ARM64 production targets. Theme, semantic colors, typography, spacing,
shapes, motion, resources, and reusable component APIs remain in commonMain. JVM-only AWT clipboard adaptation,
pointer hover/secondary-click handling, resize cursors, and interactive scrollbar chrome are isolated in jvmMain;
Android and iOS provide native Compose clipboard adapters, long-press context menus, touch-native scrolling, and
safe no-op pointer-only affordances behind the same common contracts.
:ui:companion:sharedUi now depends on :ui:core, renders under KNetTheme, and derives status colors, spacing,
shapes, and Material values from the shared design system instead of maintaining a companion palette. The root
architecture gate now rejects future feature-owned companion palette definitions and qualifies the shared core on
JVM, Android, and iOS Simulator. UI-core JVM tests, the complete UI-core check, companion shared-UI JVM tests,
architecture verification, and companionFoundationQualification passed across 194 tasks. The Android product
source and complete desktop product then compiled successfully across 210 tasks. Earlier focused production
compilation also passed for iOS ARM64 and iOS Simulator ARM64. No APK was assembled, no product was installed, and
no application was launched.
Started on 2026-08-26. Implement Android-first, iOS-ready KMP certificate readiness without enumerating private or unsupported platform trust stores. Shared domain state and application use cases will distinguish certificate trust from transport/route readiness. Android Settings and trust-store events will only trigger a bounded, end-to-end TLS challenge against the paired KNet desktop; only Android trust validation plus the expected challenge identity and nonce may produce a trusted result. Platform APIs remain in Android adapters, desktop challenge serving remains in desktop connectivity, and common UI continues through ViewModel and use cases. The phase requires security, replay, failure, concurrency, architecture, and JVM/Android/iOS compile verification without assembling an APK or launching a product.
Completed locally on 2026-08-26. :core:companion now owns portable readiness states, a validated Base64URL
challenge nonce, and versioned certificate-proof wire constants. :application:companion separates authenticated
root retrieval, platform trust proof, and trust-store recheck notifications; use cases alone read protected
credentials and may bind verification to the expected active desktop. The shared ViewModel treats platform events
as triggers, cancels superseded work, rejects stale results after selection changes, and never promotes an event or
download into trusted state.
Phase 115 initially used a narrowly scoped, fail-closed bootstrap trust manager to pin the pairing identity before
transmitting a credential. Phase 116 supersedes that bootstrap implementation with platform-managed PKIX trust
created from the invitation's validated root material. HTTPS hostname verification, transport identity, exact
root, and fresh nonce checks remain mandatory. The process-owned trust-store receiver only emits recheck events.
The Android application enables user anchors solely for companion.knet.local; unrelated destinations keep
platform defaults. The Android product graph owns the adapters and their use cases, while certificate installation
UI remains intentionally outside this no-UI phase.
Desktop composition now owns a process-stable KNet-CA-signed TLS identity and a separate authenticated certificate gateway. The gateway has strict bounded HTTP parsing, TLS 1.2-or-newer policy, scoped device authentication, bounded admission, bounded five-minute nonce retention, replay/capacity rejection, defensive public-root copies, and deterministic shutdown. The future general pairing/control surface must advertise this secure endpoint; this phase does not invent a second pairing protocol or claim the still-missing general mobile transport/VPN backend.
Focused model, application, presentation, Android-adapter, and real desktop TLS tests passed. The combined
companionFoundationQualification, Android application compilation/unit tests/lint, desktop compilation/product
tests, and architecture guards passed across 452 actionable tasks. Android, JVM, and iOS Simulator boundaries were
compiled. No APK was assembled, no product was installed or launched, and physical-device/OEM trust behavior
remains explicit release evidence rather than an inferred local-test result. The design and extension boundary are
documented in docs/companion_certificate_readiness.md.
Started on 2026-08-26. Replace the Android certificate-bootstrap custom X509TrustManager with a standard PKIX
trust manager created by TrustManagerFactory. The versioned companion invitation will carry bounded public KNet
root material alongside its fingerprint so every platform can validate the trust anchor before constructing its
native TLS policy. Android will use an in-memory KeyStore, retain HTTPS hostname verification, and transmit no
credential until the platform TLS handshake succeeds. The existing user-anchor network security configuration
continues to prove post-installation readiness. This phase includes protocol/persistence migration, Android and
desktop composition updates, negative certificate-chain tests, lint, multiplatform compilation, and architecture
verification without assembling an APK or launching a product.
Completed locally on 2026-08-26. Pairing invitation protocol v2 now carries a bounded defensive copy of the public KNet root DER together with its SHA-256 fingerprint. Registrations persist both values under schema v2; legacy protocol/schema v1 inputs fail closed and require re-pairing rather than silently acquiring a new trust anchor. The application layer preserves that material from invitation to registration, and control requests expose it to platform adapters without coupling common code to Android TLS APIs.
The Android adapter validates that the paired DER is a currently valid, self-signed CA whose fingerprint matches
the invitation. It then places that certificate in an in-memory KeyStore and delegates chain validation to the
default TrustManagerFactory; there is no production custom X509TrustManager and no lint suppression. HTTPS
endpoint identification, SNI, the pinned transport identity, and the expected root relationship are checked before
the device credential is written. The post-installation challenge still uses Android's default socket factory and
the host-scoped user-anchor network security policy, so successful bootstrap trust cannot be mistaken for proof
that the user installed the KNet CA.
Protocol, persistence, use-case, presentation, Android adapter, and real certificate-chain tests passed, including
malformed roots, mismatched fingerprints, non-CA anchors, platform PKIX acceptance, protocol-v1 rejection, and
defensive-copy coverage. The complete companionFoundationQualification, Android adapter/app unit tests and lint,
desktop compilation/product tests, and architecture verification passed across 455 actionable tasks. Android,
JVM, and iOS Simulator boundaries were compiled. No APK was assembled, no product was installed or launched, and
physical-device/OEM trust behavior remains explicit release evidence.
Started on 2026-08-26. Promote the Android-only :connectivity:companion:android leaf into the multiplatform
:connectivity:companion module. Preserve the qualified Android connectivity and certificate behavior in
androidMain, retain host-side Android tests under the Android-KMP test compilation, and add explicit iOS
placeholder adapters that compile for device and simulator without claiming network, certificate, or inspection
support. Product composition remains platform-owned. The migration must update architecture guards and companion
qualification while compiling Android and iOS Simulator targets without assembling or launching an application.
Completed locally on 2026-08-26. The Android-only child project was removed and its production adapters, manifest,
host tests, and real certificate fixtures now live in :connectivity:companion Android source sets. The module uses
the repository's Android-KMP library convention and publishes Android, iOS ARM64, and iOS Simulator ARM64 targets.
Android product composition now depends on the promoted module without changing its native adapter APIs or runtime
behavior.
The serialized inspection lifecycle reducer moved to commonMain, so locking, idempotent start/stop behavior,
permission-state mapping, cancellation recovery, and failure containment are shared. Android androidMain now
adapts VpnService consent and the replaceable packet backend into that reducer. iosMain contains explicitly
named placeholders for network observation, certificate retrieval/trust/rechecks, and inspection. They fail closed
with PLATFORM_ADAPTER_UNAVAILABLE, publish no synthetic trust events, and are not registered in a product.
Common lifecycle tests run through both platform test trees; iOS tests prove placeholder behavior.
The complete companion foundation, Android host tests, iOS device compilation, iOS Simulator tests, Android product unit tests/lint/compilation, and architecture verification passed across 343 actionable tasks. Qualification now permanently includes the connectivity module's Android host tests, iOS ARM64 compilation, and iOS Simulator tests. No APK or iOS application was assembled, installed, or launched. Native iOS Network, Security, and Network Extension adapters remain future implementation work rather than an inferred capability.
Started on 2026-08-26. Introduce one portable companion-platform adapter bundle and a narrowly scoped
expect/actual factory boundary while keeping every Android Context and future Apple native dependency solely
inside its platform source set. The common API must not accept Any, an opaque context wrapper, or a global
service locator. Decompose the Android connectivity and certificate adapters into cohesive files, share
fail-closed unavailable behavior instead of duplicating iOS placeholders, centralize multiplatform test fixtures,
and preserve the already-qualified Android certificate and lifecycle behavior. Completion requires Android host
tests, Android product tests/lint/compilation, iOS Simulator tests, iOS device/simulator compilation, and
architecture qualification without assembling or launching an application.
Completed on 2026-08-26. commonMain now exposes one portable adapter bundle, one factory interface, and a
constructor-free expected platform factory. Android constructs its actual factory with Context only in
androidMain; iOS provides a no-argument actual factory that assembles shared fail-closed capabilities until its
native implementations exist. No native context, opaque wrapper, Any bridge, or service locator crosses the
common boundary. The Android product composition root consumes only the portable adapter bundle and owns its
callback lifecycle.
The former Android connectivity and certificate monoliths were decomposed into lifecycle, consent, network, certificate retrieval, trust verification, store observation, X.509 validation, paired PKIX trust, and bounded TLS client files. Common lifecycle tests now cover concurrent start serialization, cancellation recovery, unexpected backend failures, preparation while running, stop failure recovery, and idempotency. Android host tests retain the real certificate-chain and platform adapter checks; iOS Simulator tests verify that every unavailable capability fails closed. Shared fixtures remove duplicated registration/configuration construction.
Architecture verification now rejects native imports in all commonMain code and specifically rejects native
context types, Any-typed bridge declarations, or a common constructor on the companion expected factory. The
full companion foundation and Android lint qualification passed across 337 actionable tasks, including Android
host tests, Android product compilation, both iOS production target compilations, iOS Simulator tests, shared
application/data/presentation tests, and architecture checks. No APK or iOS application was assembled, installed,
or launched.
Started on 2026-08-26. Replace the redundant Android-named package beneath androidMain with feature-owned
packages. Common production code will be grouped under platform, inspection, and fallback; Android code under
platform, network, inspection, and certificate; and tests will mirror those feature boundaries. The
expected and actual platform factories remain in the same Kotlin package, while .android.kt and .ios.kt
filenames continue to identify platform implementations. Redundant Android adapter APIs will become internal,
except for the public packet-backend extension contract required by the Android actual factory. Completion requires
Android host tests, Android product compilation/lint, iOS device and simulator compilation, iOS Simulator tests,
and architecture verification without assembling or launching an application.
Completed on 2026-08-26. The redundant connectivity.android and connectivity.ios packages were removed.
Production sources now use capability-owned platform, inspection, fallback, network, and certificate
packages, while tests mirror platform, inspection, and certificate and isolate shared builders under
testing. The expected and actual factories share connectivity.platform; platform-specific filename suffixes
remain for source navigation.
Concrete Android network, consent, and inspection-controller adapters are now internal implementation details.
Only AndroidInspectionBackend and AndroidInspectionBackendResult remain public because the Android actual
factory deliberately exposes that qualified future packet-backend extension point. Documentation and the expected
factory architecture guard follow the new paths. Companion foundation qualification, Android product compilation,
unit tests and lint, Android host tests, iOS device/simulator compilation, iOS Simulator tests, and architecture
verification passed across 343 actionable tasks. No APK or iOS application was assembled, installed, or launched.
Started on 2026-08-26. Replace the companion foundation placeholder with a state-gated Compose Multiplatform
onboarding and readiness experience built on Navigation 3. The shared flow will cover desktop invitation entry,
desktop confirmation, certificate installation and authoritative trust verification, inspection permission, and
the paired home state. Serializable navigation keys and explicit multiplatform saved-state configuration will live
in :ui:companion:sharedUi; navigation types will not leak into the framework-neutral presentation module.
The presentation monolith will be decomposed into state, actions, effects, flow-stage resolution, and ViewModel
files. Product-owned native effects will remain strongly typed and free of Context or Any in common code.
Every screen will reuse :ui:core theme tokens and components, provide responsive scrolling, and prevent restored
or back-stack state from bypassing pairing and certificate gates. Completion requires presentation tests,
Navigation 3 state tests, shared UI compilation/tests, Android product compilation/tests, iOS production
compilation, and architecture verification without assembling or launching an application.
Completed on 2026-08-26. :ui:companion:presentation is decomposed into immutable state, typed actions/effects,
flow-stage resolution, and a framework-neutral lifecycle-owned ViewModel. :ui:companion:sharedUi now provides
serializable Navigation 3 routes with explicit multiplatform saved-state configuration, guarded restored-stack
reconciliation, a responsive setup scaffold, and shared invitation, confirmation, certificate, VPN-explanation,
and ready screens using only :ui:core tokens and components.
The Android product now owns the ViewModel lifecycle and native QR-image import, certificate installer, security settings, and VPN-consent effects. Unimplemented secure pairing/data-plane backends remain typed and fail-closed. Presentation JVM/iOS tests, shared UI navigation tests and JVM/iOS compilation, Android product compilation/tests, and the full architecture-foundation verification passed across 208 actionable tasks. No APK was assembled, installed, or launched.
Started on 2026-08-26. Replace the presentation-owned coroutine lifecycle with the multiplatform AndroidX
ViewModel contract. CompanionViewModel will use viewModelScope; the Android product will obtain it from the
Activity ViewModelStore through an explicit factory and collect native effects only while the Activity is
started. The manual parent scope, public close contract, and Activity-owned coroutine lifecycle will be removed.
Completion requires lifecycle cancellation coverage, focused presentation tests, and Android companion
compilation/tests without assembling an APK.
Completed on 2026-08-26. CompanionViewModel now extends the multiplatform AndroidX ViewModel and owns all
presentation coroutines through viewModelScope. The manual parent scope, child SupervisorJob, closed-state
guard, and public close() contract were removed. Presentation-only invitation material and effect delivery are
cleared through onCleared() after lifecycle-owned coroutine cancellation.
The Android product retrieves the ViewModel from the Activity ViewModelStore with an explicit dependency factory,
retains it across configuration changes, and collects native effects only while the Activity is started. Tests now
construct the ViewModel through ViewModelProvider and prove that clearing the store stops repository collectors.
Focused presentation tests, Android compilation/unit tests, iOS device and simulator compilation, and the complete
companionFoundationQualification passed; the final qualification completed 196 actionable tasks. No APK was
assembled, installed, or launched.
Started on 2026-08-26. Keep CompanionViewModel lifecycle-owned on viewModelScope while moving blocking Android
storage, keystore, cryptographic, and selected-image decoding operations behind adapter-owned coroutine dispatchers.
Decompose the Android companion data adapters into cohesive files, retain deterministic committed persistence,
make execution policies injectable for tests, and ensure product callbacks never decode QR images on the main
thread. Completion requires focused dispatcher-boundary tests, Android companion compilation and unit tests,
multiplatform companion qualification, and architecture verification without assembling or launching an APK.
Completed on 2026-08-26. The Android registration store now has a suspending factory that restores its first SharedPreferences snapshot on a worker dispatcher, and committed writes publish durable and in-memory state in one non-suspending operation. The encrypted credential vault, Android Keystore P-256 identity provider, and proof signer route preference, cipher, key-generation, key-loading, and signature work through the same injectable blocking-call boundary. The former four-class Android storage monolith is decomposed into cohesive files.
The Android process graph is restored asynchronously before lifecycle ViewModel creation, while ActivityResult
launchers remain registered during Activity creation. Selected QR image reads and bitmap decoding run on IO, QR
recognition runs on a computation dispatcher, and results return through the Activity lifecycle scope. Failed or
cancelled graph construction closes already-created platform adapters. The ViewModel remains on viewModelScope;
use cases and presentation code do not choose Android execution threads.
New Android host tests prove configured worker dispatch and failure preservation, and the host-test gate is now a
permanent part of companionFoundationQualification. Focused Android host/product tests and lint passed across
214 actionable tasks. Architecture verification, Android compilation/tests/lint, JVM tests, iOS device/simulator
compilation, iOS Simulator tests, and the complete companion qualification passed across 348 actionable tasks. No
APK was assembled, installed, or launched.
Started on 2026-08-26. Replace the Android companion's manual product graph and ViewModelProvider factory with
the repository-standard Koin container already used by the desktop product. Keep Koin confined to the Android
product composition layer, finish suspending Android storage restoration before module creation, bind contracts to
their platform/data implementations, construct application use cases through Koin, resolve the lifecycle-owned
CompanionViewModel through Koin Compose, and close process resources deterministically. Completion requires
container resolution/lifecycle tests, Android compilation/tests/lint, companion qualification, and architecture
verification without assembling or launching an APK.
Completed on 2026-08-26. The manual AndroidCompanionProductGraph and Activity ViewModelProvider factory were
removed. The Android product now owns five focused Koin modules for restored platform dependencies, data adapters,
runtime ports, application use cases, and presentation. Every application contract is bound to its concrete
product choice, the complete CompanionViewModelDependencies graph is resolved during process bootstrap, and
CompanionViewModel is registered with Koin's lifecycle ViewModel DSL and obtained through koinViewModel().
Disk-backed stores are still restored asynchronously before Koin startup, so synchronous Koin definitions never
hide blocking Android initialization. The callback-owning platform adapter is an eager Koin singleton with an
onClose lifecycle callback. Bootstrap failure closes resources whether failure occurs before or after global Koin
startup, while KNetCompanionApplication stops Koin during process test/emulator termination. Koin imports and
dependencies remain confined to :products:companion:androidApp; common, application, data, connectivity,
presentation, and shared UI companion modules remain DI-framework-free.
The new module-resolution test resolves stores, platform contracts, repositories, credential protection, codecs,
device identity/signing ports, the complete use-case dependency bundle, and the lifecycle ViewModel. It also proves
that Koin closure releases the platform adapter exactly once. Focused compilation and product tests passed across
128 actionable tasks. Architecture verification, Android compilation/tests/lint, JVM tests, iOS device/simulator
compilation, iOS Simulator tests, and companionFoundationQualification passed across 348 actionable tasks. No APK
was assembled, installed, or launched.
Started on 2026-08-26. Add a distinct Connect Companion App entry to the desktop Connect Device workspace, separate from the browser-oriented Wi-Fi proxy setup. Opening the entry creates an in-memory, short-lived, one-time companion invitation through the application pairing use case and presents its QR code, reachable desktop details, expiry state, refresh action, and concise certificate/connection guidance in the shared responsive drawer.
Completed on 2026-08-26. Desktop encoding and companion decoding now share one bounded canonical
knet://pair/v2 codec in :core:companion; the former version-1 desktop payload was removed. The application
onboarding use case combines a one-time invitation with a product-owned environment containing current LAN,
endpoint, stable desktop, transport-pin, root-pin, and public-root data. Koin resolves that environment from the
active Wi-Fi session and process-stable KNet certificate identity without exposing private key material.
The Connect Device grid now contains separate Wi-Fi Proxy Setup and Connect Companion App cards. The companion drawer has immutable idle/creating/ready/expired/failure states, a QR expiry countdown, refresh and recovery actions, and bounded desktop guidance. Secret-bearing payloads remain only in ViewModel state and are removed on drawer close, expiry, or replacement. Drawer hosting, active content, and recovery panels are decomposed into cohesive files. The invitation presentation is not recorded as completion of the general authenticated pairing handler or secured companion data plane; the Android product continues to fail closed until those adapters are implemented.
Focused core/data/application/UI/product tests passed across 176 actionable tasks, and desktop connectivity plus product compilation passed across 152 actionable tasks. Architecture verification and diff validation complete the phase without packaging, launching, or assembling an APK.
Started on 2026-08-26 from desktop visual feedback. Align the Connect Companion App drawer with the existing Wi-Fi setup drawer's shared standard width, while preserving the larger companion QR scan area required by its denser canonical invitation payload. Narrative descriptions, instructions, warnings, and failure guidance will wrap vertically instead of truncating with ellipses; compact identifiers, endpoints, labels, and controls may remain single-line. Completion requires focused connectivity tests, desktop compilation, architecture verification, and diff validation without launching or packaging the application.
Completed on 2026-08-26. The companion drawer now uses the same shared standard width as Wi-Fi setup. Header copy, instructions, warnings, inactive guidance, and operation failures wrap naturally within that width, while compact identity and endpoint fields retain their deliberate single-line presentation. The QR renderer is unchanged and shared with Wi-Fi setup; its larger scan surface is retained because the canonical companion invitation contains a denser authenticated pairing payload. Focused desktop connectivity tests, desktop product compilation, and architecture verification passed across 163 actionable tasks. Diff validation passed without launching or packaging the application.
Started on 2026-08-26. Replace the certificate-heavy companion QR payload with a bounded bootstrap reference that contains only protocol version, one-time retrieval identity and secret, expiry, reachable TLS endpoint, and the desktop transport pin. Publish the complete pairing invitation behind a bounded TLS redemption endpoint, consume the retrieval secret atomically without consuming the later pairing invitation, and make companion acceptance an asynchronous resolve-and-validate workflow. The mobile boundary must authenticate the advertised desktop identity before accepting the returned root, endpoints, scopes, or pairing secret. Completion requires codec size and malformation tests, expiry and replay coverage, TLS gateway integration tests, companion application/presentation tests, platform compilation, architecture verification, and diff validation without packaging or launching apps.
Completed locally on 2026-08-26. The canonical protocol is now knet://pair/v3: its QR contains only a bounded
bootstrap id, separately generated one-time retrieval secret, expiry, the active public-root and TLS redemption
authorities, and independent root/transport fingerprints. The public Wi-Fi setup portal supplies only the DER root
at /knet-ca.crt; Android rejects that response unless its exact fingerprint, validity, self-signature, and CA
constraints match the QR. The validated root is promoted through an in-memory KeyStore and the platform
TrustManagerFactory. No production custom X509TrustManager or lint suppression is present. The retrieval secret
is sent only after PKIX, HTTPS hostname, transport-pin, and root-chain validation succeeds.
Desktop application code now stores the complete invitation behind a distinct digest-protected bootstrap record. The TLS gateway consumes that record atomically, returns the bounded complete invitation once, and gives invalid, expired, wrong-secret, and replayed requests one non-descriptive rejection without consuming the later pairing invitation. Composition derives the public-root authority from the active Wi-Fi session's actual setup URL, so its ordered port fallback remains correct. Companion acceptance is asynchronous, rejects expired input before network I/O, validates returned expiry/endpoints/root/transport identities, and ignores stale ViewModel jobs. The desktop presentation descriptor exposes only display metadata, expiry, and the lightweight QR text; the complete pairing secret remains confined to the one-time store and TLS response.
Codec size/malformed-field tests, complete-response round trips, expiry-before-I/O, metadata mismatch, root-pin,
wrong-secret, one-shot replay, bounded-store, real TLS gateway, resolver, persistence, and presentation tests pass.
The focused cross-module suite passed across 212 tasks. companionFoundationQualification, Android product
compilation/unit tests/lint, iOS device/simulator compilation, iOS Simulator tests, and architecture verification
then passed across 348 tasks. No APK was assembled, no application was installed or launched, and physical-device
LAN/OEM behavior remains explicit future release evidence.
Started on 2026-08-26. Add a shared Navigation 3 scanner stage and portable scanner capability contract while keeping camera permission, frame acquisition, and QR recognition in the Android product. Android will use a lifecycle-bound CameraX preview and bundled ML Kit QR-only analyzer, deliver at most one payload per scanner session, and reuse the existing asynchronous invitation acceptance use case. Gallery import remains an explicit fallback rather than being presented as camera scanning. Completion requires common presentation/navigation tests, Android scanner state and duplicate-delivery tests, Android compilation/unit tests/lint, companion KMP qualification, architecture verification, and diff validation without assembling or launching an APK.
Completed on 2026-08-26. The companion now owns a shared Navigation 3 scanner stage and portable scanner contract,
while the Android product supplies the Activity-scoped CameraX preview, permission flow, QR-only bundled ML Kit
analyzer, and app-settings recovery. Camera and gallery acquisition converge on the existing invitation acceptance
use case, invalid payloads remain on the scanner with an explicit retry, scanner dismissal cancels in-flight work,
and one scanner composition can deliver at most one payload. Common presentation/navigation coverage and Android
permission/single-delivery coverage were added. companionFoundationQualification, Android Kotlin compilation,
Android unit tests, Android lint, and verifyArchitectureFoundation passed together across 348 Gradle tasks;
git diff --check also passed. No APK was assembled or launched, so physical Android camera, permission, OEM, and
deep-link behavior remains release evidence rather than an automated qualification claim.
Started on 2026-08-26 after physical Android QR redemption reached the deliberate fail-closed pairing adapter. Complete the authenticated control plane without enabling the separate VPN/data-plane carrier: define one shared, bounded pairing and credential-refresh wire protocol; expose a platform-neutral control transport contract; provide Android pinned-root PKIX, hostname, and transport-identity verification; handle pairing and atomic credential rotation on the desktop TLS gateway; and replace only the Android pairing placeholder through Koin. Completion requires proof, malformed-body, wrong-secret, invitation replay, authorization, credential-rotation replay, TLS identity, Android transport, real TLS end-to-end, persistence, compilation, lint, KMP qualification, architecture, and diff checks. No APK will be assembled or launched.
Completed locally on 2026-08-26. :core:companion now owns bounded canonical pairing-completion, initial-grant,
and credential-refresh codecs. :application:companion owns a typed platform-neutral control request boundary,
strict authorization tokens, and fail-closed local commit rules that never restore a credential after the desktop
has replaced it. :data:companion supplies the shared proof-bearing pairing/refresh client. Android provides the
native transport: it validates the QR-pinned root, builds platform PKIX trust without a custom trust manager,
performs SNI/HTTPS hostname verification, verifies the served root chain and exact transport fingerprint, and only
then transmits a pairing secret or paired credential. Koin now binds this production pairing path while the
separate VPN/data plane remains deliberately unavailable.
The desktop's renamed CompanionControlGateway now owns one bounded TLS control surface for bootstrap redemption,
proof-bearing one-shot pairing, authenticated credential refresh, and certificate readiness. Credential rotation
uses a Room compare-and-set update, so concurrent or replayed old credentials cannot both succeed. Pairing and
refresh responses expose a credential once; malformed requests and authorization failures remain bounded and
presentation-safe. Gateway shutdown now closes admitted blocking sockets, and a test-discovered concurrent-set
shutdown race in the authenticated proxy gateway was removed.
Coverage now includes codec round trips and malformed fields, proof rejection without invitation consumption,
wrong-secret and invitation replay, real-TLS pairing, old-credential refresh replay, Room rotation/revocation,
Android root-pin validation before network access, fail-closed iOS control fallback, Koin binding, local
persistence failure behavior, and gateway lifecycle regressions. Focused cross-module tests passed, then
companionFoundationQualification, Android product unit tests/lint, desktop product tests, data persistence tests,
and architecture checks passed across 466 actionable tasks. git diff --check passed. No APK was assembled,
installed, or launched. The user's earlier physical Android scan already proves QR/bootstrap acquisition; pressing
Pair securely against this completed control path remains the explicit physical-device re-test.
Started on 2026-08-26. Replace Android-only manual HTTP/TLS socket clients with one bounded commonMain Ktor
exchange used for bootstrap redemption, pairing, credential refresh, and certificate endpoint calls. Keep TLS
enforcement native: Android configures the Ktor Android engine with platform PKIX and fixed-hostname/root/transport
identity checks; iOS configures the Darwin engine with Security-framework hostname policy, request-scoped pinned
anchors, system trust where required, and the same exact identities. No native context or Any bridge may enter
common code, and the separate VPN/data plane remains out of scope.
Completion requires common MockEngine coverage for request mapping, response limits, public-root-before-secret sequencing, and authenticated control calls; Android host tests; iOS Simulator tests; Android/iOS target compilation; companion foundation, Android product, desktop gateway, persistence, lint, architecture, and diff qualification. No APK or iOS application will be assembled or launched.
Completed locally on 2026-08-26. :connectivity:companion now owns one request-scoped Ktor exchange in
commonMain for public-root retrieval, one-time bootstrap redemption, pairing, credential refresh, and Android
certificate endpoint calls. The former Android manual HTTP/TLS socket clients and unused unavailable control
fallback were removed. Shared policy rejects redirects, requires bounded declared response lengths, copies bodies
defensively, keeps invitation secrets out of the public-root request, and releases native client/certificate
resources deterministically.
The Android engine validates CA material, builds platform PKIX trust without a custom X509TrustManager, and
enforces the fixed hostname, exact root chain, and transport identity. The Darwin engine performs the equivalent
Security-framework trust challenge with request-scoped pinned anchors or native system trust; invitation and
control transport are therefore ready for a future iOS product while network observation, certificate readiness,
and the Network Extension data plane remain explicitly fail-closed.
Common SHA-256 vectors and MockEngine tests cover request mapping, body/response bounds, root-before-secret sequencing, pin mismatch short-circuiting, and authenticated control calls. Android host and iOS Simulator tests, Android/iOS device target compilation, architecture checks, companion foundation qualification, Android product unit tests/lint, desktop gateway tests, and desktop persistence tests passed across 466 actionable tasks. No APK or iOS application was assembled, installed, or launched; the Android physical pairing flow and future iOS product remain device qualification evidence.
Physical-device diagnosis on 2026-08-26 then showed that Android's product network policy rejected the first
dynamic-LAN HTTP request before Ktor could retrieve /knet-ca.crt. The Android product now permits runtime-LAN
cleartext at the platform boundary because Android network-security XML cannot express a QR-discovered IP plus an
exact path. The shared transport still exposes only a typed bootstrap-root capability: credential-free GET, the
exact root path and media type, no custom headers or body, a certificate-sized response bound, redirects disabled,
and QR SHA-256 verification before any secret-bearing TLS request. Android host tests, iOS Simulator tests, Android
compilation/lint, packaged-manifest/resource inspection, architecture verification, and git diff --check pass.
No APK was assembled or installed; the corrected physical pairing flow remains the explicit device re-test.
The subsequent physical certificate-install attempt exposed one desktop HTTP/1.1 framing incompatibility: Ktor's
Android engine correctly omitted Content-Length from its bodyless authenticated root-certificate GET, while
the control gateway required that header for every method and rejected the request before authentication. The
gateway now interprets an absent request length as a zero-length body, while continuing to reject malformed or
oversized lengths, duplicate headers, and unsupported transfer encoding. A real-TLS regression sends the root
request without Content-Length; malformed-length, oversized-length, and chunked-framing cases remain rejected.
Focused desktop gateway tests, Android companion host tests, Android compilation, and lint pass. Existing pairing
and credential records are unchanged; the running desktop must be restarted before the physical re-test.
Completed on 2026-08-29. Added the capability to select and decode a pairing QR code image from the local photo gallery or file storage on both Android and iOS in the KNet Companion application. The feature preserves Clean Architecture and platform decoupling by routing user intent through the shared MVI Action/Effect pipeline (CompanionAction.PickInvitationImageRequested, CompanionAction.InvitationImageDecodeFailed, and CompanionEffect.PickInvitationImage), and uses platform-native barcode decoders (AndroidQrImageDecoder using Google ML Kit on Android, IosQrImagePicker using PhotosUI and CoreImage on iOS) without introducing external third-party libraries. Added KNetIcons.Image in :ui:core and integrated a secondary button on ConnectDesktopScreen. Companion presentation unit tests, shared UI tests, Android unit tests, Android lint analysis, iOS Simulator compilation, and architecture verification pass.
Completed on 2026-08-29. Updated the platform-owned iOS certificate installation guidance to provide 5 clear, numbered steps that guide users through both required iOS security phases: (1) installing the downloaded profile in Settings > Profile Downloaded (or VPN & Device Management), and (2) navigating to Settings > General > About > Certificate Trust Settings and toggling "Enable full trust for root certificates" ON. Updated products:companion:iosApp localized string resources and CompanionIosApplication.kt guidance constructor. Passed iOS Simulator compilation (compileKotlinIosSimulatorArm64), Kotlin-first and architecture verification, and the 235-task companionFoundationQualification suite.