From 09bf835953909ed53921328c0aecdb47167166d1 Mon Sep 17 00:00:00 2001 From: "Flavio S. Glock" Date: Tue, 4 Aug 2026 13:46:17 +0200 Subject: [PATCH 1/2] fix: restore File::Temp handle compatibility Implement IO::Handle-compatible write semantics and restore the upstream ten-character default filename contract. This allows HTTP::Body multipart and octet-stream request parsing to pass its complete upstream test suite. Document the Catalyst dependency probe and remaining compatibility work. Generated with [Codex](https://openai.com/codex/) Co-Authored-By: Codex --- dev/design/catalyst-support.md | 71 +++++++++++++++++++ src/main/perl/lib/File/Temp.pm | 19 ++++- .../resources/unit/file_temp_handle_methods.t | 21 ++++++ 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 dev/design/catalyst-support.md create mode 100644 src/test/resources/unit/file_temp_handle_methods.t diff --git a/dev/design/catalyst-support.md b/dev/design/catalyst-support.md new file mode 100644 index 000000000..e60fb6472 --- /dev/null +++ b/dev/design/catalyst-support.md @@ -0,0 +1,71 @@ +# Catalyst Support + +## Goal + +Run an unmodified Catalyst application on PerlOnJava, fixing CPAN tooling, +compiler, runtime, and general-purpose module compatibility instead of +patching Catalyst. + +## Compatibility Strategy + +1. Install upstream `Catalyst::Runtime` with `jcpan` and preserve complete logs. +2. Reduce each failure to a standard-Perl-validated regression test. +3. Prefer fixes in the compiler, runtime, CPAN tooling, or general-purpose + bundled modules. +4. Add Java XS replacements only when an upstream dependency has no usable + pure-Perl implementation. +5. Verify Catalyst through PSGI using `Plack::Handler::Netty` without `fork`. + +## Progress Tracking + +### Current Status: Phase 1 in progress + +### Completed Work + +- [x] Initial dependency probes (2026-08-04) + - Probed both `Catalyst` and the narrower `Catalyst::Runtime` target. + - Confirmed that the full target pulls developer tooling including + `MooseX::Getopt` and `Test::Trap`. + - Confirmed many dependencies pass unchanged, including URI, Path::Tiny, + Params::Validate PP, MooseX::Role::Parameterized, and LWP components. + - Logs: `/tmp/catalyst-install-1.log`, `/tmp/catalyst-install-2.log`, and + `/tmp/catalyst-runtime-install-1.log`. +- [x] HTTP request-body compatibility (2026-08-04) + - Added the standard `File::Temp->write($buffer, $length, $offset)` method. + - Restored the upstream ten-character default temporary filename contract. + - Added a system-Perl-validated unit regression test. + - Full PerlOnJava unit suite passes. + - Upstream HTTP::Body 1.23 passes 13/13 files and 250/250 assertions. + - HTTP::Body installs normally with `jcpan` after the fixes. + +### Current Work + +- [ ] Fix inherited method-modifier handling exercised by + `MooseX::MethodAttributes` Catalyst-style controllers. + - 20/22 upstream test files pass and 130/131 completed assertions pass. + - `t/catalyst.t` fails while wrapping an inherited attributed method with + `Moose::Exception::MethodNameNotFoundInInheritanceHierarchy`. + - `t/catalyst_role.t` has one method-list count mismatch. + +### Next Steps + +1. Reduce the MooseX::MethodAttributes inherited modifier failure to a local + compiler/runtime regression test. +2. Resume installing Catalyst::Runtime after method attributes pass. +3. Boot a minimal Catalyst PSGI application under Plack::Handler::Netty. +4. Fix the Plack dependency stack's POSIX timezone and `tzset` differences. +5. Return to Catalyst developer-tool installation and Test::Trap failures. + +### Open Issues + +- `Encode::Locale` exposes incorrect tied `%ENV` mutation behavior. +- `AnyDBM_File` is missing from the bundled core-module inventory, causing + CPAN to suggest installing a full Perl distribution. +- `Test::Trap` exposes non-local labeled-loop and parser failures. It is a + developer-tool dependency rather than the first runtime blocker. +- Class::C3::Adopt::NEXT has warning-text and warning-disable differences. +- `POSIX::strftime::Compiler` exposes timezone-offset, timezone-name, and + `POSIX::tzset` compatibility gaps. These affect Plack access-log formatting, + not Catalyst dispatch itself. +- `MooseX::Getopt` has failures concentrated in help/usage output and trapped + exit behavior; it was force-installed only to continue dependency discovery. diff --git a/src/main/perl/lib/File/Temp.pm b/src/main/perl/lib/File/Temp.pm index e011565bf..7261c1678 100644 --- a/src/main/perl/lib/File/Temp.pm +++ b/src/main/perl/lib/File/Temp.pm @@ -185,6 +185,22 @@ sub read { return CORE::read($self->{_fh}, $_[0], $_[1], defined $_[2] ? $_[2] : 0); } +sub write { + my $self = shift; + my $buf = shift; + my $len = @_ ? shift : length($buf); + my $offset = @_ ? shift : 0; + + my $data; + { + use bytes; + $data = substr($buf, $offset, $len); + } + utf8::encode($data) if utf8::is_utf8($data); + local $\; + return print { $self->{_fh} } $data; +} + sub binmode { my $self = shift; return @_ ? CORE::binmode($self->{_fh}, $_[0]) : CORE::binmode($self->{_fh}); @@ -594,8 +610,7 @@ sub _parse_args { } sub _generate_template { - my $base = "temp" . sprintf("%04d", $TEMPLATE_COUNTER++ % 10000); - return $base . "XXXXXX"; + return "XXXXXXXXXX"; } # Wrapper for File::Spec->tmpdir for compatibility diff --git a/src/test/resources/unit/file_temp_handle_methods.t b/src/test/resources/unit/file_temp_handle_methods.t new file mode 100644 index 000000000..44e2f0efc --- /dev/null +++ b/src/test/resources/unit/file_temp_handle_methods.t @@ -0,0 +1,21 @@ +use strict; +use warnings; +use Test::More tests => 8; +use File::Temp; +use File::Basename qw(basename); + +my $file = File::Temp->new; + +ok($file->can('write'), 'File::Temp object exposes IO::Handle write method'); +ok($file->write('abcdef', 3), 'write accepts an explicit byte length'); +ok($file->write('012345', 2, 2), 'write accepts a byte offset'); +ok($file->seek(0, 0), 'temporary file can seek back to the start'); + +my $contents = ''; +is($file->read($contents, 5), 5, 'read reports the number of bytes read'); +is($contents, 'abc23', 'write length and offset match IO::Handle semantics'); + +is(length(basename(File::Temp->new->filename)), 10, + 'default temporary filename contains ten generated characters'); +like(basename(File::Temp->new(SUFFIX => '.pl')->filename), qr/^.{10}\.pl$/, + 'suffix follows the ten-character default temporary filename'); From 8084288d5f6713ab351fc0dc57f2626bb1db5d54 Mon Sep 17 00:00:00 2001 From: "Flavio S. Glock" Date: Tue, 4 Aug 2026 13:54:52 +0200 Subject: [PATCH 2/2] docs: make Catalyst plan an operational handoff Define scope, completion gates, isolated CPAN-state requirements, dependency classification, milestone acceptance criteria, and exact reproduction steps for the current MooseX::MethodAttributes blocker. Keep chronological progress in commits and the PR while retaining only the current execution state needed for a reliable handoff. Generated with [Codex](https://openai.com/codex/) Co-Authored-By: Codex --- dev/design/catalyst-support.md | 489 ++++++++++++++++++++++++++++----- 1 file changed, 418 insertions(+), 71 deletions(-) diff --git a/dev/design/catalyst-support.md b/dev/design/catalyst-support.md index e60fb6472..8fddf27de 100644 --- a/dev/design/catalyst-support.md +++ b/dev/design/catalyst-support.md @@ -1,71 +1,418 @@ -# Catalyst Support - -## Goal - -Run an unmodified Catalyst application on PerlOnJava, fixing CPAN tooling, -compiler, runtime, and general-purpose module compatibility instead of -patching Catalyst. - -## Compatibility Strategy - -1. Install upstream `Catalyst::Runtime` with `jcpan` and preserve complete logs. -2. Reduce each failure to a standard-Perl-validated regression test. -3. Prefer fixes in the compiler, runtime, CPAN tooling, or general-purpose - bundled modules. -4. Add Java XS replacements only when an upstream dependency has no usable - pure-Perl implementation. -5. Verify Catalyst through PSGI using `Plack::Handler::Netty` without `fork`. - -## Progress Tracking - -### Current Status: Phase 1 in progress - -### Completed Work - -- [x] Initial dependency probes (2026-08-04) - - Probed both `Catalyst` and the narrower `Catalyst::Runtime` target. - - Confirmed that the full target pulls developer tooling including - `MooseX::Getopt` and `Test::Trap`. - - Confirmed many dependencies pass unchanged, including URI, Path::Tiny, - Params::Validate PP, MooseX::Role::Parameterized, and LWP components. - - Logs: `/tmp/catalyst-install-1.log`, `/tmp/catalyst-install-2.log`, and - `/tmp/catalyst-runtime-install-1.log`. -- [x] HTTP request-body compatibility (2026-08-04) - - Added the standard `File::Temp->write($buffer, $length, $offset)` method. - - Restored the upstream ten-character default temporary filename contract. - - Added a system-Perl-validated unit regression test. - - Full PerlOnJava unit suite passes. - - Upstream HTTP::Body 1.23 passes 13/13 files and 250/250 assertions. - - HTTP::Body installs normally with `jcpan` after the fixes. - -### Current Work - -- [ ] Fix inherited method-modifier handling exercised by - `MooseX::MethodAttributes` Catalyst-style controllers. - - 20/22 upstream test files pass and 130/131 completed assertions pass. - - `t/catalyst.t` fails while wrapping an inherited attributed method with - `Moose::Exception::MethodNameNotFoundInInheritanceHierarchy`. - - `t/catalyst_role.t` has one method-list count mismatch. - -### Next Steps - -1. Reduce the MooseX::MethodAttributes inherited modifier failure to a local - compiler/runtime regression test. -2. Resume installing Catalyst::Runtime after method attributes pass. -3. Boot a minimal Catalyst PSGI application under Plack::Handler::Netty. -4. Fix the Plack dependency stack's POSIX timezone and `tzset` differences. -5. Return to Catalyst developer-tool installation and Test::Trap failures. - -### Open Issues - -- `Encode::Locale` exposes incorrect tied `%ENV` mutation behavior. -- `AnyDBM_File` is missing from the bundled core-module inventory, causing - CPAN to suggest installing a full Perl distribution. -- `Test::Trap` exposes non-local labeled-loop and parser failures. It is a - developer-tool dependency rather than the first runtime blocker. -- Class::C3::Adopt::NEXT has warning-text and warning-disable differences. -- `POSIX::strftime::Compiler` exposes timezone-offset, timezone-name, and - `POSIX::tzset` compatibility gaps. These affect Plack access-log formatting, - not Catalyst dispatch itself. -- `MooseX::Getopt` has failures concentrated in help/usage output and trapped - exit behavior; it was force-installed only to continue dependency discovery. +# Catalyst Support Handoff + +## Objective + +Run an unmodified Catalyst application on PerlOnJava through PSGI and +`Plack::Handler::Netty`. + +Fix compatibility at the lowest reusable layer: CPAN tooling, compiler, +runtime, core modules, or general-purpose CPAN dependencies. Do not patch +Catalyst to hide PerlOnJava defects. + +The compatibility target is currently: + +| Distribution | Version | +|---|---:| +| Catalyst-Runtime | 5.90132 | +| MooseX-MethodAttributes | 0.32 | +| Plack | 1.0054 | +| HTTP-Body | 1.23 | +| Moose | 2.4000 | + +Update this table deliberately when CPAN resolves a newer release. Do not let +an implicit version change invalidate an established baseline. + +## Definition of Done + +Catalyst runtime support is complete when all of the following hold: + +1. A clean, isolated `jcpan install Catalyst::Runtime` succeeds without + `-f`, skipped runtime prerequisites, or Catalyst-specific source patches. +2. `./jperl -MCatalyst -e 'print $Catalyst::VERSION'` succeeds. +3. An unmodified minimal Catalyst application starts as a PSGI application + under `Plack::Handler::Netty`. +4. End-to-end requests verify: + - `:Path`, `:Local`, `:Args`, `:CaptureArgs`, `:Chained`, and `:Private` + action discovery and dispatch; + - query and URL-encoded parameters; + - multipart upload handling; + - response status, headers, cookies, redirects, and UTF-8 response bodies; + - exception-to-500 behavior and request logging. +5. The full PerlOnJava unit suite passes with `make`. +6. Every new Perl regression test was first validated with standard Perl. +7. Compiler/runtime changes shared by both backends are tested with the JVM + backend and `--interpreter`. +8. The final PR documents unsupported deployment modes and optional Catalyst + components. + +Passing every test in every transitive distribution is desirable but is not a +release gate when a failure is confined to a test-only or unsupported feature. +Runtime prerequisites must install and function without force. + +## Scope + +### Required + +- `Catalyst::Runtime` and its runtime dependency graph. +- Catalyst method/action attributes and Moose metaclass integration. +- PSGI operation through `Plack::Handler::Netty`. +- Single-process, non-forking operation. +- Request parsing through `HTTP::Body`. +- A reproducible clean-install test environment. + +### Deferred + +- `Catalyst::Devel`, application generators, and development-server reloaders. +- Prefork servers, daemonization, and worker management. +- Plugins outside the minimal acceptance application, including authentication, + sessions, DBIx::Class models, and template views. +- Complete compatibility for test-only modules such as `Test::Trap`. +- Performance tuning beyond preventing obvious hangs or pathological fallback. + +Deferred work must not be installed accidentally as part of the runtime gate. +If CPAN requests it, first determine whether prerequisite phase/type handling is +incorrect. + +## Engineering Rules + +1. Keep upstream Catalyst and its dependencies unchanged during diagnosis. +2. Reduce failures before changing implementation code. +3. Validate new Perl tests with system Perl before running them with `jperl`. +4. Prefer a general compiler/runtime/tooling fix over a bundled module change. +5. A bundled module fix is appropriate when PerlOnJava's implementation of + that module violates its public Perl API. +6. Use Java replacements only for unavoidable XS/native functionality with no + viable pure-Perl path. +7. Never use `git stash`, alter upstream tests, or run `jperl`, `jcpan`, or + `prove` without `timeout`. +8. Capture complete command output in `/tmp`; record durable conclusions here + or in the PR because `/tmp` logs are not handoff artifacts. +9. Keep commits narrow. Commit history and the PR are the progress ledger; + this document describes current state, decisions, and future work. + +## Reproducible Environment + +### Current contamination warning + +The workstation's `~/.perlonjava` is not a clean baseline. Dependency discovery +force-installed unchanged copies of `Test::Trap` and `MooseX::Getopt`, and many +other prerequisites were installed incrementally. Do not use the current +`~/.perlonjava` to claim that a clean Catalyst installation succeeds. + +Do not delete, clean, restore, or replace `~/.perlonjava` in place. It may +contain unrelated user state. + +### Required tooling improvement + +Before the final installation gate, add a supported isolated home override, +provisionally named `PERLONJAVA_HOME`, with these semantics: + +- default remains `~/.perlonjava`; +- library, CPAN metadata, sources, build directories, preferences, patches, + scripts, and manpages all derive from the override; +- `jperl` automatically includes `$PERLONJAVA_HOME/lib` in `@INC`; +- `jcpan` installs only beneath the override; +- the override works on Unix and Windows launchers; +- tests can create a temporary isolated home without mutating user state. + +Acceptance test: + +```bash +isolated_root=$(mktemp -d /tmp/perlonjava-catalyst.XXXXXX) +PERLONJAVA_HOME="$isolated_root" timeout 1200 ./jcpan install Try::Tiny \ + > /tmp/catalyst-isolated-cpan.log 2>&1 +PERLONJAVA_HOME="$isolated_root" timeout 60 ./jperl -MTry::Tiny -e 'print "ok\n"' \ + >> /tmp/catalyst-isolated-cpan.log 2>&1 +``` + +The implementation must include a regression test that verifies no files were +written beneath the default user home. Temporary-directory cleanup should be +left to the test harness or performed only on the exact validated temporary +path. + +## Dependency Status + +| Component | Class | Current result | Gate | Next action | +|---|---|---|---|---| +| HTTP-Body 1.23 | runtime | 13/13 files, 250/250 assertions pass; installs normally | cleared | retain regression coverage | +| Moose 2.4000 | runtime | bundled; broad upstream/DBIx::Class coverage already exists | monitor | investigate only Catalyst-relevant failures | +| MooseX-MethodAttributes 0.32 | runtime | 20/22 files pass; Catalyst-specific inherited modifier failure | blocking | reduce and fix at Moose/MOP/runtime layer | +| Catalyst-Runtime 5.90132 | runtime | downloaded, not successfully installed | blocking | resume after method attributes and isolation | +| Plack 1.0054 | runtime | dependency installation incomplete | blocking later | classify runtime versus test-only prerequisites | +| Class-C3-Adopt-NEXT 0.14 | runtime | functional tests mostly pass; warning differences remain | non-blocking until proven otherwise | defer | +| Encode-Locale 1.05 | transitive runtime | tied `%ENV` mutation tests fail | risk | verify whether Catalyst runtime path exercises mutation | +| POSIX-strftime-Compiler 0.46 | Plack logging | timezone and `POSIX::tzset` differences | non-blocking for initial dispatch | fix before logging acceptance gate | +| AnyDBM_File | optional/transitive | missing bundled core module makes CPAN suggest installing Perl | tooling defect | add/import core module or correct capability metadata | +| MooseX-Getopt 0.78 | runtime/development boundary | force-installed for discovery; help and trapped-exit tests fail | classify | determine which Catalyst runtime code requires it | +| Test-Trap 0.3.5 | test/development | force-installed for discovery; many failures | deferred | do not block runtime installation if only test-time | + +When a new dependency appears, add it here only if it is blocking, forced, +incorrectly classified, or exposes a reusable PerlOnJava defect. + +## Current Handoff State + +Start with Milestone 0, then Milestone 1. The shared CPAN state cannot support +a trustworthy clean-install result, while the known framework blocker is the +inherited attributed-method case described below. Use the dependency table as +the baseline; use commit history and the PR for chronological progress. + +When a milestone is completed, update this paragraph to name the next active +milestone and record its acceptance result, without adding a work diary. + +## Milestone Plan + +### Milestone 0: Isolated CPAN state + +Deliverables: + +- Implement and document `PERLONJAVA_HOME` or an equivalently named override. +- Add Unix and Windows launcher coverage. +- Add a test proving installation and loading happen entirely within an + isolated temporary root. + +Exit criteria: + +- A known-small CPAN distribution installs and loads from an isolated root. +- The default `~/.perlonjava` remains untouched by the test. + +### Milestone 1: Catalyst method attributes + +Deliverables: + +- Reduce the two MooseX-MethodAttributes Catalyst failures. +- Add standard-Perl-validated local regression tests. +- Fix inheritance, method-modifier, metaclass, MRO, cache invalidation, or code + attribute behavior at the responsible reusable layer. + +Exit criteria: + +- Upstream `MooseX-MethodAttributes` `t/catalyst.t` and + `t/catalyst_role.t` pass unchanged. +- The complete upstream MooseX-MethodAttributes suite has no regressions. +- Relevant local tests pass on both PerlOnJava backends. + +### Milestone 2: Clean Catalyst runtime installation + +Deliverables: + +- Install Catalyst-Runtime 5.90132 into a fresh isolated home. +- Classify every failed prerequisite as runtime, configure/build, test-only, + optional, or unsupported. +- Correct CPAN prerequisite handling when optional/test modules block runtime + installation. +- Fix remaining runtime dependency failures without force installs. + +Exit criteria: + +```bash +PERLONJAVA_HOME="$isolated_root" timeout 1200 ./jcpan install Catalyst::Runtime +PERLONJAVA_HOME="$isolated_root" timeout 60 ./jperl \ + -MCatalyst -e 'print $Catalyst::VERSION, "\n"' +``` + +Both commands exit zero, and the install log contains no forced distribution. + +### Milestone 3: Minimal application boot and dispatch + +Create a small upstream-compatible fixture application. First run its tests +with standard Perl in an environment containing Catalyst 5.90132, then run it +with PerlOnJava. + +Required controller coverage: + +```perl +sub index :Path('/') :Args(0) { ... } +sub local :Local { ... } +sub base :Chained('/') :PathPart('api') :CaptureArgs(0) { ... } +sub item :Chained('base') :PathPart('item') :Args(1) { ... } +sub private :Private { ... } +``` + +Exit criteria: + +- Application setup completes without patching Catalyst. +- Every required action is discovered with the correct attributes. +- Direct dispatcher tests select the expected action and arguments. + +### Milestone 4: PSGI and Netty end-to-end behavior + +Deliverables: + +- Expose the fixture application as PSGI. +- Run it with `Plack::Handler::Netty` using a hard timeout. +- Exercise it through an HTTP client with deterministic request fixtures. +- Verify request bodies, uploads, headers, cookies, redirects, UTF-8, and 500s. + +Expected PSGI flags: + +```perl +psgi.multithread => 0 +psgi.multiprocess => 0 +psgi.run_once => 0 +``` + +Exit criteria: + +- End-to-end tests pass without `fork` or Perl threads. +- Server termination is deterministic and leaves no orphaned JVM. + +### Milestone 5: Hardening and documentation + +Deliverables: + +- Run `make` and the relevant bundled/upstream suites. +- Verify installation once more from a new isolated home. +- Document supported deployment, known limitations, and JDBC setup references. +- Decide whether Catalyst::Devel deserves a follow-up PR. + +Exit criteria: + +- All items in Definition of Done are satisfied. +- The PR contains exact test commands and results. + +## Current Blocker: MooseX-MethodAttributes + +### Reproduction source + +Downloaded distribution: + +```text +~/.perlonjava/cpan/build/MooseX-MethodAttributes-0.32-0/ +``` + +The numeric build suffix is CPAN-generated and may differ on another machine. + +Run the complete upstream suite: + +```bash +cd ~/.perlonjava/cpan/build/MooseX-MethodAttributes-0.32-0 +timeout 300 make test > /tmp/moosex-methodattributes.log 2>&1 +``` + +Run the two Catalyst-focused files directly: + +```bash +cd ~/.perlonjava/cpan/build/MooseX-MethodAttributes-0.32-0 +timeout 60 /path/to/PerlOnJava4/jperl -Ilib -It/lib t/catalyst.t \ + > /tmp/moosex-methodattributes-catalyst.log 2>&1 +timeout 60 /path/to/PerlOnJava4/jperl -Ilib -It/lib t/catalyst_role.t \ + > /tmp/moosex-methodattributes-role.log 2>&1 +``` + +### Observed behavior + +- `t/catalyst.t` aborts while compiling/loading the Catalyst-like subclass: + + ```text + Moose::Exception::MethodNameNotFoundInInheritanceHierarchy=HASH(...) + Compilation failed in require + ``` + +- The failure occurs around an `after get_attribute => sub { ... }` modifier + wrapping an inherited method carrying a custom `:Local` attribute. +- `t/catalyst_role.t` completes but reports one method-list count mismatch. +- Ordinary inherited Moose modifiers pass in a smaller probe. The reduction + must preserve MooseX::MethodAttributes metaroles and attributed methods. + +### Relevant upstream files + +```text +t/catalyst.t +t/catalyst_role.t +t/lib/CatalystLike/Controller.pm +t/lib/CatalystLike/Controller/Moose.pm +t/lib/CatalystLike/Controller/Moose/MethodModifiers.pm +lib/MooseX/MethodAttributes/Role/Meta/Class.pm +``` + +### Relevant PerlOnJava files + +```text +src/main/perl/lib/Class/MOP/Class.pm +src/main/perl/lib/Class/MOP/Mixin/HasMethods.pm +src/main/perl/lib/Moose/Meta/Class.pm +src/main/java/org/perlonjava/runtime/mro/InheritanceResolver.java +src/main/java/org/perlonjava/runtime/perlmodule/Attributes.java +src/main/java/org/perlonjava/frontend/parser/SubroutineParser.java +src/main/java/org/perlonjava/backend/jvm/EmitSubroutine.java +src/main/java/org/perlonjava/backend/bytecode/OpcodeHandlerExtended.java +``` + +### Investigation order + +1. Provision a standard-Perl Catalyst/Moose environment; the workstation's + current system Perl does not have Moose installed. +2. Reduce the upstream package hierarchy while retaining: + - an inherited attributed method; + - `MooseX::MethodAttributes` inheritable metaroles; + - an `after` modifier in the subclass. +3. Compare the class precedence list, `@ISA`, local method map, and + `find_next_method_by_name` immediately before the failing modifier. +4. Determine whether the parent method is absent, stale in a method/MRO cache, + or represented by the wrong metaclass. +5. Test both JVM and interpreter backends. +6. Add the reduced test under `src/test/resources/unit/` only after standard + Perl validates it. +7. Run the full MooseX-MethodAttributes suite and `make`. + +Do not add Catalyst names to generic cache invalidation or method lookup code. +The fix must be driven by ordinary Perl/Moose semantics. + +## Standard Command Set + +All output-producing test commands write complete logs before summaries are +read. + +```bash +# Full project gate +timeout 1200 make > /tmp/make-catalyst.log 2>&1 + +# Standard-Perl validation of a new unit test +timeout 60 prove src/test/resources/unit/catalyst_regression.t \ + > /tmp/catalyst-regression-perl.log 2>&1 + +# PerlOnJava backend comparison +timeout 60 ./jperl src/test/resources/unit/catalyst_regression.t \ + > /tmp/catalyst-regression-jvm.log 2>&1 +timeout 60 ./jperl --interpreter src/test/resources/unit/catalyst_regression.t \ + > /tmp/catalyst-regression-interpreter.log 2>&1 + +# Dependency installation; never run bare jcpan +timeout 1200 ./jcpan install Catalyst::Runtime \ + > /tmp/catalyst-runtime-install.log 2>&1 + +# Cleanup audit +ps aux | awk '$3 > 20 {print $2, $3, $11, $12}' +``` + +Do not force-install modules in an acceptance run. A force install is allowed +only for dependency discovery, must use an isolated home, and must be recorded +in the dependency table. + +## PR and Commit Strategy + +Prefer one independently verified commit per reusable fix: + +1. isolated CPAN-home tooling; +2. each compiler/runtime semantic fix with regression tests; +3. each bundled general-purpose module compatibility fix; +4. Catalyst fixture and PSGI integration; +5. final documentation. + +The PR should summarize milestone results, exact versions, install/test +commands, forced-install discoveries that were eliminated, and remaining +deferred work. Avoid duplicating a chronological work diary in this document. + +## Related Documentation + +- [AGENTS.md](../../AGENTS.md) — mandatory safety, testing, and Git workflow. +- [Using CPAN Modules](../../docs/guides/using-cpan-modules.md) — `jcpan` + behavior. +- [Module Porting](../../docs/guides/module-porting.md) — XS and Java + replacement policy. +- [Bundled Modules](../../docs/reference/bundled-modules.md) — bundled Moose, + DBI, and Plack handler. +- [Netty PSGI Example](../../examples/http_server_plack/README.md) — deployment + model. +- [Moose Support](../modules/moose_support.md) — Moose/Class::MOP status and + diagnostics.