feat(php): add PHP source lift kit (self-hosted) + php-language-signature#600
Conversation
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (82)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d973584508
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if ($stmt instanceof \PhpParser\Node\Stmt\Break_) { | ||
| return ctor('php:break', unit_const()); | ||
| } | ||
| if ($stmt instanceof \PhpParser\Node\Stmt\Continue_) { | ||
| return ctor('php:continue', unit_const()); |
There was a problem hiding this comment.
Preserve break/continue levels or refuse unsupported forms
This lowering drops the optional numeric level on break/continue (e.g., break 2;), so nested-loop control flow is silently changed instead of being represented or refused. In PHP code that uses multi-level exits, the lifted IR will no longer match source semantics, which can corrupt downstream analysis/rewrites. Please either encode the level in the IR or emit a refusal when $stmt->num is present.
Useful? React with 👍 / 👎.
| 'php:while' => new \PhpParser\Node\Stmt\While_($this->exprNode($args[0]), $this->stmtNodes($args[1])), | ||
| 'php:echo' => new \PhpParser\Node\Stmt\Echo_([$this->exprNode($args[0])]), | ||
| 'php:throw' => new \PhpParser\Node\Stmt\Throw_($this->exprNode($args[0])), | ||
| default => new \PhpParser\Node\Stmt\Expression($this->exprNode($term)), |
There was a problem hiding this comment.
Handle lifted statement ops in compiler instead of expr fallback
The compiler's statement switch only handles a small subset, then falls back to Expression($this->exprNode($term)). However the lifter emits statement operators like php:for, php:dowhile, php:foreach, php:break, and php:continue that are not valid expression ops in exprNode, so compiling valid lifted IR can throw InvalidArgumentException. This makes compile fail for accepted PHP programs once source-unit passthrough is unavailable (e.g., transformed/body-only IR).
Useful? React with 👍 / 👎.
Review: PR #600 —
|
| # | Item | Status | Note |
|---|---|---|---|
| 1 | php: prefix on every op; no php:binop/php:unknown/php:skip; ==≠===, .≠+ |
PASS | ctor() enforces prefix + bans the three catch-alls (Ir.php:64-72); php:eq/php:identical/php:ne/php:not_identical/php:concat all distinct (lowerBinaryOp) |
| 2 | arity_shape on every op, sane; short-circuit RHS / ternary / ?? mark evaluation:"unevaluated"; mirrors csharp |
PASS | op_and/op_or/op_nullcoalesce slot[1] unevaluated; op_ternary slots 1,2 unevaluated; op_seq positional arity 2; op_assign named target/value; op_call/op_methodcall args slot shape:{kind:set} |
| 3 | php:source-unit(bytes, operational_term) present AND emitted carrying full file bytes |
PASS | op_source-unit.spec.json; source_unit_contract($path, $sourceBytes, …) uses raw file_get_contents/$source incl. <?php prologue + inline HTML (InlineHTML is skipped from the term but the bytes are intact) |
| 4 | Refuse-not-fake for unhandled AST: closures/arrow-fns, generators, try/catch, switch/match, refs, variadic/named/byref args, list(), $$x, eval/call_user_func, traits, magic methods, instanceof, clone, @, goto |
PASS | Catch-alls: lowerStatement/lowerExpr/lowerTarget/lowerBinaryOp all throw $this->refuse(...); explicit refusals for byref returns/params, variadic, default params, named/unpack/byref args, variable-variables, dynamic calls/props/classes, traits, __* magic methods, anon classes, eval/call_user_func; Yield_/Closure/ArrowFunction/TryCatch/Switch_/Match_/List_/Instanceof_/Clone_/ErrorSuppress/Goto_ all fall through to the nodeKind catch-all refusal (no silent skip) |
| 5 | fnName provably unique — ns\fn, ns\Class::method |
PASS | qualifyFunctionName + :: for methods; <source-unit:path> uses <> (illegal in real PHP names); PHP has no overloading, no static-vs-instance same-name |
| 6 | Effects on canonical wire shapes, sorted by sort_key() incl. secondary sort; no alloc/resolved-call |
PASS | EffectSet: reads/writes w/ target, io, panics, unresolved_call w/ name, opaque_loop w/ loopCid:"blake3-512:…"; sortKey = "0:reads:…"…"6:opaque_loop:…" matching the Java/Swift Effect::sort_key; loops (while/do/for/foreach) → opaque_loop; echo/print/file_*/curl_*/printf/header/fopen/fread/fwrite/readfile → io; throw/exit/die + trigger_error(…,E_USER_ERROR) → panics; no alloc, calls are unresolved_call not resolved call |
| 7 | Round-trip lift(compile(lift(src))) byte/CID-identity driving the real PrettyPrinter, not the byte-copy fast-path |
PASS (with caveat) | test_compile_lift_roundtrip_body_term_is_byte_identical lifts f, calls compileBodyTerm (→ PrettyPrinter in CI), re-lifts, asserts Jcs::encode($body) === Jcs::encode($reliftedBody). Drives the real compiler. Caveat = finding #1: the document-level compileIrDocument is byte-copy, so lift(compile(lift(src))) at doc level is trivially identical via copy |
| 8 | Determinism | PASS | EffectSet dedups by JCS key + sorts; liftPaths sorts files SORT_STRING; fold_seq deterministic left-fold; no timestamps |
| 9 | CID-correctness — reuses provekit-ir-symbolic's canonicalizer/BLAKE3, not rolled-own |
PASS | Ir.php / EffectSet.php use ProvekIt\Canonicalizer\Jcs + Blake3 (the existing classes, bootstrap.php requires them directly); cid_of_json = 'blake3-512:' . Blake3::hash(Jcs::encode(...)). No new JCS/BLAKE3 — Supra omnia, rectum satisfied |
| 10 | Wiring — composer adds nikic/php-parser; existing php manifest not repointed; new php-source manifest w/ working command + version 0.1.0-draft; no .provekit/ci/accepted/self-contract changes; no php-language-signature entry in menagerie/manifest.yaml |
PASS | composer.json adds "nikic/php-parser": "^5.0" + ProvekIt\\LiftPhpSource\\ autoload + test script entry; implementations/php/.provekit/lift/php/manifest.toml untouched (empty diff); new php-source/manifest.toml → command = ["php","provekit-lift-php-source/bin/main.php","--rpc"], version 0.1.0-draft; no accepted/self-contract diffs; menagerie/manifest.yaml diff empty (matches csharp-language-signature which also has no entry) |
| 11 | Existing PHP project still builds/tests | UNVERIFIED LOCALLY | no composer in sandbox per task note. composer wiring is plausible — only additive (new autoload key, new require, new test script line); CI composer install && composer test is the verifier |
| 12 | --rpc server initialize/lift/compile/shutdown match the lift-plugin protocol; initialize reports version 0.1.0-draft, dialect php-source |
PASS | Rpc.php: initialize → {name, version:"0.1.0-draft", protocol_version:"provekit-lift/1", dialect:"php-source", capabilities:{authoring_surfaces:["php-source"], ir_version:"v1.1.0", emits_signed_mementos:false}} — mirrors SwiftSourceRPC.initializeResult(); lift checks surface, returns ir-document; compile returns compiled-formula; shutdown → null; line-delimited JSON-RPC 2.0; test_initialize_declares_php_source_draft covers it |
| 13 | cargo test -p provekit-bug-zoo --test smoke still passes with new php-source surface |
N/A IN THIS WORKTREE | no provekit-bug-zoo crate exists in implementations/rust/ on this branch — item stale. The only Rust change is KNOWN_SURFACES += "php-source" in provekit-cli/src/project_config.rs plus its unit-test assertion — clean and minimal |
The one thing to look at first
Finding #1 — confirm with the maintainer that the compile RPC returning byte-copied source for a real lifted document is the intended PHP design (vs #590's term-in / compile-out). If a future caller mutates IR and round-trips through compile, they get stale bytes. Not a blocker; a follow-up issue at most.
Comparison to #590's bar
Meets it. Same shape: self-hosted lifter + IR↔source compiler + --rpc JSON-RPC server + 0.1.0-draft manifest + a *-language-signature menagerie (68 specs) + KNOWN_SURFACES registration, no menagerie/manifest.yaml entry, no self-contract pins. PHP refuses more aggressively than csharp (every unhandled node → Refusal{kind,function,line,reason}), which is the right instinct. The two deltas from #590: (a) the byte-copy compile fast-path (finding #1), (b) the token-fallback second lifter for composer-less environments (finding #5) — csharp has no analog because dotnet is always present. Neither is disqualifying.
— reviewed against origin/main...d973584, worktree /tmp/pk-600-review.
There was a problem hiding this comment.
Pull request overview
Adds a self-hosted PHP source lift kit (php-source) and a corresponding PHP language-signature menagerie catalog, mirroring the existing pattern for other source lifters (RPC initialize/lift/compile, lossless php:source-unit, deterministic signatures/specs, and unit tests).
Changes:
- Introduces
implementations/php/provekit-lift-php-source(RPC server, lifter, compiler, effects tracking) plus a PHP test suite. - Adds
menagerie/php-language-signature/with sorts/ops/effects/effect-signatures and alanguage_signature_phpindex. - Wires the new surface into the Rust CLI (
KNOWN_SURFACES) and adds amake test-phptarget + Composer dependency onnikic/php-parser.
Reviewed changes
Copilot reviewed 81 out of 82 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| Makefile | Adds test-php target and help text entry. |
| implementations/rust/provekit-cli/src/project_config.rs | Registers php-source as a known surface and asserts it in tests. |
| implementations/php/composer.json | Adds PHP-parser dependency and php-source test script; adds PSR-4 mapping for the new kit. |
| implementations/php/.provekit/lift/php-source/manifest.toml | Declares the php-source lift surface manifest (RPC command + capabilities). |
| implementations/php/provekit-lift-php-source/bin/main.php | RPC entrypoint (--rpc required). |
| implementations/php/provekit-lift-php-source/src/bootstrap.php | Bootstraps vendor autoload + local includes for the kit. |
| implementations/php/provekit-lift-php-source/src/EffectSet.php | Canonical/deduped effect collection + deterministic sorting. |
| implementations/php/provekit-lift-php-source/src/Ir.php | IR helpers + function-contract/source-unit contract constructors + CID helpers. |
| implementations/php/provekit-lift-php-source/src/PhpSourceCompiler.php | IR → PHP compilation (php-parser pretty-printer with fallback). |
| implementations/php/provekit-lift-php-source/src/PhpSourceLifter.php | PHP source → IR lifter (php-parser frontend with token fallback). |
| implementations/php/provekit-lift-php-source/src/Rpc.php | JSON-RPC dispatcher implementing initialize/lift/compile/shutdown. |
| implementations/php/provekit-lift-php-source/tests/PhpSourceLifterTest.php | End-to-end tests for lift/refusals/effects/round-trip/initialize/signature shapes. |
| menagerie/php-language-signature/README.md | Describes the PHP language signature scope and intent. |
| menagerie/php-language-signature/generate_assets.php | Deterministic generator for all PHP language-signature spec assets. |
| menagerie/php-language-signature/specs/eff_io.spec.json | Effect op spec: IO. |
| menagerie/php-language-signature/specs/eff_opaque_loop.spec.json | Effect op spec: opaque loop. |
| menagerie/php-language-signature/specs/eff_panic.spec.json | Effect op spec: panic/termination. |
| menagerie/php-language-signature/specs/eff_read.spec.json | Effect op spec: read. |
| menagerie/php-language-signature/specs/eff_unresolved_call.spec.json | Effect op spec: unresolved call. |
| menagerie/php-language-signature/specs/eff_write.spec.json | Effect op spec: write. |
| menagerie/php-language-signature/specs/effsig_io.spec.json | Effect-signature: Io. |
| menagerie/php-language-signature/specs/effsig_opaque_loop.spec.json | Effect-signature: Loop. |
| menagerie/php-language-signature/specs/effsig_panic.spec.json | Effect-signature: Panic. |
| menagerie/php-language-signature/specs/effsig_read.spec.json | Effect-signature: Read. |
| menagerie/php-language-signature/specs/effsig_unresolved_call.spec.json | Effect-signature: Call. |
| menagerie/php-language-signature/specs/effsig_write.spec.json | Effect-signature: Write. |
| menagerie/php-language-signature/specs/language_signature_php.spec.json | Top-level PHP language signature index (sorts/ops/effects). |
| menagerie/php-language-signature/specs/op_add.spec.json | Op spec: php:add. |
| menagerie/php-language-signature/specs/op_and.spec.json | Op spec: php:and. |
| menagerie/php-language-signature/specs/op_assign.spec.json | Op spec: php:assign. |
| menagerie/php-language-signature/specs/op_bitand.spec.json | Op spec: php:bitand. |
| menagerie/php-language-signature/specs/op_bitnot.spec.json | Op spec: php:bitnot. |
| menagerie/php-language-signature/specs/op_bitor.spec.json | Op spec: php:bitor. |
| menagerie/php-language-signature/specs/op_bitxor.spec.json | Op spec: php:bitxor. |
| menagerie/php-language-signature/specs/op_break.spec.json | Op spec: php:break. |
| menagerie/php-language-signature/specs/op_call.spec.json | Op spec: php:call. |
| menagerie/php-language-signature/specs/op_concat.spec.json | Op spec: php:concat. |
| menagerie/php-language-signature/specs/op_continue.spec.json | Op spec: php:continue. |
| menagerie/php-language-signature/specs/op_div.spec.json | Op spec: php:div. |
| menagerie/php-language-signature/specs/op_dowhile.spec.json | Op spec: php:dowhile. |
| menagerie/php-language-signature/specs/op_echo.spec.json | Op spec: php:echo. |
| menagerie/php-language-signature/specs/op_eq.spec.json | Op spec: php:eq. |
| menagerie/php-language-signature/specs/op_exit.spec.json | Op spec: php:exit. |
| menagerie/php-language-signature/specs/op_for.spec.json | Op spec: php:for. |
| menagerie/php-language-signature/specs/op_foreach.spec.json | Op spec: php:foreach. |
| menagerie/php-language-signature/specs/op_ge.spec.json | Op spec: php:ge. |
| menagerie/php-language-signature/specs/op_gt.spec.json | Op spec: php:gt. |
| menagerie/php-language-signature/specs/op_identical.spec.json | Op spec: php:identical. |
| menagerie/php-language-signature/specs/op_if.spec.json | Op spec: php:if. |
| menagerie/php-language-signature/specs/op_index.spec.json | Op spec: php:index. |
| menagerie/php-language-signature/specs/op_le.spec.json | Op spec: php:le. |
| menagerie/php-language-signature/specs/op_lt.spec.json | Op spec: php:lt. |
| menagerie/php-language-signature/specs/op_methodcall.spec.json | Op spec: php:methodcall. |
| menagerie/php-language-signature/specs/op_mod.spec.json | Op spec: php:mod. |
| menagerie/php-language-signature/specs/op_mul.spec.json | Op spec: php:mul. |
| menagerie/php-language-signature/specs/op_ne.spec.json | Op spec: php:ne. |
| menagerie/php-language-signature/specs/op_neg.spec.json | Op spec: php:neg. |
| menagerie/php-language-signature/specs/op_not_identical.spec.json | Op spec: php:not_identical. |
| menagerie/php-language-signature/specs/op_not.spec.json | Op spec: php:not. |
| menagerie/php-language-signature/specs/op_nullcoalesce.spec.json | Op spec: php:nullcoalesce. |
| menagerie/php-language-signature/specs/op_or.spec.json | Op spec: php:or. |
| menagerie/php-language-signature/specs/op_pos.spec.json | Op spec: php:pos. |
| menagerie/php-language-signature/specs/op_print.spec.json | Op spec: php:print. |
| menagerie/php-language-signature/specs/op_propfetch.spec.json | Op spec: php:propfetch. |
| menagerie/php-language-signature/specs/op_return.spec.json | Op spec: php:return. |
| menagerie/php-language-signature/specs/op_seq.spec.json | Op spec: php:seq. |
| menagerie/php-language-signature/specs/op_shl.spec.json | Op spec: php:shl. |
| menagerie/php-language-signature/specs/op_shr.spec.json | Op spec: php:shr. |
| menagerie/php-language-signature/specs/op_source-unit.spec.json | Op spec: php:source-unit. |
| menagerie/php-language-signature/specs/op_staticcall.spec.json | Op spec: php:staticcall. |
| menagerie/php-language-signature/specs/op_staticprop.spec.json | Op spec: php:staticprop. |
| menagerie/php-language-signature/specs/op_sub.spec.json | Op spec: php:sub. |
| menagerie/php-language-signature/specs/op_ternary.spec.json | Op spec: php:ternary. |
| menagerie/php-language-signature/specs/op_throw.spec.json | Op spec: php:throw. |
| menagerie/php-language-signature/specs/op_while.spec.json | Op spec: php:while. |
| menagerie/php-language-signature/specs/sort_bool.spec.json | Sort spec: Bool. |
| menagerie/php-language-signature/specs/sort_int.spec.json | Sort spec: Int. |
| menagerie/php-language-signature/specs/sort_real.spec.json | Sort spec: Real. |
| menagerie/php-language-signature/specs/sort_stmt.spec.json | Sort spec: Stmt. |
| menagerie/php-language-signature/specs/sort_string.spec.json | Sort spec: String. |
| menagerie/php-language-signature/specs/sort_unit.spec.json | Sort spec: Unit. |
| menagerie/php-language-signature/specs/sort_value.spec.json | Sort spec: Value. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| $parent = is_dir($candidate) ? $candidate : dirname($candidate); | ||
| $realParent = realpath($parent); | ||
| if ($realParent === false) { | ||
| return null; | ||
| } | ||
| $resolved = $realParent . DIRECTORY_SEPARATOR . basename($candidate); |
| $fileResult = $this->liftSource($source, $file); | ||
| $result['ir'] = array_merge($result['ir'], $fileResult['ir']); |
| } catch (\JsonException $e) { | ||
| write_rpc(error_response(null, -32700, 'PARSE_ERROR: ' . $e->getMessage())); | ||
| } catch (\Throwable $e) { | ||
| write_rpc(error_response($request['id'] ?? null, -32603, $e->getMessage())); | ||
| } |
| private function targetNode(array $term): object | ||
| { | ||
| $node = $this->exprNode($term); | ||
| return $node; | ||
| } |
| "psr-4": { | ||
| "Provekit\\Ir\\": "provekit-ir-symbolic/src/Ir/", | ||
| "Provekit\\Canonicalizer\\": "provekit-ir-symbolic/src/Canonicalizer/", | ||
| "Provekit\\ClaimEnvelope\\": "provekit-ir-symbolic/src/ClaimEnvelope/", | ||
| "Provekit\\ProofEnvelope\\": "provekit-ir-symbolic/src/ProofEnvelope/", | ||
| "Provekit\\SelfContracts\\": "provekit-self-contracts/slabs/" | ||
| "Provekit\\SelfContracts\\": "provekit-self-contracts/slabs/", | ||
| "ProvekIt\\LiftPhpSource\\": "provekit-lift-php-source/src/" | ||
| } |
…ture menagerie A self-hosted PHP source-language lift kit, mirroring PR #590 (the C# source lifter) and the merged Go/Python/TypeScript/Zig lifters: a PHP program using nikic/php-parser that lifts PHP function definitions into ProvekIt function-contract mementos over a php:-namespaced operation algebra, plus menagerie/php-language-signature/, plus a round-trip compiler. Built to the conventions the C#/Go/Java/Python/TS/Zig review rounds settled: namespaced op CIDs, arity_shape on every op spec, a php:source-unit lossless wrapper actually emitted, loud Refusals for unhandled syntax (no php:unknown/skip catch-all), provably-unique qualified fnName, effects on the canonical Effect wire shapes sorted by sort_key(), BLAKE3/JCS loop CIDs via the existing per-language canonicalizer (not a rolled-own one), a lift(compile(lift(src))) round-trip test driving the real IR->source compiler path (not just the source-unit byte-copy fast-path), deterministic JSON, version 0.1.0-draft. The existing php kit surface manifest is untouched; the source lifter gets its own php-source surface. PHP unit tests pass; signature generator deterministic; RPC initialize reports 0.1.0-draft/php-source; composer install couldn't run locally (no composer in sandbox) — CI verifies the php-parser-dependent compiler path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
d973584 to
8dc3828
Compare
…#596/#598/#599/#600 Per-kit changes: - rust/provekit-cli: extend KNOWN_SURFACES anchor test to assert ruby-source, csharp-source, swift-source, zig-source are all registered (were in the array, not in the test) - Makefile: wire test-ruby and test-php into test-all so the new lift kits run under ci (boy-scout -- flagged in #598 review) - typescript-language-signature/mint.sh: replace find with explicit enumeration to match c11/rust pattern and remove portability footgun (PR #595 nit #3) - ruby/ruby_source.rb: add instance_variable_get, instance_variable_set, const_get, const_set to METAPROGRAMMING_CALLS (PR #598 nit #4) - php/PhpSourceCompiler.php: simplify isUnit() to remove precedence-reliant double-condition (PR #600 nit #2) Already swept on origin/main (codex/lift-kit-nits-cleanup, empty cherry-picks confirmed): - effect sort-key alignment: 5:unresolved_call -> 5:unresolved: (ruby + swift) - csharp-source backfill in KNOWN_SURFACES - swift: emit Refusal for unparseable function signatures + ThrowStmt API fix Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…#596/#598/#599/#600 Per-kit changes: - rust/provekit-cli: extend KNOWN_SURFACES anchor test to assert ruby-source, csharp-source, swift-source, zig-source are all registered (were in the array, not in the test) - Makefile: wire test-ruby and test-php into test-all so the new lift kits run under ci (boy-scout -- flagged in #598 review) - typescript-language-signature/mint.sh: replace find with explicit enumeration to match c11/rust pattern and remove portability footgun (PR #595 nit #3) - ruby/ruby_source.rb: add instance_variable_get, instance_variable_set, const_get, const_set to METAPROGRAMMING_CALLS (PR #598 nit #4) - php/PhpSourceCompiler.php: simplify isUnit() to remove precedence-reliant double-condition (PR #600 nit #2) Already swept on origin/main (codex/lift-kit-nits-cleanup, empty cherry-picks confirmed): - effect sort-key alignment: 5:unresolved_call -> 5:unresolved: (ruby + swift) - csharp-source backfill in KNOWN_SURFACES - swift: emit Refusal for unparseable function signatures + ThrowStmt API fix Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…599/#600 (#632) * chore(lift-kits): sweep accumulated MERGE-WITH-NITS nits from PRs #595/#596/#598/#599/#600 Per-kit changes: - rust/provekit-cli: extend KNOWN_SURFACES anchor test to assert ruby-source, csharp-source, swift-source, zig-source are all registered (were in the array, not in the test) - Makefile: wire test-ruby and test-php into test-all so the new lift kits run under ci (boy-scout -- flagged in #598 review) - typescript-language-signature/mint.sh: replace find with explicit enumeration to match c11/rust pattern and remove portability footgun (PR #595 nit #3) - ruby/ruby_source.rb: add instance_variable_get, instance_variable_set, const_get, const_set to METAPROGRAMMING_CALLS (PR #598 nit #4) - php/PhpSourceCompiler.php: simplify isUnit() to remove precedence-reliant double-condition (PR #600 nit #2) Already swept on origin/main (codex/lift-kit-nits-cleanup, empty cherry-picks confirmed): - effect sort-key alignment: 5:unresolved_call -> 5:unresolved: (ruby + swift) - csharp-source backfill in KNOWN_SURFACES - swift: emit Refusal for unparseable function signatures + ThrowStmt API fix Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ruby-language-signature): regen op_source-unit.spec.json with notes field The generator `generate_assets.py` was updated to emit a `notes` field on the `source-unit` op spec but the committed file was never regenerated. CI gate at Makefile:606 (`generate_assets.py --check`) caught the staleness. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: add composer to conformance job apt block (fixes test-php exit 127) test-php runs `composer install && composer test`; the conformance job installed php-cli but never composer, so the command was not found. Adds the `composer` Ubuntu apt package to the shared system-deps step so make test-all (and make ci) can reach it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Self-hosted PHP source-language lift kit +
menagerie/php-language-signature/. Mirrors PR #590 (the C# source lifter) and the merged Go/Python/TS/Zig lifters.function-contractmementos overphp:-namespaced opsphp:source-unitlossless wrapper; round-tripcompile+ alift(compile(lift(src)))test driving the real IR→source path (not the source-unit byte-copy fast-path)arity_shapeon every op spec;Refusals (not fakes) for unhandled syntax; effects on the canonicalEffectwire shapes, sorted; loop CIDs via the existing canonicalizer (not rolled-own)php-sourcelift surface (existingphpkit surface manifest untouched — the feat(csharp): add C# language lifter with RPC protocol and menagerie signature #590 lesson);version 0.1.0-draft; nomenagerie/manifest.yamlentry (the recurring nit —*-language-signaturecatalogs don't belong in that destinations list)🤖 Generated with Claude Code