Skip to content

Complete Prompts correctness, parity, and terminal lifecycles - #488

Merged
binaryfire merged 21 commits into
0.4from
audit/prompts-correctness-parity-lifecycle
Aug 8, 2026
Merged

Complete Prompts correctness, parity, and terminal lifecycles#488
binaryfire merged 21 commits into
0.4from
audit/prompts-correctness-parity-lifecycle

Conversation

@binaryfire

@binaryfire binaryfire commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

This brings hypervel/prompts to the current Laravel Prompts surface and makes terminal, signal, stream, and renderer-process cleanup deterministic.

  • Add Callouts with headings, lists, key-value rows, and links.
  • Correct decorated and redirected rendering across prompts, spinners, tasks, streams, and progress bars.
  • Make standalone Task transport, child exit, signal restoration, and reaping failure-safe.
  • Preserve exact operation failures when rendering or cleanup also fails.
  • Remove unused Prompts Termwind code and correct package metadata and documentation.
  • Keep Testbench shutdown cleanup in the process that owns its runtime files.

Why

Prompts runs inside long-lived CLI processes and Swoole coroutines. Terminal and process state therefore cannot be left to object destruction or process exit.

Several paths could retain a hidden cursor, modified TTY mode, replaced SIGINT handler, live renderer child, or incomplete socket frame after a failure. Redirected output could also contain terminal control bytes, and the package was missing the current Callout API.

The changes give each operation a clear owner and a normal settlement path. Destructors remain a best-effort fallback for interrupted operations instead of handling ordinary cleanup.

Rendering and current parity

The new Callout surface follows Laravel's current API and supports structured content without adding new collection or normalization abstractions. The renderer also handles empty key-value lists, sparse list keys, and numeric display keys correctly.

Terminal escape handling now has one shared boundary. It recognizes complete CSI sequences, BEL- and ST-terminated OSC strings, OSC 8 hyperlinks, and Symfony style tags without allowing control bytes to consume later visible text. Unterminated sequences remain literal.

Undecorated output no longer writes cursor movement or erase sequences. Spinner and Task use stable static output, Stream writes chunks directly, and Progress emits one useful final result rather than a sequence of intermediate frames. Prompt::fake() continues to model an interactive decorated terminal so existing renderer assertions keep their meaning.

Operation lifecycles

Prompt, Spinner, Progress, Stream, and Task now restore the state they acquire through exception-safe settlement paths. Cleanup attempts independent resources separately and keeps the original operation exception primary.

Progress restores the exact previous SIGINT handler and async-signals mode. Its weak signal callback does not retain an abandoned operation, generators are consumed once, invalid totals fail before rendering, and retained instances start cleanly.

Terminal access owns /dev/tty handles and process resources explicitly. EOF and read failures are reported truthfully, while transient empty reads used by input doubles remain supported. Stream performs terminal probing before cursor acquisition and no longer retains itself through stored fade closures.

Task renderer transport

Standalone animated Tasks now own a complete socket and child-process transaction:

  • Validate the socket pair before terminal or signal mutation.
  • Treat fork failure as a static-render fallback before user work starts.
  • Write every protocol frame completely or record a terminal transport failure.
  • Stop sending frames after protocol corruption.
  • Close unused endpoints in both processes.
  • Exit the renderer child on every path.
  • Terminate only an explicitly owned positive PID.
  • Retry interrupted reaping and handle kernels that auto-reap ignored SIGCHLD children.
  • Preserve user callback failures over renderer and cleanup failures.

Static and coroutine Tasks use an in-process Logger with the same public behavior. Retained Task state is reset per run, caller configuration is restored after terminal-derived clamping, and successful summary output matches current Laravel behavior.

Package boundaries and documentation

Queue now declares Termwind directly because its work command calls the package itself. Prompts removes its unused Termwind concern and dependency, and advertises PCNTL and POSIX only as optional capabilities where they are actually used.

Testbench runtime and purge shutdown callbacks capture their registering PID. A forked child cannot delete its parent PHPUnit worker's application skeleton, while a child that registers its own callbacks still performs its own cleanup.

The Prompts guide documents Callouts, Collection-compatible inputs, coroutine-only Spinner animation, standalone Task requirements, and redirected Progress behavior in Laravel-style prose. The package README remains a thin index of public differences and the canonical guide.

Compatibility and performance

No supported Laravel API, named argument, or protected extension point is removed or narrowed. Callout is additive, and Hypervel's existing Collection-compatible inputs remain supported. The intentional behavior difference is cleaner redirected Progress output.

Normal decorated coroutine behavior is unchanged. Redirected modes do less work by avoiding terminal probes, animation, sleeps, and repeated frames. Full-write loops add iterations only after a native partial write, and normal process settlement no longer waits on a fixed delay. No web-request hot path gains new work.

Validation

  • Ran the complete composer fix checkpoint, including formatting, static analysis, the parallel component suite, and Testbench package mode.
  • Ran focused Prompts, Testbench, Console, Testing, Queue, and Composer coverage after review corrections.
  • Rechecked targeted Prompts and Testbench PHPStan analysis.
  • Covered ANSI and OSC boundaries, redirected output, retained-object reuse, cleanup failure precedence, signal restoration, terminal failures, socket transport, child exit and reaping, and both directions of Testbench fork ownership.

Summary by CodeRabbit

  • New Features

    • Added styled callouts with lists, links, and rich content.
    • Added reusable heading, list, key-value, and link elements.
    • Added Collection support across data-driven prompts and tables.
    • Improved static rendering when terminal decoration or coroutine support is unavailable.
  • Bug Fixes

    • Improved terminal, cursor, signal, process, stream, and cleanup handling.
    • Fixed empty table messaging, hyperlink wrapping, prompt retries, and task completion output.
    • Improved error preservation during rendering and cleanup failures.
  • Documentation

    • Expanded prompt documentation, usage guidance, callout examples, and platform requirements.

Port the current Callout and element surface with headings, lists, key-value rows, and links. Preserve upstream factory shapes while correcting empty and sparse list rendering and numeric display keys.

Make the prompt fake model a decorated interactive terminal, report missing renderers clearly, and centralize escape stripping and complete stream writes in the existing support utility. Add focused coverage for the public Callout API, theme selection, output decoration, escape removal, and full payload writes.
Parse complete ECMA-48 CSI sequences and both OSC terminators without letting control bytes consume later visible text. Only SGR changes styling, only OSC 8 changes hyperlink state, and unterminated input remains literal.

Route measurement through the shared stripping boundary and add counterfactual coverage for private parameters, intermediate bytes, parameterized links, BEL and ST termination, and incomplete escape sequences.
Make cursor and erase operations decoration-aware, acquire terminal ownership before mutation, and restore cursor and TTY state through one idempotent settlement path. Preserve the original operation failure when cleanup also fails and keep destructors as best-effort fallbacks only.

Remove the dead nullable input path, preserve transient empty reads, initialize static callback state explicitly, and add regressions for redirected interactive frames, failed TTY setup, cursor cleanup failure, and terminal restoration.
Own the worker-static form revert callback for the full submission loop and clear it from a finally block on both success and failure. This prevents a completed or failed form from changing the behavior of a later form.

Cover normal completion, exceptions, and retained callback state without introducing a second form registry or coroutine-specific abstraction for one physical terminal.
Reset operation-owned frames and counters for every spin, use an operation-local animation completion flag, and settle erase and terminal restoration independently. Static rendering now handles non-coroutine and redirected output without starting background animation.

Preserve callback failures over cleanup failures and cover retained spinner reuse, coroutine teardown, undecorated output, non-coroutine execution, and failed restoration paths.
Materialize only non-countable iterables, reject unusable totals, reset retained render state, and preserve yielded order. Redirected output now emits one useful terminal result instead of cursor controls and intermediate frames.

Capture and restore the exact SIGINT handler and async mode with weak callback ownership, settle acquisition and cancellation failures deterministically, and add coverage for reuse, generators, totals, redirected output, callback precedence, destructor fallback, and real signal delivery.
Make terminal EOF and read failures explicit, probe the controlling TTY without warnings, and run stty through one owned process boundary with guaranteed handle cleanup. Preserve transient empty reads used by input doubles.

Select Stream's direct redirected mode before terminal probing, acquire decorated cursor ownership only after dimension and color work succeeds, and prevent stored fade closures from retaining abandoned streams. Cover EOF, missing TTY, probe failures, exact direct output, cleanup precedence, and immediate release.
Give each standalone Task operation explicit ownership of its socket pair, child PID, signal state, cursor, protocol buffers, and terminal settlement. Complete or fail every framed write, stop after transport corruption, terminate only an owned positive PID, and reap through interrupted and auto-reaped child paths.

Keep callback exceptions primary over renderer and cleanup failures, preserve Logger behavior in static and coroutine modes through a direct in-process implementation, reset retained operation state, restore caller configuration after per-run clamping, and remove the obsolete coroutine logger.

Add deterministic regressions for setup failure, partial and timed-out writes, closed peers, reset failure, child exceptions, settlement timeouts, signal restoration, EINTR and ECHILD handling, destructor cleanup, retained reuse, summaries, limits, and exact child reaping.
Resolve a valid column width when a data table has no headers and no rows instead of calling max on an empty array. Reuse the same shape in active and cancelled rendering so both states retain their search affordance and message.

Add focused coverage for empty active and cancelled tables without introducing width caching or a broader renderer abstraction.
Capture the registering PID for runtime-copy and purge shutdown callbacks. Forked children now leave their parent's disposable application and purge targets intact, while a child that registers its own callbacks still performs both cleanup paths.

Add non-coroutine process regressions for both ownership directions with independent runtime, file, and directory assertions so either callback becoming an unconditional no-op fails visibly.
Queue's work command calls Termwind directly, so the split package must require it rather than relying on another package to install it incidentally.

Add Termwind to the direct-runtime dependency inventory so package metadata tests keep the standalone boundary honest.
Delete the protected Termwind concern that has no consumer and removes visible text with an unsafe escape expression. Drop the resulting direct dependency from the Prompts split package.

Describe PCNTL and POSIX as optional capabilities for cancellation and standalone Task animation without suggesting sockets or retaining a dead integration tombstone.
Add Laravel-style guidance for callouts, Collection-compatible inputs, coroutine-only Spinner animation, standalone Task requirements, and redirected Progress output. Keep the package README as a thin index of public differences and canonical documentation.

Correct three renderer method descriptions so their source metadata names the prompt each renderer actually handles.
Record the final source-backed design, accepted findings, rejected complexity, regression surface, performance accounting, validation, and review result for Prompts.

Mark the package complete in the audit checklist and route Queue's direct Termwind dependency and Testbench's fork-safe shutdown ownership to their owning package boundaries. Keep the detailed plan as the compact final implementation reference.
…ess-parity-lifecycle

# Conflicts:
#	docs/plans/2026-07-12-0900-framework-coroutine-state-lifecycle-audit.md
#	docs/plans/2026-07-12-0915-framework-coroutine-state-lifecycle-audit-ledger.md
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@binaryfire, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 21 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4b0da2cf-0b1c-46da-9c6a-b270f8c2ad2e

📥 Commits

Reviewing files that changed from the base of the PR and between 73700f5 and 36ea9b8.

📒 Files selected for processing (4)
  • docs/plans/2026-07-12-0915-framework-coroutine-state-lifecycle-audit-ledger.md
  • docs/plans/2026-08-07-1654-prompts-correctness-current-parity-and-terminal-lifecycles.md
  • src/prompts/src/Task.php
  • tests/Prompts/TaskProcessTest.php
📝 Walkthrough

Walkthrough

The Prompts package adds callouts, rich rendering, ANSI and terminal handling, deterministic coroutine and process cleanup, socket-write handling, collection support documentation, and fork-aware Testbench cleanup. Regression tests cover these behaviors.

Changes

Prompts parity and lifecycle

Layer / File(s) Summary
Audit plan and validation scope
docs/plans/...
The audit index, ledger, and implementation plan document Prompts, Queue, and Testbench changes.
Callout elements and rendering
src/prompts/src/Callout.php, src/prompts/src/Elements/*, src/prompts/src/Themes/Default/CalloutRenderer.php, src/prompts/src/helpers.php, tests/Prompts/CalloutTest.php, tests/Prompts/DataTablePromptTest.php
Callouts, rich content elements, sparse-list rendering, empty DataTable handling, and related tests are added.
Terminal modes and ANSI handling
src/prompts/src/Concerns/*, src/prompts/src/Support/Utils.php, src/prompts/src/Terminal.php, src/prompts/src/Themes/Default/Concerns/*, tests/Prompts/AnsiWordwrapTest.php, tests/Prompts/ParseAnsiTextTest.php, tests/Prompts/TerminalTest.php, tests/Prompts/UtilsTest.php, tests/Prompts/ThemesTest.php
Decorated and undecorated output, TTY ownership, complete writes, escape stripping, and OSC-8 hyperlink parsing are updated.
Prompt, spinner, and stream settlement
src/prompts/src/Prompt.php, src/prompts/src/Spinner.php, src/prompts/src/Stream.php, src/prompts/src/FormBuilder.php, related tests
Prompt cleanup, static fallbacks, stream direct output, form revert cleanup, and retained-instance state resets are implemented.
Progress settlement and signal restoration
src/prompts/src/Progress.php, tests/Prompts/ProgressTest.php, tests/Prompts/ProgressSignalTest.php
Progress validates totals, materializes traversables, restores signal state, settles terminal frames, and preserves primary failures.
Task processes and socket logging
src/prompts/src/Task.php, src/prompts/src/Support/*, tests/Prompts/TaskTest.php, tests/Prompts/TaskProcessTest.php, tests/Prompts/LoggerTest.php
Task process ownership, socket protocols, renderer settlement, signal restoration, logging failures, reaping, and destructor cleanup are reworked.
Package metadata and documentation
src/boost/docs/prompts.md, src/prompts/README.md, src/prompts/composer.json, src/queue/composer.json, metadata tests
Documentation describes Collection inputs and execution fallbacks. Composer metadata records optional extensions and the Queue Termwind dependency.
Fork-aware Testbench cleanup
src/testbench/src/Bootstrapper.php, tests/Testbench/BootstrapperForkCleanupTest.php
Shutdown callbacks restrict cleanup to the registering process, with isolated parent and child process tests.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • hypervel/components#430: Both changes modify Prompts spinner and task lifecycle cleanup, including terminal-state restoration and coroutine failure tests.
  • hypervel/components#431: This change extends the coroutine and lifecycle audit plan and ledger with Prompts-specific findings.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.80% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the PR's main Prompts parity, correctness, and terminal lifecycle changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch audit/prompts-correctness-parity-lifecycle

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 8, 2026

Copy link
Copy Markdown

Greptile Summary

This PR expands Prompts API parity while making terminal, signal, stream, and renderer-process ownership deterministic.

  • Adds Callouts and structured elements, including corrected list and hyperlink rendering.
  • Separates decorated, static, and redirected rendering behavior across prompts, tasks, spinners, streams, and progress bars.
  • Makes Task transport, child settlement, signal restoration, and cleanup failure-safe.
  • Corrects package metadata, Testbench fork-owned shutdown cleanup, documentation, and regression coverage.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/prompts/src/Task.php Reworks Task execution into explicit static, coroutine, and child-process paths with complete transport, failure precedence, renderer settlement, and resource restoration.
src/prompts/src/Progress.php Corrects iterable handling, retained-operation state, redirected rendering, and exact signal and terminal restoration.
src/prompts/src/Prompt.php Centralizes deterministic prompt terminal settlement while preserving operation failures and fake-terminal behavior.
src/prompts/src/Stream.php Adds direct undecorated streaming and ensures decorated fade state does not retain abandoned operations.
src/prompts/src/Terminal.php Makes controlling-terminal handles, EOF reporting, process execution, and TTY restoration explicit.
src/prompts/src/Support/Utils.php Introduces shared escape-sequence stripping and complete stream-write boundaries.
src/prompts/src/Themes/Default/CalloutRenderer.php Adds structured Callout rendering with corrected empty, sparse, numeric-key, and hyperlink behavior.
src/testbench/src/Bootstrapper.php Restricts shutdown cleanup to the process that registered each callback.
src/prompts/composer.json Removes the unused Termwind dependency and advertises optional native capabilities.
src/queue/composer.json Declares Queue's direct Termwind runtime dependency.

Reviews (3): Last reviewed commit: "fix(prompts): scale renderer settlement ..." | Re-trigger Greptile

@binaryfire

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (7)
src/prompts/src/Stream.php (1)

83-91: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use Sleep::usleep() for the fade delay.

Line 87 calls the raw usleep() function inside source code. The coding guidelines require Sleep::usleep() in source and reserve raw sleep functions for tests and cases that need real time.

If the fade pacing must use real wall-clock time and must not be affected by a test-time fake, keep usleep() and add a short comment that records that requirement.

♻️ Proposed change
             while (count($this->currentlyFading) > 0) {
                 $this->message .= array_shift($this->currentlyFading);
                 $this->render();
-                usleep(25_000);
+                Sleep::usleep(25_000);
             }

Add the import:

use Hypervel\Support\Sleep;

As per coding guidelines: "Use Sleep::usleep() and Sleep::sleep() for delays in source code; reserve raw sleep functions for tests and cases requiring real time."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/prompts/src/Stream.php` around lines 83 - 91, Replace the raw usleep call
in the fade loop within the surrounding Stream flow with
Hypervel\Support\Sleep::usleep(), adding the required import. Only retain the
raw function if real wall-clock timing is explicitly required, and document that
requirement with a brief comment.

Source: Coding guidelines

tests/Prompts/ProgressSignalTest.php (1)

44-47: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Discard inherited output buffers in the forked child.

pcntl_fork() duplicates the PHPUnit process, including any active output buffers and the shared stdout descriptor. The child exits through exit inside the SIGINT handler, which flushes those buffers. Any PHPUnit output that was buffered at fork time is then written a second time to the shared stdout and can corrupt the test report. Clear the inherited buffers as the first action in the child.

♻️ Proposed safeguard
         if ($pid === 0) {
+            while (ob_get_level() > 0) {
+                ob_end_clean();
+            }
+
             Prompt::fake();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Prompts/ProgressSignalTest.php` around lines 44 - 47, In the child
branch immediately after pcntl_fork() returns 0, before Prompt::fake() or any
other work, discard all inherited output buffers so the child cannot flush
duplicated PHPUnit output when exiting through the SIGINT handler.
src/prompts/src/Progress.php (1)

122-145: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Guard against capturing Progress-owned signal state as the original.

start() captures pcntl_signal_get_handler(SIGINT) unconditionally. If a caller invokes start() twice without an intervening finish(), map(), or destruction, the second capture stores the weak-reference closure installed by the first start(). The caller's real handler is then lost, and resetSignals() later restores a Progress-owned closure into the process-global SIGINT slot. Settle any previously captured state first, so the original handler is preserved.

♻️ Proposed guard
     public function start(): void
     {
+        // A prior unsettled operation still owns the captured signal state.
+        $this->resetSignals();
+
         $this->progress = 0;
         $this->state = 'initial';
         $this->prevFrame = '';
         $this->capturePreviousNewLines();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/prompts/src/Progress.php` around lines 122 - 145, Update
Progress::start() to settle any previously captured signal state before calling
pcntl_signal_get_handler(SIGINT) and installing a new handler, preventing a
prior Progress-owned closure from being saved as the original. Reuse the
existing signal-reset or cleanup mechanism, such as resetSignals(), while
preserving the caller’s real SIGINT handler for later restoration.
src/prompts/src/Terminal.php (2)

137-165: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Drain both pipes before proc_close to avoid a stall on large stderr.

stream_get_contents($pipes[1]) runs to completion before $pipes[2] is read. If a command writes more than the pipe buffer to stderr while stdout stays open, the child blocks and this method blocks with it. The current commands are stty invocations with small output, so this is a latent risk only. stream_select over both pipes, or reading stderr first for these known-small outputs, removes it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/prompts/src/Terminal.php` around lines 137 - 165, Update execWithInput to
drain stdout and stderr concurrently before calling proc_close, using
stream_select or equivalent nonblocking reads on both pipes; preserve the
existing output capture, pipe cleanup, and error handling behavior.

225-229: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse Utils::writeAll() for the query write.

Utils::writeAll() in src/prompts/src/Support/Utils.php already loops over partial writes and reports timed-out, EOF, and failed streams with specific messages. The manual fwrite check here treats any short write as a hard failure.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/prompts/src/Terminal.php` around lines 225 - 229, Update the terminal
color query write in the surrounding method to call Utils::writeAll() instead of
manually using fwrite and comparing the byte count. Preserve the existing fflush
check and RuntimeException behavior while relying on writeAll’s handling of
partial writes and stream failures.
src/prompts/src/Themes/Default/CalloutRenderer.php (1)

198-223: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Centralize OSC 8 hyperlink construction.

The OSC 8 sequence is now built in three places with different styling rules:

  • renderLink() at Line 204.
  • autoFormat() at Line 221.
  • Link::__toString() in src/prompts/src/Elements/Link.php at Line 29.

Link::__toString() emits \e[4m for underline, while both renderer paths emit \e[4;36m. autoFormat() therefore has to detect \e[4m to reconstruct the renderer style. A single helper that formats a URL, label, and underline flag would remove the coupling between the element and the renderer.

autoFormat() also matches only the \e\\ (ST) terminator. parseAnsiText() in src/prompts/src/Themes/Default/Concerns/InteractsWithStrings.php accepts both \x07 (BEL) and \e\\. A BEL-terminated hyperlink embedded in callout text is not re-styled by autoFormat().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/prompts/src/Themes/Default/CalloutRenderer.php` around lines 198 - 223,
Centralize OSC 8 hyperlink formatting in a shared helper accepting URL, label,
and underline state, then update renderLink(), autoFormat(), and
Link::__toString() to use it with consistent styling. Adjust autoFormat() to
recognize both BEL (\x07) and ST (\e\\) hyperlink terminators while preserving
URL and visible-label extraction.
src/prompts/src/Task.php (1)

376-391: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider whether logger-driven label and subLabel mutations should also reset.

resetOperationState() clears per-operation output state but keeps label and subLabel. A callback that calls $logger->label() or $logger->subLabel() therefore leaks the mutated text into the next run() on the same instance. If the constructor values are the intended baseline for each operation, capture them once and restore them here. If callers own label after a run, no change is needed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/prompts/src/Task.php` around lines 376 - 391, The resetOperationState()
method currently preserves logger-mutated label and subLabel values between
runs; capture the constructor-provided baseline values and restore both
properties during each reset if they are intended to be operation defaults,
while leaving caller-owned post-run labels unchanged if that is the established
contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@docs/plans/2026-08-07-1654-prompts-correctness-current-parity-and-terminal-lifecycles.md`:
- Around line 190-191: Update reapRenderer() so ECHILD is not treated as a
successful renderer reaping result when the exit status is unavailable: require
an explicit success acknowledgement or report failure, and preserve
nonzero/signaled renderer failures during reset. Add a regression covering a
failing renderer with ignored SIGCHLD, while retaining the existing
interrupted-wait retry and PID-clearing behavior.
- Around line 229-245: Update Utils::writeAll() to enforce the ten-second
timeout during blocking writes, rather than relying on stream metadata after
fwrite(). Use a bounded write-ready approach such as non-blocking writes with
stream_select(), or equivalent low-level socket I/O, while preserving
positive-progress handling and the existing timeout, EOF, and generic failure
distinctions.

In `@src/boost/docs/prompts.md`:
- Line 1214: Change the “Rich Content” heading in the documentation from level
four to level three, using `### Rich Content` so it follows the surrounding `##
Callouts` hierarchy without skipping a level.
- Around line 635-636: Update the dynamic options return-type descriptions in
src/boost/docs/prompts.md at lines 635-636 and 970-971 so both `suggest` and
`autocomplete` callback paragraphs state that callbacks may return either arrays
or `Hypervel\Support\Collection` instances, matching the documented `options`
contract.

In `@src/prompts/src/Prompt.php`:
- Around line 210-215: Update runLoop() to treat an empty string returned by
Terminal::read() as EOF rather than continuing to the callback; exit the loop
immediately on the first empty read and preserve existing handling for non-empty
keys.

In `@src/prompts/src/Stream.php`:
- Around line 52-60: Update Stream::append() in the $this->direct branch to use
the raw-write path static::writeDirectly($message) instead of
static::output()->write($message), while preserving message accumulation and the
existing return behavior.

In `@src/prompts/src/Terminal.php`:
- Around line 220-244: Update queryColors() so failures writing to or reading
from the terminal query use the same default foreground and background colors as
the openTty() failure path instead of throwing. Preserve the existing finally
cleanup and response parsing behavior, and ensure Stream::fadeOut() can continue
rendering when the color query fails.

In `@src/prompts/src/Themes/Default/Concerns/InteractsWithStrings.php`:
- Around line 313-317: Update the OSC 8 handling in the escapeSequence branch to
parse the sequence’s params and URI fields instead of matching only the two
exact close strings. Treat any OSC 8 sequence with an empty URI, including
parameterized forms such as id=1, as closing the link; otherwise preserve the
sequence as currentLink.

In `@tests/Prompts/SpinnerTest.php`:
- Around line 66-104: Update both retained-spinner tests to configure a short,
fixed interval on their Spinner instances before calling spin, using
Spinner::$interval or its available setter/configuration mechanism. Ensure the
tick-count assertions in
testRetainedSpinnerStartsEachAnimatedOperationWithFreshState and
testRetainedSpinnerCanAnimateAfterAStaticOperation depend on that configured
interval rather than the default 100ms timing.

---

Nitpick comments:
In `@src/prompts/src/Progress.php`:
- Around line 122-145: Update Progress::start() to settle any previously
captured signal state before calling pcntl_signal_get_handler(SIGINT) and
installing a new handler, preventing a prior Progress-owned closure from being
saved as the original. Reuse the existing signal-reset or cleanup mechanism,
such as resetSignals(), while preserving the caller’s real SIGINT handler for
later restoration.

In `@src/prompts/src/Stream.php`:
- Around line 83-91: Replace the raw usleep call in the fade loop within the
surrounding Stream flow with Hypervel\Support\Sleep::usleep(), adding the
required import. Only retain the raw function if real wall-clock timing is
explicitly required, and document that requirement with a brief comment.

In `@src/prompts/src/Task.php`:
- Around line 376-391: The resetOperationState() method currently preserves
logger-mutated label and subLabel values between runs; capture the
constructor-provided baseline values and restore both properties during each
reset if they are intended to be operation defaults, while leaving caller-owned
post-run labels unchanged if that is the established contract.

In `@src/prompts/src/Terminal.php`:
- Around line 137-165: Update execWithInput to drain stdout and stderr
concurrently before calling proc_close, using stream_select or equivalent
nonblocking reads on both pipes; preserve the existing output capture, pipe
cleanup, and error handling behavior.
- Around line 225-229: Update the terminal color query write in the surrounding
method to call Utils::writeAll() instead of manually using fwrite and comparing
the byte count. Preserve the existing fflush check and RuntimeException behavior
while relying on writeAll’s handling of partial writes and stream failures.

In `@src/prompts/src/Themes/Default/CalloutRenderer.php`:
- Around line 198-223: Centralize OSC 8 hyperlink formatting in a shared helper
accepting URL, label, and underline state, then update renderLink(),
autoFormat(), and Link::__toString() to use it with consistent styling. Adjust
autoFormat() to recognize both BEL (\x07) and ST (\e\\) hyperlink terminators
while preserving URL and visible-label extraction.

In `@tests/Prompts/ProgressSignalTest.php`:
- Around line 44-47: In the child branch immediately after pcntl_fork() returns
0, before Prompt::fake() or any other work, discard all inherited output buffers
so the child cannot flush duplicated PHPUnit output when exiting through the
SIGINT handler.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e8e12fcf-fd9e-4db9-82c3-fffcb80fbea6

📥 Commits

Reviewing files that changed from the base of the PR and between 0848a9c and 9cd7e64.

📒 Files selected for processing (61)
  • docs/plans/2026-07-12-0900-framework-coroutine-state-lifecycle-audit.md
  • docs/plans/2026-07-12-0915-framework-coroutine-state-lifecycle-audit-ledger.md
  • docs/plans/2026-08-07-1654-prompts-correctness-current-parity-and-terminal-lifecycles.md
  • src/boost/docs/prompts.md
  • src/prompts/README.md
  • src/prompts/composer.json
  • src/prompts/src/Callout.php
  • src/prompts/src/Concerns/Cursor.php
  • src/prompts/src/Concerns/Erase.php
  • src/prompts/src/Concerns/FakesInputOutput.php
  • src/prompts/src/Concerns/Termwind.php
  • src/prompts/src/Concerns/Themes.php
  • src/prompts/src/Elements/BulletedList.php
  • src/prompts/src/Elements/Element.php
  • src/prompts/src/Elements/ElementContract.php
  • src/prompts/src/Elements/Heading.php
  • src/prompts/src/Elements/KeyValueList.php
  • src/prompts/src/Elements/Link.php
  • src/prompts/src/Elements/NumberedList.php
  • src/prompts/src/FormBuilder.php
  • src/prompts/src/Progress.php
  • src/prompts/src/Prompt.php
  • src/prompts/src/Spinner.php
  • src/prompts/src/Stream.php
  • src/prompts/src/Support/InProcessLogger.php
  • src/prompts/src/Support/Logger.php
  • src/prompts/src/Support/Utils.php
  • src/prompts/src/Task.php
  • src/prompts/src/Terminal.php
  • src/prompts/src/Themes/Default/AutoCompletePromptRenderer.php
  • src/prompts/src/Themes/Default/CalloutRenderer.php
  • src/prompts/src/Themes/Default/Concerns/InteractsWithStrings.php
  • src/prompts/src/Themes/Default/DataTableRenderer.php
  • src/prompts/src/Themes/Default/MultiSearchPromptRenderer.php
  • src/prompts/src/Themes/Default/SearchPromptRenderer.php
  • src/prompts/src/Themes/Default/TaskRenderer.php
  • src/prompts/src/helpers.php
  • src/queue/composer.json
  • src/testbench/src/Bootstrapper.php
  • tests/Prompts/AnsiWordwrapTest.php
  • tests/Prompts/CalloutTest.php
  • tests/Prompts/CoroutineCreateFailureTest.php
  • tests/Prompts/CoroutineSafetyTest.php
  • tests/Prompts/DataTablePromptTest.php
  • tests/Prompts/FormTest.php
  • tests/Prompts/LoggerTest.php
  • tests/Prompts/ParseAnsiTextTest.php
  • tests/Prompts/ProgressSignalTest.php
  • tests/Prompts/ProgressTest.php
  • tests/Prompts/PromptLifecycleTest.php
  • tests/Prompts/SpinnerNonCoroutineTest.php
  • tests/Prompts/SpinnerTest.php
  • tests/Prompts/StreamTest.php
  • tests/Prompts/TaskProcessTest.php
  • tests/Prompts/TaskTest.php
  • tests/Prompts/TerminalTest.php
  • tests/Prompts/TextPromptTest.php
  • tests/Prompts/ThemesTest.php
  • tests/Prompts/UtilsTest.php
  • tests/Queue/PackageMetadataTest.php
  • tests/Testbench/BootstrapperForkCleanupTest.php
💤 Files with no reviewable changes (1)
  • src/prompts/src/Concerns/Termwind.php

Comment thread src/boost/docs/prompts.md
Comment thread src/boost/docs/prompts.md
Comment thread src/prompts/src/Prompt.php
Comment thread src/prompts/src/Stream.php
Comment thread src/prompts/src/Terminal.php
Comment thread src/prompts/src/Themes/Default/Concerns/InteractsWithStrings.php
Comment thread tests/Prompts/SpinnerTest.php
A caller may ignore SIGCHLD or enable automatic child reaping, which discards the renderer exit status. A child that failed during final rendering could therefore look successful after the task callback completed.\n\nSend one checked settlement acknowledgement over the existing socket after final rendering succeeds. Keep waitpid status authoritative when it is available, and consult the acknowledgement only when the kernel has discarded that status.\n\nCover clean and failing auto-reaped renderers while preserving interrupted-wait behavior and the protected renderer extension contract.
Calling start twice previously captured the first Progress handler as application state. Finishing the second operation then left SIGINT owned by Progress and kept asynchronous signal handling enabled.\n\nRestore any captured signal state before a new manual operation captures it again. The normal settled path remains a no-op, while repeated starts now return both process-global settings to their caller-owned values.\n\nAdd a process-isolated regression that proves the original handler and async mode survive the full sequence.
Undecorated streams passed caller text through Symfony's formatter. Formatter-like text was changed on output even though the Stream value retained the original bytes.\n\nUse Symfony's raw output option for the direct path. This skips tag parsing while keeping the normal write and newline-accounting boundary intact. Decorated renderer frames continue using their existing measured formatting path.\n\nStrengthen the exact-chunk regression with formatter-significant input and verify emitted content, lines, and the retained value stay identical.
OSC 8 parsing recognized parameterized hyperlink openers but only recognized canonical closers. A matching parameterized closer therefore left the link active and wrapped later text in a stale hyperlink.\n\nParse the parameter and URI boundary and treat every empty URI as a close for both BEL and ST terminators. Split only on the first separator so valid semicolons remain part of the URI.\n\nKeep canonical hyperlink coverage and add focused regressions for both parameterized closer forms and semicolon-bearing URIs.
Suggest and Autocomplete already accept Collection results from dynamic option callbacks, and nearby examples use that behavior. Two paragraphs still described arrays as the only supported return type.\n\nDocument both accepted forms so the prose matches the public API and its examples.
@binaryfire

Copy link
Copy Markdown
Collaborator Author

@coderabbitai Thanks for the review. I worked through every inline, nitpick, and summary item against the current tree.

Applied:

  • Added a checked child settlement acknowledgement so automatic child reaping cannot hide renderer failure. Exit status remains authoritative when available.
  • Restored application SIGINT state before repeated Progress starts recapture it.
  • Preserved literal undecorated Stream chunks with Symfony OUTPUT_RAW while retaining newline accounting.
  • Recognized parameterized OSC 8 closers for BEL and ST, with canonical, parameterized, and semicolon URI coverage.
  • Corrected the dynamic Suggest and Autocomplete return-type prose.

No change:

  • Socket write timeouts are already enforced and covered by a deterministic full-buffer regression.
  • Empty non-EOF terminal reads are retries; EOF is rejected in Terminal::read().
  • Terminal color I/O failures remain observable after /dev/tty is acquired.
  • Rich Content follows the current Laravel heading structure.
  • Spinner interval assignments in the test would be overwritten by the renderer.
  • The remaining nitpicks would add dependency, process, pipe, or formatting machinery without a supported failure, or would change caller-owned Task state.

The focused Prompts suite, broader consumers, static analysis, formatting checks, and Testbench contract suite are green. The follow-up is in 75ee908 through 73700f5.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- Follow-up commits ---'
git log --oneline --decorate 75ee908f4^..73700f568

echo
echo '--- Changed files in follow-up range ---'
git diff --name-only 75ee908f4^..73700f568

echo
echo '--- Relevant symbols and tests ---'
rg -n -C 3 \
  -e 'settlement|acknowledg|awaitRenderer|renderer.*failure|transportFailure' \
  -e 'SIGINT|SIG_IGN|pcntl_async_signals|signal' \
  -e 'OUTPUT_RAW|undecorated|isDecorated' \
  -e 'OSC|osc|hyperlink|parameterized' \
  -e 'Suggest|Autocomplete|return type' \
  src/prompts tests/Prompts

Length of output: 54143


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- Symbol map ---'
ast-grep outline src/prompts/src/Task.php --items all --type method --match 'settle|render|await|reap'
ast-grep outline src/prompts/src/Progress.php --items all --type method --match 'start|reset|settle'
ast-grep outline src/prompts/src/Stream.php --items all --type method --match 'write|close'
ast-grep outline src/prompts/src/Themes/Default/Concerns/InteractsWithStrings.php --items all --type method --match 'parseAnsiText'
ast-grep outline tests/Prompts/TaskProcessTest.php --items all --type method --match 'AutoReaping|ChildFailure'
ast-grep outline tests/Prompts/ProgressTest.php --items all --type method --match 'Repeated|start'
ast-grep outline tests/Prompts/StreamTest.php --items all --type method --match 'Undecorated'
ast-grep outline tests/Prompts/ParseAnsiTextTest.php --items all --type method --match 'Hyperlink|OSC|Osc'

echo
echo '--- Task settlement and child paths ---'
sed -n '500,790p' src/prompts/src/Task.php

echo
echo '--- Progress restart handling ---'
sed -n '110,145p' src/prompts/src/Progress.php
sed -n '285,310p' src/prompts/src/Progress.php

echo
echo '--- Stream direct output ---'
sed -n '30,110p' src/prompts/src/Stream.php

echo
echo '--- OSC 8 parsing ---'
sed -n '270,340p' src/prompts/src/Themes/Default/Concerns/InteractsWithStrings.php

echo
echo '--- Focused follow-up test sections ---'
sed -n '85,135p' tests/Prompts/TaskProcessTest.php
sed -n '140,165p' tests/Prompts/ProgressTest.php
sed -n '1,110p' tests/Prompts/StreamTest.php
sed -n '1,180p' tests/Prompts/ParseAnsiTextTest.php

echo
echo '--- Documentation correction ---'
git diff 73700f56^ 73700f56 -- src/boost/docs/prompts.md

Length of output: 31065


@binaryfire Verified the follow-up commits.

The Task acknowledgement prevents automatic child reaping from hiding a renderer failure. Exit status remains authoritative when it is available.

Progress::start() restores prior SIGINT state before it captures new state.

Direct Stream output preserves literal chunks with OutputInterface::OUTPUT_RAW. The regression test verifies Symfony-style tags and newline accounting.

The OSC 8 parser now closes parameterized links for BEL and ST terminators. The tests cover canonical, parameterized, and semicolon-containing URIs.

The Suggest and Autocomplete documentation now states the supported Hypervel\Support\Collection return type.

I verified the source changes and focused regression coverage. I did not execute the test suite, static analysis, or formatting checks in this environment.

🐇 ✅


✏️ Learnings added
Learnt from: binaryfire
URL: https://github.com/hypervel/components/pull/488

Timestamp: 2026-08-08T01:58:21.664Z
Learning: In `src/prompts/src/Terminal.php`, an empty non-EOF input read is a retry condition. `Terminal::read()` rejects EOF input.

Learnt from: binaryfire
URL: https://github.com/hypervel/components/pull/488

Timestamp: 2026-08-08T01:58:21.664Z
Learning: In `src/prompts/src/Task.php`, Task cleanup must not change caller-owned Task state. Avoid adding process or pipe machinery unless a supported failure mode requires it.

Learnt from: binaryfire
URL: https://github.com/hypervel/components/pull/488

Timestamp: 2026-08-08T01:58:21.664Z
Learning: In `src/prompts/src/Themes/Default/CalloutRenderer.php`, rich callout content follows the current Laravel heading structure.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

You are interacting with an AI system.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/prompts/src/Task.php (1)

29-31: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Scale renderer settlement timeout to Task::$interval.

runRendererProcess() processes reset messages only after usleep($this->interval * 1000) at Lines 618-620. If Task::$interval is greater than one second, reset can arrive just after sleep starts and awaitRendererClosure() will report a healthy renderer as failed.

Derive the settlement timeout from the configured interval and include a scheduling margin.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/prompts/src/Task.php` around lines 29 - 31, Update the
RENDERER_SETTLEMENT_TIMEOUT_SECONDS constant and its usage in
awaitRendererClosure() so the settlement timeout is derived from Task::$interval
rather than fixed at one second, including a scheduling margin sufficient to
cover the runRendererProcess() sleep interval.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/prompts/src/Task.php`:
- Around line 29-31: Update the RENDERER_SETTLEMENT_TIMEOUT_SECONDS constant and
its usage in awaitRendererClosure() so the settlement timeout is derived from
Task::$interval rather than fixed at one second, including a scheduling margin
sufficient to cover the runRendererProcess() sleep interval.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4af4faa3-4f8b-4496-9cdc-78f0cf3be7db

📥 Commits

Reviewing files that changed from the base of the PR and between 9cd7e64 and 73700f5.

📒 Files selected for processing (10)
  • docs/plans/2026-08-07-1654-prompts-correctness-current-parity-and-terminal-lifecycles.md
  • src/boost/docs/prompts.md
  • src/prompts/src/Progress.php
  • src/prompts/src/Stream.php
  • src/prompts/src/Task.php
  • src/prompts/src/Themes/Default/Concerns/InteractsWithStrings.php
  • tests/Prompts/ParseAnsiTextTest.php
  • tests/Prompts/ProgressTest.php
  • tests/Prompts/StreamTest.php
  • tests/Prompts/TaskProcessTest.php
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/prompts/src/Themes/Default/Concerns/InteractsWithStrings.php
  • src/boost/docs/prompts.md
  • tests/Prompts/ParseAnsiTextTest.php
  • src/prompts/src/Progress.php
  • docs/plans/2026-08-07-1654-prompts-correctness-current-parity-and-terminal-lifecycles.md
  • tests/Prompts/StreamTest.php

A standalone Task renderer only checks its reset socket between animation frames. The fixed one-second settlement timeout could therefore terminate a healthy child when a custom theme selected a slower cadence.

Sample the renderer-selected interval before user work starts and add the existing one-second scheduling margin when waiting for acknowledgement and EOF. Split the resulting millisecond budget into valid seconds and microseconds without delaying renderers that settle promptly.

Add a deterministic process regression that waits beyond the former fixed bound, preserves the callback result, and proves the exact child is reaped. Record the derived bound and the deliberately rejected protocol complexity in the audit plan and ledger.
@binaryfire

Copy link
Copy Markdown
Collaborator Author

@coderabbitai Thanks for the follow-up. This finding was correct.

The standalone Task renderer drains reset messages only between animation frames. A fixed one-second settlement timeout could therefore terminate a healthy renderer when a custom theme selected a cadence above one second.

Fixed in 36ea9b8:

  • The parent samples the renderer-selected interval before user work begins, matching the cadence inherited by the child.
  • Settlement now allows one complete frame interval plus a fixed one-second scheduling margin.
  • The millisecond budget is split into valid seconds and microseconds for stream_set_timeout.
  • A deterministic process regression uses a 1.2-second custom renderer cadence, waits beyond the former fixed bound, preserves the callback result, and proves the exact child is reaped.

The timeout remains an upper bound. A renderer that acknowledges and closes promptly returns immediately, so the default path gains no waiting or meaningful overhead.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@binaryfire Confirmed. The fixed timeout now permits one complete renderer frame interval before settlement fails. The one-second scheduling margin prevents premature termination for custom renderer cadences above one second.

The regression covers the former failure path and verifies callback completion and child reaping.

🐇 ✅


✏️ Learnings added
Learnt from: binaryfire
URL: https://github.com/hypervel/components/pull/488

Timestamp: 2026-08-08T02:33:32.411Z
Learning: In `src/prompts/src/Task.php`, standalone Task renderer settlement must allow at least one complete renderer-selected animation interval before timing out. The parent must sample that interval before user work begins because the forked child inherits the renderer cadence. A fixed one-second timeout can terminate healthy custom renderers with intervals above one second; retain a scheduling margin and preserve prompt acknowledgement and child reaping behavior.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

@binaryfire
binaryfire merged commit ed19935 into 0.4 Aug 8, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant