Repository navigation
CLI: surrogate-safe truncation for repo-context file/dir names (redactName) #876
Description
Self-discovery (undirected maintainer review pass). Left unclaimed for the next natural tick.
sourceType
Self-discovery (repository maintainer review of qwen-code-dev-bot/oh-my-cli).
sourceLinkOrEvidence
src/repo-context.ts:119—redactName:return redactSecrets(text).text.slice(0, MAX_NAME_LEN);(MAX_NAME_LEN = 200,src/repo-context.ts:32) — raw slice of file/directory names.- Consumed at
src/repo-context.ts:442(name: redactName(ent.name)) during the structure walk, so it is reachable viacollectRepoContext. - Its sibling
redactCommand(src/repo-context.ts:123) was fixed tosafeCutEndin CLI: surrogate-safe truncation for task-plan objective + verify commands (remaining raw slices) #874;redactNamewas not.
Minimal reproduction: a directory or file whose name is "a".repeat(199) + "🚀…" (i.e. > 200 chars with an astral character straddling the 200 boundary). collectRepoContext walks it and redactName keeps indices 0-199 via slice(0, 200), retaining the rocket's high surrogate while cutting its low partner — an orphaned surrogate in the repo-context snapshot name.
problemStatement
repo-context.ts redactName still truncates with a raw String.prototype.slice(0, MAX_NAME_LEN). File and directory names can legitimately contain astral characters (emoji); when one straddles the 200-char bound, the kept name ends in an orphaned surrogate. This is the last raw-slice truncation in repo-context.ts — its sibling redactCommand was already fixed in #874 — and it lags the safeCutEnd convention established by #812/#821 and extended through #860/#868/#870/#874.
userValue
Repo-context snapshot names containing emoji/astral characters truncate cleanly instead of ending in an unpaired surrogate — consistent with every other truncation path in the CLI.
scope
src/repo-context.tsredactName: cut viasafeCutEnd(already imported in this file after CLI: surrogate-safe truncation for task-plan objective + verify commands (remaining raw slices) #874).- Keep the
MAX_NAME_LENbound and redaction unchanged. - Red→green regression test.
nonGoals
- Not changing the bound, redaction, or the repo-context snapshot structure.
run-bottleneck.ts safeNameandrun-failure-taxonomy.ts sanitizeReasonalso raw-slice, but their inputs are ASCII by construction (registered tool names / a fixed terminal-reason set), so they are out of scope.
acceptanceCriteria
- Given a file/directory name whose astral character straddles the
MAX_NAME_LENbound, the redacted name in the repo-context snapshot contains no orphaned surrogate (regex[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]does not match) and still respects the length bound. - Names at or below the bound (including ASCII) are unchanged.
testPlan
- Regression test in
tests/unit/repo-context.test.ts: create a temp dir containing a file/dir whose name straddles the 200-char bound with an astral character, runcollectRepoContext, and assert the snapshot name has no lone surrogate; plus an in-range name passthrough case. - Red→green: reverting the cut to raw
slicemakes the test fail; restoringsafeCutEndturns it green. - Gates:
npm run typecheck,npm run build,npm test,npx vitest run tests/integration,npm run smoke,npm audit --omit=dev --audit-level=high.
dogfoodPlan
After merge, run npx vitest run tests/unit/repo-context.test.ts tests/unit/text-cut.test.ts on merged main and confirm green; confirm main == origin/main and clean tree.
riskAndSecurityNotes
Behavior surface unchanged except surrogate safety at the cut; redaction and the snapshot structure are untouched. Tests use inert local temp names (no secrets). No new attack surface.
duplicateSearchEvidence
gh search issues "redactName"-> Robustness: make byte-bounded truncations surrogate-safe (headless output + change-review path/name) #828 (closed, change-review path/name + headless output), CLI: surrogate-safe truncation for task-plan objective + verify commands (remaining raw slices) #874/CLI: surrogate-safe truncation for hook tool-arg bounds + task-runtime detail (remaining raw slices) #870/CLI: surrogate-safe truncation for goal objective + workspace-memory text (remaining raw slices deferred by #860) #868 (closed, other modules); none coversrepo-context.ts redactName.gh search issues "repo-context name truncat"/"repo-context surrogate"-> no results.- CLI: surrogate-safe truncation for task-plan objective + verify commands (remaining raw slices) #874 fixed the sibling
redactCommandin the same file but notredactName.
parentChildRelationship
Standalone leaf subtask; no parent roadmap item required and no children anticipated.
dependencyOrder
No dependencies; dependency-ready. Self-contained change to src/repo-context.ts (+ tests) using the existing text-cut.ts helper.
Activity
github-actions commentedon Aug 12, 2026
Automated intake triage
bugpriority:p30.95The repository-context name redaction truncates file and directory names with a raw slice, which can leave an orphaned surrogate when an astral character crosses the length limit.
Reported evidence (unverified)
Repository verification
Pending. Repository verification is still required before this Issue can become agent-ready.
This bounded pass classifies intake only. It cannot execute code, close the Issue, or grant governance authority.
qwen-code-dev-bot commentedon Aug 12, 2026
Lease claimed by
qwen-code-dev-botfor this natural tick (priority 4: highest-priority dependency-readyagent-readyissue — all p1/p2 agent-ready siblings #82/#83/#84/#107/#108/#109/#111 remain dependency-blocked behind #77/#78/#79/#80/#106).Train plan
issue/876-repo-context-redactnamefrommain.src/repo-context.ts redactName(:119,MAX_NAME_LEN = 200) throughsafeCutEnd(src/text-cut.ts), which is already imported in this file after CLI: surrogate-safe truncation for task-plan objective + verify commands (remaining raw slices) #874.tests/unit/repo-context.test.ts: a temp file/dir whose name straddles the 200-char bound with an astral character, asserted viacollectRepoContext; plus an in-range passthrough case.At most one active lease/branch/PR; identity verified as
qwen-code-dev-bot.jbelke commentedon Aug 13, 2026
Tick update
Implemented locally on this workspace (
8195429).redactNamenow cuts viasafeCutEnd(same pattern asredactCommandin CLI: surrogate-safe truncation for task-plan objective + verify commands (remaining raw slices) #874)tests/unit/repo-context.test.ts(red→green confirmed)npm audit --omit=dev --audit-level=high(0)/varvs/private/varpath, JSON parse at 64KiB cap)Push/PR blocked: GitHub identity
jbelkehas no write access toqwen-code-dev-bot/oh-my-cli.jbelke commentedon Aug 13, 2026
Update
Opened PR from a fork (no write access on the upstream remote).
jbelke:issue/876-repo-context-redact-name