Skip to content

feat(zig): add Zig source lift kit (self-hosted) + zig-language-signature#596

Merged
TSavo merged 2 commits into
mainfrom
codex/zig-source-lift-kit
May 11, 2026
Merged

feat(zig): add Zig source lift kit (self-hosted) + zig-language-signature#596
TSavo merged 2 commits into
mainfrom
codex/zig-source-lift-kit

Conversation

@TSavo
Copy link
Copy Markdown
Owner

@TSavo TSavo commented May 11, 2026

Self-hosted Zig source-language lift kit + menagerie/zig-language-signature/. Mirrors PR #590 (the C# source lifter).

  • Zig lifter via std.zig.Astfunction-contract mementos over zig:-namespaced ops
  • per-file zig:source-unit lossless wrapper; round-trip compile + a lift(compile(lift(src))) test
  • arity_shape on every op spec; Refusals (not fakes) for comptime/error-unions/try-catch/defer/async/inline-for/switch/@-builtins; effects on the canonical Effect wire shapes, sorted; BLAKE3/JCS loop CIDs
  • new zig-source lift surface (existing zig kit surface manifest provekit-lift-zig untouched — the lesson from feat(csharp): add C# language lifter with RPC protocol and menagerie signature #590); version 0.1.0-draft
  • make test-zig + zig build test pass

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings May 11, 2026 14:53
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

Warning

Rate limit exceeded

@TSavo has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minute and 9 seconds before requesting another review.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9e0f79a8-6fcb-472e-8470-7e1c1ffa28f7

📥 Commits

Reviewing files that changed from the base of the PR and between 5b2f45b and ac38549.

📒 Files selected for processing (77)
  • Makefile
  • implementations/rust/provekit-cli/src/project_config.rs
  • implementations/zig/.provekit/lift/zig-source/manifest.toml
  • implementations/zig/provekit-lift-zig-source/build.zig
  • implementations/zig/provekit-lift-zig-source/build.zig.zon
  • implementations/zig/provekit-lift-zig-source/src/lift.zig
  • implementations/zig/provekit-lift-zig-source/src/main.zig
  • menagerie/zig-language-signature/README.md
  • menagerie/zig-language-signature/generate_assets.py
  • menagerie/zig-language-signature/specs/effsig_io.spec.json
  • menagerie/zig-language-signature/specs/effsig_opaque_loop.spec.json
  • menagerie/zig-language-signature/specs/effsig_panic.spec.json
  • menagerie/zig-language-signature/specs/effsig_read.spec.json
  • menagerie/zig-language-signature/specs/effsig_unresolved_call.spec.json
  • menagerie/zig-language-signature/specs/effsig_unsafe.spec.json
  • menagerie/zig-language-signature/specs/effsig_write.spec.json
  • menagerie/zig-language-signature/specs/eq_and_false.spec.json
  • menagerie/zig-language-signature/specs/eq_and_true.spec.json
  • menagerie/zig-language-signature/specs/eq_or_false.spec.json
  • menagerie/zig-language-signature/specs/eq_or_true.spec.json
  • menagerie/zig-language-signature/specs/eq_seq_assoc.spec.json
  • menagerie/zig-language-signature/specs/eq_seq_skip_left.spec.json
  • menagerie/zig-language-signature/specs/eq_seq_skip_right.spec.json
  • menagerie/zig-language-signature/specs/language_signature_zig.spec.json
  • menagerie/zig-language-signature/specs/op_add.spec.json
  • menagerie/zig-language-signature/specs/op_addr.spec.json
  • menagerie/zig-language-signature/specs/op_and.spec.json
  • menagerie/zig-language-signature/specs/op_assign.spec.json
  • menagerie/zig-language-signature/specs/op_bitand.spec.json
  • menagerie/zig-language-signature/specs/op_bitnot.spec.json
  • menagerie/zig-language-signature/specs/op_bitor.spec.json
  • menagerie/zig-language-signature/specs/op_bitxor.spec.json
  • menagerie/zig-language-signature/specs/op_break.spec.json
  • menagerie/zig-language-signature/specs/op_call.spec.json
  • menagerie/zig-language-signature/specs/op_cast.spec.json
  • menagerie/zig-language-signature/specs/op_continue.spec.json
  • menagerie/zig-language-signature/specs/op_decl.spec.json
  • menagerie/zig-language-signature/specs/op_deref.spec.json
  • menagerie/zig-language-signature/specs/op_div.spec.json
  • menagerie/zig-language-signature/specs/op_eq.spec.json
  • menagerie/zig-language-signature/specs/op_field.spec.json
  • menagerie/zig-language-signature/specs/op_for.spec.json
  • menagerie/zig-language-signature/specs/op_ge.spec.json
  • menagerie/zig-language-signature/specs/op_gt.spec.json
  • menagerie/zig-language-signature/specs/op_if.spec.json
  • menagerie/zig-language-signature/specs/op_index.spec.json
  • menagerie/zig-language-signature/specs/op_le.spec.json
  • menagerie/zig-language-signature/specs/op_lt.spec.json
  • menagerie/zig-language-signature/specs/op_mod.spec.json
  • menagerie/zig-language-signature/specs/op_mul.spec.json
  • menagerie/zig-language-signature/specs/op_ne.spec.json
  • menagerie/zig-language-signature/specs/op_neg.spec.json
  • menagerie/zig-language-signature/specs/op_not.spec.json
  • menagerie/zig-language-signature/specs/op_or.spec.json
  • menagerie/zig-language-signature/specs/op_panic.spec.json
  • menagerie/zig-language-signature/specs/op_return.spec.json
  • menagerie/zig-language-signature/specs/op_seq.spec.json
  • menagerie/zig-language-signature/specs/op_shl.spec.json
  • menagerie/zig-language-signature/specs/op_shr.spec.json
  • menagerie/zig-language-signature/specs/op_skip.spec.json
  • menagerie/zig-language-signature/specs/op_source-unit.spec.json
  • menagerie/zig-language-signature/specs/op_sub.spec.json
  • menagerie/zig-language-signature/specs/op_unit.spec.json
  • menagerie/zig-language-signature/specs/op_unreachable.spec.json
  • menagerie/zig-language-signature/specs/op_while.spec.json
  • menagerie/zig-language-signature/specs/sort_bool.spec.json
  • menagerie/zig-language-signature/specs/sort_bottom.spec.json
  • menagerie/zig-language-signature/specs/sort_expr.spec.json
  • menagerie/zig-language-signature/specs/sort_fieldname.spec.json
  • menagerie/zig-language-signature/specs/sort_int.spec.json
  • menagerie/zig-language-signature/specs/sort_listofexpr.spec.json
  • menagerie/zig-language-signature/specs/sort_lvalue.spec.json
  • menagerie/zig-language-signature/specs/sort_ptr.spec.json
  • menagerie/zig-language-signature/specs/sort_reason.spec.json
  • menagerie/zig-language-signature/specs/sort_stmt.spec.json
  • menagerie/zig-language-signature/specs/sort_string.spec.json
  • menagerie/zig-language-signature/specs/sort_unit.spec.json
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/zig-source-lift-kit

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 and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee631639c3

ℹ️ 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".

Comment on lines +266 to +267
try appendUniqueString(self.alloc, &self.known_functions, name);
try appendUniqueString(self.alloc, &self.known_functions, qualified);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Record namespace-only names for known functions

Calls to functions declared inside containers are misclassified as unresolved because exprName produces callees like Ns.func, but the known-function table only stores func and path.Ns.func. In a file with const Ns = struct { pub fn f() ... }, a call Ns.f() will incorrectly add an unresolved_call effect, which pollutes effect summaries and downstream memento requirements.

Useful? React with 👍 / 👎.


fn emitString(self: *Lifter, node: Node.Index) !provekit.Term {
const raw = self.tree.getNodeSource(node);
if (raw.len >= 2 and raw[0] == '"' and raw[raw.len - 1] == '"') return provekit.Str(raw[1 .. raw.len - 1]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Decode string literal escapes before building term constants

String literals are stored as raw token text without unescaping, so escape sequences like "\n" are represented as backslash+n instead of a newline character. This changes literal semantics in lifted IR and also breaks compile/lift round-tripping for escaped strings because recompilation escapes the backslashes again.

Useful? React with 👍 / 👎.


fn zigTypeForSort(sort: provekit.Sort) []const u8 {
return switch (sort) {
.primitive => |name| if (std.mem.eql(u8, name, "Bool")) "bool" else if (std.mem.eql(u8, name, "Unit")) "void" else if (std.mem.eql(u8, name, "String")) "[]const u8" else "i32",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Map Ptr sort to a pointer type when recompiling contracts

Recompilation falls back to i32 for any primitive sort other than Bool/Unit/String, which includes Ptr produced by sortFromType for pointer parameters and returns. This makes generated Zig invalid or type-changed for pointer-using functions (e.g., emitted i32 with later .* dereference), so compile/lift round-trips fail on valid lifted inputs.

Useful? React with 👍 / 👎.

@TSavo
Copy link
Copy Markdown
Owner Author

TSavo commented May 11, 2026

Review: PR #596 — Zig source lift kit (self-hosted)

Verdict: MERGE-WITH-NITS — the kit is structurally sound, reuses the existing Zig canonicalizer/BLAKE3 (not a re-roll), refuses unhandled AST node tags loudly rather than faking ops, builds and tests clean; the nits are draft-grade gaps (string-escape fidelity, lift/compile surface asymmetry) that should be tracked before any non-draft promotion.

The one thing to look at first

CID-correctness (item 9): confirmed good. lift.zig imports provekit-ir and routes every canonical-bytes/CID call through provekit.jcsStringify / provekit.jcsHash (addOpaqueLoop, canonicalTermBytes, the tests). It does not roll its own JCS or BLAKE3 — loopCid values are blake3-512:... from the same module the rest of the Zig kit uses. zig build test for provekit-ir, provekit-lift-zig, and provekit-lift-zig-source all pass on zig 0.16.0. No Supra omnia, rectum stop.

Blocking findings

None.

Non-blocking findings (track before promoting past 0.1.0-draft)

  1. String literals are lifted without unescapinglift.zig:495-499 (emitString) strips the outer "/" but leaves the inner bytes verbatim. So source "oops\n" becomes Str("oops\n") with a literal backslash-n, i.e. the canonical term — and therefore its CID — misrepresents the runtime string value. No test exercises an escaped string literal, so the round-trip test doesn't catch it. Also asymmetric: compileContract re-escapes on the way out (appendEscapedString, line 951), so even a plain "\\"-containing literal won't round-trip. Fix: unescape on lift (and unescape-not-re-escape on compile), or refuse any string literal containing \. Concrete instance of the exact failure shape that contaminates downstream predicates.

  2. lift surface is wider than the compile surface — the lifter emits zig:for, zig:break, zig:continue (and zig:panic), but emitTermAsStmt/emitTermAsExpr (lift.zig:797-927) handle none of them; they fall through to the literal "unreachable" default. compileContract on any function with a for loop or break/continue produces broken Zig. The round-trip test (lift.zig:1107) only uses a single add example, which camouflages this. Either widen compileContract or have it refuse terms it can't render.

  3. options.layer / identify-only ignoredmain.zig:62 substring-matches "lift" and always runs the proof-producing path; per protocol/specs/2026-04-30-lift-plugin-protocol.md a plugin that doesn't implement identify-only MAY return error 1006. Note this is the same pattern the existing provekit-lift-zig already uses (provekit-lift-zig/src/main.zig), so it's a kit-wide gap, not a regression — flagging for the eventual sweep, not for this PR.

  4. ir-document carries extra fields — the lift response emits callEdges/opacityReport/refusals alongside kind/ir; the ir-document grammar in the spec doesn't list a * text => json-value wildcard (unlike identity-document). The Rust CLI extracts fields by name so it's harmless in practice, and provekit-lift-zig does the analogous thing (implications). Cosmetic.

  5. <source-unit:input.zig> fnName collision risk in source-mode RPC — when lifting via {"source":...} with no path, path defaults to "input.zig", so two such calls in one session produce colliding fnNames. Same shape as the other lifters; the angle-bracket form keeps it distinct from real functions; not introduced here.

Conformance checklist

# Item Status Note
1 zig: prefix on every op, no binop/unknown catch-all PASS All 41 op_*.spec.json fn_names are zig:*; lifter's emitExpr else-branch is refuseFmt(... "unhandled Zig AST node tag"), not a synthesized op
2 arity_shape present & sane on every op PASS binops named lhs/rhs; zig:seq/zig:unit/zig:unreachable positional; zig:assign named target/value; zig:and/zig:or mark rhs evaluation:"unevaluated"; mirrors the c11/csharp op-spec shape
3 zig:source-unit(bytes, operational_term) present AND emitted with real bytes PASS op_source-unit.spec.json has the right shape; sourceUnitContract (lift.zig:611) emits zig:source-unit(Str(self.source), operational); verified via RPC the bytes are the verbatim source
4 Refuse-not-fake for unhandled AST tags (comptime/error-union/try/catch/errdefer/defer/suspend/resume/inline loops/switch/optional/@-builtins/anon structs/generics) PASS All explicitly enumerated in emitStmt/emitExpr/sortFromType/emitFunction with structured Refusal{kind,function,line,reason}; AST-only, no Sema import; comptime params and anytype refused as unsupported-generic
5 fnName provably unique PASS (with caveat 5 above) qualifiedName = path + namespace chain + name; no overloading in Zig; parse-error path returns empty declarations, no colliding fallback
6 Effects on canonical wire shapes, sorted by sort_key() PASS Effect union = reads/writes/io/unsafe/panics/unresolved_call/opaque_loop with rank 0-6; Effect.lessThan does primary rank then secondary (std.mem.lessThan on target/name/cid); sorted via std.mem.sort before emission; no alloc, no resolved-call; opaque_loop.loopCid is blake3-512:...; unsafe is defined in the signature but not yet emitted by the lifter (acceptable for draft)
7 Round-trip lift(compile(lift(src))) byte/CID-identity, drives the real compiler PASS (narrow) lift.zig:1107 checks canonicalTermBytes(bodyTerm()) equality through compileContract → real Ast.parse; compileContract renders actual Zig from the term (return (x + y);), no zig:source-unit byte-copy fast-path → the Go/Python/TS tautology nit does not apply. But the test covers only add; see non-blocking #2
8 Determinism — stable key order, no HashMap iteration leak, no timestamps PASS ArrayList throughout; custom jsonStringify impls emit keys alphabetically; canonical bytes via provekit.jcsStringify; no AutoHashMap/StringHashMap; generate_assets.py re-run reproduces all 77 spec files byte-identically (git clean)
9 CID-correctness — reuses existing canonicalizer + BLAKE3 PASS See "the one thing to look at first"
10 Wiring — existing zig manifest not repointed; new zig-source surface manifest; version 0.1.0-draft; no .provekit/ci/accepted changes; no zig-language-signature in menagerie/manifest.yaml PASS git diff shows existing implementations/zig/.provekit/lift/zig/manifest.toml untouched; new .provekit/lift/zig-source/manifest.toml with command = ["zig","build","run","--","--rpc"], working_dir = "provekit-lift-zig-source", version 0.1.0-draft; build.zig produces a provekit-lift-zig-source executable + a run step; zero ci//accepted//self-contract changes; grep language-signature menagerie/manifest.yaml → no match (clean); KNOWN_SURFACES in provekit-cli/src/project_config.rs gains "zig-source" next to clr-bytecode (same pattern as #590)
11 Existing Zig kit still builds PASS provekit-lift-zig zig build test and provekit-ir zig build test both green; Makefile's test-zig/build-zig extended (not replaced) to add provekit-lift-zig-source
12 --rpc initialize/lift/shutdown match the lift-plugin protocol PASS (with #4) initialize returns name/version/protocol_version: "provekit-lift/1"/capabilities{authoring_surfaces,emits_signed_mementos,ir_version}; lift returns kind:"ir-document" + ir array; shutdown returns result:null; no compile RPC method (correct — the protocol has none; compileContract is internal-only for the round-trip test)

Comparison to #590's bar

Meets it. Same shape as the CLR/csharp kits: separate module (correctly not folded into the annotation-adapter provekit-lift-zig), language-prefixed op algebra with a generated menagerie signature, refuse-don't-fake on anything outside the modeled subset, 0.1.0-draft version, reuses the kit's own canonicalizer. The string-escape gap (#1) is the one item I'd want closed before this surface graduates from draft; #590's reviewers would have weighted the canonicalizer-reuse question highest, and that one is clean.

— review by Claude (Opus 4.7, 1M ctx), worktree build/test on zig 0.16.0

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new self-hosted Zig source lift kit (zig-source) plus a draft Zig language-signature menagerie entry, aligning with the repo’s lift-plugin protocol approach (JSON-RPC over stdio) and the existing “language signature” catalog structure.

Changes:

  • Introduces implementations/zig/provekit-lift-zig-source (RPC entrypoint + AST lifter + unit tests) and registers it as a project-local lift surface (zig-source).
  • Adds menagerie/zig-language-signature/ with generated sort/op/equation/effect-signature specs and a generator script.
  • Extends make test-zig / build-zig and CLI known surfaces to include zig-source.

Reviewed changes

Copilot reviewed 77 out of 77 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
Makefile Adds menagerie generation target and builds/tests the new Zig source lifter as part of Zig CI targets.
implementations/rust/provekit-cli/src/project_config.rs Registers zig-source as a known authoring surface in the CLI.
implementations/zig/.provekit/lift/zig-source/manifest.toml Adds project-local lift-plugin manifest for the new zig-source surface.
implementations/zig/provekit-lift-zig-source/build.zig.zon Declares the new Zig package metadata for provekit-lift-zig-source.
implementations/zig/provekit-lift-zig-source/build.zig Zig build wiring for the lifter module, executable, and unit tests.
implementations/zig/provekit-lift-zig-source/src/main.zig JSON-RPC (lift-plugin protocol) stdin/stdout loop and request handling for initialize/lift/shutdown.
implementations/zig/provekit-lift-zig-source/src/lift.zig Core Zig AST lifter emitting function-contract mementos + effects + compile/roundtrip helpers + tests.
menagerie/zig-language-signature/README.md Documents the draft Zig source algebra and effect vocabulary.
menagerie/zig-language-signature/generate_assets.py Script that generates the Zig language-signature spec JSON assets.
menagerie/zig-language-signature/specs/language_signature_zig.spec.json Top-level Zig language signature catalog referencing sorts/ops/equations/effect signatures.
menagerie/zig-language-signature/specs/sort_bool.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/sort_bottom.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/sort_expr.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/sort_fieldname.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/sort_int.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/sort_listofexpr.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/sort_lvalue.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/sort_ptr.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/sort_reason.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/sort_stmt.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/sort_string.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/sort_unit.spec.json Zig signature sort spec.
menagerie/zig-language-signature/specs/op_add.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_addr.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_and.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_assign.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_bitand.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_bitnot.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_bitor.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_bitxor.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_break.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_call.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_cast.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_continue.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_decl.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_deref.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_div.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_eq.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_field.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_for.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_ge.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_gt.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_if.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_index.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_le.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_lt.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_mod.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_mul.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_ne.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_neg.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_not.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_or.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_panic.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_return.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_seq.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_shl.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_shr.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_skip.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_source-unit.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_sub.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_unit.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_unreachable.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/op_while.spec.json Zig signature operation spec.
menagerie/zig-language-signature/specs/eq_and_false.spec.json Zig signature equation spec.
menagerie/zig-language-signature/specs/eq_and_true.spec.json Zig signature equation spec.
menagerie/zig-language-signature/specs/eq_or_false.spec.json Zig signature equation spec.
menagerie/zig-language-signature/specs/eq_or_true.spec.json Zig signature equation spec.
menagerie/zig-language-signature/specs/eq_seq_assoc.spec.json Zig signature equation spec.
menagerie/zig-language-signature/specs/eq_seq_skip_left.spec.json Zig signature equation spec.
menagerie/zig-language-signature/specs/eq_seq_skip_right.spec.json Zig signature equation spec.
menagerie/zig-language-signature/specs/effsig_io.spec.json Zig effect-signature spec (currently shaped inconsistently with repo minting expectations).
menagerie/zig-language-signature/specs/effsig_opaque_loop.spec.json Zig effect-signature spec (currently shaped inconsistently with repo minting expectations).
menagerie/zig-language-signature/specs/effsig_panic.spec.json Zig effect-signature spec (currently shaped inconsistently with repo minting expectations).
menagerie/zig-language-signature/specs/effsig_read.spec.json Zig effect-signature spec (currently shaped inconsistently with repo minting expectations).
menagerie/zig-language-signature/specs/effsig_unresolved_call.spec.json Zig effect-signature spec (currently shaped inconsistently with repo minting expectations).
menagerie/zig-language-signature/specs/effsig_unsafe.spec.json Zig effect-signature spec (currently shaped inconsistently with repo minting expectations).
menagerie/zig-language-signature/specs/effsig_write.spec.json Zig effect-signature spec (currently shaped inconsistently with repo minting expectations).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2 to +22
"kind": "effect-signature",
"version": "0.1.0-draft",
"fn_name": "zig:effect:IO",
"formals": [],
"return_sort": {
"kind": "ctor",
"name": "Unit",
"args": []
},
"pre": {
"kind": "atomic",
"name": "true",
"args": []
},
"post": {
"kind": "effect-signature-description",
"name": "IO"
},
"effects": {
"effects": []
},
Comment on lines +2 to +22
"kind": "effect-signature",
"version": "0.1.0-draft",
"fn_name": "zig:effect:MemRead",
"formals": [],
"return_sort": {
"kind": "ctor",
"name": "Unit",
"args": []
},
"pre": {
"kind": "atomic",
"name": "true",
"args": []
},
"post": {
"kind": "effect-signature-description",
"name": "MemRead"
},
"effects": {
"effects": []
},
Comment on lines +2 to +22
"kind": "effect-signature",
"version": "0.1.0-draft",
"fn_name": "zig:effect:MemWrite",
"formals": [],
"return_sort": {
"kind": "ctor",
"name": "Unit",
"args": []
},
"pre": {
"kind": "atomic",
"name": "true",
"args": []
},
"post": {
"kind": "effect-signature-description",
"name": "MemWrite"
},
"effects": {
"effects": []
},
Comment on lines +2 to +22
"kind": "effect-signature",
"version": "0.1.0-draft",
"fn_name": "zig:effect:Panic",
"formals": [],
"return_sort": {
"kind": "ctor",
"name": "Unit",
"args": []
},
"pre": {
"kind": "atomic",
"name": "true",
"args": []
},
"post": {
"kind": "effect-signature-description",
"name": "Panic"
},
"effects": {
"effects": []
},
Comment on lines +2 to +22
"kind": "effect-signature",
"version": "0.1.0-draft",
"fn_name": "zig:effect:UnresolvedCall",
"formals": [],
"return_sort": {
"kind": "ctor",
"name": "Unit",
"args": []
},
"pre": {
"kind": "atomic",
"name": "true",
"args": []
},
"post": {
"kind": "effect-signature-description",
"name": "UnresolvedCall"
},
"effects": {
"effects": []
},
Comment on lines +2 to +22
"kind": "effect-signature",
"version": "0.1.0-draft",
"fn_name": "zig:effect:Unsafe",
"formals": [],
"return_sort": {
"kind": "ctor",
"name": "Unit",
"args": []
},
"pre": {
"kind": "atomic",
"name": "true",
"args": []
},
"post": {
"kind": "effect-signature-description",
"name": "Unsafe"
},
"effects": {
"effects": []
},
Comment on lines +2 to +22
"kind": "effect-signature",
"version": "0.1.0-draft",
"fn_name": "zig:effect:OpaqueLoop",
"formals": [],
"return_sort": {
"kind": "ctor",
"name": "Unit",
"args": []
},
"pre": {
"kind": "atomic",
"name": "true",
"args": []
},
"post": {
"kind": "effect-signature-description",
"name": "OpaqueLoop"
},
"effects": {
"effects": []
},
Comment on lines +155 to +168
for key, name in {
"read": "MemRead", "write": "MemWrite", "io": "IO", "unsafe": "Unsafe", "panic": "Panic", "unresolved_call": "UnresolvedCall", "opaque_loop": "OpaqueLoop",
}.items():
write(SPECS / f"effsig_{key}.spec.json", {
"kind": "effect-signature",
"version": VERSION,
"fn_name": f"zig:effect:{name}",
"formals": [],
"return_sort": sort("Unit"),
"pre": true_formula(),
"post": {"kind": "effect-signature-description", "name": name},
"effects": {"effects": []},
"locus": LOCUS,
})
}
if (std.mem.eql(u8, op, "zig:unreachable")) return out.appendSlice(alloc, "unreachable");
if (std.mem.eql(u8, op, "zig:unit")) return out.appendSlice(alloc, "{}");
try out.appendSlice(alloc, "unreachable");
Comment on lines +72 to +80
"effect_signatures": [
"effsig_io.spec.json",
"effsig_opaque_loop.spec.json",
"effsig_panic.spec.json",
"effsig_read.spec.json",
"effsig_unresolved_call.spec.json",
"effsig_unsafe.spec.json",
"effsig_write.spec.json"
],
TSavo added a commit that referenced this pull request May 11, 2026
…ue in the IR-to-Zig compiler

Review nit-fixes for PR #596 (verdict was MERGE-WITH-NITS): (1) emitString refused
to decode escape sequences — a Zig "oops\n" lifted to a Str term with a literal
backslash-n, so the canonical term (and its CID) misrepresented the runtime value;
now any string literal containing \ is refused with Refusal{kind:'unsupported-string-escape'}
rather than lifted wrong (the Supra-omnia-rectum-aligned choice); (2) compileContract
(the IR-to-Zig path) didn't handle zig:for / zig:break / zig:continue (they fell to a
literal "unreachable"), so loop-bearing functions wouldn't round-trip and the single
zig:add round-trip test camouflaged it; now those ops emit the corresponding Zig syntax
and a loop-body canonical-byte round-trip test (via provekit-ir's jcsStringify/jcsHash)
exercises it. make test-zig passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
TSavo and others added 2 commits May 11, 2026 08:52
…ture menagerie

A self-hosted Zig source-language lift kit, mirroring PR #590 (the C# source
lifter): a Zig program using std.zig.Ast that lifts Zig function definitions into
ProvekIt function-contract mementos over a zig:-namespaced operation algebra, plus
menagerie/zig-language-signature/, plus a round-trip compiler. Built to the
conventions #590's review rounds established: namespaced op CIDs, arity_shape on
every op spec, a zig:source-unit lossless wrapper actually emitted, loud Refusals
for unhandled syntax (comptime / error unions / try-catch / defer / async / inline-for
/ switch / @-builtins are refused; no zig:unknown/skip catch-all), provably-unique
qualified fnName, effects on the canonical Effect wire shapes sorted by sort_key(),
BLAKE3/JCS loop CIDs, a lift(compile(lift(src))) round-trip test, version 0.1.0-draft.
The existing zig kit surface manifest (provekit-lift-zig) is untouched; the source
lifter gets its own zig-source surface. make test-zig + zig build test pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ue in the IR-to-Zig compiler

Review nit-fixes for PR #596 (verdict was MERGE-WITH-NITS): (1) emitString refused
to decode escape sequences — a Zig "oops\n" lifted to a Str term with a literal
backslash-n, so the canonical term (and its CID) misrepresented the runtime value;
now any string literal containing \ is refused with Refusal{kind:'unsupported-string-escape'}
rather than lifted wrong (the Supra-omnia-rectum-aligned choice); (2) compileContract
(the IR-to-Zig path) didn't handle zig:for / zig:break / zig:continue (they fell to a
literal "unreachable"), so loop-bearing functions wouldn't round-trip and the single
zig:add round-trip test camouflaged it; now those ops emit the corresponding Zig syntax
and a loop-body canonical-byte round-trip test (via provekit-ir's jcsStringify/jcsHash)
exercises it. make test-zig passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@TSavo TSavo force-pushed the codex/zig-source-lift-kit branch from 88cc382 to ac38549 Compare May 11, 2026 15:52
@TSavo TSavo merged commit 161cf19 into main May 11, 2026
18 checks passed
TSavo added a commit that referenced this pull request May 12, 2026
…#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>
TSavo added a commit that referenced this pull request May 12, 2026
…rm bytes match source semantics (#639)

The lifter was refusing all string literals containing escape sequences
(\n, \t, \\, \", \xNN, \u{NNNN}) with `unsupported-string-escape`.
This meant any Zig source with escape sequences could not be lifted at
all, and no CID could be produced. The stopgap refusal was a placeholder
from PR #596.

Fix:
- `.string_literal`: use `std.zig.string_literal.parseAlloc` (Zig
  stdlib) to decode all escape sequences per spec. Returns decoded bytes
  to IR; the CID now hashes the runtime value, not the source text.
- `.multiline_string_literal`: walk the `multiline_string_literal_line`
  tokens, strip the `\\` two-byte prefix from each, join with `\n`.
  Multiline strings have no escape sequences per Zig spec; they are
  raw byte content.
- `appendEscapedString` (pretty-printer path): extended to handle `\r`,
  `\t`, and a `\xNN` fallback for all other non-printable bytes so that
  `lift(compile(lift(src)))` round-trips correctly for all decoded
  string content.

CID drift: 0 committed fixtures moved. No existing zig-language-
signature or cross-language-port fixture exercised string literals with
escapes (they were being refused, so none could have been committed).
The regression tests are the new pins.

Boy-scout: char_literal is already refused (unchanged). Numeric literals
with underscores work correctly via std.fmt.parseInt base-0. No unrelated
changes in this PR.

New regression tests (7 added, 1 updated):
- decodes \\n escape in string literal to newline byte in IR term
- decodes \\t and \\r escape sequences in string literals
- decodes \\x hex escape to raw byte
- decodes \\u{NNNN} unicode escape to UTF-8 bytes
- decodes \\\\ escaped backslash to single backslash byte
- lifts multiline string literal as raw decoded bytes
- round trip string literal with escape sequences preserves decoded bytes

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
TSavo added a commit that referenced this pull request May 12, 2026
…#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>
TSavo added a commit that referenced this pull request May 12, 2026
…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>
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.

2 participants