Resolve rename-mapped reconciliation gaps#87
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds build-info generation and staging, flake/installer wiring for reproducible source metadata, a Linux tray patch to display build metadata, a Thorium Chrome-plugin integration with patcher and stage hook, launcher app-local native-host manifest support, RPM ELF-suffixed .so Requires, docs updates, and expanded tests. ChangesBuild Reproducibility and Metadata
Thorium Chrome Plugin Integration
Chrome Native Host Manifest Path Configuration
RPM Architecture-Specific Dependencies
Documentation and Test Coverage
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
|
| Filename | Overview |
|---|---|
| scripts/lib/build-info.js | New module generating build provenance metadata; contains a P1 bug where runGit returns null for both clean-tree (empty stdout) and git failures, causing dirty: null on every clean build and "dirty state unknown" in the tray menu. |
| scripts/lib/package-common.sh | Adds stage_update_builder_source_info with an inline Node heredoc that duplicates sanitizeGitRemoteUrl / shortSourceCommit from build-info.js; carries a maintenance risk if the two copies diverge. |
| scripts/patches/main-process.js | Adds applyLinuxBuildInfoTrayPatch that injects build-info helpers and a "Build Information" tray item into the Electron main bundle; idempotency, variable-name resolution, brace-matching, and class-insertion ordering all look correct. |
| port-integrations/thorium-chrome-plugin/stage.sh | Stage hook correctly checks for the bundled Chrome plugin before writing the manifest-paths entry, and uses grep de-duplication; previously-flagged ordering issue is resolved. |
| launcher/start.sh.template | Extends write_chrome_native_host_manifests to read extra manifest locations from .codex-linux/chrome-native-host-manifest-paths; path validation correctly rejects blanks, comments, absolute paths, .. traversal, and current-directory entries. |
| packaging/linux/codex-app.spec | Switches RPM Requires from package names to soname dependencies with a ()(64bit) ELF suffix for the listed 64-bit architectures; more portable and correctly resolved by RPM dependency solver. |
| flake.nix | Exposes flakeSourceCommit and flakeSourceDateEpoch from flake self-metadata so reproducible builds carry real source provenance instead of the static epoch 1. |
| tests/scripts_smoke.sh | Adds smoke coverage for build-info files in the update-builder bundle, source-info credential sanitization (SSH and local-path remotes), manifest-path de-duplication, and the RPM soname/ELF-suffix assertions. |
Sequence Diagram
sequenceDiagram
participant install as install.sh
participant bish as build-info.sh
participant bijs as build-info.js
participant git as git
participant fs as filesystem
install->>bish: write_build_info(dmg_path, app_dir)
bish->>bijs: node build-info.js args
bijs->>git: rev-parse --is-inside-work-tree
git-->>bijs: true/null
bijs->>git: status --porcelain
git-->>bijs: empty string (clean) OR output (dirty) OR null (error)
Note over bijs: runGit() collapses empty stdout to null
Note over bijs: dirty = null for BOTH clean trees AND git errors
bijs->>fs: readFileSync(Codex.dmg) sha256
bijs->>fs: writeFileSync(build-info.json)
participant pkg as package-common.sh
participant updater as update-builder/
pkg->>updater: cp build-info.js
pkg->>updater: stage_update_builder_source_info()
Note over pkg: Inline Node heredoc duplicates sanitizeGitRemoteUrl
participant tray as Electron tray (patched)
participant dialog as dialog
tray->>fs: readFileSync(build-info.json)
tray->>dialog: showMessageBox(detail)
Note over tray: dirty===null shows dirty state unknown even for clean builds
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
scripts/lib/build-info.js:19-26
**Clean working trees reported as "dirty state unknown"**
`runGit` returns `null` for two distinct cases: git command failure (nonzero exit) and git command success with empty output. For `git status --porcelain`, an empty output means the tree is clean — but `runGit` collapses this to `null`, the same sentinel used for errors. Consequently `dirty` in `sourceInfoFromGit` is always `null` or `true`; it is never `false`. Every clean checkout build will show "dirty state unknown" in the tray menu instead of showing the bare revision hash.
The fix is to compute `dirty` without going through `runGit`: call `spawnSync` directly for the status check so exit-code-0-with-empty-stdout (clean) can be distinguished from a nonzero exit (unknown).
### Issue 2 of 2
scripts/lib/package-common.sh:508-616
**Credential-sanitization logic duplicated from `build-info.js`**
`sanitizeGitRemoteUrl`, `shortSourceCommit`, and `isoTimestamp` are pasted verbatim into the heredoc here. `build-info.js` is already copied into the update-builder bundle (`update_builder_root/scripts/lib/build-info.js`) earlier in `stage_update_builder_bundle`, so it exists on disk before `stage_update_builder_source_info` runs. Any future change to the sanitizer in `build-info.js` that is not mirrored in this heredoc could silently let credentials through in the packaged update-builder's `source-info.json`.
Reviews (7): Last reviewed commit: "fix(build-info): keep dirty short revisi..." | Re-trigger Greptile
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 27e95666db
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
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 `@launcher/start.sh.template`:
- Around line 758-773: The code currently accepts bare "." (and equivalents)
from the extra_locations file; normalize each relative entry and reject
current-directory forms before deduping. After computing relative and pure_path
in the extra_locations read loop, normalize the entry (e.g., via
pathlib.PurePosixPath(relative).as_posix() or os.path.normpath on the POSIX
string), skip if the normalized value is "" or "." (or begins with "./" that
normalizes to "."), continue to reject absolute or ".." as already done, and
then use the normalized string when checking/adding to manifest_locations so "."
will not be appended to manifest_locations.
In `@port-integrations/thorium-chrome-plugin/README.md`:
- Line 8: The README currently instructs users to modify
port-integrations/integrations.json but the correct documented config filename
is port-integrations.json; update the enablement instructions in
thorium-chrome-plugin/README.md to reference port-integrations.json (and any
related mentions of the implementation path or env vars) so they match the
canonical names used elsewhere (port-integrations/, port-integrations.json,
CODEX_PORT_INTEGRATIONS_*); ensure any example commands or copy text replace
"port-integrations/integrations.json" with "port-integrations.json".
In `@scripts/patch-linux-window-ui.test.js`:
- Around line 290-292: Replace the test fixture file name "integrations.json"
with the canonical "port-integrations.json" (and any corresponding writes) so
the test uses the real path/config naming; update the fs.writeFileSync call that
currently writes path.join(integrationsRoot, "integrations.json") (and the
matching enabled value for "zed-opener") to write path.join(integrationsRoot,
"port-integrations.json") instead, and likewise ensure any other occurrence in
the same test (e.g., the call around line 302) is updated; keep the
integrations.example.json write as-is if intended but ensure all integration
config references use the "port-integrations.json"/port-integrations convention
and the integrationsRoot variable.
In `@tests/scripts_smoke.sh`:
- Around line 3430-3436: The test injects an absolute path (/tmp/ignored) into
"$app_dir/.codex-linux/chrome-native-host-manifest-paths" but the assertion
later checks for "$home_dir/tmp/ignored" (wrong target); update the assertion in
tests/scripts_smoke.sh that verifies absolute-path rejection to check for the
actual absolute path "/tmp/ignored" (or assert both "/tmp/ignored" and
"$home_dir/tmp/ignored") under the same manifest file/installed paths (use the
existing variables app_dir and home_dir and the manifest path
".codex-linux/chrome-native-host-manifest-paths") so the test fails if an
absolute path is erroneously accepted and written as absolute.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: b7627df8-35c7-4bca-b74b-487ccac9f8e5
📒 Files selected for processing (19)
docs/maintainers/fork-divergences.mdflake.nixinstall.shlauncher/start.sh.templatepackaging/linux/codex-app.specport-integrations/thorium-chrome-plugin/README.mdport-integrations/thorium-chrome-plugin/integration.jsonport-integrations/thorium-chrome-plugin/patch-chrome-plugin.jsport-integrations/thorium-chrome-plugin/patch.jsport-integrations/thorium-chrome-plugin/stage.shport-integrations/thorium-chrome-plugin/test.jsscripts/lib/build-info.jsscripts/lib/build-info.shscripts/lib/package-common.shscripts/patch-linux-window-ui.jsscripts/patch-linux-window-ui.test.jsscripts/patches/core/all-linux/main-process/window-shell/patch.jsscripts/patches/main-process.jstests/scripts_smoke.sh
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: df36c8649a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/lib/build-info.js (1)
84-88:⚠️ Potential issue | 🟠 Major | ⚡ Quick winWhitelist staged source-info fields before packaging them.
sanitizeSourceInfo()still preserves arbitrary keys, andsourceInfo()then spreads them into the final build-info payload. Since this metadata is now surfaced in the tray “Build Information” UI, any unexpected fields added to.codex-linux/source-info.jsonwill be shipped verbatim and can leak builder-local data. Limit the staged object to the known provenance fields instead of copying everything through.Proposed fix
function sanitizeSourceInfo(info) { - const { sourceInfoPath, ...sanitized } = info; - void sourceInfoPath; - sanitized.remote = sanitizeGitRemoteUrl(sanitized.remote); - return sanitized; + return { + commit: typeof info.commit === "string" ? info.commit : null, + shortCommit: typeof info.shortCommit === "string" ? info.shortCommit : null, + branch: typeof info.branch === "string" ? info.branch : null, + remote: sanitizeGitRemoteUrl(info.remote), + describe: typeof info.describe === "string" ? info.describe : null, + dirty: typeof info.dirty === "boolean" ? info.dirty : null, + capturedAt: typeof info.capturedAt === "string" ? info.capturedAt : null, + }; }Also applies to: 114-117
🤖 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 `@scripts/lib/build-info.js` around lines 84 - 88, sanitizeSourceInfo currently spreads all keys from info which can leak arbitrary staged metadata; change it to construct and return a new object that only includes an explicit whitelist of expected provenance fields (e.g., gitSha, branch, remote, buildHost, buildUser, buildTimestamp) rather than ...sanitized, then set sanitized.remote = sanitizeGitRemoteUrl(sanitized.remote) (or sanitize the remote when building the whitelisted object); likewise update the other occurrence around the 114-117 region so both places only copy the known fields and ignore sourceInfoPath.
🤖 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.
Outside diff comments:
In `@scripts/lib/build-info.js`:
- Around line 84-88: sanitizeSourceInfo currently spreads all keys from info
which can leak arbitrary staged metadata; change it to construct and return a
new object that only includes an explicit whitelist of expected provenance
fields (e.g., gitSha, branch, remote, buildHost, buildUser, buildTimestamp)
rather than ...sanitized, then set sanitized.remote =
sanitizeGitRemoteUrl(sanitized.remote) (or sanitize the remote when building the
whitelisted object); likewise update the other occurrence around the 114-117
region so both places only copy the known fields and ignore sourceInfoPath.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: f41eeb6c-7de0-49e3-aec8-e3b86aa00112
📒 Files selected for processing (5)
launcher/start.sh.templateport-integrations/thorium-chrome-plugin/README.mdscripts/lib/build-info.jsscripts/patch-linux-window-ui.test.jstests/scripts_smoke.sh
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ebb5e5bf39
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/lib/package-common.sh (1)
517-599:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winMissing error handling for embedded Node.js script failure.
If the heredoc Node.js script fails (e.g.,
fs.writeFileSyncthrows due to disk full or permission issues), the non-zero exit code is silently ignored since there's noset -ein this file and no explicit|| error ...after the heredoc. This could produce an incomplete staged bundle without alerting the packager.Proposed fix
fs.writeFileSync(infoFile, `${JSON.stringify(info, null, 2)}\n`, "utf8"); NODE + [ -f "$info_file" ] || error "Failed to write source-info.json" }🤖 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 `@scripts/lib/package-common.sh` around lines 517 - 599, The embedded Node.js heredoc that writes the info file can fail (e.g., fs.writeFileSync) but its non-zero exit status is ignored; after the heredoc invocation ("$node_bin" - "$REPO_DIR" "$info_file" <<'NODE' ... NODE) check the command's exit status and fail the script if non-zero (for example, add an immediate if [ $? -ne 0 ]; then echo "error: failed to write ${info_file}"; exit 1; fi) or enable strict shell failure (set -euo pipefail) earlier; keep the Node script as-is (it defines commit, isoTimestamp, sanitizeGitRemoteUrl, etc.) but ensure the wrapper treats node failures as fatal so incomplete outputs aren't silently accepted.
🤖 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.
Outside diff comments:
In `@scripts/lib/package-common.sh`:
- Around line 517-599: The embedded Node.js heredoc that writes the info file
can fail (e.g., fs.writeFileSync) but its non-zero exit status is ignored; after
the heredoc invocation ("$node_bin" - "$REPO_DIR" "$info_file" <<'NODE' ...
NODE) check the command's exit status and fail the script if non-zero (for
example, add an immediate if [ $? -ne 0 ]; then echo "error: failed to write
${info_file}"; exit 1; fi) or enable strict shell failure (set -euo pipefail)
earlier; keep the Node script as-is (it defines commit, isoTimestamp,
sanitizeGitRemoteUrl, etc.) but ensure the wrapper treats node failures as fatal
so incomplete outputs aren't silently accepted.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 29a84cbf-5fda-44a7-92a1-39120229d27e
📒 Files selected for processing (2)
scripts/lib/package-common.shtests/scripts_smoke.sh
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 19e703779a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
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 `@scripts/patches/main-process.js`:
- Around line 650-651: The code in codexLinuxBuildInfoDetail constructs the
source revision string using i.commit before i.shortCommit when i.dirty===null,
causing full SHAs to be shown; change the logic to prefer i.shortCommit over
i.commit in all cases (compute a base like const base = i.shortCommit ||
i.commit) and then append the dirty suffix: if i.dirty===true => `${base}
(dirty)`, if i.dirty===null => `${base} (dirty state unknown)`, else just
`base`, and fall back to `"unknown"` if no base exists; update the variables s/c
assignment in codexLinuxBuildInfoDetail accordingly so shortCommit is always
preferred.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 062da745-9089-45cd-890d-63830569a1fe
📒 Files selected for processing (4)
port-integrations/thorium-chrome-plugin/stage.shport-integrations/thorium-chrome-plugin/test.jsscripts/patch-linux-window-ui.test.jsscripts/patches/main-process.js
Summary
Resolve the rename-mapped reconciliation audit for issue #75 in this implementation PR. No standalone audit report is committed; this PR body is the durable ledger.
Closes #75.
Audit Ledger
Method:
upstream/mainand prior sync candidates againstdocs/maintainers/fork-divergences.md,.agents/fork-sync-policy.toml, anddocs/maintainers/fork-sync-policy.md.enhancementand retainedready-for-agent.Applied reconciliations:
linux-features/thorium-chrome-pluginshape into a disabled-by-defaultport-integrations/thorium-chrome-plugin..config/thorium/NativeMessagingHosts.officialDmgandportIntegrationsterminology.Build Informationitem backed by generated build metadata.Candidate dispositions:
UPSTREAM_DMG_*compatibility,CODEX_UPSTREAM_APP_DIRcompatibility, andinspect-upstreamalias behavior.codex-app/codex-app-updateridentity and local install layout remain authoritative.fork-divergences.md.Security/design review:
..traversal.Verification
node --test scripts/patch-linux-window-ui.test.js- pass, 158 tests.node --test port-integrations/thorium-chrome-plugin/test.js- pass, 6 tests.bash -n port-integrations/thorium-chrome-plugin/stage.sh- pass after Greptile review fix.node --test --test-name-pattern "build info strips credentials" scripts/patch-linux-window-ui.test.js- failed before the sanitizer fix forrepo.git, then passed after rejecting plain local-path remotes.bash tests/scripts_smoke.sh- failed before the manifest path normalization fix for.entries, then passed after rejecting current-directory manifest paths.bash -n launcher/start.sh.template tests/scripts_smoke.sh port-integrations/thorium-chrome-plugin/stage.sh- pass after CodeRabbit/Codex review fixes.bash tests/scripts_smoke.sh- failed before the package source-info sanitizer fix forfoo/bar.git, then passed after rejecting local-path remotes in packaged update-builder metadata.bash -n scripts/lib/package-common.sh tests/scripts_smoke.sh- pass after the package source-info sanitizer fix.node --test --test-name-pattern "build info preserves unknown dirty state" scripts/patch-linux-window-ui.test.js- failed before the dirty-state fix, then passed after preservingdirty: nullwhen git status is unavailable.node --test scripts/patch-linux-window-ui.test.js- pass, 159 tests after dirty-state coverage.node --test port-integrations/thorium-chrome-plugin/test.js- failed before the manifest marker composition fix, then passed after preserving existing native-host manifest marker entries while appending Thorium.node --test --test-name-pattern "adds Linux build information to the tray menu" scripts/patch-linux-window-ui.test.js- failed before the tray-detail provenance fix, then passed after renderingdirty: nullas an unknown dirty state instead of a clean-looking short commit.bash -n port-integrations/thorium-chrome-plugin/stage.sh- pass after manifest marker append/de-dupe fix.node --test --test-name-pattern "build info keeps dirty suffixes" scripts/patch-linux-window-ui.test.js- failed before the short provenance fix, then passed after preserving-dirtyin short source revisions.node --test --test-name-pattern "build information tray detail prefers readable dirty-unknown revisions" scripts/patch-linux-window-ui.test.js- failed before the CodeRabbit review fix, then passed after preferring the readable short revision while still labeling dirty state unknown.bash -n scripts/lib/package-common.sh- pass after aligning packaged update-builder source-info short revisions.node --test scripts/patch-linux-window-ui.test.js- pass, 161 tests after readable dirty-unknown provenance coverage.bash tests/scripts_smoke.sh- pass,All script smoke tests passed.bash -n install.sh launcher/start.sh.template scripts/lib/package-common.sh scripts/lib/build-info.sh port-integrations/thorium-chrome-plugin/stage.sh tests/scripts_smoke.sh- pass.git diff --checkandgit diff --cached --check- pass.bash tests/scripts_smoke.sh > /tmp/codex-app-linux-smoke.log 2>&1- pass,All script smoke tests passed.stat -c '%n %Y %y' Codex.dmg- cached official DMG from2026-05-26 03:04:17.212768856 -0400.env npm_config_cache=/tmp/codex-app-linux-npm-cache NPM_CONFIG_CACHE=/tmp/codex-app-linux-npm-cache make build-app- pass; generated build info and patchedapp.asar.rg -n -o "codexLinuxShowBuildInfo|Build Information|Codex App Linux build information|Official OpenAI DMG SHA256" /tmp/codex-app-asar-review-issue75-final.GuAiP7/.vite/build/main-*.js- confirms generated main bundle contains the build-info tray/dialog strings.node -e '...' codex-app/.codex-linux/build-info.json- confirms official app version26.519.41501, SHA2563101c05dfd40314115418c4ad87edee02419d097f7164c677ddbdd4559ad8a42, source provenancegit, and enabled port integrations.cargo check -p codex-app-updater- pass.scripts/build-pacman.sh > /tmp/codex-app-linux-pacman.log 2>&1- pass; builtdist/codex-app-26.519.41501-1-x86_64.pkg.tar.zst.rg -n "Name :|Version :|Depends On :|/opt/codex-app/.codex-linux/build-info.json|update-builder/scripts/lib/build-info.js|update-builder/port-integrations/thorium-chrome-plugin|Built package" /tmp/codex-app-linux-pacman.log- confirms package metadata plus build-info and Thorium update-builder payload.scripts/build-rpm.sh- blocked by host prerequisite:rpmbuild is required (install rpm-build). RPM spec coverage is included in smoke assertions.rg -n "chrome-native-host-manifest-paths|thorium/NativeMessagingHosts|Chrome plugin not found" port-integrations/thorium-chrome-plugin launcher/start.sh.template tests/scripts_smoke.sh- confirms the manifest marker is written only by the Thorium stage hook and consumed by the launcher safe-path reader.Ralph Review
port-integrations.jsonoverride path.foo/bar.git.dirty: nullinstead of reporting a false clean state.-dirtysuffix, the tray detail prefers that readable short revision for dirty-unknown builds, and packaged update-builder source-info uses the same short-revision logic.Summary by CodeRabbit
New Features
Documentation
Chores
Tests