Skip to content

test: id + file/ignore — monotonic ID ordering and ignore pattern coverage#394

Closed
anandgupta42 wants to merge 1 commit intomainfrom
claude/test-id-ignore-20260323-012pJZ9ApRnh2fGKMS957frr
Closed

test: id + file/ignore — monotonic ID ordering and ignore pattern coverage#394
anandgupta42 wants to merge 1 commit intomainfrom
claude/test-id-ignore-20260323-012pJZ9ApRnh2fGKMS957frr

Conversation

@anandgupta42
Copy link
Contributor

@anandgupta42 anandgupta42 commented Mar 23, 2026

Summary

What does this PR do?

1. Identifiersrc/id/id.ts (8 new tests)

This module generates all monotonic IDs used across the application for sessions, messages, parts, permissions, and tools. Zero tests existed previously. New coverage includes:

  • Ascending IDs are strictly increasing (lexicographic order matches creation order)
  • Descending IDs are strictly decreasing
  • Correct prefix for all ID types (ses_, msg_, prt_, per_, tool_)
  • Same-millisecond uniqueness via internal counter (100 rapid-fire IDs all unique)
  • given parameter passthrough when prefix matches, throws on mismatch
  • timestamp() relative ordering is preserved between IDs created at different times
  • timestamp() round-trips exactly for small timestamps within 48-bit range

Why it matters: ID misordering would cause messages to display out of order in the TUI and API. Duplicate IDs would cause silent data corruption. The timestamp() function is used in truncation.ts for retention cleanup — incorrect relative ordering would cause premature or missed cleanup.

Notable finding: timestamp() does not return the actual wall-clock Date.now() for modern timestamps because BigInt(ts) * BigInt(0x1000) exceeds 48 bits (the storage width). However, relative comparisons between timestamp() values remain correct, which is how it's used in practice. The tests document this behavior.

2. FileIgnore.matchsrc/file/ignore.ts (6 new tests, extending 1 existing)

This function controls which files are excluded from watching, scanning, and tool access. The existing test only covered node_modules directory matching. New coverage includes:

  • All registered directory patterns beyond node_modules (dist, build, .git, __pycache__, .next, out, bin, desktop)
  • File glob patterns (.swp, .DS_Store, .pyc, .log, tmp/**)
  • Negative cases — normal source files (src/index.ts, README.md, package.json) are NOT ignored
  • Whitelist override — whitelisted patterns prevent directory matches
  • Extra patterns — caller-supplied patterns extend the default ignore set
  • Windows-style path separators (\\) are handled correctly

Why it matters: If whitelist overrides don't work, users can't customize which directories are watched. If extra patterns silently fail, config-driven ignore rules are broken. False positives would silently exclude source files from the agent's view.

Type of change

  • New feature (non-breaking change which adds functionality)

Issue for this PR

N/A — proactive test coverage from automated test discovery

How did you verify your code works?

bun test test/id/id.test.ts          # 8 pass
bun test test/file/ignore.test.ts    # 7 pass (1 existing + 6 new)

Checklist

  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

https://claude.ai/code/session_012pJZ9ApRnh2fGKMS957frr

Summary by CodeRabbit

  • Tests
    • Increased test coverage for file pattern matching behavior, with improvements for advanced directory patterns, glob file matching, configuration options, and cross-platform path separator handling.
    • Implemented comprehensive tests validating identifier monotonic ID generation behavior, including type-specific ID prefixes, strict ID ordering (ascending and descending), uniqueness guarantees, and accurate timestamp handling.

…erage

Adds 8 tests for Identifier module (zero prior coverage) verifying monotonic
ordering, prefix correctness, uniqueness, and timestamp relative ordering.
Extends FileIgnore.match tests from 1 to 7 covering whitelist overrides,
extra patterns, file globs, Windows separators, and negative cases.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

https://claude.ai/code/session_012pJZ9ApRnh2fGKMS957frr
Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai
Copy link

coderabbitai bot commented Mar 23, 2026

📝 Walkthrough

Walkthrough

Two test suites were added or expanded to increase coverage for file ignore pattern matching and identifier monotonic ID generation, validating directory patterns, glob matches, option handling, ID uniqueness, and timestamp properties.

Changes

Cohort / File(s) Summary
FileIgnore pattern matching tests
packages/opencode/test/file/ignore.test.ts
Expanded test suite with new describe block covering directory/file pattern matching, whitelist suppression, extra pattern extension, and Windows path separator handling.
Identifier monotonic ID generation tests
packages/opencode/test/id/id.test.ts
New test suite validating ascending/descending ID generation, type-specific prefixes, uniqueness across milliseconds, overloaded function behavior with existing IDs, and timestamp round-trip accuracy.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

contributor

Poem

🐰 A rabbit hops through test cases true,
Checking IDs ascending, descending too!
File patterns, timestamps, all aligned,
Quality assurance, perfectly designed! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically summarizes the two main changes: adding test coverage for monotonic ID ordering and ignore pattern matching.
Description check ✅ Passed The description comprehensively covers all required template sections with detailed explanations of what changed, why it matters, and verification steps.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/test-id-ignore-20260323-012pJZ9ApRnh2fGKMS957frr

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/test/id/id.test.ts`:
- Around line 33-39: Change the test to use a fixed timestamp so the counter
path is exercised deterministically: instead of repeatedly calling
Identifier.ascending("session") with real time, call the Identifier creation API
that accepts an explicit timestamp (e.g., Identifier.create or
Identifier.ascending overload that takes a timestamp) and pass a constant value
when generating the 100 IDs, then assert ids.size === 100; this guarantees all
IDs share the same millisecond and forces the monotonic counter behavior in
Identifier.create / Identifier.ascending.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ca7a2a4c-236b-404c-89f4-e72403c24e06

📥 Commits

Reviewing files that changed from the base of the PR and between 8eb13d4 and ad3a7f8.

📒 Files selected for processing (2)
  • packages/opencode/test/file/ignore.test.ts
  • packages/opencode/test/id/id.test.ts

Comment on lines +33 to +39
test("same-millisecond IDs are unique via counter", () => {
const ids = new Set<string>()
for (let i = 0; i < 100; i++) {
ids.add(Identifier.ascending("session"))
}
expect(ids.size).toBe(100)
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Make the “same-millisecond” uniqueness test deterministic.

Line 33-39 does not force a single timestamp, so it can pass without actually exercising the counter path (e.g., if calls span multiple milliseconds). Use a fixed timestamp in Identifier.create(...) to guarantee this test validates the intended behavior.

Suggested patch
   test("same-millisecond IDs are unique via counter", () => {
+    const fixedTs = 1_000_000
     const ids = new Set<string>()
     for (let i = 0; i < 100; i++) {
-      ids.add(Identifier.ascending("session"))
+      ids.add(Identifier.create("session", false, fixedTs))
     }
     expect(ids.size).toBe(100)
   })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/opencode/test/id/id.test.ts` around lines 33 - 39, Change the test
to use a fixed timestamp so the counter path is exercised deterministically:
instead of repeatedly calling Identifier.ascending("session") with real time,
call the Identifier creation API that accepts an explicit timestamp (e.g.,
Identifier.create or Identifier.ascending overload that takes a timestamp) and
pass a constant value when generating the 100 IDs, then assert ids.size === 100;
this guarantees all IDs share the same millisecond and forces the monotonic
counter behavior in Identifier.create / Identifier.ascending.

anandgupta42 added a commit that referenced this pull request Mar 23, 2026
Merges 9 test PRs (#390, #394, #395, #396, #397, #398, #399, #401, #387)
into a single PR, discarding 4 duplicates (#391, #392, #393, #400).

**New test coverage:**
- `id.test.ts` — 14 tests: Identifier generation, monotonic ordering, timestamp extraction, Zod schema
- `shell.test.ts` — 9 tests: shell blacklist enforcement for fish/nu, cache reset, fallback
- `path-traversal.test.ts` — 7 tests (new): `Protected.isSensitiveWrite` for .pem/.key, .gnupg, .env variants
- `ignore.test.ts` — 7 tests (new): `FileIgnore.match` directory patterns, globs, whitelist overrides
- `paths-parsetext.test.ts` — 16 tests: `ConfigPaths.parseText` env/file substitution, JSONC parsing
- `finops-formatting.test.ts` — 14 tests: `formatBytes`/`truncateQuery` edge cases
- `finops-role-access.test.ts` — 10 tests: RBAC `formatGrants`/`formatHierarchy`/`formatUserRoles`
- `tool-lookup.test.ts` — 4 tests: Zod schema introspection for tool parameters
- `summary-git-path.test.ts` — 10 tests: `unquoteGitPath` decoding for non-ASCII filenames
- `tracing.test.ts` — 2 tests (added): Recap loop detection boundaries
- `patch.test.ts` — 9 tests (added): `maybeParseApplyPatchVerified` entry point coverage
- `instruction.test.ts` — 13 tests (new): `InstructionPrompt.loaded()` dedup guards
- `message-v2.test.ts` — 23 tests (new): `MessageV2.filterCompacted()` boundary detection

**Bug fixes (discovered during testing):**
- `finops-formatting.ts`: fix `formatBytes` crash on negative/NaN/fractional inputs
- `finops-formatting.ts`: fix `truncateQuery` returning empty for whitespace-only, exceeding `maxLen` when < 4
- `training-import.test.ts`: fix pre-existing typecheck errors (missing `context`/`rule` mock keys)
- `instruction.test.ts`, `message-v2.test.ts`: fix `MessageV2.Part` cast and branded ID type errors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@anandgupta42
Copy link
Contributor Author

Consolidated into #403

@anandgupta42 anandgupta42 deleted the claude/test-id-ignore-20260323-012pJZ9ApRnh2fGKMS957frr branch March 23, 2026 17:11
anandgupta42 added a commit that referenced this pull request Mar 23, 2026
* test: consolidated test coverage across 9 modules (133 new tests)

Merges 9 test PRs (#390, #394, #395, #396, #397, #398, #399, #401, #387)
into a single PR, discarding 4 duplicates (#391, #392, #393, #400).

**New test coverage:**
- `id.test.ts` — 14 tests: Identifier generation, monotonic ordering, timestamp extraction, Zod schema
- `shell.test.ts` — 9 tests: shell blacklist enforcement for fish/nu, cache reset, fallback
- `path-traversal.test.ts` — 7 tests (new): `Protected.isSensitiveWrite` for .pem/.key, .gnupg, .env variants
- `ignore.test.ts` — 7 tests (new): `FileIgnore.match` directory patterns, globs, whitelist overrides
- `paths-parsetext.test.ts` — 16 tests: `ConfigPaths.parseText` env/file substitution, JSONC parsing
- `finops-formatting.test.ts` — 14 tests: `formatBytes`/`truncateQuery` edge cases
- `finops-role-access.test.ts` — 10 tests: RBAC `formatGrants`/`formatHierarchy`/`formatUserRoles`
- `tool-lookup.test.ts` — 4 tests: Zod schema introspection for tool parameters
- `summary-git-path.test.ts` — 10 tests: `unquoteGitPath` decoding for non-ASCII filenames
- `tracing.test.ts` — 2 tests (added): Recap loop detection boundaries
- `patch.test.ts` — 9 tests (added): `maybeParseApplyPatchVerified` entry point coverage
- `instruction.test.ts` — 13 tests (new): `InstructionPrompt.loaded()` dedup guards
- `message-v2.test.ts` — 23 tests (new): `MessageV2.filterCompacted()` boundary detection

**Bug fixes (discovered during testing):**
- `finops-formatting.ts`: fix `formatBytes` crash on negative/NaN/fractional inputs
- `finops-formatting.ts`: fix `truncateQuery` returning empty for whitespace-only, exceeding `maxLen` when < 4
- `training-import.test.ts`: fix pre-existing typecheck errors (missing `context`/`rule` mock keys)
- `instruction.test.ts`, `message-v2.test.ts`: fix `MessageV2.Part` cast and branded ID type errors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address code review findings — test artifact leakage and cleanup

- summary-git-path.test.ts: use tmpdir() instead of projectRoot to prevent
  Storage.write() from polluting the developer's .opencode/storage/ directory
- finops-role-access.test.ts: consolidate duplicate afterAll hooks to ensure
  ALTIMATE_TELEMETRY_DISABLED env var is cleaned up after tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants