Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions docs/schema/requirement.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

## Reference (`REF`)

### Record Reference (A to B)

| ID | Name | Severity | Description |
| -------- | ------------------------------------- | -------- | ------------------------------------------------------------------------- |
| `REF001` | `scene-to-log` | `ERROR` | `Scene.log_token` refers to `Log` record. |
Expand All @@ -41,15 +43,25 @@
| `REF010` | `instance-to-first-sample-annotation` | `ERROR` | `Instance.first_annotation_token` refers to `SampleAnnotation` record. |
| `REF011` | `instance-to-last-sample-annotation` | `ERROR` | `Instance.last_annotation_token` refers to `SampleAnnotation` record. |
| `REF012` | `lidarseg-to-sample-data` | `ERROR` | `LidarSeg.sample_data_token` refers to `SampleData` record. |
| `REF013` | `sample-data-filename-presence` | `ERROR` | `SampleData.filename` exists. |
| `REF014` | `sample-data-info-filename-presence` | `ERROR` | `SampleData.info_filename` exists if it is not `None`. |
| `REF015` | `lidarseg-filename-presence` | `ERROR` | `LidarSeg.filename` exists if `lidarseg.json` exists. |
| `REF016` | `sample-next-to-another` | `ERROR` | `Sample.next` refers to another one unless it is empty. |
| `REF017` | `sample-prev-to-another` | `ERROR` | `Sample.prev` refers to another one unless it is empty. |
| `REF018` | `sample-annotation-next-to-another` | `ERROR` | `SampleAnnotation.next` refers to another one unless it is empty. |
| `REF019` | `sample-annotation-prev-to-another` | `ERROR` | `SampleAnnotation.prev` refers to another one unless it is empty. |
| `REF020` | `sample-data-next-to-another` | `ERROR` | `SampleData.next` refers to another one unless it is empty. |
| `REF021` | `sample-data-prev-to-another` | `ERROR` | `SampleData.prev` refers to another one unless it is empty. |

### Record Reference (A to A')

| ID | Name | Severity | Description |
| -------- | ----------------------------------- | -------- | ----------------------------------------------------------------- |
| `REF101` | `sample-next-to-another` | `ERROR` | `Sample.next` refers to another one unless it is empty. |
| `REF102` | `sample-prev-to-another` | `ERROR` | `Sample.prev` refers to another one unless it is empty. |
| `REF103` | `sample-annotation-next-to-another` | `ERROR` | `SampleAnnotation.next` refers to another one unless it is empty. |
| `REF104` | `sample-annotation-prev-to-another` | `ERROR` | `SampleAnnotation.prev` refers to another one unless it is empty. |
| `REF105` | `sample-data-next-to-another` | `ERROR` | `SampleData.next` refers to another one unless it is empty. |
| `REF106` | `sample-data-prev-to-another` | `ERROR` | `SampleData.prev` refers to another one unless it is empty. |

### File Reference

| ID | Name | Severity | Description |
| -------- | ------------------------------------ | -------- | ------------------------------------------------------ |
| `REF201` | `sample-data-filename-presence` | `ERROR` | `SampleData.filename` exists. |
| `REF202` | `sample-data-info-filename-presence` | `ERROR` | `SampleData.info_filename` exists if it is not `None`. |
| `REF203` | `lidarseg-filename-presence` | `ERROR` | `LidarSeg.filename` exists if `lidarseg.json` exists. |

## Format (`FMT`)

Expand Down
18 changes: 9 additions & 9 deletions t4_devkit/sanity/reference/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
from .ref010 import * # noqa
from .ref011 import * # noqa
from .ref012 import * # noqa
from .ref013 import * # noqa
from .ref014 import * # noqa
from .ref015 import * # noqa
from .ref016 import * # noqa
from .ref017 import * # noqa
from .ref018 import * # noqa
from .ref019 import * # noqa
from .ref020 import * # noqa
from .ref021 import * # noqa
from .ref101 import * # noqa
from .ref102 import * # noqa
from .ref103 import * # noqa
from .ref104 import * # noqa
from .ref105 import * # noqa
from .ref106 import * # noqa
from .ref201 import * # noqa
from .ref202 import * # noqa
from .ref203 import * # noqa
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
from ..registry import CHECKERS
from .base import RecordReferenceChecker

__all__ = ["REF101"]


@CHECKERS.register()
class REF016(RecordReferenceChecker):
"""A checker of REF016."""
class REF101(RecordReferenceChecker):
"""A checker of REF101."""

id = RuleID("REF016")
id = RuleID("REF101")
name = RuleName("sample-next-to-another")
severity = Severity.ERROR
description = "'Sample.next' refers to another one unless it is empty."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
from ..registry import CHECKERS
from .base import RecordReferenceChecker

__all__ = ["REF102"]


@CHECKERS.register()
class REF017(RecordReferenceChecker):
"""A checker of REF017."""
class REF102(RecordReferenceChecker):
"""A checker of REF102."""

id = RuleID("REF017")
id = RuleID("REF102")
name = RuleName("sample-prev-to-another")
severity = Severity.ERROR
description = "'Sample.prev' refers to another one unless it is empty."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
from ..registry import CHECKERS
from .base import RecordReferenceChecker

__all__ = ["REF103"]


@CHECKERS.register()
class REF018(RecordReferenceChecker):
"""A checker of REF018."""
class REF103(RecordReferenceChecker):
"""A checker of REF103."""

id = RuleID("REF018")
id = RuleID("REF103")
name = RuleName("sample-annotation-next-to-another")
severity = Severity.ERROR
description = "'SampleAnnotation.next' refers to another one unless it is empty."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
from ..registry import CHECKERS
from .base import RecordReferenceChecker

__all__ = ["REF104"]


@CHECKERS.register()
class REF019(RecordReferenceChecker):
"""A checker of REF019."""
class REF104(RecordReferenceChecker):
"""A checker of REF104."""

id = RuleID("REF019")
id = RuleID("REF104")
name = RuleName("sample-annotation-prev-to-another")
severity = Severity.ERROR
description = "'SampleAnnotation.prev' refers to another one unless it is empty."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
from ..registry import CHECKERS
from .base import RecordReferenceChecker

__all__ = ["REF105"]


@CHECKERS.register()
class REF020(RecordReferenceChecker):
"""A checker of REF020."""
class REF105(RecordReferenceChecker):
"""A checker of REF105."""

id = RuleID("REF020")
id = RuleID("REF105")
name = RuleName("sample-data-next-to-another")
severity = Severity.ERROR
description = "'SampleData.next' refers to another one unless it is empty."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
from ..registry import CHECKERS
from .base import RecordReferenceChecker

__all__ = ["REF106"]


@CHECKERS.register()
class REF021(RecordReferenceChecker):
"""A checker of REF021."""
class REF106(RecordReferenceChecker):
"""A checker of REF106."""

id = RuleID("REF021")
id = RuleID("REF106")
name = RuleName("sample-data-prev-to-another")
severity = Severity.ERROR
description = "'SampleData.prev' refers to another one unless it is empty."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
from ..context import SanityContext


__all__ = ["REF013"]
__all__ = ["REF201"]


@CHECKERS.register()
class REF013(FileReferenceChecker):
"""A checker of REF013."""
class REF201(FileReferenceChecker):
"""A checker of REF201."""

id = RuleID("REF013")
id = RuleID("REF201")
name = RuleName("sample-data-filename-presence")
severity = Severity.ERROR
description = "'SampleData.filename' exists."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
from ..context import SanityContext


__all__ = ["REF014"]
__all__ = ["REF202"]


@CHECKERS.register()
class REF014(FileReferenceChecker):
"""A checker of REF014."""
class REF202(FileReferenceChecker):
"""A checker of REF202."""

id = RuleID("REF014")
id = RuleID("REF202")
name = RuleName("sample-data-filename-presence")

Copilot AI Dec 3, 2025

Copy link

Choose a reason for hiding this comment

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

The name field 'sample-data-filename-presence' is inconsistent with the description and actual functionality. This checker validates 'info_filename', not 'filename'. The name should be 'sample-data-info-filename-presence' to match the documentation and checker ID REF202.

Suggested change
name = RuleName("sample-data-filename-presence")
name = RuleName("sample-data-info-filename-presence")

Copilot uses AI. Check for mistakes.
severity = Severity.ERROR
description = "'SampleData.filename' exists."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
from ..context import SanityContext


__all__ = ["REF015"]
__all__ = ["REF203"]


@CHECKERS.register()
class REF015(FileReferenceChecker):
"""A checker of REF015."""
class REF203(FileReferenceChecker):
"""A checker of REF203."""

id = RuleID("REF015")
id = RuleID("REF203")
name = RuleName("lidarseg-filename-presence")
severity = Severity.ERROR
description = "'LidarSeg.filename' exists."
Expand Down
20 changes: 10 additions & 10 deletions tests/sanity/test_reference_checkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
from t4_devkit.sanity.reference.ref010 import REF010
from t4_devkit.sanity.reference.ref011 import REF011
from t4_devkit.sanity.reference.ref012 import REF012
from t4_devkit.sanity.reference.ref013 import REF013
from t4_devkit.sanity.reference.ref014 import REF014
from t4_devkit.sanity.reference.ref201 import REF201
from t4_devkit.sanity.reference.ref202 import REF202

# Sample dataset root (non-versioned)
SAMPLE_ROOT = Path(__file__).parent.parent.joinpath("sample", "t4dataset")
Expand Down Expand Up @@ -86,8 +86,8 @@ def _ensure_is_valid(records: list[dict]) -> list[dict]:
REF009,
REF010,
REF011,
REF013,
REF014,
REF201,
REF202,
],
)
def test_reference_checkers_pass(checker_cls: type) -> None:
Expand Down Expand Up @@ -198,8 +198,8 @@ def test_ref005_fail_invalid_sample_reference(tmp_path: Path) -> None:
assert any("nonexistent_sample_token" in r for r in report.reasons)


def test_ref013_fail_missing_filename(tmp_path: Path) -> None:
"""Mutate sample_data.json to point to a missing file for REF013."""
def test_ref201_fail_missing_filename(tmp_path: Path) -> None:
"""Mutate sample_data.json to point to a missing file for REF201."""
root = _copy_dataset(tmp_path / "dataset_ref013_fail")

Copilot AI Dec 3, 2025

Copy link

Choose a reason for hiding this comment

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

The directory name 'dataset_ref013_fail' should be updated to 'dataset_ref201_fail' to match the renamed checker REF201.

Suggested change
root = _copy_dataset(tmp_path / "dataset_ref013_fail")
root = _copy_dataset(tmp_path / "dataset_ref201_fail")

Copilot uses AI. Check for mistakes.
ann_dir = root / "annotation"
if not ann_dir.exists():
Expand All @@ -210,15 +210,15 @@ def test_ref013_fail_missing_filename(tmp_path: Path) -> None:
records[0]["filename"] = "data/CAM_FRONT/does_not_exist.jpg"
_dump_json(sd_path, records)

checker = REF013()
checker = REF201()
report = checker(_context(root))
assert not report.is_passed(strict=True)
assert report.reasons
assert any("does_not_exist.jpg" in r for r in report.reasons)


def test_ref014_fail_missing_info_filename(tmp_path: Path) -> None:
"""Add an info_filename pointing to a non-existing file to trigger REF014 failure."""
def test_ref202_fail_missing_info_filename(tmp_path: Path) -> None:
"""Add an info_filename pointing to a non-existing file to trigger REF202 failure."""
root = _copy_dataset(tmp_path / "dataset_ref014_fail")

Copilot AI Dec 3, 2025

Copy link

Choose a reason for hiding this comment

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

The directory name 'dataset_ref014_fail' should be updated to 'dataset_ref202_fail' to match the renamed checker REF202.

Suggested change
root = _copy_dataset(tmp_path / "dataset_ref014_fail")
root = _copy_dataset(tmp_path / "dataset_ref202_fail")

Copilot uses AI. Check for mistakes.
ann_dir = root / "annotation"
if not ann_dir.exists():
Expand All @@ -229,7 +229,7 @@ def test_ref014_fail_missing_info_filename(tmp_path: Path) -> None:
records[0]["info_filename"] = "data/CAM_FRONT/missing_info.json"
_dump_json(sd_path, records)

checker = REF014()
checker = REF202()
report = checker(_context(root))
assert not report.is_passed(strict=True)
assert report.reasons
Expand Down
Loading