Skip to content

chore(benchmarks): scrub committed home-directory paths and stop the harnesses re-emitting them - #7165

Merged
proggeramlug merged 1 commit into
PerryTS:mainfrom
jdalton:fix/scrub-absolute-home-paths
Aug 1, 2026
Merged

chore(benchmarks): scrub committed home-directory paths and stop the harnesses re-emitting them#7165
proggeramlug merged 1 commit into
PerryTS:mainfrom
jdalton:fix/scrub-absolute-home-paths

Conversation

@jdalton

@jdalton jdalton commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

What is wrong

Four tracked benchmark artifacts and three documentation files record absolute
filesystem paths that start with a home directory. Because a macOS home
directory is /Users/<account-name>, every one of those paths publishes the
account name of the developer who produced the file. Three different people are
affected, and this repository is public.

The largest offender is the honest-bench results file, which stores the full
path of every workload binary it timed — 180 of them in one file. The rest are
one to five sites each.

This is not only a leftover. One of the harnesses still produces these paths on
every run, so the artifacts would have regrown them the next time anybody
refreshed a baseline.

What this changes

The committed data is scrubbed. Paths that point inside the repository are
now recorded relative to the repository root, which is both shorter and more
useful than the original — benchmarks/honest_bench/workloads/.../image_conv
tells a reader exactly which binary was measured, whereas the absolute path told
them that plus somebody's account name. One path pointed at a tool installed
under a home directory rather than inside the repository; that one is recorded
with a ~ prefix. The prose in the docs was reworded.

The harnesses can no longer emit an absolute home path. Each one now passes
paths through a small portable_path helper before serializing them. The rule
is the same everywhere: inside the checkout, record it relative to the
repository root; under the operator's home directory, record it with a ~
prefix; anything else — a system executable such as /usr/bin/env — record
unchanged.

The helper is applied in three generators, and then once more in
benchmarks/public_baseline.py at assemble time. That last one matters: assemble
is the single funnel every benchmark component passes through on its way to the
committed public artifact, so a component harness that gets added or missed
later still cannot leak through it.

I checked what reads these fields before changing them

The instruction here was not to silently drop a field something depends on, so
each field was traced to its readers first.

Consumer trace, field by field

gc-ratchet baseline (toolchain.binaries.*.path, runtime_dir, and the
suite's compile_command).
Nothing reads them. validate_artifact checks the
schema version, kind, commit, platform, probe set, metric distributions,
correctness status and minor-cycle count; evaluate compares probe metrics.
Neither function touches the toolchain block, and the suite block is stored
as an opaque pass-through. These fields are pure provenance.

Proof the gate still parses the scrubbed file:

$ python3 benchmarks/gc_ratchet/gc_ratchet.py validate
gc-ratchet: .../benchmarks/gc_ratchet/baseline/gc-ratchet-v1.json is a valid pinned baseline

$ python3 -m unittest discover -s tests -p 'test_gc_ratchet.py'
Ran 34 tests in 0.026s — OK

Those are the two commands the gc-ratchet workflow runs in its validate step.

honest-bench results (binary). No reader anywhere. report.py,
summary.py and plot.py never look at it, and neither does
public_baseline.py. The committed snapshot predates the harness's command
field and does not contain one.

Public artifact (runtimes.bun.resolved_executable). This is the top-level
runtimes block, which is written by assemble and never read back. The
per-component runtime_metadata blocks are validated, but those contained no
home paths. Rendering is unaffected — suite_results() and readme_block()
produce byte-identical output before and after the scrub, verified by
substituting a sentinel value and diffing.

One validation rule had to move

public_baseline.py required every recorded resolved_executable and every
measured_command[0] to be an absolute path. That directly blocks recording
a repo-relative path.

Reading the check in context, its purpose is to catch a harness that recorded an
unresolved bare word such as bun instead of resolving it to a concrete
executable. Requiring absoluteness was a proxy for that, not the goal. The rule
is now written as _is_resolved_path: a value passes if it is absolute or
contains a path separator. A bare bun is still rejected, which is the case the
check existed for.

tests/test_public_baseline.py passes unchanged (7 tests), and every component
plus the suite in the committed artifact still validates against the new rule.

Verification

What was run

The requested sweep now returns only intentional placeholders:

$ git grep -nE '/Users/|/home/[a-z]' -- benchmarks docs
docs/CROSS_PLATFORM.md:179:  multipass mount /path/to/perry perry-dev:/home/ubuntu/perry
docs/src/cli/perry-toml.md:560,563,565:  "/Users/me/.perry/..."   (x3)
docs/po/*.po, docs/po/messages.pot:  translations of the same three lines

/home/ubuntu is the guest mount point inside a Multipass Ubuntu VM, which is
correct as written. /Users/me is the documentation placeholder used throughout
the perry.toml reference; the .po catalogues are machine-generated
translations of that same page. Everything else in the repository that still
matches is a synthetic test fixture (/Users/test, /home/user, /home/u), a
CI runner path, or an elision that was already anonymous.

The generators were exercised live rather than just read:

Harness Input Recorded
run_bench.sh binary inside the checkout benchmarks/honest_bench/workloads/_probe_bin
run_bench.sh binary under $HOME ~/.perry-pathscrub-probe
run_bench.sh /bin/echo /bin/echo
run_bench.sh argument --flag --flag (non-path arguments untouched)
compare.sh compiler inside the checkout target/release/perry
gc_ratchet.py compiler inside the checkout wt-ratchet-target/release/perry

Both modified shell scripts pass bash -n, and the extracted Python heredocs
compile. All three scrubbed JSON files still parse.

Gates: gc_ratchet.py validate passes, test_gc_ratchet.py 34/34 passes,
test_public_baseline.py 7/7 passes. check_file_size.sh and the addr-class
ratchet only inspect *.rs files and this branch changes none, so they are
unaffected.

One gate is red on this branch, and it was already red on main

Please read this before judging the checks. benchmarks/ci_public_baseline_check.py
fails here with:

public baseline error: public artifact benchmark inputs changed;
regenerate it with ./benchmarks/run_public_baseline.sh

It fails identically on a clean, unmodified checkout of main. Both recorded
fingerprints — source and harness — have already drifted from what the committed
artifact records, and clearing that means re-running the full Node/Bun/Perry
suite on a quiet host, which is not something a data scrub can or should do.

Two details that matter for diagnosing it. The fingerprint deliberately
normalizes the workspace version line in Cargo.toml, so routine version bumps
are not what broke it — something in the benchmark sources or the harness set
genuinely changed. And the lint job never reaches this step today anyway,
because it exits earlier at "Audit workspace architecture", which is also red on
main.

This red predates the change; nothing here caused it and nothing here can clear
it.

One judgement call to flag

Pushing to PerryTS/perry returned 403, so this arrives as a fork PR under the
external-contributor rule in CLAUDE.md. Accordingly it does not touch
Cargo.toml, Cargo.lock, or the CLAUDE.md version line — the maintainer
applies the bump at merge. It does add the PR-keyed changelog.d/ fragment,
which contributors are expected to write.

The one hunk worth a second look is the CHANGELOG.md edit. That file is a
frozen archive and the PR template says not to edit it, so I want to be explicit
about what this is: it adds nothing and removes nothing. It replaces a
home-directory prefix in six historical entries that quote build commands
verbatim. Leaving them would have meant leaving the same leak in place in one of
the most-read files in the repository, which seemed like the wrong trade against
a freeze rule aimed at stopping the file from growing. It is one hunk away
from being dropped if you disagree.

Suggested follow-up: a CI guard

The repository has no hook or CI check that would catch this, and no
.claude/settings.json at all. A guard would be a small script in the shape of
scripts/check_file_size.sh, grepping tracked files for /Users/<name> and
/home/<name> and failing on anything outside a short allowlist — the allowlist
is genuinely needed, since /Users/test, /Users/me, /home/user, /home/u,
/home/ubuntu and the CI runner paths are all legitimate. Adding it here would
have meant shipping a new gate alongside a data scrub, so it is proposed rather
than included. Happy to open it as a separate PR.

Summary by CodeRabbit

  • Documentation

    • Replaced developer-specific absolute filesystem paths with portable home-relative or repository-relative paths across documentation and changelog entries.
    • Clarified that the ECS performance fixture uses an external scratch checkout.
  • Benchmarking

    • Benchmark metadata and results now record portable paths, improving reproducibility across environments.
    • Existing benchmark measurements remain unchanged.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Benchmark tooling now sanitizes absolute paths into repository-relative or home-relative forms. Existing benchmark artifacts and documentation were updated to remove machine-specific paths without changing measurements.

Changes

Path portability

Layer / File(s) Summary
Path normalization and validation
benchmarks/public_baseline.py, benchmarks/gc_ratchet/gc_ratchet.py
Added portable_path handling and resolved executable validation for benchmark metadata and fingerprints.
Benchmark metadata serialization
benchmarks/compare.sh, benchmarks/honest_bench/harness/run_bench.sh
Pass repository roots to serializers and normalize executable and command paths before writing metadata.
Portable benchmark artifacts
benchmarks/gc_ratchet/baseline/gc-ratchet-v1.json, benchmarks/honest_bench/results/results.json, benchmarks/results/public-node-bun-v1.json
Replaced machine-specific artifact paths with repository-relative or home-relative paths.
Documentation and version references
CHANGELOG.md, changelog.d/7165-scrub-absolute-home-paths.md, docs/ecs-perf-case-study.md, docs/history/*
Replaced machine-specific paths and documented the path-sanitization changes.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BenchmarkScript
  participant PathNormalizer
  participant MetadataArtifact
  BenchmarkScript->>PathNormalizer: provide repository root and paths
  PathNormalizer->>PathNormalizer: resolve and sanitize paths
  PathNormalizer->>MetadataArtifact: write portable executable and command paths
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the benchmark path scrubbing and prevention of future absolute home-directory paths.
Description check ✅ Passed The description clearly covers the problem, changes, validation, known baseline failure, and maintainer considerations, despite not using the template headings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jdalton
jdalton force-pushed the fix/scrub-absolute-home-paths branch from 3fb241d to ff7a46d Compare August 1, 2026 06:26

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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 `@benchmarks/compare.sh`:
- Around line 153-159: Update the command expansion before the Python heredoc to
use the Bash array-preserving form "${NODE_CMD[@]}" instead of "${NODE_CMD[*]}".
Keep the existing argument ordering and Python command-normalization logic
unchanged so multi-argument commands such as node --experimental-strip-types
remain separate arguments.

In `@benchmarks/public_baseline.py`:
- Around line 96-113: Update portable_path in benchmarks/public_baseline.py
(lines 96-113) and the corresponding normalizers in
benchmarks/gc_ratchet/gc_ratchet.py (lines 181-195), benchmarks/compare.sh
(lines 161-170), and benchmarks/honest_bench/harness/run_bench.sh (lines 97-106)
to expand ~ before realpath and anchor relative inputs to the repository root
before resolving. Use ROOT/REPO_ROOT in the Python scripts, root in compare.sh,
and repo_root in run_bench.sh; preserve existing repo/home portability behavior
for absolute inputs.

In `@Cargo.toml`:
- Line 295: Revert the release metadata edits: restore the workspace package
version in Cargo.toml at lines 295-295 and restore the documented current
version in CLAUDE.md at lines 11-11. Leave the PR-keyed changelog fragment
unchanged; these version fields are maintainer-owned.

In `@CHANGELOG.md`:
- Line 5686: Revert all historical portability edits in CHANGELOG.md: restore
the original entries at lines 5686, 8938, 9020, 10506, 10521, and 10561. Keep
portability updates in the current changelog fragment or documentation instead;
do not modify the frozen top-level changelog release entries.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4132f12a-2f6b-4bcc-8ccd-b95764b1a50d

📥 Commits

Reviewing files that changed from the base of the PR and between df7214b and 3fb241d.

📒 Files selected for processing (14)
  • CHANGELOG.md
  • CLAUDE.md
  • Cargo.toml
  • benchmarks/compare.sh
  • benchmarks/gc_ratchet/baseline/gc-ratchet-v1.json
  • benchmarks/gc_ratchet/gc_ratchet.py
  • benchmarks/honest_bench/harness/run_bench.sh
  • benchmarks/honest_bench/results/results.json
  • benchmarks/public_baseline.py
  • benchmarks/results/public-node-bun-v1.json
  • changelog.d/7165-scrub-absolute-home-paths.md
  • docs/ecs-perf-case-study.md
  • docs/history/OPTIMIZATION_PLAN.md
  • docs/history/UI_ADJSUTMENTS.md

Comment thread benchmarks/compare.sh
Comment on lines +153 to +159
"${NODE_CMD[*]}" "$ROOT" <<'PY'
import json
import os
import sys

path, perry, has_node, has_bun, perry_version, node_version, bun_version, node_command = sys.argv[1:]
path, perry, has_node, has_bun, perry_version, node_version, bun_version, node_command, root = sys.argv[1:]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

rg -n -C 5 'NODE_CMD' benchmarks/compare.sh

Repository: PerryTS/perry

Length of output: 1855


🌐 Web query:

Bash array expansion ${array[*]} ${array[@]} behavior spaces elements

💡 Result:

In Bash, the difference between ${array[]} and ${array[@]} relates to how array elements are expanded into words, particularly when enclosed in double quotes [1][2]. Unquoted behavior: When not enclosed in double quotes, both ${array[]} and ${array[@]} behave identically [3]. They expand all elements of the array into separate words, where word splitting is performed based on the characters in the IFS (Internal Field Separator) variable [4][5]. Consequently, if array elements contain spaces, they will be split into multiple words [1][3]. Quoted behavior: When enclosed in double quotes, the expansion behavior differs significantly [2][6]: "${array[@]}" This form expands each element of the array into a separate word [1][2]. It preserves the boundaries of each element, even if the element contains spaces, tabs, or newlines [7][8]. This is the recommended method for iterating over arrays or passing all array elements to a command while maintaining their integrity [7][8]. "${array[]}" This form expands the entire array into a single word [1][2]. The elements are concatenated, separated by the first character of the IFS special variable (which defaults to a space) [4][2]. This is primarily useful when you intend to convert the entire array into a single string for output or processing [7][8]. Summary table: Expansion | Quoted ("") | Unquoted --- | --- | --- ${array[@]} | Expands to separate words (preserves elements) | Expands to separate words (subject to word splitting) ${array[]} | Expands to a single word (joined by IFS) | Expands to separate words (subject to word splitting) As a best practice, always quote array expansions (e.g., "${array[@]}") to prevent unintended word splitting and globbing, unless you specifically require the single-string concatenation behavior of "${array[*]}" [5][7][8].

Citations:


Use "${NODE_CMD[@]}" before passing the command to Python.

NODE_CMD is a Bash array, so "${NODE_CMD[*]}" expands to one argument. If the chosen command is node --experimental-strip-types, Python receives sys.argv[7] as node --experimental-strip-types instead of a two-argument command list, breaking the command normalization.

🤖 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 `@benchmarks/compare.sh` around lines 153 - 159, Update the command expansion
before the Python heredoc to use the Bash array-preserving form "${NODE_CMD[@]}"
instead of "${NODE_CMD[*]}". Keep the existing argument ordering and Python
command-normalization logic unchanged so multi-argument commands such as node
--experimental-strip-types remain separate arguments.

Comment thread benchmarks/public_baseline.py
Comment thread Cargo.toml Outdated

[workspace.package]
version = "0.5.1269"
version = "0.5.1266"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Tracked file relevant lines:\n'
python3 - <<'PY'
for path, lines in (('Cargo.toml', [295]), ('CLAUDE.md', [11])):
    print(f'-- {path} --')
    try:
        with open(path, 'r', encoding='utf-8') as f:
            data = f.read()
        for line in lines:
            content = data.splitlines()[line-1]
            print(f'{line}: {content}')
    except Exception as e:
        print(f'ERROR reading {path}: {e}')
PY

printf '\nChangelog fragments and release metadata mentions:\n'
for pat in 'changelog.d/*' 'CLAUDE.md' 'Cargo.toml'; do
  printf '\n-- glob: %s --\n' "$pat"
  git ls-files "$pat" | sed -n '1,200p'
done

printf '\nVersion mentions (limited):\n'
rg -n "0\.5\.1266|version = \"|Current Version|Current:" Cargo.toml CLAUDE.md changelog.d 2>/dev/null | sed -n '1,200p'

printf '\nDiff stat and changed files:\n'
git diff --stat HEAD 2>/dev/null || true
git diff --name-only HEAD 2>/dev/null | sed -n '1,200p' || true

Repository: PerryTS/perry

Length of output: 10915


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'PR metadata:\n'
printf 'PULL_REQUEST_NUMBER=%s\n' "${PULL_REQUEST_NUMBER:-<missing>}"
printf 'PULL_REQUEST_TITLE=%s\n' "${PULL_REQUEST_TITLE:-<missing>}"
printf 'PULL_REQUEST_HEAD_SHA=%s\n' "${PULL_REQUEST_HEAD_SHA:-<missing>}"
printf 'PULL_REQUEST_BASE_SHA=%s\n' "${PULL_REQUEST_BASE_SHA:-<missing>}"

if [ -n "${PULL_REQUEST_NUMBER:-}" ]; then
  printf '\nChangelog fragment matching PR number:\n'
  rg -n "^$PULL_REQUEST_NUMBER[-_]|$PULL_REQUEST_NUMBER" changelog.d Cargo.toml CLAUDE.md 2>/dev/null || true
fi

printf '\nWorkspace package section:\n'
sed -n '288,298p' Cargo.toml | cat -n
printf '\nCLAUDE metadata section:\n'
sed -n '8,18p' CLAUDE.md | cat -n

Repository: PerryTS/perry

Length of output: 2241


Keep release metadata maintainer-owned.

The PR already adds the required PR-keyed changelog fragment. Revert these version edits unless this is an explicitly maintainer-owned release update.

  • Cargo.toml#L295: restore the workspace package version.
  • CLAUDE.md#L11: restore the documented current version.

External contributors must not edit release metadata fields; maintainers apply version metadata during merge or release when a changelog.d/<PR>-<slug>.md fragment is present.

📍 Affects 2 files
  • Cargo.toml#L295-L295 (this comment)
  • CLAUDE.md#L11-L11
🤖 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 `@Cargo.toml` at line 295, Revert the release metadata edits: restore the
workspace package version in Cargo.toml at lines 295-295 and restore the
documented current version in CLAUDE.md at lines 11-11. Leave the PR-keyed
changelog fragment unchanged; these version fields are maintainer-owned.

Sources: Coding guidelines, Learnings

Comment thread CHANGELOG.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@CLAUDE.md`:
- Line 11: Revert the version metadata in CLAUDE.md from 0.5.1270 to 0.5.1269,
leaving the user-facing change in changelog.d/7165-scrub-absolute-home-paths.md
unchanged and avoiding any updates to frozen CHANGELOG.md.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c354c7f2-2270-4abd-a30e-f0e9b1d1d274

📥 Commits

Reviewing files that changed from the base of the PR and between 3fb241d and ff7a46d.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • CHANGELOG.md
  • CLAUDE.md
  • Cargo.toml
  • benchmarks/compare.sh
  • benchmarks/gc_ratchet/baseline/gc-ratchet-v1.json
  • benchmarks/gc_ratchet/gc_ratchet.py
  • benchmarks/honest_bench/harness/run_bench.sh
  • benchmarks/honest_bench/results/results.json
  • benchmarks/public_baseline.py
  • benchmarks/results/public-node-bun-v1.json
  • changelog.d/7165-scrub-absolute-home-paths.md
  • docs/ecs-perf-case-study.md
  • docs/history/OPTIMIZATION_PLAN.md
  • docs/history/UI_ADJSUTMENTS.md
🚧 Files skipped from review as they are similar to previous changes (13)
  • docs/history/OPTIMIZATION_PLAN.md
  • benchmarks/results/public-node-bun-v1.json
  • docs/ecs-perf-case-study.md
  • benchmarks/public_baseline.py
  • benchmarks/gc_ratchet/gc_ratchet.py
  • benchmarks/honest_bench/harness/run_bench.sh
  • docs/history/UI_ADJSUTMENTS.md
  • Cargo.toml
  • benchmarks/honest_bench/results/results.json
  • benchmarks/compare.sh
  • CHANGELOG.md
  • benchmarks/gc_ratchet/baseline/gc-ratchet-v1.json
  • changelog.d/7165-scrub-absolute-home-paths.md

Comment thread CLAUDE.md
Perry is a native TypeScript compiler written in Rust that compiles TypeScript source code directly to native executables. It uses SWC for TypeScript parsing and LLVM for code generation.

**Current Version:** 0.5.1269
**Current Version:** 0.5.1270

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Revert the contributor-owned version bump.

If this is an external-contributor PR, restore **Current Version:** 0.5.1269. The file's own “External contributor PRs” section says contributors must not change this line; the maintainer updates it at merge time. Keep the user-facing change in changelog.d/7165-scrub-absolute-home-paths.md.

Based on learnings, contributors must not update release/version metadata. As per coding guidelines, keep detailed change history in changelog.d/ and do not append to frozen CHANGELOG.md.

Proposed fix
-**Current Version:** 0.5.1270
+**Current Version:** 0.5.1269
📝 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.

Suggested change
**Current Version:** 0.5.1270
**Current Version:** 0.5.1269
🤖 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 `@CLAUDE.md` at line 11, Revert the version metadata in CLAUDE.md from 0.5.1270
to 0.5.1269, leaving the user-facing change in
changelog.d/7165-scrub-absolute-home-paths.md unchanged and avoiding any updates
to frozen CHANGELOG.md.

Sources: Coding guidelines, Learnings

…nesses re-emitting them

Four tracked artifacts and three docs recorded absolute filesystem paths
containing the account names of three different developers. This is a public
repository, so those paths were published.

Scrubbed the committed data:

  - benchmarks/honest_bench/results/results.json (180 sites) -> repo-relative
  - benchmarks/gc_ratchet/baseline/gc-ratchet-v1.json (5) -> repo-relative
  - benchmarks/results/public-node-bun-v1.json (1) -> ~-relative
  - docs/ecs-perf-case-study.md, docs/history/*, CHANGELOG.md -> ~-relative
    or reworded

Every consumer of the scrubbed fields was checked first. The gc-ratchet
baseline's toolchain paths are pure provenance that neither `gc_ratchet.py
validate` nor the regression comparison reads, and the honest_bench `binary`
field has no reader at all.

Fixed the generators so this cannot recur. `portable_path` records a path
inside the checkout relative to the repository root, a path under the
operator's home directory with a `~` prefix, and anything else unchanged. It
is applied in gc_ratchet.py, honest_bench/harness/run_bench.sh and compare.sh,
and again in public_baseline.py at assemble time -- the single funnel every
benchmark component passes through on its way to the committed artifact.

public_baseline.py required `resolved_executable` and `measured_command[0]` to
be absolute. The intent is to reject an unresolved bare word such as `bun`,
not to require an absolute path, so that is now `_is_resolved_path`: absolute
or containing a path separator. A bare `bun` is still rejected.
@jdalton
jdalton force-pushed the fix/scrub-absolute-home-paths branch from ff7a46d to 99c0b50 Compare August 1, 2026 06:39

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@changelog.d/7165-scrub-absolute-home-paths.md`:
- Line 3: Revise the changelog statement beginning “Every harness that
serializes a path” to exclude the polyglot harness, which can still emit
resolved executable paths directly. Clarify that public_baseline.py remains the
sanitization funnel for the committed public artifact, without claiming all
harnesses sanitize paths before serialization.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 77c7708b-d59f-4e70-9b74-d29d80f40e7c

📥 Commits

Reviewing files that changed from the base of the PR and between ff7a46d and 99c0b50.

📒 Files selected for processing (12)
  • CHANGELOG.md
  • benchmarks/compare.sh
  • benchmarks/gc_ratchet/baseline/gc-ratchet-v1.json
  • benchmarks/gc_ratchet/gc_ratchet.py
  • benchmarks/honest_bench/harness/run_bench.sh
  • benchmarks/honest_bench/results/results.json
  • benchmarks/public_baseline.py
  • benchmarks/results/public-node-bun-v1.json
  • changelog.d/7165-scrub-absolute-home-paths.md
  • docs/ecs-perf-case-study.md
  • docs/history/OPTIMIZATION_PLAN.md
  • docs/history/UI_ADJSUTMENTS.md
🚧 Files skipped from review as they are similar to previous changes (11)
  • docs/history/UI_ADJSUTMENTS.md
  • benchmarks/honest_bench/harness/run_bench.sh
  • benchmarks/honest_bench/results/results.json
  • benchmarks/gc_ratchet/gc_ratchet.py
  • docs/history/OPTIMIZATION_PLAN.md
  • CHANGELOG.md
  • docs/ecs-perf-case-study.md
  • benchmarks/compare.sh
  • benchmarks/results/public-node-bun-v1.json
  • benchmarks/gc_ratchet/baseline/gc-ratchet-v1.json
  • benchmarks/public_baseline.py

@@ -0,0 +1,5 @@
Removed absolute home-directory paths belonging to three different developers from the tracked benchmark artifacts and docs, and fixed the three harnesses that kept writing them back in. `benchmarks/honest_bench/results/results.json` recorded the full filesystem path of every workload binary it timed (180 of them), `benchmarks/gc_ratchet/baseline/gc-ratchet-v1.json` recorded the compiler and static-archive paths it fingerprinted, `benchmarks/results/public-node-bun-v1.json` recorded a home-installed Bun executable, and `docs/ecs-perf-case-study.md`, `docs/history/`, and `CHANGELOG.md` quoted build commands verbatim. This is a public repository, so each of those published the operator's account name.

Every harness that serializes a path now runs it through a `portable_path` helper first: a path inside the checkout is recorded relative to the repository root, a path under the operator's home directory is recorded with a `~` prefix, and anything else (a system executable such as `/usr/bin/env`) is recorded unchanged. The helper is applied in `benchmarks/gc_ratchet/gc_ratchet.py` (binary fingerprints), `benchmarks/honest_bench/harness/run_bench.sh` (the measured binary and any absolute argument in its command line), and `benchmarks/compare.sh` (the recorded Perry compile command). `benchmarks/public_baseline.py` sanitizes again at assemble time, which is the single funnel every benchmark component passes through on its way to the committed public artifact, so a component harness that is missed in future still cannot leak.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Repo files matching polyglot and benchmark paths:"
git ls-files | rg '(^|/)(benchmarks|changelog\.d)/|benchmarks/polyglot|benchmarks/public_baseline.py|gc_ratchet.py|run_bench.sh|compare.sh' || true

echo
echo "changelog fragment:"
if [ -f changelog.d/7165-scrub-absolute-home-paths.md ]; then
  cat -n changelog.d/7165-scrub-absolute-home-paths.md
else
  echo "missing changelog.d/7165-scrub-absolute-home-paths.md"
fi

echo
echo "Search portable_path:"
rg -n "portable_path|resolve\(\)|shutil\.which|pubic_baseline|public_baseline|polyglot/run_all.sh" -S . || true

Repository: PerryTS/perry

Length of output: 50370


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "benchmarks/polyglot/run_all.sh relevant sections:"
if [ -f benchmarks/polyglot/run_all.sh ]; then
  wc -l benchmarks/polyglot/run_all.sh
  sed -n '1,260p' benchmarks/polyglot/run_all.sh | cat -n
else
  echo "missing benchmarks/polyglot/run_all.sh"
fi

echo
echo "benchmarks/public_baseline.py sanitize/assemble path:"
if [ -f benchmarks/public_baseline.py ]; then
  wc -l benchmarks/public_baseline.py
  rg -n "sanitize|serial|portable_path|resolved_executable|measured_command" benchmarks/public_baseline.py || true
  sed -n '1,260p' benchmarks/public_baseline.py | cat -n
fi

echo
echo "focused portable_path occurrences:"
rg -n "\bportable_path\b|\bfrozenset\(|public_baseline" benchmarks -S || true

echo
echo "focused executable path writes in polyglot:"
python3 - <<'PY'
import pathlib, re
p = pathlib.Path("benchmarks/polyglot/run_all.sh")
if p.exists():
    s = p.read_text()
    for name in ["resolve(", "shutil.which(", "exec"]:
        print(f"\n{name} references:")
        for i,line in enumerate(s.splitlines(),1):
            if name in line:
                print(f"{i}: {line.strip()}")
PY

Repository: PerryTS/perry

Length of output: 30367


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "benchmarks/polyglot/run_all.sh produce/assemble section:"
sed -n '350,460p' benchmarks/polyglot/run_all.sh | cat -n

echo
echo "public_baseline.py assemble output handling:"
sed -n '280,355p' benchmarks/public_baseline.py | cat -n

Repository: PerryTS/perry

Length of output: 9307


Update the changelog wording for the public baseline funnel.

The polyglot harness writes resolved executable paths directly, and the current changelog says this harness still leaks those values. Either narrow “every harness that serializes a path” or fix benchmarks/polyglot/run_all.sh to avoid publishing str(Path(...).resolve()) / shutil.which(...) without public_baseline.py sanitization.

🤖 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 `@changelog.d/7165-scrub-absolute-home-paths.md` at line 3, Revise the
changelog statement beginning “Every harness that serializes a path” to exclude
the polyglot harness, which can still emit resolved executable paths directly.
Clarify that public_baseline.py remains the sanitization funnel for the
committed public artifact, without claiming all harnesses sanitize paths before
serialization.

@proggeramlug
proggeramlug merged commit 7beb3a5 into PerryTS:main Aug 1, 2026
7 checks passed
bradmccormack pushed a commit to bradmccormack/perry that referenced this pull request Aug 2, 2026
Brings in 39 upstream commits (a3b31c0..7d1dc9c) on top of the
local context-mode experimental patches (b72f6f9, c3d1141, 6d28ca7).

Resolution notes:

* The local CHANGELOG.md diverged only in home-directory paths
  (`/Users/amlug/...` vs `~/projects/...`) that upstream scrubbed in
  PerryTS#7165. CHANGELOG.md is FROZEN at v0.5.1264 (see
  `changelog.d/README.md`), so the file is restored to its state at
  the merge base (df7214b, the v0.5.1264 version bump). The new
  context-mode entries go in `changelog.d/7220-context-mode-patches.md`
  instead, per the per-PR fragment policy.

* The five perry-related file changes (eval_classifier, expr_new,
  alias_tracking, freshness, lib) all auto-merged cleanly. The
  workspace reorg from `perry/...` to `crates/perry/...` is picked
  up via git's rename detection, so the `freshness.rs` patch rides
  along at its new path.

* No upstream-side changes were dropped or hand-edited.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants