Skip to content

Add request-owned start time and correct runtime timing lifecycles - #478

Merged
binaryfire merged 20 commits into
0.4from
feature/request-start-time
Aug 6, 2026
Merged

Add request-owned start time and correct runtime timing lifecycles#478
binaryfire merged 20 commits into
0.4from
feature/request-start-time

Conversation

@binaryfire

@binaryfire binaryfire commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Why

HYPERVEL_START is captured when an Artisan process starts. That works for a short-lived PHP process, but it is not a request start time in a long-lived Swoole worker. Health responses can report worker uptime, and consumers either need to know about REQUEST_TIME_FLOAT or maintain their own fallback chain.

Tracing those consumers also exposed the same process-level assumption in console and scheduler handling. Telescope classified commands from a fixed argv position, recorded the long-running schedule:run daemon instead of each task, and deferred task storage until a coroutine that may never exit. Scheduled Sentry transactions could also be finalized as successful before a non-zero exit code was published.

What changed

This PR makes request start time part of the request itself:

$startedAt = $request->startedAt();

Request::initialize() captures the precise REQUEST_TIME_FLOAT value supplied by Swoole or Symfony. Directly constructed requests use one microtime(true) fallback. Missing REQUEST_TIME_FLOAT and REQUEST_TIME server values are populated at that boundary, while supplied server values remain unchanged.

The stored timestamp is stable for the request lifetime. startedAt() returns a CarbonImmutable only when called, so ordinary requests pay for one float and do not allocate a Carbon instance unless a consumer needs it.

The health view now receives the routed request explicitly and always renders duration from startedAt(). Telescope request duration and Sentry HTTP transaction start time use the same API instead of reading transport details or a process constant.

The existing server bag remains the complete metadata API. Swoole keys continue to use the PHP/Symfony uppercase form, so developers can retrieve the raw value with $request->server("REQUEST_TIME_FLOAT") or inspect all server metadata with $request->server().

Console and scheduler lifecycle

The request timing audit found several places where long-lived command state was treated as one short process:

  • Console command classification now uses Symfony ArgvInput::getFirstArgument(), including the public runningConsoleCommand() API and the Testbench Artisan entrypoint. This handles common global-option prefixes without adding a custom argument parser.
  • Telescope uses the resolved command name from BeforeHandle. The schedule:run daemon remains unrecorded, while each approved scheduled task starts recording in its own finite coroutine.
  • Waiter::wait() and the wait() helper gain the same optional all-key or selected-key context copying supported by the other coroutine helpers. The default remains a fresh context.
  • Scheduled user filters and task execution run in a waited child coroutine. Scheduler-owned pause, maintenance, and interruption checks stay in the scheduler coroutine. Foreground tasks remain sequential, and background tasks keep the existing bounded concurrency path.
  • Paused repeatable events advance at their natural cadence, and a repeatable event with no prior check no longer passes null into abs().
  • Telescope schedule listeners are registered when the watcher boots. Completed task entries use normal coroutine-deferred storage, and the Finished-then-Failed sequence for a non-zero task records one entry.
  • Sentry finalizes scheduled transactions from the published exit code, producing an error status for non-zero outcomes and finishing each transaction once.
  • The unused sentry.ignore_commands configuration is removed rather than retained as a non-functional option.

These changes do not replace the existing HTTP or console kernel lifecycle clocks. Those clocks still describe the narrower handle() and terminate() lifecycle, while Request::startedAt() belongs to the request and scheduled-task events belong to each task.

Compatibility and performance

The public API remains Laravel-shaped and additive. Existing request server access, kernel timing APIs, foreground ordering, and bounded background scheduling behavior are preserved.

The HTTP hot path adds one float property assignment per request. Carbon conversion is lazy. The additional coroutine boundary applies only to due scheduled task invocations, not HTTP request handling.

Documentation and tests

The request and coroutine documentation now covers the new APIs and timing boundaries. The health, Request bridge, Telescope, Sentry, scheduler, console classification, and Testbench behavior all have focused regression coverage, including consecutive requests in one worker and task-local recording/storage.

The complete formatter, static analysis, parallel component suite, Testbench suite, and package dogfood checks pass.

Summary by CodeRabbit

  • New Features
    • Added request start-time tracking through Request::startedAt() for accurate health, tracing, and duration reporting.
    • Added optional coroutine context copying for background and scheduled tasks.
    • Improved scheduled task execution, repeat handling, skipped-task events, and completion reporting.
  • Bug Fixes
    • Improved console command detection across command-line options and execution modes.
    • Corrected Telescope recording and Sentry status reporting for scheduled tasks.
  • Documentation
    • Documented request timing, server metadata, coroutine context copying, and updated timeout examples.

Use Symfony ArgvInput command discovery instead of assuming the command is always argv[1].

Preserve the existing public Application API while correctly recognizing commands preceded by valueless global options or inline option values. Add focused coverage for long and short option prefixes.
Create one Symfony ArgvInput before Testbench application bootstrap and use its first argument for serve and watch mode detection.

Pass the same input instance into the console kernel so bootstrap classification and command execution cannot disagree.
Capture the precise worker-side request timestamp during Request initialization and normalize the standard server time fields when they are absent.

Expose the stable instant as a lazily-created CarbonImmutable through startedAt(), regenerate the Request facade metadata, and cover construction, conversion, duplication, bridge precision, mutation stability, and kernel termination boundaries.
Pass the routed Request explicitly into both framework and Testbench health views and calculate render duration from its owned start instant.

Remove the process-wide constant guard and add deterministic consecutive-request coverage so long-lived workers cannot report accumulated process uptime.
Derive Telescope request duration from Request::startedAt() instead of reading transport metadata directly.

Remove the nullable fallback branch and freeze time in the watcher regression so the recorded millisecond duration is exact.
Start HTTP transactions from the Request-owned Carbon instant and preserve its microsecond precision when converting to Sentry epoch seconds.

Delete the server-value and process-constant fallback chain, and prove later ServerBag mutation cannot alter the captured transaction start.
Document Request::startedAt(), normalized uppercase server metadata, kernel timing boundaries, and WebSocket handshake semantics.

Replace the collection timeout example built from process startup with an invocation-local now() deadline and remove its obsolete import.
Add the established boolean or selected-key context-copy contract to Waiter and the global wait helper while preserving a fresh child context by default.

Move synthetic HTTP testing onto the base Waiter with explicit full-context copying, retain replication-failure coverage, delete the redundant Foundation wrapper, and document the public behavior.
Keep pause, interruption, and maintenance control in the scheduler while running user filters and each task invocation in a finite child carrying only replicated Log Context.

Share foreground and bounded-background dispatch across initial and repeated runs, preserve foreground ordering, and make claimed single-server work count as handled.

Guard never-checked repeat events at their public predicate and advance paused repeats at their configured cadence, with regressions for context isolation, defers, background repeats, pause behavior, and user-visible output.
Use BeforeHandle command names instead of positional process arguments, correct the default ignored command set, and keep the long-lived schedule daemon outside recording.

Start recording inside approved scheduled-task coroutines at the storage-opportunity boundary so every enabled watcher shares the real task lifecycle. Cover configured ignores, daemon silence, package discovery, and task-local recording.
Boot-register scheduled-task terminal listeners without argv gates and let Telescope own deferred storage at each finite coroutine boundary.

Remove explicit repository and store ownership, suppress duplicate Finished-to-Failed terminal delivery for one task, and verify success, failure, configured ignores, distinct batches, output, and persistence before the scheduler parent exits.
Read the task exit code published before ScheduledTaskFinished to assign success or internal-error status from the finalized outcome.

Finish and flush each scheduled transaction once across successful, non-zero Finished-to-Failed, and throw-before-Finished paths, with integration coverage for every terminal sequence.
Delete the published ignore_commands option because no current Hypervel or Sentry code consumes it.

Remove the matching provider filter entry rather than preserving dead configuration or adding a command-tracing mechanism solely to justify the stale surface.
Capture the Laravel, Swoole, Hypervel, Telescope, Sentry, console, and scheduler research behind the request-owned timing design.

Document the final ownership boundaries, anti-overengineering constraints, implementation map, regression plan, validation cadence, and completion criteria so future maintenance can distinguish deliberate runtime adaptations from missing Laravel behavior.
Bring the View correctness and lifecycle parity work from PR #477 into the request start-time branch.\n\nThe branches modify no common files, and the merged behavior has been checked across request timing, health rendering, View compilation and cleanup, Testbench lifecycle cleanup, Waiter context handling, and synthetic request synchronization. No request-timing or scheduler design changes are required.
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f2e29732-3d1d-4457-bd45-2eb90b8831fa

📥 Commits

Reviewing files that changed from the base of the PR and between fa63e45 and 359354b.

📒 Files selected for processing (12)
  • docs/plans/2026-08-06-1121-request-start-time-and-runtime-timing.md
  • src/console/src/Application.php
  • src/foundation/src/Application.php
  • src/sentry/src/Features/ConsoleSchedulingFeature.php
  • src/telescope/src/ListensForStorageOpportunities.php
  • src/testbench/composer.json
  • src/testbench/hypervel/artisan
  • src/testbench/src/Console/Commander.php
  • tests/Console/ConsoleApplicationCommandNameTest.php
  • tests/Foundation/ApplicationRunningInConsoleTest.php
  • tests/Foundation/Console/KernelTest.php
  • tests/Testbench/CommanderEnvironmentTest.php
🚧 Files skipped from review as they are similar to previous changes (5)
  • tests/Foundation/ApplicationRunningInConsoleTest.php
  • src/telescope/src/ListensForStorageOpportunities.php
  • src/foundation/src/Application.php
  • src/testbench/hypervel/artisan
  • src/sentry/src/Features/ConsoleSchedulingFeature.php

📝 Walkthrough

Walkthrough

The change replaces process-global request timing with request-owned timestamps, adds coroutine context-copying controls, updates scheduler execution and Telescope recording, improves CLI command resolution, and updates Sentry tracing, health rendering, documentation, and regression tests.

Changes

Runtime lifecycle changes

Layer / File(s) Summary
Request timing and health rendering
src/http/src/Request.php, src/foundation/src/..., src/support/src/Facades/Request.php, src/boost/docs/..., tests/Http/*, tests/Integration/Foundation/...
Requests capture stable normalized start timestamps. Health views, request watchers, Sentry middleware, and documentation use startedAt().
Coroutine-aware scheduled execution
src/coroutine/src/*, src/console/src/Commands/ScheduleRunCommand.php, src/console/src/Scheduling/Event.php, tests/Coroutine/*, tests/Console/Scheduling/*, tests/Integration/Console/Scheduling/*
Waiter::wait supports fresh, copied, and selective contexts. Scheduled tasks use finite coroutines, centralized dispatch, pause tracking, and repeat safety.
Command and Telescope recording lifecycle
src/telescope/src/*, tests/Telescope/*
Telescope resolves command names explicitly, ignores configured command classes, and records scheduled tasks from terminal events with duplicate suppression.
Sentry timing and task outcomes
src/sentry/src/*, src/sentry/config/sentry.php, tests/Sentry/*
Sentry uses request-owned transaction timestamps and maps scheduled-task outcomes to successful or internal-error span statuses.
CLI parsing and implementation validation
src/console/src/Application.php, src/foundation/src/Application.php, src/testbench/..., tests/Console/*, tests/Foundation/*, tests/Testbench/*, docs/plans/*
Console command detection uses Symfony ArgvInput. The artisan entrypoint and Testbench commander reuse parsed input. The implementation plan documents sequencing and validation.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.31% 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 primary change: request-owned start timing and corrected runtime timing lifecycles.
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 feature/request-start-time

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 6, 2026

Copy link
Copy Markdown

Greptile Summary

The PR introduces request-owned start timestamps and corrects command, scheduler, Telescope, and Sentry lifecycle timing in long-lived workers.

  • Adds stable request start-time capture and migrates health and tracing consumers.
  • Improves option-aware console command resolution.
  • Isolates scheduled task execution and observability in finite coroutines.
  • Corrects scheduled-task repetition, recording, storage, and transaction outcomes.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/http/src/Request.php Adds stable request-owned start-time capture, server-time normalization, and lazy immutable timestamp access.
src/console/src/Application.php Adds Symfony-definition-backed command resolution for option-prefixed console invocations.
src/console/src/Commands/ScheduleRunCommand.php Moves user filters and task execution into finite task-owned coroutines while preserving scheduler-owned control checks.
src/coroutine/src/Waiter.php Extends waited coroutines with optional full or selective context propagation.
src/telescope/src/ListensForStorageOpportunities.php Uses resolved command identity and starts Telescope recording within scheduled-task coroutine lifecycles.
src/telescope/src/Watchers/ScheduleWatcher.php Registers schedule listeners at boot, relies on coroutine-deferred storage, and suppresses duplicate terminal records.
src/sentry/src/Features/ConsoleSchedulingFeature.php Finalizes scheduled transactions once using the task's published exit code.
src/testbench/hypervel/artisan Reuses one option-aware ArgvInput and now consistently imports referenced classes, resolving the previous style finding.

Reviews (2): Last reviewed commit: "docs: update request timing implementati..." | Re-trigger Greptile

Comment thread src/testbench/hypervel/artisan Outdated

@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.

🧹 Nitpick comments (3)
src/telescope/src/ListensForStorageOpportunities.php (1)

94-111: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add void return types to the new listeners.

Both closures complete without a value. Declare : void on both closures.

As per coding guidelines, “use native types for parameters, return values, and properties wherever permitted.”

Proposed fix
-        $events->listen(BeforeHandleCommand::class, function (BeforeHandleCommand $event) {
+        $events->listen(BeforeHandleCommand::class, function (BeforeHandleCommand $event): void {
             // The long-lived scheduler records only inside each finite task coroutine.
             if ($event->command->getName() === 'schedule:run') {
                 return;
             }
@@
-        $events->listen(ScheduledTaskStarting::class, function () {
+        $events->listen(ScheduledTaskStarting::class, function (): void {
             if (static::shouldListen() && static::commandIsApproved('schedule:run')) {
                 static::startRecording();
             }
🤖 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/telescope/src/ListensForStorageOpportunities.php` around lines 94 - 111,
Add the native : void return type to both listener closures registered in the
BeforeHandleCommand and ScheduledTaskStarting listeners, without changing their
existing control flow or behavior.

Source: Coding guidelines

src/support/src/Facades/Request.php (1)

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

Import CarbonImmutable for this facade annotation.

Line 16 uses a fully qualified class name. Add a use Hypervel\Support\CarbonImmutable; statement and use CarbonImmutable in the annotation. As per coding guidelines, import classes with use statements instead of using fully qualified class names.

🤖 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/support/src/Facades/Request.php` at line 16, Add a use statement for
Hypervel\Support\CarbonImmutable in the facade file, then update the startedAt()
annotation to reference CarbonImmutable without the fully qualified namespace.

Source: Coding guidelines

tests/Foundation/ApplicationRunningInConsoleTest.php (1)

230-246: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add regression cases for separate option values.

These tests cover --env=production and the -v flag. They do not cover --env production or -e production. The current unbound ArgvInput path returns the option value as the command in those cases. (raw.githubusercontent.com)

Add assertions for both separate-value forms.

🤖 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/Foundation/ApplicationRunningInConsoleTest.php` around lines 230 - 246,
Extend the regression tests in
testRunningConsoleCommandMatchesCommandAfterLongOption and
testRunningConsoleCommandMatchesCommandAfterShortOption to use separate option
values: --env followed by production and -e followed by production. Assert the
actual command is detected and neither option nor its separate value is reported
as the command.
🤖 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.

Nitpick comments:
In `@src/support/src/Facades/Request.php`:
- Line 16: Add a use statement for Hypervel\Support\CarbonImmutable in the
facade file, then update the startedAt() annotation to reference CarbonImmutable
without the fully qualified namespace.

In `@src/telescope/src/ListensForStorageOpportunities.php`:
- Around line 94-111: Add the native : void return type to both listener
closures registered in the BeforeHandleCommand and ScheduledTaskStarting
listeners, without changing their existing control flow or behavior.

In `@tests/Foundation/ApplicationRunningInConsoleTest.php`:
- Around line 230-246: Extend the regression tests in
testRunningConsoleCommandMatchesCommandAfterLongOption and
testRunningConsoleCommandMatchesCommandAfterShortOption to use separate option
values: --env followed by production and -e followed by production. Assert the
actual command is detected and neither option nor its separate value is reported
as the command.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9b8460bc-1ef0-4922-bfa7-3191c7ffeee9

📥 Commits

Reviewing files that changed from the base of the PR and between 51709b4 and fa63e45.

📒 Files selected for processing (45)
  • docs/plans/2026-08-06-1121-request-start-time-and-runtime-timing.md
  • src/boost/docs/collections.md
  • src/boost/docs/coroutines.md
  • src/boost/docs/requests.md
  • src/console/src/Commands/ScheduleRunCommand.php
  • src/console/src/Scheduling/Event.php
  • src/coroutine/src/Waiter.php
  • src/coroutine/src/functions.php
  • src/foundation/src/Application.php
  • src/foundation/src/Configuration/ApplicationBuilder.php
  • src/foundation/src/Testing/Concerns/MakesHttpRequests.php
  • src/foundation/src/Testing/Coroutine/Waiter.php
  • src/foundation/src/resources/health-up.blade.php
  • src/http/src/Request.php
  • src/sentry/config/sentry.php
  • src/sentry/src/Features/ConsoleSchedulingFeature.php
  • src/sentry/src/SentryServiceProvider.php
  • src/sentry/src/Tracing/Middleware.php
  • src/support/src/Facades/Request.php
  • src/telescope/src/ListensForStorageOpportunities.php
  • src/telescope/src/Telescope.php
  • src/telescope/src/Watchers/CommandWatcher.php
  • src/telescope/src/Watchers/RequestWatcher.php
  • src/telescope/src/Watchers/ScheduleWatcher.php
  • src/testbench/hypervel/artisan
  • src/testbench/src/Workbench/Workbench.php
  • tests/Console/Scheduling/EventTest.php
  • tests/Console/Scheduling/ScheduleRunCommandTest.php
  • tests/Console/Scheduling/ScheduleRunContextPropagationTest.php
  • tests/Coroutine/WaiterTest.php
  • tests/Foundation/ApplicationRunningInConsoleTest.php
  • tests/Foundation/Http/KernelTest.php
  • tests/Foundation/Testing/Coroutine/WaiterTest.php
  • tests/Foundation/Testing/RequestContextSynchronizerTest.php
  • tests/Http/HttpRequestTest.php
  • tests/HttpServer/RequestBridgeTest.php
  • tests/Integration/Console/Scheduling/SubMinuteSchedulingTest.php
  • tests/Integration/Foundation/Support/Providers/RouteServiceProviderHealthTest.php
  • tests/Sentry/Features/ConsoleSchedulingIntegrationTest.php
  • tests/Sentry/Tracing/MiddlewareTest.php
  • tests/Telescope/Telescope/TelescopeTest.php
  • tests/Telescope/Watchers/CommandWatcherTest.php
  • tests/Telescope/Watchers/RequestWatchersTest.php
  • tests/Telescope/Watchers/ScheduleWatcherTest.php
  • tests/Testbench/Workbench/DiscoversTest.php
💤 Files with no reviewable changes (4)
  • src/foundation/src/Testing/Coroutine/Waiter.php
  • src/sentry/config/sentry.php
  • src/sentry/src/SentryServiceProvider.php
  • tests/Foundation/Testing/Coroutine/WaiterTest.php

Pre-bootstrap command checks used an unbound ArgvInput, so a separated optional --env value could be mistaken for the command name.

Add one shared resolver that binds Symfony's authoritative global definition plus Hypervel's environment option using Symfony's own catch-and-rebind flow. Use it for the public application classifier while preserving the existing protected environment-option extension point.

Cover attached and separated global option values, command-specific options rejected during preliminary binding, and execution after the real console kernel rebinds the same input.
Both Testbench CLI paths classified server commands before Symfony had bound the global input definition. A separated --env value could therefore leave APP_RUNNING_IN_CONSOLE enabled for a serve invocation.

Route the skeleton artisan and bin/testbench Commander through the shared console resolver, keep the same ArgvInput for kernel execution, and normalize the entrypoint imports and constructor style.

Declare Testbench's direct hypervel/console dependency and add a focused regression for the separated environment option form.
Declare the command and scheduled-task storage opportunity closures as void.

This makes their callback contracts explicit and aligns the listeners with the repository's full-typing convention without changing recording behavior.
Add concise Laravel-style method documentation to the three scheduled-task lifecycle handlers.

The comments state each handler's tracing responsibility while keeping the upstream-derived feature implementation free of a broad documentation-only rewrite.
Replace the earlier bounded command-name parsing proposal with the final shared Symfony-definition-backed resolver design.

Record all three shipped CLI consumers, the generic kernel boundary, signal setup behavior, direct Testbench dependency, regression coverage, stale-code checks, and final review criteria so the plan matches the implemented code without preserving rejected approaches.
@binaryfire

Copy link
Copy Markdown
Collaborator Author

@greptile-apps @coderabbitai I reviewed every finding and pushed the accepted changes.

Accepted changes:

  • The Testbench artisan entrypoint now imports all referenced classes and uses short names consistently.
  • Both Telescope listener closures now declare : void.
  • The three touched Sentry scheduling handlers now have concise method documentation.

The separate --env report exposed a real issue, but the local test-only change was too narrow. I fixed it at the shared console boundary instead. The resolver binds the Symfony global definition plus Hypervel --env, follows the Symfony catch-and-rebind flow, and is used by runningConsoleCommand() plus all three shipped CLI entrypoints. It handles --env=production, --env production, -v, --ansi, and command-specific options without a custom parser or shared cache. Hypervel defines no -e shortcut, so -e production remains invalid by design.

Two suggestions were intentionally not applied:

  • The generated Request facade annotation remains fully qualified. The facade generator emits that form across the file, so a manual import would be overwritten and would make the generated output inconsistent.
  • I did not add repository-wide comments to satisfy the 80% docstring metric. That would add noise outside the changed behavior and conflict with the project convention of documenting methods only where the comment adds useful context.

The follow-up audit also added Testbench direct dependency on hypervel/console rather than relying on a transitive Foundation edge. composer fix and the focused Testbench validation are green.

@coderabbitai

coderabbitai Bot commented Aug 6, 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 '=== changed files ==='
git diff --name-status HEAD^ HEAD

echo
echo '=== relevant diff ==='
git diff --unified=60 HEAD^ HEAD -- \
  src/foundation/src/Application.php \
  src/testbench/hypervel/artisan \
  src/testbench/composer.json \
  src/telescope/src/ListensForStorageOpportunities.php \
  src/sentry/src/Features/ConsoleSchedulingFeature.php \
  src/support/src/Facades/Request.php \
  tests/Foundation/ApplicationRunningInConsoleTest.php \
  tests/Testbench/Workbench/DiscoversTest.php

echo
echo '=== source outlines ==='
fd -a -t f 'Application.php|artisan|ConsoleSchedulingFeature.php|ListensForStorageOpportunities.php|Request.php|composer.json' \
  src/foundation/src src/testbench src/sentry/src src/telescope/src src/support/src 2>/dev/null \
  | while IFS= read -r file; do
      echo "--- $file"
      ast-grep outline "$file" --items all 2>/dev/null || true
    done

echo
echo '=== console option resolver and CLI entrypoint usages ==='
rg -n -C 5 --glob '*.php' --glob 'artisan' \
  'ArgvInput|InputDefinition|runningConsoleCommand\s*\(|--env|resolve.*Command|bind.*Definition' \
  src/foundation src/testbench tests

Length of output: 117346


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== PR commit and file metadata ==='
gh api repos/hypervel/components/pulls/478 --jq '{base: .base.sha, head: .head.sha, commits: .commits, changed_files: .changed_files}'
gh api repos/hypervel/components/pulls/478/files --paginate \
  --jq '.[] | [.filename, .status] | `@tsv`' | sort

echo
echo '=== command resolver implementation ==='
resolver_file="$(fd -a -t f 'Application.php' src/console/src | head -n 1)"
echo "--- $resolver_file"
rg -n -A100 -B15 'resolveCommandName\s*\(' "$resolver_file"

echo
echo '=== shipped CLI entrypoints and resolver calls ==='
rg -n -C 8 --glob 'artisan' --glob '*.php' \
  'resolveCommandName\s*\(|new ArgvInput|APP_RUNNING_IN_CONSOLE' \
  src/testbench src/foundation tests/Testbench

echo
echo '=== Testbench console dependency ==='
cat src/testbench/composer.json
printf '\n--- lock references ---\n'
rg -n -C 2 '"hypervel/console"' composer.json composer.lock src/testbench/composer.json 2>/dev/null || true

echo
echo '=== Telescope closure signatures ==='
rg -n -A18 -B8 --glob '*.php' 'function\s*\([^)]*\)\s*(:\s*void)?\s*\{' \
  src/telescope/src/ListensForStorageOpportunities.php

echo
echo '=== Sentry scheduling handler docs ==='
sed -n '/function handleScheduledTaskStarting/,/function startCheckIn/p' \
  src/sentry/src/Features/ConsoleSchedulingFeature.php

echo
echo '=== generated Request facade annotations ==='
sed -n '1,215p' src/support/src/Facades/Request.php

Length of output: 48192


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== committed artisan entrypoints ==='
fd -a -t f -p '/artisan$' . -E vendor -E .git | sort

echo
echo '=== resolver calls in committed entrypoints ==='
fd -a -t f -p '/artisan$' . -E vendor -E .git -x sh -c '
  echo "--- $1"
  rg -n -C 5 "resolveCommandName\s*\(|new ArgvInput|APP_RUNNING_IN_CONSOLE" "$1" || true
' sh {}

Length of output: 1251


@binaryfire Verified the follow-up changes in PR #478.

The shared ConsoleApplication::resolveCommandName() path handles the documented global options and command-specific options. Dedicated tests cover the reported cases.

The Testbench entrypoint imports its dependencies and uses the shared resolver. src/testbench/composer.json now directly requires hypervel/console.

Both relevant Telescope listener closures declare : void. The Sentry handlers have focused documentation.

Keeping the generated Request facade annotations fully qualified is consistent with the file. Skipping repository-wide docstrings is appropriate because those changes are outside this PR’s behavior.

I did not run composer fix or the focused tests in this inspection sandbox. Your reported validation is noted. No related concern remains.


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.

@greptile-apps

greptile-apps Bot commented Aug 6, 2026

Copy link
Copy Markdown

Everything checks out. The implementation is clean across all touched files.

A few specific observations on the landed code:

resolveCommandName — The design is exactly right. Constructing a fresh SymfonyApplication solely to get its default InputDefinition, appending --env, binding, and catching ExceptionInterface before delegating to getFirstArgument() is the minimal, correct approach. No shared state, no custom parser.

Sentry double-flush guard — Having verified TracksPushedScopesAndSpans::maybeFinishSpan(), the !== null gate in both handleScheduledTaskFinished and handleScheduledTaskFailed is correct: it returns the finished span on success and null when the span stack is already empty, so Integration::flushEvents() inside maybePopScope() fires at most once per task regardless of which terminal event arrives.

Telescope ScheduleWatcher — The CoroutineContext deduplication key on spl_object_id($task) correctly handles the ScheduledTaskFinishedScheduledTaskFailed sequence without relying on event ordering.

One thing to confirm: CommandWatcher now ignores package:discover instead of crontab:run. If crontab:run still exists as a long-running daemon (analogous to schedule:run), it should probably remain on that list to avoid recording the process rather than its constituent tasks. If the command was removed or renamed, the current state is fine.

@binaryfire
binaryfire merged commit af91108 into 0.4 Aug 6, 2026
2 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