chore: drop legacy visual studio project files#10
Merged
Conversation
This was referenced Jan 11, 2026
jsavin
added a commit
that referenced
this pull request
Feb 10, 2026
- #1: Enable system.compiler.threads registration (was TODO/deferred). Register before globals swap, unregister after restore. evaluate uses "anonymous", callscript uses script verb name. - #2: Save/restore langerrordisable, tryerror, tryerrorstack in thread globals swap (matching legacy copythreadglobals from process.c). - #3: Document cooperative kill() limitation (no yield points yet). - #4: Error state audit confirmed isolation is complete for all globals saved by legacy Frontier. Added 3 missing struct-field globals. - #5: Check pthread_cond_timedwait return value, log errors. - #7: Add upper bounds check in get_nth_thread_id (n > MAX_THREADS). - #8: Replace magic number 2 with idapplicationthread constant. - #9: Document return semantics for evaluate and callscript. - #10: Normalize test timeouts to 3s. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
jsavin
added a commit
that referenced
this pull request
Feb 10, 2026
#404) * feat: Add cooperative threading with thread registry for headless mode Implement cooperative threading infrastructure matching legacy Frontier's fire-and-forget thread model. Threads run synchronously (one at a time) with proper globals save/restore to isolate thread state. Key changes: - Thread registry: register_main_thread(), get_nth_thread_id() for singleton thread ID allocation. Main thread gets ID 2 (idapplicationthread), spawned threads start at 3+. - Thread globals: alloc/dispose/save/restore functions that properly handle C globals (fllangerror, flreturn, flbreak, etc.) separate from the hthreadglobals struct pointer swap. - Thread verbs: Rewrite all thread.* verb implementations to use registry and cooperative globals swap (evaluate, callscript, getCurrentID, getCount, exists, kill, sleep, wake, getNthID). - Error containment: scriptError() in spawned thread stops execution within that thread but does not propagate to the calling thread. - Build: Link threadregistry.c into CLI binary, initialize at startup. - Tests: 10 integration tests (all passing), expanded registry unit tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Address Codex review feedback on cooperative threading P1: Propagate callscript launch failures to the caller. When langrunscript fails (bad script name, parameter binding, etc.), thread.callscript now returns false instead of silently reporting success with a thread ID. P2: Initialize spawned thread cwd from process default. Matches legacy newthreadglobals (process.c:1426) so that relative file operations in thread.evaluate/thread.callscript see the correct working directory. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Address Claude review feedback — callscript resolution split and tests #1: Add NULL check for register_main_thread() in main.c. Startup now fails cleanly instead of silently continuing without a registered main thread. #3: Use memset to reset thread record slots on mutex/condvar init failure in register_main_thread(), ensuring pristine state for slot reuse. #4/#5: Split thread.callscript into resolution and execution phases. Script name resolution, lookup, and compilation happen in the MAIN thread context (failures propagate to caller). Execution via langrunscriptcode happens in the cooperative thread context (runtime errors are fire-and-forget). This correctly distinguishes spawn failures from runtime errors. Add 4 thread.callscript integration tests: - Basic execution with ODB side effects - Parameter passing (on myScript(x) pattern) - Error containment (scriptError is fire-and-forget) - Nonexistent script (resolution failure propagates to caller) 14/14 thread integration tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Address Claude bot review feedback on cooperative threading - #1: Enable system.compiler.threads registration (was TODO/deferred). Register before globals swap, unregister after restore. evaluate uses "anonymous", callscript uses script verb name. - #2: Save/restore langerrordisable, tryerror, tryerrorstack in thread globals swap (matching legacy copythreadglobals from process.c). - #3: Document cooperative kill() limitation (no yield points yet). - #4: Error state audit confirmed isolation is complete for all globals saved by legacy Frontier. Added 3 missing struct-field globals. - #5: Check pthread_cond_timedwait return value, log errors. - #7: Add upper bounds check in get_nth_thread_id (n > MAX_THREADS). - #8: Replace magic number 2 with idapplicationthread constant. - #9: Document return semantics for evaluate and callscript. - #10: Normalize test timeouts to 3s. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Defensive cleanup, shutdown docs, and consistent error logging - Add langdisposetree() guard in thread evaluate error path - Document single-threaded shutdown assumption in main.c cleanup - Replace remaining magic number 2 with idapplicationthread in cleanup - Add log_error to all silent failure paths in allocate_thread_record Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
4 tasks
jsavin
added a commit
that referenced
this pull request
Mar 20, 2026
…n tests Add two new test files covering integration test gaps #9 and #10: - webserver_http_roundtrip_tests.yaml (9 tests, 7 active, 2 skipped): Tests HTTP request/response round-trip at the TCP transport layer using tcp.listenStream callbacks. Covers GET, POST, Content-Type headers, path extraction, sequential requests, 404 responses, and large response bodies. Full inetd/webserver stack tests are skipped pending fwsNetEvent* migration. - bigstring_boundary_tests.yaml (27 tests): Documents behavior at the 255-byte bigstring boundary (lenbigstring limit). Tests string creation, concatenation, content integrity, ODB storage, comparison, sizeOf/string.length agreement, file paths, substring operations, pattern matching, and environment variables at 254/255/256 bytes. Confirms UserTalk heap strings are NOT subject to the 255 limit. Key findings documented in test comments: - tcp.readStream() returns binary data type for empty reads; sizeOf() on empty binary returns -4, requiring thread.sleepFor() between write and poll - UserTalk string variables are heap-allocated with no 255-byte limit - The bigstring limit only affects C-level APIs (file paths, env vars) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4 tasks
jsavin
added a commit
that referenced
this pull request
Mar 21, 2026
* test: Add webserver HTTP round-trip and bigstring boundary integration tests Add two new test files covering integration test gaps #9 and #10: - webserver_http_roundtrip_tests.yaml (9 tests, 7 active, 2 skipped): Tests HTTP request/response round-trip at the TCP transport layer using tcp.listenStream callbacks. Covers GET, POST, Content-Type headers, path extraction, sequential requests, 404 responses, and large response bodies. Full inetd/webserver stack tests are skipped pending fwsNetEvent* migration. - bigstring_boundary_tests.yaml (27 tests): Documents behavior at the 255-byte bigstring boundary (lenbigstring limit). Tests string creation, concatenation, content integrity, ODB storage, comparison, sizeOf/string.length agreement, file paths, substring operations, pattern matching, and environment variables at 254/255/256 bytes. Confirms UserTalk heap strings are NOT subject to the 255 limit. Key findings documented in test comments: - tcp.readStream() returns binary data type for empty reads; sizeOf() on empty binary returns -4, requiring thread.sleepFor() between write and poll - UserTalk string variables are heap-allocated with no 255-byte limit - The bigstring limit only affects C-level APIs (file paths, env vars) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: Update OPML exports for new integration test files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Address PR #485 review feedback - Fix ODB content integrity test: 246→248 fill bytes for correct 256-byte total - Move HTTP test ports from 11000 range to ephemeral 49200+ range - Add try/else error-path cleanup to all active HTTP tests so tcp.closeListen runs even if client operations fail - Add body content assertion to large response test (size + content check) - Regenerate OPML reports Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Tighten large response body assertion in webserver tests Extract body after \r\n\r\n header separator and verify body length >= 500, rather than checking total response size which trivially passes due to ~60 bytes of HTTP headers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Document bigstring C-level truncation limitations and add 256-byte env var test Add comment to file path tests (category 7) explaining that they only test UserTalk string construction, not C-level bigstring truncation (tracked under issue #475). Add env var test at 256 bytes that confirms truncation occurs: the value is truncated from 256 to 255 bytes when round-tripping through sys.setenvironmentvariable/sys.getenvironmentvariable. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Use distinct ports per test and clean up env vars Add port assignment documentation comment block to webserver tests (ports were already unique 49200-49206, but now documented). Add env var cleanup in bigstring boundary tests - both the 255-byte and 256-byte env var tests now reset their variables to empty string before returning to prevent leakage between test runs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 tasks
jsavin
added a commit
that referenced
this pull request
Jun 30, 2026
Round 2 of M1: fold in the three P1 findings from the local /gate review (security + concurrency reviewers) plus the cheap P2s that are part of the same edits. No behavior change to the existing 12 M1 tests; one new test exercises the back-pressure surface. Concurrency P1 -- input_decoder.h threading contract was wrong: - Previous text said "single-threaded, GIL-held" then "releases the GIL before entering the read loop", which contradict each other and would have misled the M6 sub-agent. - Rewrite the threading block to state the single-owner invariant explicitly: exactly one decoder per process, GIL held at every API entry/exit, GIL dropped ONLY inside the M6 blocking read inside input_decoder_poll, mutations during that window are safe because no other thread holds a pointer to the decoder. Concurrency P1 -- set_mouse / kitty_enable owner-thread invariant was implicit: - Document that these must be called from GIL-held context AND only when no poll is in progress. The REPL event loop satisfies this naturally (slash commands dispatch between polls), but it needs to be a documented invariant rather than an accident, because M3+ will turn these into TTY writes that would race the in-flight read(2) otherwise. Security P1 -- silent drop-on-overflow contract: - Previous inject_bytes returned void and silently truncated. M2/M3 read-loop overflow would have been an invisible parser-desync surface. - Change inject_bytes to return the number of bytes accepted (size_t). - Add a monotonic dropped_bytes counter on the struct, exposed via input_decoder_dropped_bytes() (test seam, mirrors buffered_bytes). - Add behavioral test test_inject_overflow_increments_dropped_counter that floods 5 KiB into the 4 KiB ring and asserts accepted+dropped = attempted, then verifies a second inject when full drops everything. Cheap P2s folded in: - Rename head_len -> fill_len (bar-raiser P2 #6: "head" implied an index, it's actually a fill level). Will keep the M2 state-machine commit honest about what's an index vs a count. - assert(fill_len <= INPUT_DECODER_BUFFER_SIZE) at top of inject_bytes (bar-raiser P2 #4): cheap insurance for the M2 drain refactor. - assert(bytes != NULL) when len > 0 (security P2): test seam should catch caller bugs, not silently no-op. - Add input_decoder_kitty_enabled() symmetric query (bar-raiser P2 #7): the field was write-only with no observer; tests can now assert the bit flipped, and M5 has the seam pre-built. - Document tty_fd ownership: caller owns the fd, decoder does not validate or close it (bar-raiser P2 #5/8). - Document SIGWINCH non-interaction (concurrency P2 #12). - Unify the threading comment between header and .c (concurrency P2 #11). Test-harness P2 (bar-raiser #5): - Rename all 49 SKIP-stub functions test_* -> test_skip_* so a grep over tests/tmp/unit/input_decoder_tests.json discloses the deferred set without parsing stderr. - Add g_skip_count counter bumped by tr_skip(); main() prints "[skip-summary] 49 of 62 tests are SKIP stubs deferred to M2-M5" alongside the green tally so the 62/62 doesn't conceal unimplemented behavior. Test count: Before: 61/61 (12 real + 49 SKIP). After: 62/62 (13 real + 49 SKIP). Net suite: 882 -> 883 (no other tests touched). Deferred to follow-up issues (P2s not folded in here): - Forward-compat note about future M2 signed/unsigned hazard in drain arithmetic (security P2 #10) -- belongs in the M2 PR review checklist. - "Document the implementation's actual behavior of bytes==NULL" -- resolved by switching to assert (no separate doc needed now). Plan: planning/phase_c/INPUT_DECODER_PLAN.md PR: #816
5 tasks
jsavin
added a commit
that referenced
this pull request
Jun 30, 2026
* feat(boxen): C M1 #809 -- input_decoder PTY-replay harness + stub Phase C input-decoder milestone M1. Pure infrastructure: a stub decoder module and a 61-test harness that exercises the M1 API surface (create / destroy / inject-bytes / poll / mouse-enable / kitty-enable). What this adds: - frontier-cli/boxen/input_decoder.h -- private API (typedef, lifecycle, poll, mouse / kitty enable, INPUT_DECODER_TEST_SEAM-guarded inject / buffered-bytes accessor). - frontier-cli/boxen/input_decoder.c -- minimal skeleton: 4 KiB linear scratch buffer, NULL-safe everywhere. poll() always returns BOXEN_ERR_TIMEOUT (the state machine lands in M2). Wired into the frontier-cli production build so the CLI continues to link, but NOT yet wired into backend_tb2.c (the M6 cutover). - tests/input_decoder_tests.c -- TR_RUN harness. 12 M1 behavioral tests (create / destroy round-trip, NULL safety, mouse-enable round-trip, inject deposits bytes, poll-on-empty returns TIMEOUT, etc.). 49 SKIP stubs ranged by milestone (M2: cursor keys + UTF-8, M3: mouse, M4: paste, M5: Kitty). Each SKIP stub prints "[SKIP] <protocol entry>" to stderr so deferrals are visible in the test log; the M2-M5 sub-agents rewrite each stub as a behavioral assert when its milestone lands. - tests/Makefile -- new input_decoder_tests target (link slice: input_decoder.c only, no termbox2, no Frontier runtime; uses -DINPUT_DECODER_TEST_SEAM to expose the inject seam). - frontier-cli/Makefile -- input_decoder.c added to BOXEN_SOURCES. SKIP mechanism note (no TR_SKIP exists in test_report.h): the SKIP stubs return without firing assert(), so TR_RUN records them as passing. This keeps the 61/61 green count accurate (we are not claiming protocol behavior we have not implemented). The early-return + stderr SKIP line makes the deferral visible in the log without polluting the JSON tally. Done criterion (per plan section 7, M1): make -C tests input_decoder_tests && ./tests/input_decoder_tests --> compiles, passes (61/61 green, of which 49 print SKIP). Full unit suite: 882/882 (was 821 pre-existing, +61 new). Out of scope for M1 (per plan section 7): the state machine (M2), SGR mouse (M3), bracketed paste with BOXEN_EV_PASTE ABI add (M4), Kitty keyboard protocol (M5), backend_tb2 cutover (M6), /mouse toggle (M7). No production input-path behavior changes; backend_tb2.c is untouched. Plan: planning/phase_c/INPUT_DECODER_PLAN.md Closes #809 * fix(boxen): C M1 #809 -- address /gate P1 findings (3) + cheap P2s Round 2 of M1: fold in the three P1 findings from the local /gate review (security + concurrency reviewers) plus the cheap P2s that are part of the same edits. No behavior change to the existing 12 M1 tests; one new test exercises the back-pressure surface. Concurrency P1 -- input_decoder.h threading contract was wrong: - Previous text said "single-threaded, GIL-held" then "releases the GIL before entering the read loop", which contradict each other and would have misled the M6 sub-agent. - Rewrite the threading block to state the single-owner invariant explicitly: exactly one decoder per process, GIL held at every API entry/exit, GIL dropped ONLY inside the M6 blocking read inside input_decoder_poll, mutations during that window are safe because no other thread holds a pointer to the decoder. Concurrency P1 -- set_mouse / kitty_enable owner-thread invariant was implicit: - Document that these must be called from GIL-held context AND only when no poll is in progress. The REPL event loop satisfies this naturally (slash commands dispatch between polls), but it needs to be a documented invariant rather than an accident, because M3+ will turn these into TTY writes that would race the in-flight read(2) otherwise. Security P1 -- silent drop-on-overflow contract: - Previous inject_bytes returned void and silently truncated. M2/M3 read-loop overflow would have been an invisible parser-desync surface. - Change inject_bytes to return the number of bytes accepted (size_t). - Add a monotonic dropped_bytes counter on the struct, exposed via input_decoder_dropped_bytes() (test seam, mirrors buffered_bytes). - Add behavioral test test_inject_overflow_increments_dropped_counter that floods 5 KiB into the 4 KiB ring and asserts accepted+dropped = attempted, then verifies a second inject when full drops everything. Cheap P2s folded in: - Rename head_len -> fill_len (bar-raiser P2 #6: "head" implied an index, it's actually a fill level). Will keep the M2 state-machine commit honest about what's an index vs a count. - assert(fill_len <= INPUT_DECODER_BUFFER_SIZE) at top of inject_bytes (bar-raiser P2 #4): cheap insurance for the M2 drain refactor. - assert(bytes != NULL) when len > 0 (security P2): test seam should catch caller bugs, not silently no-op. - Add input_decoder_kitty_enabled() symmetric query (bar-raiser P2 #7): the field was write-only with no observer; tests can now assert the bit flipped, and M5 has the seam pre-built. - Document tty_fd ownership: caller owns the fd, decoder does not validate or close it (bar-raiser P2 #5/8). - Document SIGWINCH non-interaction (concurrency P2 #12). - Unify the threading comment between header and .c (concurrency P2 #11). Test-harness P2 (bar-raiser #5): - Rename all 49 SKIP-stub functions test_* -> test_skip_* so a grep over tests/tmp/unit/input_decoder_tests.json discloses the deferred set without parsing stderr. - Add g_skip_count counter bumped by tr_skip(); main() prints "[skip-summary] 49 of 62 tests are SKIP stubs deferred to M2-M5" alongside the green tally so the 62/62 doesn't conceal unimplemented behavior. Test count: Before: 61/61 (12 real + 49 SKIP). After: 62/62 (13 real + 49 SKIP). Net suite: 882 -> 883 (no other tests touched). Deferred to follow-up issues (P2s not folded in here): - Forward-compat note about future M2 signed/unsigned hazard in drain arithmetic (security P2 #10) -- belongs in the M2 PR review checklist. - "Document the implementation's actual behavior of bytes==NULL" -- resolved by switching to assert (no separate doc needed now). Plan: planning/phase_c/INPUT_DECODER_PLAN.md PR: #816
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Testing