Thanks to visit codestin.com
Credit goes to github.com

Skip to content

test: property-check display-width clustering and parseKey totality - #598

Merged
ndycode merged 3 commits into
mainfrom
claude/audit-79-display-width-property
Jun 19, 2026
Merged

ndycode merged 3 commits into
mainfrom
claude/audit-79-display-width-property

Conversation

@ndycode

@ndycode ndycode commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

What Changed

New test/property/display-width.property.test.ts (6 properties):

display-width — generated over an adversarial alphabet that includes every cluster mechanic the implementation special-cases (ZWJ, variation selector-16, combining keycap, combining accents, skin-tone modifiers, regional indicators, CJK, emoji):

  1. Totality and boundsdisplayWidth returns a non-negative integer bounded by two columns per code point, for any combination including pathological joiner/modifier soup.
  2. Plain-alphabet oracle — with no joiners/modifiers present, width equals the per-character sum and concatenation is exactly additive — the standing assumption the table formatter's geometry rests on (deliberately not asserted for the adversarial alphabet, where VS-16 promotion makes concatenation legitimately non-additive).
  3. Truncation contracttruncateToWidth returns a prefix whose reported width is displayWidth of the kept text (self-consistency between the two exports), never exceeds the budget, stops early only when the remaining gap is 0–1 columns (clusters max out at 2, so a 2-column gap proves the next cluster would have fit), and is idempotent.
  4. Budget monotonicity — widening the budget only ever extends the kept prefix.

parseKey:

  1. Totality — arbitrary byte buffers always produce a member of the KeyAction union; no input throws.
  2. Table fidelity — all 16 recognized ANSI sequences map to their documented actions, and every other generated string maps to null.

No SUT bugs found.

Validation

  • npm test -- test/property/display-width.property.test.ts test/display-width.test.ts test/ansi.test.ts — 25/25 (new 6 + existing suites untouched)
  • npm run typecheck (also via pre-commit hook)
  • npx eslint test/property/display-width.property.test.ts --max-warnings=0

Docs and Governance Checklist

  • Test-only; no behavior or docs surface changed

Risk and Rollback

  • Risk level: minimal — additive test file; conventions match the existing test/property/ suites.
  • Rollback plan: revert the single commit.

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB


Generated by Claude Code

note: greptile review for oc-chatgpt-multi-auth. cite files like lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.

Greptile Summary

adds six fast-check property tests for lib/ui/display-width.ts and lib/ui/ansi.ts#parseKey. the suite covers totality/bounds over an adversarial grapheme-cluster alphabet, a plain-text additive-width oracle, truncation self-consistency / maximality / idempotence, budget monotonicity with an embedded cluster-granularity guard, and parseKey totality + known-sequence table fidelity. no SUT bugs were found during the review.

  • display-width properties (4): adversarial alphabet exercises every cluster mechanic (ZWJ, VS-16, keycap, skin-tone, regional indicators, CJK, emoji); the monotonicity property doubles as a ≤2-column-per-cluster enforcement check via the step.width - narrow.width ≤ 2 assertion.
  • parseKey properties (2): totality test uses fc.uint8ArrayBuffer to probe raw bytes; table-fidelity test covers all 16 recognized ANSI escape sequences and asserts unknown strings map to null.
  • risk: test-only, purely additive; no production code paths are changed.

Confidence Score: 5/5

purely additive test file with no changes to production code — safe to merge

the change is a single new test file exercising well-understood pure functions with no side effects; the properties are logically sound, the adversarial alphabet covers all cluster mechanics the SUT special-cases, and there are no changes to library code, configuration, or any auth/token path

no files require special attention

Important Files Changed

Filename Overview
test/property/display-width.property.test.ts new property suite: 6 well-scoped fast-check properties covering display-width totality, plain-text oracle, truncation self-consistency/maximality/idempotence/monotonicity, and parseKey totality+table fidelity — no logic errors found

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[arbAdversarialText\nfc.array of grapheme cluster atoms] --> P1[Property 1\ndisplayWidth totality + bounds]
    B[arbPlainText\nfc.array of plain chars] --> P2[Property 2\nplain-text width oracle]
    A --> P3[Property 3\ntruncation self-consistency\nmaximality · idempotence]
    A --> P4[Property 4\nmonotonicity + cluster-granularity\nstep.width − narrow.width ≤ 2]

    C[fc.uint8Array maxLength 12] --> P5[Property 5\nparseKey totality\nKEY_ACTIONS.includes result]
    D[16 literal ANSI sequences] --> P6a[Table fidelity\nknown sequences → correct action]
    E[fc.string maxLength 6\nfiltered by pre] --> P6b[Unrecognized → null]

    P6a --> SUT2[parseKey\nBuffer → KeyAction]
    P6b --> SUT2
    P5 --> SUT2

    P1 --> SUT1[displayWidth\nstring → number]
    P2 --> SUT1
    P3 --> SUT3[truncateToWidth\nstring × budget → text × width]
    P4 --> SUT3
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[arbAdversarialText\nfc.array of grapheme cluster atoms] --> P1[Property 1\ndisplayWidth totality + bounds]
    B[arbPlainText\nfc.array of plain chars] --> P2[Property 2\nplain-text width oracle]
    A --> P3[Property 3\ntruncation self-consistency\nmaximality · idempotence]
    A --> P4[Property 4\nmonotonicity + cluster-granularity\nstep.width − narrow.width ≤ 2]

    C[fc.uint8Array maxLength 12] --> P5[Property 5\nparseKey totality\nKEY_ACTIONS.includes result]
    D[16 literal ANSI sequences] --> P6a[Table fidelity\nknown sequences → correct action]
    E[fc.string maxLength 6\nfiltered by pre] --> P6b[Unrecognized → null]

    P6a --> SUT2[parseKey\nBuffer → KeyAction]
    P6b --> SUT2
    P5 --> SUT2

    P1 --> SUT1[displayWidth\nstring → number]
    P2 --> SUT1
    P3 --> SUT3[truncateToWidth\nstring × budget → text × width]
    P4 --> SUT3
Loading

Fix All in Codex

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
test/property/display-width.property.test.ts:57-66
**`KEY_ACTIONS` not exhaustiveness-checked against the union type**

`KEY_ACTIONS: readonly KeyAction[]` is a widened annotation — TypeScript doesn't require it to contain every member of `KeyAction`. if a new variant (e.g. `"left"`) is added to the union and `parseKey` begins returning it, the totality test fails at runtime with a confusing "false is not true" message rather than a compile-time error. annotating the constant with a pattern that enforces exhaustion (e.g. typing it as a `readonly [KeyAction, ...KeyAction[]]` and using a mapped-type helper, or simply adding a compile-time `satisfies` tuple) would surface the gap the moment the type grows.

Reviews (3): Last reviewed commit: "Merge branch 'main' into claude/audit-79..." | Re-trigger Greptile

Six fast-check properties over the ui-02 measurement layer and the
stdin key parser:

- displayWidth is total, integer, non-negative, and bounded by two
  columns per code point over an adversarial alphabet (ZWJ, VS-16,
  keycap, combining marks, skin tones, regional indicators, CJK,
  emoji)
- plain alphabets (no joiners/modifiers) sum per-character widths
  exactly and concatenate additively - the table formatter's standing
  assumption
- truncateToWidth returns a self-consistent prefix (its reported
  width IS displayWidth of the kept text), stays in budget, stops
  only when the remaining gap is 0 or 1 columns (clusters max out at
  2), and is idempotent
- truncation prefixes grow monotonically with the width budget
- parseKey is total over arbitrary byte buffers and only returns
  known KeyAction values
- the full recognized-sequence table is pinned, and everything else
  maps to null

Companion to the property suites in #574/#575/#592-#597.

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@ndycode, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 29 minutes and 40 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 83bee9f1-301b-4626-93ee-50032ec71ad6

📥 Commits

Reviewing files that changed from the base of the PR and between fa9bde3 and d969f5f.

📒 Files selected for processing (1)
  • test/property/display-width.property.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/audit-79-display-width-property
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/audit-79-display-width-property

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 and usage tips.

Comment thread test/property/display-width.property.test.ts
One extra budget column can admit at most two more columns of content,
which is externally equivalent to 'no cluster wider than 2' - the
assumption the truncation maximality bound relies on.

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
@ndycode
ndycode merged commit e536a4c into main Jun 19, 2026
1 of 2 checks passed
@ndycode
ndycode deleted the claude/audit-79-display-width-property branch June 19, 2026 06:04
ndycode added a commit that referenced this pull request Jun 19, 2026
)

* test: property-check forecast recommendation and summary contracts

Seven fast-check properties over recommendForecastAccount,
summarizeForecast, and buildForecastExplanation with generated result
pools (0-8 accounts, full availability/risk/wait/flag space):

- a recommendation always points at a recommendable result (not
  disabled, hard-failed, exhausted, or unavailable); null only when
  no such candidate exists
- a ready candidate always wins with the minimal risk score among
  ready candidates, and the reason says so
- with no ready candidate, the shortest delayed wait wins
- an empty candidate pool names the actual blocker class: 'blocked or
  exhausted' guidance iff some account is blocked/exhausted rather
  than disabled/hard-failed (the #exhausted-flag regression guard)
- the recommendation is invariant under input order
- the summary partitions availability exactly (ready + delayed +
  unavailable === total) and counts high-risk rows
- the explanation mirrors inputs in order and marks selected on
  exactly the recommended index

Companion to the property suites in #574/#575/#592-#598.

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB

* test: keep forecast generator in the reachable domain; shuffle permutations

Greptile flagged that availability and exhausted were drawn
independently (evaluateForecastAccount only emits exhausted accounts
as delayed) and that order-invariance only probed reversal. The
generator now derives the pairing, and the invariance property checks
an arbitrary generated permutation plus the reversal. Validated at
FAST_CHECK_NUM_RUNS=1000.

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB

---------

Co-authored-by: Claude <[email protected]>
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