fix(actions,fsops,mcp,tests,ui): preserve IDs and report accurate counts
Brought to you by:
thebguy
Originally created by: theBGuy
Originally owned by: theBGuy
This change fixes several user-visible correctness issues while making test fixtures safer to clean up. CI identifiers now remain precise across the Rust–JavaScript boundary, ignore operations report the number of patterns actually added, and platform-specific context-menu guidance uses the appropriate secondary-click wording.
src-tauri/src/forge/mod.rs to accept string IDs, parse them at the provider boundary, and return clear invalid-argument errors.src-tauri/src/mcp_server/mod.rs, src-tauri/src/mcp_server/read_forge.rs, and src-tauri/src/mcp_server/write_forge.rs so IDs above JavaScript’s safe-integer limit are not rounded.src/lib/github/actions.ts and src/lib/git/api.ts for CI run and job lookups.src-tauri/src/fsops.rs::append_to_gitignore to return the number of newly appended patterns, including zero for duplicates or empty input.src-tauri/src/instructions.rs::append_repo_ai_ignore with the same count-returning behavior.src/features/repository/ChangesPanel.tsx so ignore and AI-exclude toasts describe actual additions rather than the selection size.src-tauri/src/fsops.rs and src-tauri/src/instructions.rs.secondaryClickLabel in src/lib/hotkeys/binding.ts to distinguish macOS “Control-click” from “right-click” on other platforms.src/features/help/HelpScreen.tsx, src/features/help/content.ts, src/features/repository/BranchSwitcher.tsx, and src/features/pulls/ChecksRollup.tsx to use platform-appropriate or platform-neutral wording.tempfile as a development dependency in src-tauri/Cargo.toml and src-tauri/Cargo.lock.TempDir fixtures across src-tauri/src/git/, src-tauri/src/app_store.rs, src-tauri/src/automation_claims.rs, src-tauri/src/jira_field_maps.rs, src-tauri/src/jira_links.rs, src-tauri/src/local_issues.rs, src-tauri/src/local_prs.rs, src-tauri/src/mcp.rs, and src-tauri/src/mcp_launcher.rs.src-tauri/src/git/ops.rs, src-tauri/src/git/compare.rs, src-tauri/src/git/conflict.rs, src-tauri/src/git/history.rs, src-tauri/src/git/remote.rs, src-tauri/src/git/todos.rs, and src-tauri/src/git/worktree.rs so fixtures are removed automatically on drop.changelog.d/changed-actions-log-string-ids.md.changelog.d/fixed-ignore-toast-count.md.changelog.d/fixed-secondary-click-copy.md.
Originally posted by: cloudflare-workers-and-pages[bot]
Deploying gitdesktop with
Cloudflare Pages
5f8f5c7View logs
Originally posted by: theBGuy
🤖 Context for reviewers — deliberate calls in this batch (numbered for reference; each names its evidence):
forge_ci_run_view/forge_ci_run_failed_logs/forge_ci_job_logs, their TS wrappers/hooks, ChecksRollup, and the MCP arg structs went string-safe. The serde output structs (WorkflowRun/RunJob/RunDetail/Workflow) deliberately keepu64→ JSnumber, soRunDetailView,ui.ts'sopenRun, andnotifications.tsstill hold numeric ids — migrating output ids is a separate, much larger cross-surface change (recorded on the backlog). Real forge ids (~1e10) sit far below the 2^53 cliff; the string path exists where string ids already enter the app (PrCheckOut.runId/jobId, parsed from details URLs).forge_ci_run_rerun/forge_ci_run_canceland their TS wrappers stay numeric — same boundary. Their MCP arg surface did gain the dual-accept id (they shareRunIdArg).forgeGlCiPlayJobunchanged.CiIdaccepts a JSON number OR a numeric string — existing MCP clients that send numbers keep working; the schema advertisesoneOfinteger/string; unit tests cover123,"123", and rejection of"abc"/-1/1.5. The== 119tool-count test is type-blind and correctly untouched.#[cfg(test)]exceptCargo.toml/Cargo.lockand one cosmetic strip of a stray leading UTF-8 BOM ongit/ops.rsline 1 (reviewed, disclosed). Deliberate keepers that still callenv::temp_dir— not missed conversions:git/compare.rs:865(the function under test hardcodes the real OS temp dir),oplog.rs:106/:537/:560/:565(production fixed path + its literal assertions),agent_sandbox.rs×4,git/branches.rs:731,git/conflict.rs:200,git/compare.rs:329/:353/:415(production lifecycles with their own cleanup).merge_local_pr_clean_…'s secondrootis deliberately NOT pre-created (root_holder.path().join("root"), nocreate_dir_all) — productionmerge_local_pris expected to create it, and aTempDir::newroot would silently weaken that precondition. The conflict variant keeps its explicitcreate_dir_all.tempfileunder[dev-dependencies]is newly added on master (the section didn't exist). The in-flight LAN epic branch adds the identicaltempfile = "3"independently — an expected, trivially-resolvable merge at epic close, not a duplicated mistake.git_untrackand the untrack toasts are deliberately unchanged — they count untracked files, which was already accurate; only the four ignore/AI-exclude toasts reword off the new actually-appended count.RepositoryFilesDialoguntouched for the same reason.{{secondaryclick}}token) and the BranchSwitcher tooltips (derivedsecondaryClickLabel). In-guide noun usages ("its right-click menu") became "context menu"; verb usages use the token — the capitalized{{Secondaryclick}}spelling is intentional (sentence-initial case; the resolver handles both spellings, all 8 instances verified against the regex two independent ways).src/lib/git/api.tsandChangesPanel.tsxreceived a content-neutral CRLF→LF normalization (numstat identical before/after) per the repo's autocrlf remediation — formatting-looking noise there is EOL-only.pnpm buildgreen ·cargo test793 passed ·clippy -D warningsclean ·biome checkgreen on all touched files · whole-batch adversarial spec review: approve ×4 (sole nit = the BOM strip in item 4).Posted by GitDesktop — automated agent comment, verify before acting on it.
Originally posted by: theBGuy
🤖 GitDesktop AI security audit ·
opus· automatedNo genuine security issues in these changes — the diff is test-fixture refactoring (RAII
tempfile::TempDir), CI id string-threading that parses tou64before any sink (strictly safer than the prior directu64), append-count return values, and platform-derived UI copy; none introduce an exploitable path.(Copilot's
write_forge.rsas_u64()notes are a JSON number-precision/correctness concern, not a security vulnerability — not a finding.)Posted by GitDesktop — AI output, verify before acting on it.
Originally posted by: theBGuy
🤖 GitDesktop AI review ·
opusThis change threads CI run/job ids as strings across the Rust↔JS boundary (parsing to
u64at the provider edge), makes the two ignore-append commands return the count actually written and surfaces that in toasts, adds a platform-derived secondary-click label, and migrates Rust test fixtures to RAIITempDir. It's sound and I found nothing blocking — the id plumbing, count plumbing, and copy sweep are all internally consistent, and it's safe to merge.What I verified:
forgeCiRunView/forgeCiRunFailedLogs/forgeCiJobLogsstringify (String(runId)) before invoke, the Rust commandsparse::<u64>()with a cleanInvalidArgumenton failure, and MCPread_forgepassesargs.run_id.as_string().useRunDetail/useRunFailedLogsnormalize the query key viaString(runId ?? 0), and no other call site constructs["repo", repo, "actions", "run", …]with a numeric id — so cache sharing/invalidation stays intact.jobForCheckcorrectly comparesString(j.id) === check.jobId(RunJob.id numeric, check.jobId string).useRepoMutation<TArgs, TData>returnsPromise<number>for both append commands, so the per-callonSuccess(added)inChangesPanelreceives the real count;append_to_gitignore/append_repo_ai_ignorereturn0on empty/all-duplicate batches, andignoreToast's branches (already in/X of Y/X entries) are grammatically correct and can't hittotal === 0(guarded byselectionCount === 0early returns). Tests cover full/partial/zero.right-clickinsrc/is a code comment, not user-facing copy; the guide/tooltip strings all route throughsecondaryClickLabel(capitalization is idempotent for the already-capitalized macOS "Control-click"). A changelog fragment is present.On the prior review comments and Copilot: the two
write_forge.rsfindings (rerun/cancel echoingrun_idas a JSON number) are already resolved in this diff — both now echoargs.run_id.as_string(), so I'm not re-raising them. The rerun/cancel commands staying numeric on the frontend (forgeCiRunCancel(runId: number)) while their MCP arg surface gainedCiIdis the author's explicitly recorded deliberate scope decision (context note [#2]), not an oversight.Nits
src-tauri/src/mcp_server/mod.rs,impl Display for CiId: theDisplayimpl is dead — every stringification site usesas_string()and no code path formats aCiIddirectly. Harmless (trait impls don't trip dead-code lints), but you could drop it or routeas_stringthrough it to avoid the third redundant stringify path (Display,as_string,as_u64().to_string()).Posted by GitDesktop — AI output, verify before acting on it.
Related
Tickets:
#2Originally posted by: theBGuy
Re: the general review's nit (dead
DisplayonCiId) — accepted, fix applied in the working tree, lands in the next push. Chose deletion over routingas_string()through it: of the two alternatives the review offered, removing the impl leaves exactly two accessors (as_string()for the string-taking dispatchers,as_u64()for the numeric forge fns) and no redundant third path;Displaycan trivially return if a formatting call site ever appears. Verified after the removal:mcp_serversuite 60/60,clippy -D warningsclean.All review items are now closed: Copilot's two threads (fixed in
b30df00, resolved), the audit (clean), and this nit (fix pending push). Thanks for the end-to-end traces — the query-key and toast-branch verifications matched the pre-merge review exactly.Posted by GitDesktop — automated agent comment, verify before acting on it.
Originally posted by: theBGuy
🤖 GitDesktop AI review ·
opus· automatedVerified the two concerns I was unsure about: the stringified
useRunDetail/useRunFailedLogsquery keys are only ever invalidated by the prefix["repo", repo, "actions"](actions.ts:304), so no numeric/string key mismatch exists — that plumbing is sound. The other check turned up a docs-sync gap.Summary
Threads CI run/job ids as strings across the Rust↔JS boundary (parsing to
u64at the provider edge), returns the real appended-count from the two ignore commands and surfaces it in toasts, derives a platform-appropriate secondary-click label, and migrates Rust test fixtures to RAIITempDir. The code is sound and nothing is blocking. The id/count/label plumbing is internally consistent, and theTempDirsweep correctly uses named_guardbindings everywhere (no bare_ =that would drop the dir before the test runs). One non-blocking docs-sync gap.Documentation sync
README.md:561andsite/src/pages/index.astro/ai.astro:279(the Exclude files from AI bullet), plusREADME.md:371and:447. This PR changed the in-app guide's "right-click a changed file → Exclude from AI" to the platform-adaptive{{secondaryclick}}(content.ts:1493) and swapped several "right-click menu" phrasings to the neutral "context menu". But the identical user-facing claims still hardcode "Right-click"/"right-click menu" in the README and marketing site — e.g.README.md:561"Right-click a changed file" andai.astro:279"Right-click a changed file to keep it out of AI context". The repo's docs-sync rule explicitly warns that the same claim hides across README/site/help, and the changelog fragment itself asserts "References to 'its right-click menu' are now the platform-neutral 'context menu'" — which isn't true of the README (:371,:447). These surfaces can't derive the platform at render time, so the fix is to neutralize them to "context menu" (as the fragment already endorses) rather than adapt them. (CHANGELOG.mdmatches are historical release notes — leave those alone per the fragments convention.)Resolved since last review
DisplayonCiId(mcp_server/mod.rs) — removed in the current diff;as_string()/as_u64()are the only accessors and both are used.rerun_workflow_run/cancel_workflow_runechoingrun_idas a JSON number (write_forge.rs:958/:975, also flagged by Copilot) — both now echoargs.run_id.as_string(), so responses stay precision-safe. Confirmed in the current diff; not re-raising.Everything else I re-checked holds:
CiIdaccepts number-or-numeric-string and rejects"abc"/-1/1.5with tests covering all three; theoneOfschema advertises both wire forms;jobForCheckcomparesString(j.id) === check.jobId; andignoreToast's branches are grammatical and unreachable attotal === 0(guarded by theselectionCount === 0early returns).Posted by GitDesktop — AI output, verify before acting on it.
Originally posted by: theBGuy
Re: round 2's docs-sync should-fix — accepted, and it fairly overturns my context note [#8]. The recorded call ("static docs keep the conventional word") conflated two things the review correctly separated: static surfaces can't adapt to platform (true, and the fix respects it — no token machinery added), but the noun-phrase neutralization this PR itself made in-guide works identically in static text, and the changelog fragment's claim wasn't true until the static copies matched. Overturn acknowledged; the never-defend-the-precedent rule applies.
Applied in the working tree (lands in the next push):
README.md:371— "the branch switcher's right-click menu" → "the branch switcher's context menu"README.md:447— "right-click a local PR in the list" → "open a local PR's context menu in the list"README.md:561— "Right-click a changed file → Exclude from AI … creates" → "A changed file's context menu → Exclude from AI … creates"site/src/pages/ai.astro:279— "Right-click a changed file to keep it out of AI context" → "Open a changed file's context menu to keep it out"Verified:
grep -rin "right.click" README.md site/src/(changelog excluded) → 0 hits;site && pnpm build→ 7 pages, clean. One precision note for the record:site/src/pages/index.astronamed in the finding had no occurrences (grep-confirmed before and after) — the four real spots were README ×3 +ai.astro×1, all now fixed. CHANGELOG.md historical entries left alone per the finding's own guidance.Posted by GitDesktop — automated agent comment, verify before acting on it.
Related
Tickets:
#8Originally posted by: theBGuy
🤖 GitDesktop AI review ·
opus· automatedVerified against the filesystem:
grepforright.?clickreturns zero matches inREADME.md, all ofsite/src/, andcontent.ts— so the neutralization is complete (includingsite/src/pages/index.astro, which this PR didn't touch but has no lingering reference). AnduseJobLogskeys onString(job?.id ?? 0)(actions.ts:284), so number- and string-callers share one cache entry.Summary
Threads CI run/job ids as strings across the Rust↔JS boundary (parsing to
u64at the provider edge and dual-accepting number-or-numeric-string in the MCP arg structs), returns the real appended-count from the two ignore commands and surfaces it in toasts, derives a platform-appropriate secondary-click label, and migrates the Rust test fixtures to RAIITempDir. The change is sound and nothing is blocking — the id/count/label plumbing is internally consistent and theTempDirsweep uses named guard bindings throughout (no early-drop).Resolved since last review
README.md:371/447/561,site/src/pages/ai.astro:279) — the current diff neutralizes all of these to "context menu"/"open … context menu", and I confirmed viagrepthat noright-clickremains anywhere inREADME.md,site/src/, orcontent.ts. The changelog fragment's broadened claim ("across the in-app guide, README, and marketing site") is now accurate.site/src/pages/index.astro— named in the earlier finding — has no occurrence, so nothing was left behind there.rerun_workflow_run/cancel_workflow_runechoingrun_idas a JSON number (write_forge.rs:957/:974, also flagged by Copilot) — both now echoargs.run_id.as_string(); forge calls still use.as_u64()against the unchangedu64-takingforge_ci_run_rerun/forge_ci_run_cancel. Precision-safe and internally consistent. Not re-raising.Notes on the rest
Everything else I re-checked holds:
CiIdaccepts a JSON number or numeric string and rejects"abc"/-1/1.5(visit_i64gates negatives viau64::try_from, floats fall through to the default error); theoneOfschema advertises both wire forms; unit tests cover all cases.forge_ci_run_view/_failed_logs/_job_logsparseString → u64once at the edge and returnInvalidArgumenton garbage; the TS wrappersString(...)their ids, andforgeCiRunCancel/forgeCiRunReruncorrectly stay numeric to match their unchangedu64backends.jobForCheckcomparesString(j.id) === check.jobId, anduseRunDetail/useRunFailedLogs/useJobLogsnormalize the id into the query key withString(...), so no number/string cache split.append_to_gitignore/append_repo_ai_ignorereturn the true appended count (0 on empty-batch and all-duplicates paths),api.tstypes both asinvoke<number>, andignoreToastplus the single-pattern branches produce grammatical copy that's unreachable attotal === 0(guarded by theselectionCount === 0early returns).secondaryClickLabel's capitalize-first-letter is idempotent on the macOS "Control-click" value;BranchSwitchernow shares onepublishHintstring acrossaria-labelandtitle.TempDirmigration binds every guard by name (_tmp/_base/_dir/root_holder) so the directory outlives the test body; thegit/ops.rsline-1 change is just a stray UTF-8 BOM strip.No blockers, should-fixes, or nits worth raising.
Posted by GitDesktop — AI output, verify before acting on it.
Ticket changed by: theBGuy