Operationalize Jazz CI and alpha releases - #127
Conversation
📝 WalkthroughWalkthroughThe PR adds repository governance, pnpm website tooling, shared TextMate/Shiki highlighting, focused publication validation, tiered CI workflows, release artifact verification, and expanded compiler/package audits. ChangesRepository foundation
Website highlighting and tooling
CI and publication validation
Compiler and release verification
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 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 |
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| BestPractice | 8 medium |
| Documentation | 2 minor |
| Security | 6 medium 1 minor 5 high |
| CodeStyle | 4 minor |
| Complexity | 26 medium |
🟢 Metrics -171 complexity · 1 duplication
Metric Results Complexity -171 Duplication 1
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b9e6699a86
ℹ️ 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".
| except (OSError, UnicodeError) as error: | ||
| raise VerificationError("SHA256SUMS is missing or not UTF-8") from error | ||
| entries: dict[str, str] = {} | ||
| order: list[str] = [] |
There was a problem hiding this comment.
Reject release versions that differ from the Cabal package
When a maintainer dispatches this workflow with a valid but incorrect version such as 0.2.0-alpha.1 while jazz.cabal remains at 0.1.0.0, the builder labels every artifact as 0.2.0 but the source archive still contains jazz-0.1.0.0; this check accepts the archive because it validates only that its root is numeric. The complete workflow and final verifier therefore succeed with contradictory package and release versions, so compare the source package's numeric release line with the requested alpha version before accepting it.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in b79e7c5. Release construction and verification now map the requested alpha line to the Cabal sdist version and reject a mismatch before publication (and before expensive candidate work). The negative mismatch fixtures pass in the 24-test release-verifier suite.
| - name: Check CI workload policy | ||
| run: python3 scripts/check-ci-policy.py |
There was a problem hiding this comment.
Run the CI-policy fixture suite
This job runs only the checker against the current valid workflows, while the newly added scripts/test-check-ci-policy.py suite is not invoked by any workflow or CI script. Consequently, a regression that makes the checker stop rejecting forbidden benchmarks, missing gates, or invalid workflow conditions can still leave this step green; run the fixture suite in CI rather than exercising only its happy path.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in b79e7c5. The always-on PR docs job now runs scripts/test-check-ci-policy.py before the live policy checker, and the compact CI policy requires that protected execution. All 98 policy behavior tests pass.
| - name: Build and verify alpha artifacts | ||
| id: release | ||
| run: nix develop --command bash scripts/release/build-alpha.sh |
There was a problem hiding this comment.
Run the release verifier's negative tests
The release workflow exercises verify-artifacts.py only on artifacts produced by the same builder, and the newly added scripts/release/test-verify-artifacts.py suite is not invoked anywhere in CI. A regression that starts accepting unsafe paths, corrupt closures, bad checksums, or inconsistent evidence would therefore pass this release job as long as the builder continues producing its normal happy-path output; add the verifier fixture suite to a Nix-enabled CI tier.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in b79e7c5. The release verifier's negative suite is now required in the Nix-backed fast/main tiers, with policy coverage preventing its accidental removal. All 24 verifier behavior tests pass.
| bash scripts/check-docs.sh | ||
| find website -type f -name .DS_Store -delete |
There was a problem hiding this comment.
Remove macOS metadata from the published docs tree
On a local macOS release checkout containing docs/.DS_Store, the clean-tree check succeeds because .DS_Store is now ignored and check-public-docs.py explicitly permits it, but this cleanup only searches website/. The subsequent check-website.sh scans docs/ and rejects every non-Markdown regular file, so an otherwise clean alpha build fails solely because of ignored Finder metadata; delete .DS_Store from docs/ as well or make the website boundary apply the same exception.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in b79e7c5. Release candidate assembly now removes macOS .DS_Store metadata from both documentation source and generated website trees before packaging.
| Keep all four archives and `SHA256SUMS` in one directory, then run: | ||
|
|
||
| ```bash | ||
| shasum -a 256 -c SHA256SUMS |
There was a problem hiding this comment.
Make the download verification command usable
For a user following these instructions with the four downloaded archives in one directory, scripts/release/verify-artifacts.py is not present there and the artifacts are not located under the hard-coded repository path artifacts/release/0.1.0-alpha.1; the Cabal source archive also does not package scripts/release/verify-artifacts.py. The documented verification therefore fails unless the user separately checks out the repository and recreates its internal directory layout, so state that prerequisite and point the verifier at the actual download directory, or include a standalone verifier with the release.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in b79e7c5. The release notes now verify downloaded artifacts with the verifier from the exact release checkout, so the documented command works from an artifact directory without assuming repository-relative paths.
| With Nix flakes enabled, build or run the canonical package from the release | ||
| source tree: | ||
|
|
||
| ```bash | ||
| nix build .#jazz | ||
| nix run . -- --help | ||
| nix run . -- --run examples/functions/factorial.jz |
There was a problem hiding this comment.
Include the flake in the advertised release source
The source artifact is produced by cabal sdist, but jazz.cabal does not include flake.nix or flake.lock in its source-distribution files. After extracting that advertised release source, each of these nix build and nix run commands fails because there is no flake in the directory; either package the flake files in the source archive or describe these commands as requiring a separate repository checkout.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in b79e7c5. The Cabal sdist includes flake.nix and flake.lock, the Nix source fileset includes flake.lock, and the release verifier requires both. The source-distribution audit and all 61 Nix suites pass.
| assertJazzParity "fixtures/lexer/long-identifier.jz" (Text.replicate runLength "x") | ||
| assertJazzParity "fixtures/lexer/long-quoted-text.jz" ("\"" <> Text.replicate runLength "x" <> "\"") |
There was a problem hiding this comment.
Restore a timeout around long lexer parity runs
If the Jazz-authored lexer regresses into nontermination or extreme slowdown on either long input, these direct calls no longer fail after the previous 30-second traversal budget and instead occupy the test process until the surrounding CI job timeout (12 minutes on pull requests and 60 minutes on main). Keep the parity assertions, but wrap each long run in a bounded timeout so this targeted test reports the offending case promptly rather than stalling the entire verification tier.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in b79e7c5. Both long lexer parity inputs are wrapped in a bounded 60-second tryWithin check, with a focused timeout-classification regression. The complete lexer parity suite passes.
There was a problem hiding this comment.
4 issues found across 47 files
Confidence score: 3/5
- In
editors/vscode-jazz/package.json, the icon metadata referencesicon.pngbut the committed file is a sparse-checkout text placeholder, sovsce packagecan ship a broken extension asset and hurt release quality/user trust — replace it with a real PNG (or update the metadata to a valid asset) before packaging. - In
scripts/release/test-verify-artifacts.py, verifier behavior tests are not wired into CI ornix flake check, so regressions in artifact validation can merge undetected — add this test module to a Nix/CI check path so it runs on every PR. - In
scripts/release/verify-artifacts.py, uncaught archive parsing errors (for example truncated/malformed tar cases) can emit raw Python tracebacks instead of the expectedFAIL:diagnostics, which weakens release troubleshooting — catch tar/EOF-style parse exceptions in the existing failure handler path. - In
scripts/ci/main-functional.sh, the finalgit diff --checkruns against a clean clone state and misses whitespace issues in the committed PR diff, so style regressions can slip through despite the check — rungit diff --checkagainst the PR range/base ref instead.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="scripts/release/verify-artifacts.py">
<violation number="1" location="scripts/release/verify-artifacts.py:447">
P3: Malformed or truncated archives can print a Python traceback instead of the verifier's normal `FAIL:` diagnostic because archive parsing errors such as `EOFError` are not caught here. Include tar parsing errors in the top-level failure handler so invalid release sets fail cleanly.</violation>
</file>
<file name="scripts/release/test-verify-artifacts.py">
<violation number="1" location="scripts/release/test-verify-artifacts.py:27">
P2: Release-verifier behavior tests never run in CI or `nix flake check`, so regressions in `verify-artifacts.py` can merge despite this suite. Add this module to an appropriate Nix/CI check (run it inside the Nix development environment because its fixture requires `nix-store`).</violation>
</file>
<file name="editors/vscode-jazz/package.json">
<violation number="1" location="editors/vscode-jazz/package.json:16">
P2: The extension icon metadata points at icon.png, but the committed file is a sparse-checkout placeholder containing plain text rather than a valid PNG image. The README's `vsce package` flow will produce an extension with a broken icon (vsce validates the icon is a real PNG). Provide an actual PNG asset at editors/vscode-jazz/icon.png (or drop the `icon` field) before merging.</violation>
</file>
<file name="scripts/ci/main-functional.sh">
<violation number="1" location="scripts/ci/main-functional.sh:15">
P3: The final `git diff --check` is a no-op in CI: on a fresh clone the working tree matches HEAD, so `git diff` reports nothing and the committed PR diff is never checked for whitespace errors. Consider `git diff --check HEAD` (or `git diff-index --check HEAD`) so it actually inspects the PR's committed content.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| NIX_ROOT = "/nix/store/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb-jazz-0.1.0.0" | ||
|
|
||
|
|
||
| class ArtifactVerifierTests(unittest.TestCase): |
There was a problem hiding this comment.
P2: Release-verifier behavior tests never run in CI or nix flake check, so regressions in verify-artifacts.py can merge despite this suite. Add this module to an appropriate Nix/CI check (run it inside the Nix development environment because its fixture requires nix-store).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/release/test-verify-artifacts.py, line 27:
<comment>Release-verifier behavior tests never run in CI or `nix flake check`, so regressions in `verify-artifacts.py` can merge despite this suite. Add this module to an appropriate Nix/CI check (run it inside the Nix development environment because its fixture requires `nix-store`).</comment>
<file context>
@@ -0,0 +1,515 @@
+NIX_ROOT = "/nix/store/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb-jazz-0.1.0.0"
+
+
+class ArtifactVerifierTests(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls) -> None:
</file context>
There was a problem hiding this comment.
Fixed in b79e7c5. The release verifier's negative suite is now required in the Nix-backed fast/main tiers, with policy coverage preventing its accidental removal. All 24 verifier behavior tests pass.
| return 2 | ||
| try: | ||
| version, system = verify_release_directory(Path(arguments[0]).resolve()) | ||
| except (OSError, VerificationError) as error: |
There was a problem hiding this comment.
P3: Malformed or truncated archives can print a Python traceback instead of the verifier's normal FAIL: diagnostic because archive parsing errors such as EOFError are not caught here. Include tar parsing errors in the top-level failure handler so invalid release sets fail cleanly.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/release/verify-artifacts.py, line 447:
<comment>Malformed or truncated archives can print a Python traceback instead of the verifier's normal `FAIL:` diagnostic because archive parsing errors such as `EOFError` are not caught here. Include tar parsing errors in the top-level failure handler so invalid release sets fail cleanly.</comment>
<file context>
@@ -0,0 +1,455 @@
+ return 2
+ try:
+ version, system = verify_release_directory(Path(arguments[0]).resolve())
+ except (OSError, VerificationError) as error:
+ print(f"FAIL: {error}", file=sys.stderr)
+ return 1
</file context>
| except (OSError, VerificationError) as error: | |
| except (OSError, EOFError, tarfile.TarError, VerificationError) as error: |
There was a problem hiding this comment.
Fixed in b79e7c5. Each gzip stream is fully decompressed to EOF before TAR inspection, so trailer/CRC and truncation errors fail cleanly through the verifier's normal FAIL diagnostic. Malformed and truncated archive regressions pass.
| bash scripts/check-execution-queue.sh | ||
| bash scripts/check-examples.sh | ||
| nix flake check | ||
| git diff --check |
There was a problem hiding this comment.
P3: The final git diff --check is a no-op in CI: on a fresh clone the working tree matches HEAD, so git diff reports nothing and the committed PR diff is never checked for whitespace errors. Consider git diff --check HEAD (or git diff-index --check HEAD) so it actually inspects the PR's committed content.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/ci/main-functional.sh, line 15:
<comment>The final `git diff --check` is a no-op in CI: on a fresh clone the working tree matches HEAD, so `git diff` reports nothing and the committed PR diff is never checked for whitespace errors. Consider `git diff --check HEAD` (or `git diff-index --check HEAD`) so it actually inspects the PR's committed content.</comment>
<file context>
@@ -0,0 +1,15 @@
+bash scripts/check-execution-queue.sh
+bash scripts/check-examples.sh
+nix flake check
+git diff --check
</file context>
| git diff --check | |
| git diff --check HEAD |
There was a problem hiding this comment.
Fixed in b79e7c5. PR/main checkouts fetch full history, pass the triggering base SHA as JAZZ_DIFF_BASE, and run git diff --check BASE...HEAD; local runs retain the working-tree fallback. The compact policy has mutation coverage for this contract.
There was a problem hiding this comment.
13 issues found across 68 files
Confidence score: 2/5
- Release version integrity is the biggest risk across
.github/workflows/release.ymlandscripts/ci/release-candidate.sh: a manually requested alpha version can be published under a label that does not matchjazz.cabal, which can mis-tag artifacts and confuse downstream consumers — enforce a strict equality check againstjazz.cabalbefore exporting/publishing. - CI coverage can be silently bypassed in
.github/workflows/ci-pr.yml: mixed PRs that touch compiler code plus docs/RFC/website/CHANGELOG paths may skip compiler checks entirely, increasing regression risk in core changes — fix the path predicate logic so compiler-affecting diffs always trigger compiler jobs. - Policy/audit checks may give false confidence in
scripts/check-ci-policy.pybecause command presence can pass even when checks are in dead or uncalled code paths, so required checks might not actually run — validate executable control flow or add execution-backed assertions. - Artifact safety verification in
scripts/release/verify-artifacts.pyis incomplete because system compatibility is checked using artifact-controlled fields beforenix-store --import, which can allow wrong-system artifacts deeper into the pipeline — compare against the local Nix system and reject early.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="scripts/test-docs-pages-workflow.py">
<violation number="1" location="scripts/test-docs-pages-workflow.py:195">
P3: A regression from `cache: pnpm` to another cache mode is not covered, so the pnpm-cache workflow contract can weaken while this renamed test still passes. Also mutate `cache: pnpm` and assert the `setup-node must enable the pnpm cache` diagnostic.</violation>
</file>
<file name="scripts/ci/fast-compiler.sh">
<violation number="1" location="scripts/ci/fast-compiler.sh:42">
P2: The `git diff --check` whitespace gate is a no-op in the PR tier: in a fresh CI checkout the working tree and index both equal HEAD (no uncommitted diff), so this command always succeeds and never validates the PR's committed lines. Diff against the fetched base branch instead (and fetch full history), e.g. `git diff --check origin/main...HEAD`, so the check actually runs over the PR's changes.</violation>
</file>
<file name="scripts/release/test-verify-artifacts.py">
<violation number="1" location="scripts/release/test-verify-artifacts.py:27">
P2: Verifier behavior regressions will not block any CI tier because this new test module is never invoked. Add it to a Nix-backed protected test tier (or a test-discovery command run by one) so malformed artifact cases remain covered after this PR.</violation>
</file>
<file name=".github/workflows/release.yml">
<violation number="1" location=".github/workflows/release.yml:59">
P1: A manual run can label a source archive built from Cabal version `0.1.0.0` as any accepted version such as `0.1.1-alpha.1`. Validate the alpha numeric line against `jazz.cabal` before exporting `JAZZ_RELEASE_VERSION`, so mislabeled artifacts fail before upload.</violation>
</file>
<file name="website/scripts/render-social-card.mjs">
<violation number="1" location="website/scripts/render-social-card.mjs:164">
P3: An entirely opaque RGBA PNG passes `output.hasAlpha`, so adding an opaque background to `jazz-mark.svg` would silently violate the transparent-icon contract. Validate alpha pixel values (for example, require at least one alpha value below 255) rather than only presence of an alpha channel.</violation>
</file>
<file name="website/src/theme/CodeBlock/Content/index.tsx">
<violation number="1" location="website/src/theme/CodeBlock/Content/index.tsx:91">
P2: Jazz code blocks ignore the CodeBlock word-wrap setting because their `<code>` element omits `wordWrap.codeBlockLinesClassName`. Include it with the line classes so wrapped long lines work like other language blocks.</violation>
</file>
<file name="scripts/ci/release-candidate.sh">
<violation number="1" location="scripts/ci/release-candidate.sh:166">
P1: A requested alpha version can be published with a different Cabal package version: the source archive is renamed to `$JAZZ_RELEASE_VERSION`, but neither this gate nor the artifact verifier compares it with `jazz.cabal`. Validate the expected numeric Cabal version before accepting the sdist so release filenames cannot misrepresent their contents.</violation>
</file>
<file name=".github/workflows/ci-main.yml">
<violation number="1" location=".github/workflows/ci-main.yml:10">
P2: The job restricts permissions to `contents: read` while also using actions/upload-artifact@v4 in the failure path. If artifact upload needs `actions: write` on the GITHUB_TOKEN, the 'Upload ordinary test logs' step will fail right when the collected logs matter most, defeating the failure-debugging purpose. Verify the permission requirement for upload-artifact@v4 and, if needed, grant `actions: write` on the job or that step (keep the rest of the workflow read-only).</violation>
</file>
<file name=".codex/plans/2026-08-01-jazz-docs-pnpm-textmate.md">
<violation number="1" location=".codex/plans/2026-08-01-jazz-docs-pnpm-textmate.md:184">
P2: Node 22 requires an explicit import attribute for ESM JSON imports; a plain `import jazzTextMateGrammar from '...jazz.tmLanguage.json'` (as the Step 3 sample implies) throws ERR_IMPORT_ATTRIBUTE_MISSING under `node`, which would break test:experience and the postbuild checker. Plan for `import ... with { type: 'json' }`, or load via readFileSync/JSON.parse (or createRequire) so the project-node JSON import doesn't fail at 22.</violation>
</file>
<file name="editors/vscode-jazz/syntaxes/jazz.tmLanguage.json">
<violation number="1" location="editors/vscode-jazz/syntaxes/jazz.tmLanguage.json:176">
P3: Effectful-function scope now accepts an uppercase initial (`[\p{Alphabetic}_]` replaces `[a-z_]`). Because #purity is matched before #types in the root scope, and #types now also treats `!` as an identifier continuation, a capitalized name ending in `!` (e.g. an effectful type `Int!`) is now colored as an effectful function rather than a type. If uppercase effectful identifiers are intended, this is fine; otherwise restrict the first char to lowercase to preserve the prior semantics.</violation>
</file>
<file name=".github/workflows/ci-pr.yml">
<violation number="1" location=".github/workflows/ci-pr.yml:28">
P1: Mixed PRs (a compiler change bundled with any docs/RFC/website/CHANGELOG change) silently skip all compiler checks. With predicate-quantifier: every, every negated pattern must match, and '!docs/**' stops matching the moment any docs file changes, so the compiler output flips to false; pr-gate then asserts COMPILER_RESULT=='skipped' and passes even though compiler source changed. Enumerate the compiler-relevant paths positively (src/**, jazz/**, app/**, test/**, *.cabal, cabal.project, flake.*, .github/workflows/**, scripts/ci/**) with the default 'any' quantifier instead of '**' plus exclusions, so the compiler tier runs whenever an actual compiler path is touched.</violation>
</file>
<file name="scripts/check-ci-policy.py">
<violation number="1" location="scripts/check-ci-policy.py:211">
P2: A tier can pass this audit while executing none of its required checks, because command presence is accepted even inside an uncalled function or non-obvious dead branch. Validate executable control flow or add execution-level fixtures for these bypasses so CI workload guarantees cannot silently disappear.</violation>
</file>
<file name="scripts/release/verify-artifacts.py">
<violation number="1" location="scripts/release/verify-artifacts.py:218">
P2: Different-system artifacts still reach `nix-store --import`: this check compares two artifact-controlled strings, not local Nix system. Compare against local system and reject before import, matching release guidance.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| else | ||
| version="${TAG_NAME#v}" | ||
| fi | ||
| [[ "$version" =~ ^0\.[0-9]+\.[0-9]+-alpha\.[0-9]+$ ]] |
There was a problem hiding this comment.
P1: A manual run can label a source archive built from Cabal version 0.1.0.0 as any accepted version such as 0.1.1-alpha.1. Validate the alpha numeric line against jazz.cabal before exporting JAZZ_RELEASE_VERSION, so mislabeled artifacts fail before upload.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 59:
<comment>A manual run can label a source archive built from Cabal version `0.1.0.0` as any accepted version such as `0.1.1-alpha.1`. Validate the alpha numeric line against `jazz.cabal` before exporting `JAZZ_RELEASE_VERSION`, so mislabeled artifacts fail before upload.</comment>
<file context>
@@ -0,0 +1,72 @@
+ else
+ version="${TAG_NAME#v}"
+ fi
+ [[ "$version" =~ ^0\.[0-9]+\.[0-9]+-alpha\.[0-9]+$ ]]
+ echo "JAZZ_RELEASE_VERSION=$version" >> "$GITHUB_ENV"
+
</file context>
There was a problem hiding this comment.
Fixed in b79e7c5. Release construction and verification now map the requested alpha line to the Cabal sdist version and reject a mismatch before publication (and before expensive candidate work). The negative mismatch fixtures pass in the 24-test release-verifier suite.
| bash scripts/ci/main-functional.sh | ||
| bash scripts/ci/extended.sh | ||
|
|
||
| cabal sdist all --output-directory="$JAZZ_RELEASE_SDIST_ROOT" |
There was a problem hiding this comment.
P1: A requested alpha version can be published with a different Cabal package version: the source archive is renamed to $JAZZ_RELEASE_VERSION, but neither this gate nor the artifact verifier compares it with jazz.cabal. Validate the expected numeric Cabal version before accepting the sdist so release filenames cannot misrepresent their contents.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/ci/release-candidate.sh, line 166:
<comment>A requested alpha version can be published with a different Cabal package version: the source archive is renamed to `$JAZZ_RELEASE_VERSION`, but neither this gate nor the artifact verifier compares it with `jazz.cabal`. Validate the expected numeric Cabal version before accepting the sdist so release filenames cannot misrepresent their contents.</comment>
<file context>
@@ -0,0 +1,181 @@
+bash scripts/ci/main-functional.sh
+bash scripts/ci/extended.sh
+
+cabal sdist all --output-directory="$JAZZ_RELEASE_SDIST_ROOT"
+nix build .#jazz --out-link "$JAZZ_NIX_RESULT"
+
</file context>
There was a problem hiding this comment.
Fixed in b79e7c5. Release construction and verification now map the requested alpha line to the Cabal sdist version and reject a mismatch before publication (and before expensive candidate work). The negative mismatch fixtures pass in the 24-test release-verifier suite.
| id: filter | ||
| uses: dorny/paths-filter@v3 | ||
| with: | ||
| predicate-quantifier: every |
There was a problem hiding this comment.
P1: Mixed PRs (a compiler change bundled with any docs/RFC/website/CHANGELOG change) silently skip all compiler checks. With predicate-quantifier: every, every negated pattern must match, and '!docs/' stops matching the moment any docs file changes, so the compiler output flips to false; pr-gate then asserts COMPILER_RESULT=='skipped' and passes even though compiler source changed. Enumerate the compiler-relevant paths positively (src/, jazz/, app/, test/, .cabal, cabal.project, flake., .github/workflows/, scripts/ci/) with the default 'any' quantifier instead of '' plus exclusions, so the compiler tier runs whenever an actual compiler path is touched.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/ci-pr.yml, line 28:
<comment>Mixed PRs (a compiler change bundled with any docs/RFC/website/CHANGELOG change) silently skip all compiler checks. With predicate-quantifier: every, every negated pattern must match, and '!docs/**' stops matching the moment any docs file changes, so the compiler output flips to false; pr-gate then asserts COMPILER_RESULT=='skipped' and passes even though compiler source changed. Enumerate the compiler-relevant paths positively (src/**, jazz/**, app/**, test/**, *.cabal, cabal.project, flake.*, .github/workflows/**, scripts/ci/**) with the default 'any' quantifier instead of '**' plus exclusions, so the compiler tier runs whenever an actual compiler path is touched.</comment>
<file context>
@@ -0,0 +1,131 @@
+ id: filter
+ uses: dorny/paths-filter@v3
+ with:
+ predicate-quantifier: every
+ filters: |
+ compiler:
</file context>
There was a problem hiding this comment.
No change needed. With the pinned dorny/paths-filter semantics, the compiler filter is true when any changed file satisfies the include/exclusion set; predicate-quantifier: every applies a filter's patterns to each file, so a mixed PR containing a compiler file still enables compiler tiers.
| cabal test "${test_components[@]}" --test-show-details=direct | ||
| cabal check | ||
| bash scripts/check-examples.sh | ||
| git diff --check |
There was a problem hiding this comment.
P2: The git diff --check whitespace gate is a no-op in the PR tier: in a fresh CI checkout the working tree and index both equal HEAD (no uncommitted diff), so this command always succeeds and never validates the PR's committed lines. Diff against the fetched base branch instead (and fetch full history), e.g. git diff --check origin/main...HEAD, so the check actually runs over the PR's changes.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/ci/fast-compiler.sh, line 42:
<comment>The `git diff --check` whitespace gate is a no-op in the PR tier: in a fresh CI checkout the working tree and index both equal HEAD (no uncommitted diff), so this command always succeeds and never validates the PR's committed lines. Diff against the fetched base branch instead (and fetch full history), e.g. `git diff --check origin/main...HEAD`, so the check actually runs over the PR's changes.</comment>
<file context>
@@ -0,0 +1,42 @@
+cabal test "${test_components[@]}" --test-show-details=direct
+cabal check
+bash scripts/check-examples.sh
+git diff --check
</file context>
There was a problem hiding this comment.
Fixed in b79e7c5. PR/main checkouts fetch full history, pass the triggering base SHA as JAZZ_DIFF_BASE, and run git diff --check BASE...HEAD; local runs retain the working-tree fallback. The compact policy has mutation coverage for this contract.
| output.format !== 'png' | ||
| || output.width !== editorIconSize | ||
| || output.height !== editorIconSize | ||
| || !output.hasAlpha |
There was a problem hiding this comment.
P3: An entirely opaque RGBA PNG passes output.hasAlpha, so adding an opaque background to jazz-mark.svg would silently violate the transparent-icon contract. Validate alpha pixel values (for example, require at least one alpha value below 255) rather than only presence of an alpha channel.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At website/scripts/render-social-card.mjs, line 164:
<comment>An entirely opaque RGBA PNG passes `output.hasAlpha`, so adding an opaque background to `jazz-mark.svg` would silently violate the transparent-icon contract. Validate alpha pixel values (for example, require at least one alpha value below 255) rather than only presence of an alpha channel.</comment>
<file context>
@@ -128,6 +134,54 @@ export async function renderSocialCard({
+ output.format !== 'png'
+ || output.width !== editorIconSize
+ || output.height !== editorIconSize
+ || !output.hasAlpha
+ ) {
+ throw new Error(
</file context>
There was a problem hiding this comment.
No change needed. The editor icon is byte-compared with a fresh transparent-background render of the canonical mark, so an opaque replacement cannot pass merely by retaining an alpha channel. The deterministic brand suite passes.
| { | ||
| "name": "entity.name.function.effectful.jazz", | ||
| "match": "\\b[a-z_][A-Za-z0-9_']*!(?![A-Za-z0-9_'])" | ||
| "match": "(?<![\\p{Alphabetic}\\p{Number}_'!])[\\p{Alphabetic}_][\\p{Alphabetic}\\p{Number}_']*!(?![\\p{Alphabetic}\\p{Number}_'!])" |
There was a problem hiding this comment.
P3: Effectful-function scope now accepts an uppercase initial ([\p{Alphabetic}_] replaces [a-z_]). Because #purity is matched before #types in the root scope, and #types now also treats ! as an identifier continuation, a capitalized name ending in ! (e.g. an effectful type Int!) is now colored as an effectful function rather than a type. If uppercase effectful identifiers are intended, this is fine; otherwise restrict the first char to lowercase to preserve the prior semantics.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At editors/vscode-jazz/syntaxes/jazz.tmLanguage.json, line 176:
<comment>Effectful-function scope now accepts an uppercase initial (`[\p{Alphabetic}_]` replaces `[a-z_]`). Because #purity is matched before #types in the root scope, and #types now also treats `!` as an identifier continuation, a capitalized name ending in `!` (e.g. an effectful type `Int!`) is now colored as an effectful function rather than a type. If uppercase effectful identifiers are intended, this is fine; otherwise restrict the first char to lowercase to preserve the prior semantics.</comment>
<file context>
@@ -173,15 +173,15 @@
{
"name": "entity.name.function.effectful.jazz",
- "match": "\\b[a-z_][A-Za-z0-9_']*!(?![A-Za-z0-9_'])"
+ "match": "(?<![\\p{Alphabetic}\\p{Number}_'!])[\\p{Alphabetic}_][\\p{Alphabetic}\\p{Number}_']*!(?![\\p{Alphabetic}\\p{Number}_'!])"
}
]
</file context>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a1a0291087
ℹ️ 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".
|
|
||
| bash scripts/check-docs.sh | ||
| find website -type f -name .DS_Store -delete | ||
| pnpm --dir website install --frozen-lockfile |
There was a problem hiding this comment.
Add pnpm to the Nix development shell
On a clean machine following the documented local release command (nix develop --command ... build-alpha.sh), this aborts with pnpm: command not found: the flake.nix development shell provides nodejs_22 but no pnpm executable, while the release script now invokes pnpm directly. The GitHub workflow installs pnpm outside that shell, but that does not make the repository's advertised Nix-only local release environment self-contained; add the pinned pnpm tool to the dev shell or bootstrap it explicitly inside the script.
Useful? React with 👍 / 👎.
| `jazz-0.1.0-alpha.1-docs.tar.gz` and serve its directory with any static HTTP | ||
| server; `index.html` is at the archive root. |
There was a problem hiding this comment.
Document the required docs archive mount point
When a user follows this instruction and serves the extracted directory at the server root, the site loads broken: website/docusaurus.config.ts fixes baseUrl to /jazz/, so the generated HTML requests assets and routes below /jazz/ even though the archive places index.html and assets/ directly at its root. Either build the downloadable archive with a root base URL or explain that the archive must be mounted under /jazz/ using a server that supports the generated routes.
Useful? React with 👍 / 👎.
| "exports": { | ||
| "name": "meta.module.exports.jazz", | ||
| "begin": "\\b(module)\\s+([A-Z][A-Za-z0-9_']*(?:::[A-Z][A-Za-z0-9_']*)*)\\s*(\\()", | ||
| "begin": "\\b(module)\\s+(\\p{Lu}[\\p{Alphabetic}\\p{Number}_'!]*(?:::\\p{Lu}[\\p{Alphabetic}\\p{Number}_'!]*)*)\\s*(\\()", |
There was a problem hiding this comment.
Update the repository audit for the Unicode export regex
Every compiler-relevant pull request and the main/release verification paths run repository-audit-spec, but testEditorExtension still asserts that this begin field equals the previous ASCII-only module-name regex at test/Jazz/Repository/AuditSpec.hs:847-850. The new Unicode expression is therefore guaranteed to make that assertion fail, blocking those verification tiers until the audit expectation is updated with the grammar.
AGENTS.md reference: AGENTS.md:L10-L11
Useful? React with 👍 / 👎.
a1a0291 to
8aaf167
Compare
🤖 CodeAnt AI — Review Status
|
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
| if [[ -e "$release_directory" ]]; then | ||
| printf 'FAIL: release artifact directory already exists: %s\n' "$release_directory" >&2 | ||
| exit 1 |
There was a problem hiding this comment.
Suggestion: There is a check-then-act race between testing whether release_directory exists and moving staged_release into it. Two concurrent builds for the same version can both pass the existence check; the later mv can place the staged directory inside the already-created release directory or otherwise leave a corrupted artifact tree. Create the destination atomically or acquire an exclusive lock before assembling and publishing the release. [race condition]
Severity Level: Major ⚠️
- ⚠️ Same-version concurrent builds can leave nested release directories.
- ❌ The second release build fails after publication begins.
- ⚠️ Uploaded artifact contents can violate the exact release contract.Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** scripts/release/build-alpha.sh
**Line:** 27:29
**Comment:**
*Race Condition: There is a check-then-act race between testing whether `release_directory` exists and moving `staged_release` into it. Two concurrent builds for the same version can both pass the existence check; the later `mv` can place the staged directory inside the already-created release directory or otherwise leave a corrupted artifact tree. Create the destination atomically or acquire an exclusive lock before assembling and publishing the release.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| case [ Text.strip (Text.drop 1 remainder) | ||
| | line <- sourceLines, | ||
| let (candidateName, remainder) = Text.breakOn ":" (Text.strip line), | ||
| candidateName == fieldName, | ||
| not (Text.null remainder) |
There was a problem hiding this comment.
Suggestion: Text.breakOn ":" preserves whitespace before the delimiter, so a valid Cabal field written as name : jazz produces candidateName == "name " and is reported as missing. Normalize the candidate field name before comparing it, or use a Cabal parser. [api mismatch]
Severity Level: Major ⚠️
- ❌ Repository audit rejects valid Cabal metadata formatting.
- ⚠️ CI package-policy checks fail for affected package files.Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** test/Jazz/Repository/PackagePolicy.hs
**Line:** 149:153
**Comment:**
*Api Mismatch: `Text.breakOn ":"` preserves whitespace before the delimiter, so a valid Cabal field written as `name : jazz` produces `candidateName == "name "` and is reported as missing. Normalize the candidate field name before comparing it, or use a Cabal parser.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| text=True, | ||
| timeout=30, | ||
| ) | ||
| if "E0001" not in last_result.stderr: |
There was a problem hiding this comment.
Suggestion: The fragment checker treats any compiler invocation whose stderr does not contain the literal E0001 as successful, without checking returncode. A failed invocation reporting another diagnostic or exiting nonzero for an operational error will therefore be accepted as valid fragment syntax. Require a zero exit status before returning success and report all nonzero failures. [error handling]
Severity Level: Major ⚠️
- ⚠️ CI may accept fragments without successful compiler validation.
- ❌ Documentation syntax regressions can reach published pages.Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** scripts/check-public-docs.py
**Line:** 248:248
**Comment:**
*Error Handling: The fragment checker treats any compiler invocation whose stderr does not contain the literal `E0001` as successful, without checking `returncode`. A failed invocation reporting another diagnostic or exiting nonzero for an operational error will therefore be accepted as valid fragment syntax. Require a zero exit status before returning success and report all nonzero failures.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| index = archive.members.get("index.html") | ||
| if index is None or not index.isreg() or index.size == 0: | ||
| raise VerificationError("docs archive is missing index.html") |
There was a problem hiding this comment.
Suggestion: The documentation verifier only checks that index.html exists and is nonempty. It therefore accepts archives containing internal-only material, unapproved remote resources, or otherwise invalid generated files, even though build-alpha.sh packages the entire website/build tree. Validate the complete archive contents with the same publication-boundary checks before accepting the release. [security]
Severity Level: Major ⚠️
- ⚠️ Post-packaging verification misses forbidden generated content.
- ❌ Tampered documentation archives can pass with updated checksums.Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** scripts/release/verify-artifacts.py
**Line:** 271:273
**Comment:**
*Security: The documentation verifier only checks that `index.html` exists and is nonempty. It therefore accepts archives containing internal-only material, unapproved remote resources, or otherwise invalid generated files, even though `build-alpha.sh` packages the entire `website/build` tree. Validate the complete archive contents with the same publication-boundary checks before accepting the release.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fixThere was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 73460d9f7c
ℹ️ 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".
| import dracula from 'shiki/themes/dracula.mjs'; | ||
| import githubLight from 'shiki/themes/github-light.mjs'; | ||
|
|
||
| import jazzTextMateGrammar from '../../editors/vscode-jazz/syntaxes/jazz.tmLanguage.json' with {type: 'json'}; |
There was a problem hiding this comment.
Trigger Pages for editor grammar changes
When a commit changes only editors/vscode-jazz/syntaxes/jazz.tmLanguage.json, the Pages workflow does not run because .github/workflows/docs-pages.yml:7-21 includes website/** and docs/** but not the imported editor grammar. Since this import makes that grammar a production-site build input, such changes leave the published highlighting stale until an unrelated deployment; add the grammar path to the workflow trigger.
Useful? React with 👍 / 👎.
| import dracula from 'shiki/themes/dracula.mjs'; | ||
| import githubLight from 'shiki/themes/github-light.mjs'; | ||
|
|
||
| import jazzTextMateGrammar from '../../editors/vscode-jazz/syntaxes/jazz.tmLanguage.json' with {type: 'json'}; |
There was a problem hiding this comment.
Use Unicode-aware keyword boundaries
For valid identifiers containing an ASCII keyword suffix, such as λif, the imported grammar's remaining \b(?:if|then|else|case)\b rules match the suffix because the selected JavaScript regex engine treats λ as a non-word character. The compiler and docs/reference/lexical-grammar.md:14-16 treat the whole string as one Unicode identifier, so the new website renderer incorrectly scopes part of it as a keyword; replace the grammar's keyword and builtin \b boundaries with the same Unicode identifier-aware lookarounds used by the updated number/type rules.
AGENTS.md reference: AGENTS.md:L19-L19
Useful? React with 👍 / 👎.
| { | ||
| "name": "constant.numeric.jazz", | ||
| "match": "\\b(?:[0-9]+(?:\\.[0-9]+)?)(?:i8|i16|i32|i64|u8|u16|u32|u64|f16|f32|f64)?\\b" | ||
| "match": "(?<![\\p{Alphabetic}\\p{Number}_'!])(?:[0-9]+(?:\\.[0-9]+)?)(?:i8|i16|i32|i64|u8|u16|u32|u64|f16|f32|f64)?(?![\\p{Alphabetic}\\p{Number}_'!])" |
There was a problem hiding this comment.
Stop highlighting integer suffixes as literals
When the site displays source such as 42i16, this regex scopes the entire token as a numeric literal, although docs/reference/lexical-grammar.md:27-29 permits only f16, f32, and f64 on fractional literals and explicitly says other suffix spellings are not numeric syntax. Because the website now renders directly from this grammar, remove the integer suffixes and restrict float suffixes to the fractional branch so published highlighting agrees with the language contract.
AGENTS.md reference: AGENTS.md:L19-L19
Useful? React with 👍 / 👎.
| if DRAFT_RE.search(front_matter(texts[label])): | ||
| violations.append(f"{label}: required public page cannot be draft") |
There was a problem hiding this comment.
Accept required pages marked draft false
When a required Docusaurus page explicitly declares draft: false, DRAFT_RE still matches the field name and this condition reports that the page is a draft. That blocks documentation, Pages, main, and release checks even though Docusaurus publishes the page; inspect the YAML boolean value or restrict the check to draft: true.
Useful? React with 👍 / 👎.
| if root_lines[0] not in store_paths: | ||
| raise VerificationError("Nix closure root store path is absent from the exported closure") |
There was a problem hiding this comment.
Verify that the Nix closure root contains Jazz
When an artifact records an arbitrary importable store object as its root, these membership and requisites checks still accept it as a valid Jazz closure; the verifier's own accepted fixture demonstrates this with a plain file created by nix-store --add. The command then prints Verified Jazz alpha artifacts, but the documented $root_store_path/bin/jazz --help fails because no executable exists, so inspect the imported root and require an executable bin/jazz before accepting the artifact.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b79e7c50ec
ℹ️ 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".
| r"^(?:error|warning): (E[0-9]{4}|W[0-9]{4})\b", re.MULTILINE | ||
| DRAFT_RE = re.compile(r"(?mi)^draft\s*:\s*true\s*(?:#.*)?$") | ||
| DIAGNOSTIC_RE = re.compile(r"(?m)\bE[0-9]{4}\b") | ||
| JAZZ_FENCE_RE = re.compile(r"(?m)^```jazz(?:[ \t].*)?\r?$", re.IGNORECASE) |
There was a problem hiding this comment.
Recognize every valid Markdown Jazz fence
Parse all fence forms that Docusaurus accepts before enforcing example bindings. In docs/language/ or docs/reference/, a valid ~~~jazz fence or a backtick fence indented by up to three spaces is rendered as Jazz code but matches neither JAZZ_FENCE_RE nor EXAMPLE_BINDING_RE; the checker therefore passes an unmarked, unverified example, allowing invalid code into the public language contract.
AGENTS.md reference: AGENTS.md:L19-L19
Useful? React with 👍 / 👎.
| for fragment, message in CONFIG_REQUIREMENTS: | ||
| if fragment not in source: | ||
| violations.append(f"{CONFIG}: {message}") |
There was a problem hiding this comment.
Parse active Docusaurus configuration values
Validate active properties rather than searching the entire source for literal fragments. If a maintainer changes the live setting to baseUrl: '/' but leaves // baseUrl: '/jazz/' nearby while comparing configurations, this check passes because the required text still exists in a comment; Docusaurus then builds root-relative assets that break when the Pages artifact is served under /jazz/. The same comment-based bypass applies to the broken-link and publication-root requirements.
Useful? React with 👍 / 👎.
| with gzip.open(path, "rb") as compressed: | ||
| while compressed.read(1024 * 1024): |
There was a problem hiding this comment.
Bound decompression while validating downloads
Impose a maximum decompressed size or expansion budget before consuming the gzip stream. When a user runs the documented verifier on a malicious or corrupted high-ratio archive, this loop expands the entire stream without any byte or time limit before tar-member validation begins, so a small download can keep the verifier busy for an effectively unbounded period and exhaust CI or workstation resources instead of being rejected safely.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 39
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.codex/plans/2026-08-01-jazz-docs-pnpm-textmate.md:
- Around line 401-409: Update the final repository inspection command in Step 4
to cover all five planned commits by comparing against the actual base commit or
using HEAD~5..HEAD when the commit history is exact; keep the existing status
and log checks unchanged.
In @.github/ISSUE_TEMPLATE/documentation.yml:
- Around line 24-26: Make the correction field optional by changing its
validations in the documentation issue template so it is not required. Keep the
page and problem fields required.
In @.github/PULL_REQUEST_TEMPLATE.md:
- Line 1: Update the top-level heading in the pull request template from `##
Summary` to a level-one heading so the document satisfies markdownlint MD041.
In @.github/workflows/ci-pr.yml:
- Around line 15-17: Add an explicit timeout-minutes setting to both the changes
and docs-and-site jobs, matching the repository’s intended CI timeout policy and
preventing them from inheriting the 360-minute default. Keep the existing job
steps and pr-gate behavior unchanged.
- Around line 6-8: Add trailing explanatory comments to the contents and
pull-requests permission grants in the workflow permissions block, matching the
documentation convention used by docs-pages.yml.
In @.github/workflows/release.yml:
- Around line 43-48: Disable dependency caching in the release job’s “Set up
Node.js” step by removing the cache-related configuration, including
cache-dependency-path, while preserving the Node.js version setup. If
scripts/check-ci-policy.py enforces these settings, update its validation to
allow the release workflow without dependency caching.
In `@editors/vscode-jazz/README.md`:
- Around line 40-41: Update the VSIX packaging command in the README to use an
exact pinned `@vscode/vsce` version, or replace it with the checked-in development
dependency invocation, while preserving the existing packaging and installation
steps.
In `@release-notes/0.1.0-alpha.1.md`:
- Around line 71-74: Update the checksum verification instructions near
verify-artifacts.py to use sha256sum when available, with shasum -a 256 as a
fallback; alternatively, explicitly document the checksum utility prerequisite
so the documented setup guarantees the command used.
In `@scripts/check-ci-policy.py`:
- Around line 996-1004: Replace the main workflow trigger regex in
check_main_workflow with yaml_mapping_keys(contents, 2) so quoted event keys are
included in the allowed-event validation. Replace the job-permission override
regex with yaml_mapping_keys(contents, 4), matching the parsing used by
check_extended_workflow and check_release_workflow; preserve the existing policy
checks and violation messages.
In `@scripts/check-docs-pages-workflow.py`:
- Around line 130-141: Scope the persist-credentials validation to the checkout
block: remove its entry from REQUIRED_FRAGMENTS and explicitly check for the
setting within the checkout result from step_block(source, "Check out
repository"), preserving the existing violation message when it is absent.
- Around line 99-109: Update step_block to require the step marker to end at a
YAML line boundary, preventing names that are prefixes of longer step names from
matching. Preserve the existing block-boundary detection and return behavior
while making the lookup exact for the requested name.
In `@scripts/check-public-docs.py`:
- Around line 364-366: Replace the direct candidate.read_text call in the
example-checking flow with the existing read_text(root, path, violations)
helper, preserving the normalized expected_source assignment and ensuring read
failures become violations rather than uncaught exceptions.
- Around line 376-384: Update receipt generation in the fragment-checking flow
to hash normalized source by passing binding.group("source") through
normalized_fence before appending the newline. Keep the existing receipt
structure and observed_receipts handling unchanged, then regenerate
scripts/public-doc-fragments.tsv.
In `@scripts/check-website-boundary.py`:
- Around line 97-99: Update check_output_tree to report a violation when the
build path is missing in required/generated-output mode, while preserving the
pre-build argument-free behavior that allows an absent tree. Add a flag to
distinguish required post-build checks, pass it to the post-build invocation in
docs-pages.yml, and ensure --build-directory mode always treats a missing
explicitly named directory as an error.
In `@scripts/ci/extended.sh`:
- Around line 110-118: Update the metadata validation checks in the benchmark
environment flow to use metadata.get() for environment_label and schema_version,
matching the existing run_id lookup. Preserve the current validation messages
and expected-value comparisons so missing keys raise the intended SystemExit
validation errors instead of KeyError tracebacks.
In `@scripts/release/build-alpha.sh`:
- Around line 106-120: The Nix closure export currently passes the sorted path
list, losing requisite-before-referrer order. In scripts/release/build-alpha.sh
lines 106-120, retain the unsorted output from nix-store --query --requisites
for nix-store --export while continuing to write the sorted list to store-paths;
in scripts/release/test-verify-artifacts.py lines 487-628, expand the fixture
closure with a dependency and its referrer so verification exercises the import
order.
- Around line 27-47: Update cleanup() in the release build locking flow to stop
removing $lock_parent; retain the release-lock removal for normal cleanup, but
delete the rmdir "$lock_parent" block so concurrent builds cannot encounter a
missing parent directory.
In `@scripts/release/test-verify-artifacts.py`:
- Around line 102-110: Update the archive method’s TarInfo mode assignment so it
no longer contains the unreachable member_name == "result/bin/jazz" branch; use
the consistent 0o644 mode for all files unless the helper is explicitly updated
to archive an executable member.
- Around line 487-628: Extend the fixture in
test_build_alpha_assembles_and_verifies_a_fixture_candidate (or the shared
fixture setup) so fake nix-store exposes and exports multiple Nix store paths,
including a dependency and its referrer, with requisites returned in an order
that exercises sorted export/import handling. Update the fake import/query
behavior and closure contents as needed while preserving the existing successful
build and verify_nix assertions.
- Around line 28-38: Update setUpClass to detect whether nix-store is available
before invoking the artifact verification setup, and skip the test suite with a
clear message when it is missing. Preserve the existing fixture creation and
nix-store behavior when the executable is available.
In `@scripts/release/verify-artifacts.py`:
- Around line 363-369: Extract the archive member-name validation into a
module-level safe_member_name function that returns the validated name or raises
VerificationError, then have CheckedArchive._safe_name reuse it. Update manifest
validation to call safe_member_name(path) so unsafe paths produce the intended
manifest-specific error and no longer depend on another class’s private method.
- Around line 324-337: Update the boundary verification flow around the
subprocess result in verify-artifacts.py so that, when boundary.returncode is
nonzero, the VerificationError raised by this block includes both
boundary.stdout and boundary.stderr, preserving the existing failure condition
and error context.
In `@scripts/test-check-ci-policy.py`:
- Around line 1572-1600: Update
test_main_workflow_uploads_only_staged_logs_on_failure_for_seven_days so each
table entry explicitly stores its intended mutated fixture alongside old, rather
than applying shared chained replace calls. Use those per-case mutated values in
write, preserving the existing assertions and one-case-at-a-time mutation
behavior.
- Around line 1737-1751: Fix the replacement selection in
test_pull_request_workflow_requires_pr_scoped_cancellation so it recognizes the
two-space cancel-in-progress fixture string, removes that line entirely for the
first case, and continues using static-group only for the concurrency-group
case.
- Around line 1552-1570: The test loop in
test_main_workflow_collects_only_logs_without_filename_collisions binds expected
but ignores it. Replace the hardcoded message passed to self.assert_violation
with the loop’s expected value, preserving the existing test cases and subTest
structure.
In `@scripts/test-docs-pages-workflow.py`:
- Around line 55-59: Update REQUIRED_FRAGMENTS in check-docs-pages-workflow.py
to include editors/vscode-jazz/syntaxes/jazz.tmLanguage.json. Rewrite
test_editor_grammar_changes_trigger_pages to invoke run_checker after removing
that path from the workflow, and assert the checker reports the missing required
fragment instead of only checking the copied text.
In `@test/Jazz/Compiler/Bootstrap/JazzLexerParitySpec.hs`:
- Around line 137-146: Update assertJazzParityWithin to detect TestFailure
values in the Left err branch and rethrow/report them as ordinary assertion
failures using the TestFailure message, instead of labeling them leaked host
exceptions. Export fromException and a TestFailure matcher from
Jazz.TestHarness, then use those exported symbols to distinguish TestFailure
from genuine host exceptions while preserving timeout handling.
In `@test/Jazz/Repository/AuditSpec.hs`:
- Around line 1189-1202: Ensure testSourceDistributionWindowsRoots exercises the
Git-backed path instead of silently falling back: call
listTrackedRepositoryFiles directly for this Git-initialized repository, while
leaving listRepositoryFiles coverage to fallback tests. Preserve the existing
Windows pathspec assertion and expected normalized file result.
- Around line 1149-1152: Update the required-file membership check near
packagedFiles and missingFiles to build a Data.Set from packagedFiles and use
set membership instead of list-based notElem. Preserve the existing missingFiles
result and forbiddenFiles validation, reusing the already imported Data.Set
utilities.
- Around line 540-585: Update testIncorrectPackageMetadata, testEmptyPackageUrl,
and testLegacyPackageIdentity to compare validatePackagePolicy results against
the exact expected [PackagePolicyViolation] value for each targeted invalid
field, replacing the current null/non-empty assertions while preserving each
test’s existing fixture mutation and message.
- Around line 1293-1298: Update listScopedSourceTreeFiles and its go helper to
check whether each scoped root exists before calling listDirectory, and report a
missing directory through failTest with the directory name so
testSourceDistributionInventory produces a descriptive failure instead of an
uncaught IOException.
- Around line 1138-1147: Wrap the process launches for the `cabal sdist
--list-only` command and the `runGit` call in `try` to catch `IOException`s from
missing executables. Map each `Left` result to `failTest` with a useful error
message, while preserving the existing exit-code handling for successful
launches.
- Around line 1213-1235: Update testForbiddenSourceDistributionPaths to define
expected forbidden-path results alongside each input, then assert each
input/result pair directly rather than comparing against a positional boolean
list. Preserve the existing seven inputs and outcomes while making failures
identify the specific path involved.
In `@test/Jazz/Repository/PackagePolicy.hs`:
- Around line 189-190: Update stripComment to remove text only when the line’s
first non-whitespace characters begin with “--”, preserving inline or
continuation text containing “--”. Adjust formattedPrivatePackage if its fixture
currently relies on truncating trailing comment text.
In `@website/package.json`:
- Around line 5-19: Make the website build sequence explicit rather than relying
on pnpm lifecycle hooks: ensure scripts/sync-factorial.mjs runs before
docusaurus build, followed by scripts/check-built-highlighting.mjs, either in
scripts/check-website.sh or the website build command. Preserve the existing
warning behavior.
In `@website/scripts/render-social-card.mjs`:
- Around line 141-176: Update renderEditorIcon’s temporary-file handling to
create a unique temporary directory with mkdtemp inside the output directory,
then write the rendered PNG to a file within that directory. Keep validation and
rename behavior unchanged, and remove the temporary directory in finally instead
of deleting a shared temporary path.
In `@website/src/theme/CodeBlock/Content/index.tsx`:
- Around line 59-68: Split the Jazz-specific rendering from CodeBlockContent
into a dedicated component, keeping the non-Jazz OriginalCodeBlockContent early
return in CodeBlockContent. In the new component, call useCodeBlockContext and
useColorMode unconditionally and memoize tokenizeJazz(metadata.code, colorMode)
with useMemo, then derive lines from the memoized result. Add useMemo to the
React imports and preserve the existing Jazz token rendering behavior.
- Around line 38-45: Update getTokenProps to normalize non-positive fontStyle
values to no style before evaluating the bitmask expressions for italic, bold,
underline, and line-through. Preserve valid positive fontStyle bitmask behavior
while ensuring missing-style values such as -1 produce no inline decorations.
In `@website/src/theme/CodeBlock/Content/styles.module.css`:
- Around line 1-5: Add an empty line after the --ifm-pre-background custom
property in the .codeBlock rule, before the margin declaration, to satisfy
Stylelint's declaration-empty-line-before requirement.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: f808d11e-7cc1-47c2-a52a-058a24b04851
⛔ Files ignored due to path filters (3)
editors/vscode-jazz/icon.pngis excluded by!**/*.pngwebsite/package-lock.jsonis excluded by!**/package-lock.jsonwebsite/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (68)
.codex/plans/2026-08-01-jazz-docs-pnpm-textmate-design.md.codex/plans/2026-08-01-jazz-docs-pnpm-textmate.md.codex/plans/2026-08-09-jazz-publication-validation-simplification-design.md.codex/plans/2026-08-09-jazz-publication-validation-simplification.md.codex/plans/2026-08-09-pr127-review-followthrough.md.editorconfig.gitattributes.github/ISSUE_TEMPLATE/bug-report.yml.github/ISSUE_TEMPLATE/config.yml.github/ISSUE_TEMPLATE/documentation.yml.github/ISSUE_TEMPLATE/language-proposal.yml.github/PULL_REQUEST_TEMPLATE.md.github/dependabot.yml.github/workflows/ci-extended.yml.github/workflows/ci-main.yml.github/workflows/ci-pr.yml.github/workflows/docs-pages.yml.github/workflows/release.yml.gitignoreCHANGELOG.mdCONTRIBUTING.mdREADME.mdRELEASING.mdSECURITY.mddocs/project/contributing.mddocs/project/governance.mdeditors/vscode-jazz/LICENSEeditors/vscode-jazz/README.mdeditors/vscode-jazz/package.jsoneditors/vscode-jazz/syntaxes/jazz.tmLanguage.jsonflake.nixjazz.cabalrelease-notes/0.1.0-alpha.1.mdscripts/check-ci-policy.pyscripts/check-docs-pages-workflow.pyscripts/check-public-docs.pyscripts/check-website-boundary.pyscripts/check-website.shscripts/ci/determinism.shscripts/ci/extended.shscripts/ci/fast-compiler.shscripts/ci/main-functional.shscripts/ci/release-candidate.shscripts/release/build-alpha.shscripts/release/test-verify-artifacts.pyscripts/release/verify-artifacts.pyscripts/test-check-ci-policy.pyscripts/test-check-public-docs.pyscripts/test-check-website-boundary.pyscripts/test-docs-pages-workflow.pytest/Jazz/Compiler/Bootstrap/JazzLexerParitySpec.hstest/Jazz/Repository/AuditSpec.hstest/Jazz/Repository/PackagePolicy.hswebsite/docusaurus.config.tswebsite/package.jsonwebsite/pnpm-workspace.yamlwebsite/scripts/check-built-highlighting.mjswebsite/scripts/jazz-highlighter.d.mtswebsite/scripts/jazz-highlighter.mjswebsite/scripts/prism-jazz-grammar.d.mtswebsite/scripts/prism-jazz-grammar.mjswebsite/scripts/render-social-card.mjswebsite/scripts/test-brand-assets.mjswebsite/scripts/test-experience.mjswebsite/src/theme/CodeBlock/Content/index.tsxwebsite/src/theme/CodeBlock/Content/styles.module.csswebsite/src/theme/prism-include-languages.tswebsite/static/img/brand/README.md
💤 Files with no reviewable changes (4)
- website/scripts/prism-jazz-grammar.d.mts
- website/docusaurus.config.ts
- website/scripts/prism-jazz-grammar.mjs
- website/src/theme/prism-include-languages.ts
| - [ ] **Step 4: Inspect the final repository state** | ||
|
|
||
| ```bash | ||
| git status --short | ||
| git diff --check HEAD~4..HEAD | ||
| git log -5 --oneline | ||
| ``` | ||
|
|
||
| Expected: no uncommitted files, no whitespace errors, and separate commits for the design, implementation plan, pnpm migration, grammar adapter, and renderer. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Make the diff check cover all planned commits.
The plan requires five commits, but git diff --check HEAD~4..HEAD starts at the first listed commit and omits changes introduced by that commit. Compare against the actual base commit, or use HEAD~5..HEAD when the five-commit history is exact.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.codex/plans/2026-08-01-jazz-docs-pnpm-textmate.md around lines 401 - 409,
Update the final repository inspection command in Step 4 to cover all five
planned commits by comparing against the actual base commit or using
HEAD~5..HEAD when the commit history is exact; keep the existing status and log
checks unchanged.
| permissions: | ||
| contents: read | ||
| pull-requests: read |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Document the permission grants.
zizmor reports undocumented-permissions for this block. .github/workflows/docs-pages.yml already documents each grant with a trailing comment. Apply the same convention here.
🧹 Proposed change
permissions:
- contents: read
- pull-requests: read
+ contents: read # Checkout reads the pull-request source.
+ pull-requests: read # dorny/paths-filter reads the changed-file list.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| permissions: | |
| contents: read | |
| pull-requests: read | |
| permissions: | |
| contents: read # Checkout reads the pull-request source. | |
| pull-requests: read # dorny/paths-filter reads the changed-file list. |
🧰 Tools
🪛 zizmor (1.29.0)
[warning] 8-8: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment
(undocumented-permissions)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/ci-pr.yml around lines 6 - 8, Add trailing explanatory
comments to the contents and pull-requests permission grants in the workflow
permissions block, matching the documentation convention used by docs-pages.yml.
Source: Linters/SAST tools
| function getTokenProps({token}: TokenInputProps): TokenOutputProps { | ||
| const {color, content, fontStyle = 0} = token as JazzToken; | ||
| const decoration = [ | ||
| fontStyle & 4 ? 'underline' : undefined, | ||
| fontStyle & 8 ? 'line-through' : undefined, | ||
| ] | ||
| .filter(Boolean) | ||
| .join(' '); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
Shiki ThemedToken fontStyle FontStyle.NotSet -1 value
💡 Result:
In the context of Shiki, FontStyle.NotSet is a member of the FontStyle enum used within ThemedToken objects to represent the styling state of a token [1]. When a token has its fontStyle set to FontStyle.NotSet, it indicates that no specific font style (such as bold, italic, or underline) has been explicitly defined or applied for that token [1]. In practice, this means the renderer should not apply any specific font-style properties (e.g., font-style: normal; or font-weight: bold;), allowing the token to naturally inherit the style from its parent container or environment [1]. This is distinct from FontStyle.None, which explicitly instructs the renderer to reset or disable font styles (effectively forcing a "normal" style), overriding any potential inherited styles [1]. This behavior is consistent with the underlying VS Code TextMate grammar engine, which also utilizes NotSet to indicate that a field should be left as is [2].
Citations:
- 1: Clarification on difference between `FontStyle.NONE` and `FontStyle.NotSet` shikijs/shiki#663
- 2: https://github.com/microsoft/vscode-textmate/blob/f03a6a87/src/encodedTokenAttributes.ts
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate file =="
git ls-files | rg '^website/src/theme/CodeBlock/Content/index\.tsx$|package\.json$' || true
echo "== relevant file excerpt =="
if [ -f website/src/theme/CodeBlock/Content/index.tsx ]; then
nl -ba website/src/theme/CodeBlock/Content/index.tsx | sed -n '1,120p'
fi
echo "== search for JazzToken / getTokenProps usage =="
rg -n "JazzToken|fontStyle|getTokenProps|ThemedToken|ThemedTokenOfTheme" website/src -S || true
echo "== package references =="
rg -n '"shiki"|"`@shikijs`"|FontStyle|jazz|muse|type' package.json website -S || true
echo "== behavioral bitmask probe =="
node - <<'JS'
const style = -1;
for (const [name, flag] of [
['Italic', 1],
['Bold', 2],
['Underline', 4],
['Strikethrough', 8],
]) {
let output = [];
output.push(style & 2 ? 'bold' : undefined);
output.push(style & 4 ? 'underline' : undefined);
output.push(style & 64 ? 'italic' : undefined); /* common Shiki mapping fallback? current code only uses 4/8 */
output.push(style & 8 ? 'line-through' : undefined);
console.log(`${name}: flag=${flag}, value=${style}&flag=${style & flag}, current-decoration-relevant=${style & 4} ${style & 8}`);
}
console.log('current code from snippet relevant masks with -1:', { font_bold: (-1 & 2) !== 0, font_italic: (-1 & 64) !== 0, underline: (-1 & 4) !== 0, lineThrough: (-1 & 8) !== 0 });
JSRepository: Un3qual/jazz
Length of output: 336
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== relevant file excerpt =="
awk '{printf "%6d\t%s\n", NR, $0}' website/src/theme/CodeBlock/Content/index.tsx | sed -n '1,120p'
echo "== search for JazzToken / getTokenProps usage =="
grep -RInE "JazzToken|fontStyle|getTokenProps|ThemedToken|ThemedTokenOfTheme" website/src editors/vscode-jazz package.json website/package.json 2>/dev/null || true
echo "== behavioral bitmask probe =="
node - <<'JS'
const fontStyle = -1;
const decoration = [
fontStyle & 4 ? 'underline' : undefined,
fontStyle & 8 ? 'line-through' : undefined,
].filter(Boolean).join(' ');
console.log({
fontStyle,
italic: fontStyle & 1,
bold: fontStyle & 2,
underline: fontStyle & 4,
lineThrough: fontStyle & 8,
decoration,
});
JSRepository: Un3qual/jazz
Length of output: 5457
Reject invalid negative fontStyle values before applying the bitmask.
Shiki uses fontStyle: -1 for missing style information. With fontStyle = -1, the expressions fontStyle & 1, fontStyle & 2, fontStyle & 4, and fontStyle & 8 are all nonzero, so tokens render italic, bold, underlined, and struck through at once. Treat non-positive values as no style before deriving the inline styles.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/src/theme/CodeBlock/Content/index.tsx` around lines 38 - 45, Update
getTokenProps to normalize non-positive fontStyle values to no style before
evaluating the bitmask expressions for italic, bold, underline, and
line-through. Preserve valid positive fontStyle bitmask behavior while ensuring
missing-style values such as -1 produce no inline decorations.
| export default function CodeBlockContent(props: Props): ReactNode { | ||
| const {metadata, wordWrap} = useCodeBlockContext(); | ||
| const {colorMode} = useColorMode(); | ||
|
|
||
| if (metadata.language !== 'jazz') { | ||
| return <OriginalCodeBlockContent {...props} />; | ||
| } | ||
|
|
||
| const {bg, fg, tokens} = tokenizeJazz(metadata.code, colorMode); | ||
| const lines = tokens.map((line) => line.map(toJazzToken)); |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win
Memoize tokenization, and hoist the hook above the language branch.
Line 67 calls tokenizeJazz on every render. Tokenization is synchronous and proportional to the code length. A color-mode toggle or any parent re-render re-tokenizes every Jazz block on the page on the main thread.
Do not add useMemo at Line 67 as the code stands. The early return on Lines 63-65 sits above it, so the hook would run conditionally and break the rules of hooks. Split the Jazz path into its own component so the memo runs unconditionally.
♻️ Proposed split
+function JazzCodeBlockContent({
+ className,
+}: {
+ className: Props['className'];
+}): ReactNode {
+ const {metadata, wordWrap} = useCodeBlockContext();
+ const {colorMode} = useColorMode();
+ const {bg, fg, tokens} = useMemo(
+ () => tokenizeJazz(metadata.code, colorMode),
+ [metadata.code, colorMode],
+ );
+ const lines = useMemo(
+ () => tokens.map((line) => line.map(toJazzToken)),
+ [tokens],
+ );
+ // ...existing <pre> markup, using `className` in place of `props.className`
+}
+
export default function CodeBlockContent(props: Props): ReactNode {
- const {metadata, wordWrap} = useCodeBlockContext();
- const {colorMode} = useColorMode();
-
+ const {metadata} = useCodeBlockContext();
if (metadata.language !== 'jazz') {
return <OriginalCodeBlockContent {...props} />;
}
-
- const {bg, fg, tokens} = tokenizeJazz(metadata.code, colorMode);
- const lines = tokens.map((line) => line.map(toJazzToken));
+ return <JazzCodeBlockContent className={props.className} />;
}Add useMemo to the React import.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/src/theme/CodeBlock/Content/index.tsx` around lines 59 - 68, Split
the Jazz-specific rendering from CodeBlockContent into a dedicated component,
keeping the non-Jazz OriginalCodeBlockContent early return in CodeBlockContent.
In the new component, call useCodeBlockContext and useColorMode unconditionally
and memoize tokenizeJazz(metadata.code, colorMode) with useMemo, then derive
lines from the memoized result. Add useMemo to the React imports and preserve
the existing Jazz token rendering behavior.
| .codeBlock { | ||
| --ifm-pre-background: var(--prism-background-color); | ||
| margin: 0; | ||
| padding: 0; | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the Stylelint declaration-empty-line-before error.
Stylelint reports an error at line 3. The rule requires an empty line between the custom property and the following standard declaration.
🧹 Proposed change
.codeBlock {
--ifm-pre-background: var(--prism-background-color);
+
margin: 0;
padding: 0;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .codeBlock { | |
| --ifm-pre-background: var(--prism-background-color); | |
| margin: 0; | |
| padding: 0; | |
| } | |
| .codeBlock { | |
| --ifm-pre-background: var(--prism-background-color); | |
| margin: 0; | |
| padding: 0; | |
| } |
🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis
[notice] 1-1: website/src/theme/CodeBlock/Content/styles.module.css#L1
(selector) => Expected class selector "${selector}" to be kebab-case (selector-class-pattern)
🪛 Stylelint (17.14.0)
[error] 3-3: Expected empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/src/theme/CodeBlock/Content/styles.module.css` around lines 1 - 5,
Add an empty line after the --ifm-pre-background custom property in the
.codeBlock rule, before the margin declaration, to satisfy Stylelint's
declaration-empty-line-before requirement.
Source: Linters/SAST tools
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 258807a246
ℹ️ 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".
| for required in ("flake.nix", "flake.lock"): | ||
| if f"{package_root}/{required}" not in files: | ||
| raise VerificationError(f"source archive is missing {required}") |
There was a problem hiding this comment.
Require the active compiler trees in the source archive
Require the source artifact to contain the active src/, app/, jazz/, and test/ content rather than checking only jazz.cabal and the two flake files. An archive stripped of the compiler, CLI, standard library, and tests still passes verify_source—the verifier fixtures even accept a source archive with only one dummy src file—so a download can be reported as verified even though neither advertised build path is usable.
AGENTS.md reference: AGENTS.md:L7-L11
Useful? React with 👍 / 👎.
| index = archive.members.get("index.html") | ||
| if index is None or not index.isreg() or index.size == 0: | ||
| raise VerificationError("docs archive is missing index.html") |
There was a problem hiding this comment.
Require public routes in the documentation archive
Require the generated language and reference routes, not just a nonempty index.html. A docs archive containing only <title>Jazz</title> and an otherwise harmless asset passes both this check and the publication-boundary scan—as demonstrated by the verifier's accepted fixture—so the complete release can be labeled verified while omitting the public language contract and all usable documentation pages.
AGENTS.md reference: AGENTS.md:L19-L19
Useful? React with 👍 / 👎.
| - name: Check documentation and RFCs | ||
| run: bash scripts/check-docs.sh |
There was a problem hiding this comment.
Enforce pinned Markdown formatting in the PR docs job
Run the documentation checks inside the pinned Nix shell or invoke the pinned formatter explicitly. In this job scripts/check-docs.sh runs outside Nix, so its IN_NIX_SHELL guard skips prettier --check; a docs-only PR can therefore pass the required PR gate with formatting drift, only for the Nix-backed main-functional.sh run to reject the same commit after it has merged.
Useful? React with 👍 / 👎.
| "name": "keyword.declaration.jazz", | ||
| "match": "\\b(?:module|import|as|data|class|impl|operator|tier|precedence|left|right|nonassoc)\\b" | ||
| "match": "(?<![\\p{Alphabetic}\\p{Number}_'!])(?:module|import|as|data|class|impl|operator|tier|precedence|left|right|nonassoc)(?![\\p{Alphabetic}\\p{Number}_'!])" |
There was a problem hiding this comment.
Scope contextual words to declaration shapes
Do not classify contextual declaration words globally. The public lexical contract says class, impl, operator, and related words are identifiers outside their declaration shapes, but this pattern scopes every occurrence—including common valid bindings such as left and right—as keyword.declaration.jazz, so both VS Code and the website mis-highlight valid Jazz expressions.
AGENTS.md reference: AGENTS.md:L19-L19
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cf2a46a891
ℹ️ 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".
| candidate = root / pure_path if pure_path is not None else None | ||
| if candidate is None or not candidate.is_file(): | ||
| violations.append(f"{label}: invalid executable example: {source_path}") |
There was a problem hiding this comment.
Reject executable examples that escape examples/
When a docs/language/ or docs/reference/ marker names an examples/**/*.jz symlink—or a path below a symlinked directory—is_file() and read_text() follow it, so the fence is accepted even when its source resolves elsewhere in the repository. An extra executable fence not listed in example-cases.tsv also bypasses that checker's separate containment validation; resolve each candidate and require it to remain beneath the canonical examples/ directory before accepting it.
AGENTS.md reference: AGENTS.md:L19-L19
Useful? React with 👍 / 👎.
| source = read_text(root, readme, violations) | ||
| if source is not None: | ||
| texts["README.md"] = source |
There was a problem hiding this comment.
Validate README link targets before accepting it
When a README-only PR changes a relative link or image to a nonexistent path, this branch merely stores the source and no remaining checker validates those targets; Docusaurus builds only docs/, while .github/workflows/ci-pr.yml explicitly excludes README.md from the compiler tier. The required PR gate therefore succeeds and merges a broken repository front page, so restore local link and image target validation for README content.
Useful? React with 👍 / 👎.
| RESOURCE_ATTRIBUTE_RE = re.compile( | ||
| r"(?i)\b(?:src|srcset|poster)\s*=\s*(['\"])(.*?)\1" | ||
| ) |
There was a problem hiding this comment.
Scan object data URLs as remote resources
When a public page embeds a normal resource such as <object data="https://cdn.example/manual.pdf">, Docusaurus preserves the element and the browser fetches that remote URL, but this scanner examines only src, srcset, and poster attributes, so both the Pages boundary check and release-docs verification accept it. Include other fetch-bearing attributes such as data, background, and manifest, or parse generated HTML before deciding that the archive is self-contained.
AGENTS.md reference: AGENTS.md:L19-L19
Useful? React with 👍 / 👎.
|
|
||
| ```bash | ||
| cd artifacts/release/0.1.0-alpha.1 | ||
| shasum -a 256 -c SHA256SUMS |
There was a problem hiding this comment.
Use a portable checksum command in release instructions
On Linux or Nix installations that provide coreutils sha256sum but not Perl's shasum, this documented verification step fails with shasum: command not found even though the required checksum tool is available. Use the same sha256sum/shasum fallback already shown in the alpha release notes here and in the downloaded-artifact command later in this file.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
editors/vscode-jazz/syntaxes/jazz.tmLanguage.json (1)
62-63: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winReject identifier suffixes after numeric literals.
The numeric rule matches
1in1f32and1.0in1.0f128because the trailing assertion rejects only digits. Invalid numeric suffixes remain after the highlighting.Proposed fix
- "match": "(?<![\\p{Alphabetic}\\p{Number}_'!])(?:[0-9]+\\.[0-9]+(?:f16|f32|f64)?|[0-9]+)(?![0-9])" + "match": "(?<![\\p{Alphabetic}\\p{Number}_'!])(?:[0-9]+\\.[0-9]+(?:f16|f32|f64)?|[0-9]+)(?![\\p{Alphabetic}\\p{Number}_'!])"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@editors/vscode-jazz/syntaxes/jazz.tmLanguage.json` around lines 62 - 63, Update the numeric-literal regex match so its trailing boundary rejects identifier suffix characters, including alphabetic characters, underscores, apostrophes, and exclamation marks, rather than only digits. Preserve valid decimal, integer, and supported f16/f32/f64 literal matching while preventing partial highlighting of values such as 1f32 and 1.0f128.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/check-ci-policy.py`:
- Around line 967-969: Update check_pr_workflow’s trigger validation to require
pull_request as the only allowed event, rejecting any additional trigger such as
pull_request_target, using the same allowlist approach as check_main_workflow.
Add a fixture test in the VALID_PR_WORKFLOW tests that injects
pull_request_target and verifies the policy reports a violation.
In `@scripts/test-check-ci-policy.py`:
- Line 1842: Wrap the over-length tuple entry in the CI policy checks near the
existing “docs-and-site job” assertion across multiple lines, preserving the
exact string contents and validation behavior while bringing each line within
the project’s 159-character limit.
In `@scripts/test-check-spec-authority.py`:
- Around line 219-229: Document the rationale for the 400,000 repetitions in
test_large_documents_do_not_fail_after_an_early_match, explaining the regression
or size threshold this payload is intended to cover; alternatively, reduce the
repetition count to the smallest value that still exercises the large-document
early-match case.
---
Outside diff comments:
In `@editors/vscode-jazz/syntaxes/jazz.tmLanguage.json`:
- Around line 62-63: Update the numeric-literal regex match so its trailing
boundary rejects identifier suffix characters, including alphabetic characters,
underscores, apostrophes, and exclamation marks, rather than only digits.
Preserve valid decimal, integer, and supported f16/f32/f64 literal matching
while preventing partial highlighting of values such as 1f32 and 1.0f128.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 7a37f48e-9268-4684-a7d8-fa720434644e
📒 Files selected for processing (32)
.codex/plans/2026-08-09-pr127-review-followthrough.md.github/ISSUE_TEMPLATE/documentation.yml.github/PULL_REQUEST_TEMPLATE.md.github/workflows/ci-pr.yml.github/workflows/docs-pages.ymlRELEASING.mdeditors/vscode-jazz/README.mdeditors/vscode-jazz/syntaxes/jazz.tmLanguage.jsonflake.nixrelease-notes/0.1.0-alpha.1.mdscripts/check-ci-policy.pyscripts/check-docs-pages-workflow.pyscripts/check-docs.shscripts/check-public-docs.pyscripts/check-spec-authority.shscripts/check-website-boundary.pyscripts/check-website.shscripts/ci/extended.shscripts/release/build-alpha.shscripts/release/test-verify-artifacts.pyscripts/release/verify-artifacts.pyscripts/test-check-ci-policy.pyscripts/test-check-public-docs.pyscripts/test-check-spec-authority.pyscripts/test-check-website-boundary.pyscripts/test-docs-pages-workflow.pytest/Jazz/Repository/AuditSpec.hstest/Jazz/Repository/PackagePolicy.hswebsite/package.jsonwebsite/scripts/render-social-card.mjswebsite/scripts/test-brand-assets.mjswebsite/scripts/test-experience.mjs
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3f7a3c4acb
ℹ️ 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 [[ ! "$JAZZ_RELEASE_VERSION" =~ ^0\.[0-9]+\.[0-9]+-alpha\.[0-9]+$ ]]; then | ||
| printf 'FAIL: JAZZ_RELEASE_VERSION must match 0.<minor>.<patch>-alpha.<n>\n' >&2 | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
Reject mismatched release lines before running the candidate
When workflow_dispatch supplies a syntactically valid but mismatched version such as 0.2.0-alpha.1 while jazz.cabal is still 0.1.0.0, this block validates only the input shape and then runs release-candidate.sh, whose docs build, complete main tier, extended benchmarks/profiling, sdist, and Nix build all finish before the final artifact verifier detects the mismatch. Despite the prior thread stating this now fails before expensive work, fresh evidence in the final tree shows no preflight reading jazz.cabal, so an invalid input can consume nearly the entire 480-minute release job; compare the requested numeric line with the Cabal version here before invoking the candidate.
Useful? React with 👍 / 👎.
User description
Summary
main, weekly/manual extended, and read-only release-candidate workflows0.1.0-alpha.1source, same-system Nix closure, static docs, benchmark-evidence, checksum, and artifact-verification toolingThis PR is stacked on
codex/docusaurus-website; it contains the project-operations workstream only.CI scope
Pull requests run documentation/site checks and a focused compiler matrix when compiler-relevant paths change. The PR tier excludes
cabal bench,jazz-bench,full-parser-scale, the profiling projects, and the completeprogram-corpus-specworkload.mainruns the complete ordinary suite but still excludes those extended workloads. Exhaustive parser scale, repeated corpus checks, profiling, and benchmarks run only weekly, manually, or for release candidates.Warm local PR-tier measurements on the final commit:
All three runs passed and remain well below the ten-minute target.
Verification
Prepared alpha artifacts
The local ignored candidate directory contains:
jazz-0.1.0-alpha.1-source.tar.gz— 914 KBjazz-0.1.0-alpha.1-nix-aarch64-darwin.tar.gz— 980 MB complete runtime closurejazz-0.1.0-alpha.1-docs.tar.gz— 480 KBjazz-0.1.0-alpha.1-benchmark-evidence.tar.gz— 3.9 KBSHA256SUMSThe large Nix artifact intentionally contains the complete same-system closure; runtime closure inspection confirms build-only
cabal-installandgitare absent.Publication remains manual
This PR does not tag or publish anything. After the stack is merged, a maintainer must:
0.1.0-alpha.1on the exact intended commit;SHA256SUMS;CHANGELOG.mdandrelease-notes/0.1.0-alpha.1.mdand make the explicit publication decision;v0.1.0-alpha.1;Follow-up
npm cicurrently reports 20 moderate and 1 high transitive advisory in the Docusaurus dependency tree. The site build and tests pass; dependency remediation should be handled as a separate reviewed update rather than an automatic breakingnpm audit fix --forcein this release-preparation PR.Summary by cubic
Operationalizes tiered CI and verified alpha releases, migrates the docs site to
pnpmwith TextMate-based highlighting, and simplifies publication checks. Closes remaining PR 127 release and workflow gaps with pinned release tooling, fail-fast website preflight, tighter Pages safety, and scoped website boundary checks.New Features
0.1.0-alpha.1: reproducible sdist, same-system Nix closure, docs, benchmark evidence,SHA256SUMS, determinism checks, and an artifact verifier with tests; release workflow supports tag/manual inputs, pinspnpm@11.18.0, and fails fast on website preflight; adds build/release scripts and a determinism CI script.pnpm@11.18.0with lockfile and caching; render Jazz via Shiki from the repository TextMate grammar through a smallCodeBlockwrapper; drop Prism; add a production-build highlighter check and experience tests that assert token scopes; Pages workflow usespnpmcaching and watches the TextMate grammar.actionlint; fix authority edge cases; add README link checks; expand behavior tests..editorconfig,.gitattributes,CHANGELOG.md,CONTRIBUTING.md,SECURITY.md,RELEASING.md, issue/PR templates, anddependabot; enrichedjazz.cabal(homepage, bugs, docs), tighter package policy tests, expanded flake fileset; VS Code extension addsLICENSE, icon, and metadata with a deterministic 128×128 icon test.Migration
0.1.0-alpha.1on the intended commit.SHA256SUMS, then verify locally with the provided scripts.CHANGELOG.mdandrelease-notes/0.1.0-alpha.1.md, then tagv0.1.0-alpha.1and create a prerelease attaching the verified archives.pnpm --dir website install --frozen-lockfileandpnpm --dir website run build.Written for commit cb529e2. Summary will update on new commits.
CodeAnt-AI Description
Establish tiered CI, verified alpha releases, and focused publication checks
What Changed
Impact
✅ Faster pull-request feedback✅ Reproducible alpha release artifacts✅ Fewer unpublished or internally linked documentation errors💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.
Summary by CodeRabbit
New Features
Documentation
Bug Fixes