Skip to content

fix: avoid O(N²) shallow-copy in mapSensitivePaths schema traversal#55018

Merged
vincentkoc merged 2 commits into
openclaw:mainfrom
xdhuangyandi:yandi/sensitive
Jun 24, 2026
Merged

fix: avoid O(N²) shallow-copy in mapSensitivePaths schema traversal#55018
vincentkoc merged 2 commits into
openclaw:mainfrom
xdhuangyandi:yandi/sensitive

Conversation

@xdhuangyandi

@xdhuangyandi xdhuangyandi commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes an issue where config schema hint generation could spend excessive time copying a growing hints map while walking large Zod schema trees. As OpenClaw's config schema grows, the recursive { ...hints } copy pattern turns traversal into repeated work and can block config/schema initialization paths.

Why This Change Was Made

The traversal now copies the caller-provided hints map once at the public mapSensitivePaths boundary, then uses an internal accumulator for recursive schema walking. That keeps the existing copy-return contract for callers while removing the recursive O(N^2)-style shallow-copy cost.

User Impact

Config schema and UI-hint generation stay behaviorally identical but avoid a large repeated-allocation slowdown on bigger schema trees. Sensitive config path marking remains unchanged.

Evidence

  • Autoreview branch vs origin/main: clean, no accepted/actionable findings, patch correctness 0.98.
  • Crabbox Azure cbx_fd11288428d7, run run_627efbec345c: focused src/config/schema.hints.test.ts passed 11 tests.
  • Crabbox Azure cbx_fd11288428d7, run run_627efbec345c: corepack pnpm check:changed passed.
  • Touched-file oxfmt --check and git diff --check passed after the final rebase.
  • Synthetic benchmark on 3000 schema sections / 6000 mapped paths: old recursive shallow-copy traversal about 8599 ms; new single-copy accumulator about 11.6 ms.

Compatibility / Migration

No config, migration, or user action required. The public mapSensitivePaths function still returns a new hints map and does not mutate caller-owned entries.

Co-authored-by: Vincent Koc [email protected]

@greptile-apps

greptile-apps Bot commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes an O(N²) performance bottleneck in mapSensitivePaths by replacing per-call { ...hints } shallow copies with a single in-place mutation pass. The public API signature and return semantics are preserved; a new private mapSensitivePathsMut helper carries the recursive logic.\n\n- Correctness: The refactored logic is functionally identical to the original — both accumulate sensitive-path entries into the same hints object. All 5 existing tests pass without modification.\n- Call-site audit: The only production call site (schema-base.ts:76) passes a freshly constructed buildBaseHints() result, so the new mutation semantic has no observable side-effect on callers.\n- Behavioral change worth noting: mapSensitivePaths now mutates its hints argument in-place (in addition to returning it). Since the function is exported, a JSDoc note would help future callers avoid surprises — flagged as a non-blocking P2 suggestion.\n- Performance impact: O(N) single-pass traversal vs. the previous O(N²) allocation loop; the PR description reports ~30 s → negligible for the full OpenClawSchema tree.

Confidence Score: 5/5

Safe to merge — minimal, well-scoped refactor with no behavioral regressions and full test coverage.

The change is a clean algorithmic optimisation with a single modified file. Logic equivalence is verified by the existing test suite; the only production call site passes a fresh object so mutation semantics are harmless. The sole open item is a non-blocking documentation suggestion.

No files require special attention.

Important Files Changed

Filename Overview
src/config/schema.hints.ts Extracts a private mapSensitivePathsMut helper that mutates hints in-place instead of spreading it on every recursive call, reducing complexity from O(N²) to O(N). Logic is functionally identical; all production call sites pass freshly created objects so the mutation semantic change is safe.

Comments Outside Diff (1)

  1. src/config/schema.hints.ts, line 191-201 (link)

    P2 Document mutation side-effect on the public function

    The public mapSensitivePaths now mutates its hints argument in-place, which is a semantic change from the original (which returned a fresh object). All current call sites pass a freshly created {} or buildBaseHints(), so there's no regression here, but since the function is exported, adding a brief JSDoc note would prevent future callers from being surprised:

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/config/schema.hints.ts
    Line: 191-201
    
    Comment:
    **Document mutation side-effect on the public function**
    
    The public `mapSensitivePaths` now mutates its `hints` argument in-place, which is a semantic change from the original (which returned a fresh object). All current call sites pass a freshly created `{}` or `buildBaseHints()`, so there's no regression here, but since the function is exported, adding a brief JSDoc note would prevent future callers from being surprised:
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/config/schema.hints.ts
Line: 191-201

Comment:
**Document mutation side-effect on the public function**

The public `mapSensitivePaths` now mutates its `hints` argument in-place, which is a semantic change from the original (which returned a fresh object). All current call sites pass a freshly created `{}` or `buildBaseHints()`, so there's no regression here, but since the function is exported, adding a brief JSDoc note would prevent future callers from being surprised:

```suggestion
/**
 * Traverses the Zod schema tree and marks every sensitive path in `hints`.
 *
 * Note: `hints` is mutated in-place for performance (avoids O(N²) copies).
 * The same object is also returned for call-site convenience.
 */
export function mapSensitivePaths(
  schema: z.ZodType,
  path: string,
  hints: ConfigUiHints,
): ConfigUiHints {
  // Mutate `hints` in-place to avoid O(N²) shallow-copy overhead.
  // Previous impl did `{ ...hints }` on every recursive call which caused
  // ~30 s blocking for the full OpenClawSchema tree.
  mapSensitivePathsMut(schema, path, hints);
  return hints;
}
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: avoid O(N²) shallow-copy in mapSens..." | Re-trigger Greptile

@xdhuangyandi

Copy link
Copy Markdown
Contributor Author

Gentle ping 🙏

CI is all green, and the Greptile P2 feedback (JSDoc note on in-place mutation) has been addressed in the latest commit.
This PR is a single-file performance optimization: refactors mapSensitivePaths from O(N²) shallow copies to O(N) in-place mutation, improving performance (~30s → negligible) with identical logic (all 5 existing tests pass).
Happy to rebase, squash, or adjust if needed — thanks for reviewing!

@xdhuangyandi

Copy link
Copy Markdown
Contributor Author

Just following up on this PR in case it fell through the cracks 🙏

The branch is in good shape: CI is green, the prior review feedback has been addressed, and there shouldn’t be any remaining action items on my side.

It’s still a small, single-file performance optimization with unchanged behavior. Happy to rebase, squash, or make any further adjustments if needed. Thanks again for reviewing when you have time.

@clawsweeper

clawsweeper Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper review: did not complete due to Codex infrastructure failure. Reviewed June 23, 2026, 11:49 PM ET / 03:49 UTC.

Summary
Review failed before ClawSweeper could summarize the requested change.

PR surface: Source +11. Total +11 across 1 file.

Reproducibility: unclear. The review failed before ClawSweeper could establish a reproduction path.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: unknown-data-model-change: src/config/schema.hints.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Not assessed.
Failure reason: timeout.

This is a ClawSweeper/Codex infrastructure failure, not a PR readiness or patch-quality verdict.
Keep any merge decision on the normal maintainer review path until ClawSweeper can complete a fresh review.

Risk before merge

  • [P1] No close action taken because the review did not complete.

Maintainer options:

  1. Decide the mitigation before merge
    Retry the Codex review after fixing the execution failure.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • Review did not complete, so no work-lane recommendation was made.
Review details

Best possible solution:

Retry the Codex review after fixing the execution failure.

Do we have a high-confidence way to reproduce the issue?

Unclear. The review failed before ClawSweeper could establish a reproduction path.

Is this the best way to solve the issue?

Unclear. Retry the review first so ClawSweeper can evaluate the actual issue and fix direction.

AGENTS.md: unclear because the file could not be read completely.

Codex review notes: model internal, reasoning high; reviewed against 89acdd95dcbd.

Label changes

Label changes:

  • remove P2: Current review triage priority is none.
  • remove rating: 🧂 unranked krab: Current review failed before PR readiness was assessed, so no rating label should remain.
  • remove merge-risk: 🚨 compatibility: Current PR review selected no merge-risk labels.
  • remove status: 📣 needs proof: Current PR status no longer selects a status label.
Evidence reviewed

PR surface:

Source +11. Total +11 across 1 file.

View PR surface stats
Area Files Added Removed Net
Source 1 23 12 +11
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 1 23 12 +11

What I checked:

  • failure reason: timeout.
  • codex failure detail: Codex review failed for this PR: Codex process timed out after 1200000ms.
  • codex stderr: No stderr captured.
  • codex stdout: ":false,"requiresProductDecision":false,"reproductionAssessment":"Unclear; review still in progress.","solutionAssessment":"Unclear; review still in progress.","visionFit":"not_applicable","visionFitReason":"Review still in progress.","visionFitEvidence":[],"implementationComplexity":"not_applicable","autoImplementationCandidate":"none","rootCauseCluster":{"confidence":"low","canonicalRef":null,"currentItemRelationship":"independent","summary":"Review still in progress.","members":[]},"agentsPolicyStatus":{"found":true,"readFully":true,"applied":true,"status":"found_applied","summary":"Root AGENTS.md was read fully and its PR review, config-compatibility, and evidence requirements are being applied."},"reviewFindings":[],"securityReview":{"status":"not_applicable","summary":"Review still in progress.","concerns":[]},"realBehaviorProof":{"status":".
  • process error code: ETIMEDOUT.

Likely related people:

  • unknown: Codex failed before it could trace repository history. (role: review did not complete; confidence: low)
How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels May 19, 2026
@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label May 19, 2026
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. label May 19, 2026
@clawsweeper

clawsweeper Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat.

Where did the egg go?
  • The egg game starts only after the PR passes the real-behavior proof check.
  • Before that, no creature or rarity is rolled. The treat waits for real proof.
  • This is still just collectible flavor: proof affects review readiness, not creature quality.

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Jun 9, 2026
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 9, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label Jun 10, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. labels Jun 10, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 20, 2026
@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jun 20, 2026
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. label Jun 21, 2026
@vincentkoc vincentkoc self-assigned this Jun 24, 2026
@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Dependency graph guard cleared

This PR no longer has blocked dependency graph changes. A future dependency graph change requires a fresh /allow-dependencies-change comment after the guard blocks that new head SHA.

  • Current SHA: abf91adf242990eaa544d5d6efa61206dbc4a8d9

@vincentkoc

Copy link
Copy Markdown
Member

Maintainer closeout proof for abf91adf242990eaa544d5d6efa61206dbc4a8d9:

  • Fixed the accumulator shape so mapSensitivePaths avoids repeated recursive shallow copies while still returning a new hints map instead of mutating caller-owned input.
  • Added regression coverage for the no-mutation public contract in src/config/schema.hints.test.ts.
  • Local focused proof: ./node_modules/.bin/oxfmt --check src/config/schema.hints.ts src/config/schema.hints.test.ts, git diff --check, and a direct tsx contract smoke for non-mutating output.
  • Crabbox proof: Azure direct Crabbox cbx_fd11288428d7, run run_627efbec345c, passed corepack pnpm test:serial src/config/schema.hints.test.ts and corepack pnpm check:changed; lease stopped.
  • Autoreview: .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main returned no accepted/actionable findings.
  • Hosted exact-head gates are green; OPENCLAW_TESTBOX=1 scripts/pr prepare-run 55018 passed.

Ready to merge.

@vincentkoc

Copy link
Copy Markdown
Member

Merged via squash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. size: S triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants