Skip to content
Closed

2.5.2 #336

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
179 changes: 179 additions & 0 deletions audit/AUDIT.md

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions audit/LEDGER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
| id | title | severity | status | next | updated |
|---|---|---|---|---|---|
| F-0001 | Core lifecycle example does not compile against its documented header | major | fixed | Verifier | 2026-07-22 |
| F-0002 | Documentation and public API tests release errors with a no-op helper | major | superseded-by-class | — | 2026-07-22 |
| F-0003 | ray_eval_str null-return contract contradicts the public value invariant | major | superseded-by-class | — | 2026-07-22 |
| F-0004 | Public null-sentinel contract contradicts its own predicates | major | superseded-by-class | — | 2026-07-22 |
| F-0005 | Time atom documentation uses nanoseconds for a millisecond value | major | fixed | Verifier | 2026-07-22 |
| F-0006 | Public API test redeclares runtime functions instead of testing the header | minor | superseded-by-class | — | 2026-07-22 |
| F-0007 | Public date test labels a different epoch than the API reference | minor | fixed | Verifier | 2026-07-22 |
| CF-0001 | Public error-cleanup examples use ray_release on owned errors | major | fixed | Verifier | 2026-07-22 |
| CF-0002 | ray_eval_str comments still claim value-null is bare NULL | major | fixed | Verifier | 2026-07-22 |
| CF-0003 | Null-encoding comments conflict across scalar and vector surfaces | major | fixed | Verifier | 2026-07-22 |
| CF-0004 | Runtime API is redeclared after including the public header | minor | accepted | human | 2026-07-22 |
228 changes: 228 additions & 0 deletions audit/XCHECK.md

Large diffs are not rendered by default.

99 changes: 99 additions & 0 deletions audit/findings/CF-0001-public-error-cleanup-uses-ray-release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
id: CF-0001
title: Public error-cleanup examples use ray_release on owned errors
severity: major
dimension: api-doc-consistency
unit:
- docs/docs/c-api/core.md
- docs/docs/c-api/dag.md
- test/test_public_api.c
status: fixed
class: null
members:
- F-0002
attempts: 0
pass: P-01
created-by: RP-0001
updated: 2026-07-22
---

## Pattern

An owned `RAY_ERROR` in a public C API reference example or the
public-header conformance test is cleaned up with `ray_release`, even though
the public ownership contract says that helper is a no-op for errors and that
the owner must call `ray_error_free`.

Reproduce the census with:

```sh
rg -n -C 12 'ray_release\((result|err)\)' docs/docs/c-api test/test_public_api.c
```

For every match, retain it only when the same example/test has already proved
the released value is an error with `RAY_IS_ERR`. The search covers the whole
public C API reference tree and its public-header conformance test.

## Census

- `docs/docs/c-api/core.md:490-492`, the `RAY_IS_ERR(p)` example releases the
owned `result` error.
- `docs/docs/c-api/dag.md:373-375`, the `ray_execute` example releases the
owned `result` error.
- `test/test_public_api.c:580-592`,
`test_public_get_error_trace_populated` releases the owned `err` error.
- `test/test_public_api.c:601-604`,
`test_public_get_error_trace_cleared_on_eval` releases the owned `err`
error.

Four instances meet the project threshold of three.

## Validation

Re-ran the recorded census on 2026-07-22:

```sh
rg -n -C 12 'ray_release\((result|err)\)' docs/docs/c-api test/test_public_api.c
```

All four recorded instances remain eligible: each value is proved to be a
`RAY_ERROR` before cleanup. `include/rayforce.h` documents
`ray_error_free` as the owned-error cleanup and `src/mem/cow.c` confirms that
`ray_release` deliberately returns without freeing errors. The trace returned
by `ray_get_error_trace` is separately owned by the VM, so freeing the error
result does not invalidate either public trace test.


## Root cause

The public error-ownership norm in `include/rayforce.h` was added without a
complete update of the public examples and conformance tests that demonstrate
error cleanup.

## Global strategy

Rung (a): replace all four cleanup calls with `ray_error_free`, then run the
public API test and rebuild the documentation. Re-run the recorded census and
require zero public-contract instances.

## Remediation

Planned in `audit/plans/RP-0002.md` using the accepted rung-(a) global
strategy. No ownership norm changes or conflicts require ratification.

Replaced all four eligible cleanup calls with `ray_error_free`: the
`RAY_IS_ERR` examples in `docs/docs/c-api/core.md` and
`docs/docs/c-api/dag.md`, plus both error-trace cases in
`test/test_public_api.c`.

Self-checks completed on 2026-07-22:

- The recorded census returned only three success-path `ray_release(result)`
calls guarded by `!RAY_IS_ERR`; zero eligible class instances remain.
- `make test` passed 3638 of 3638 tests with 0 skipped and 0 failed.
- `mkdocs build --strict` completed successfully.


## Verification

Pending independent Verifier review.
99 changes: 99 additions & 0 deletions audit/findings/CF-0002-ray-eval-str-null-contract-stale.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
id: CF-0002
title: ray_eval_str comments still claim value-null is bare NULL
severity: major
dimension: api-doc-consistency
unit:
- include/rayforce.h
- test/main.c
- test/stress_eval.c
status: fixed
class: null
members:
- F-0003
attempts: 0
pass: P-01
created-by: RP-0001
updated: 2026-07-22
---

## Pattern

A comment describing `ray_eval_str` says a void/null value is represented by
bare C `NULL`, contradicting the public value invariant and current evaluator,
which use `RAY_NULL_OBJ`.

Reproduce the census with:

```sh
rg -n -i 'ray_eval_str.*(returns? NULL|NULL = void/null|void results)' \
include src docs test README.md examples fuzz bench
```

## Census

- `include/rayforce.h:667`, the public declaration says “Returns NULL for
void / null results”.
- `test/main.c:247-248`, the Rayfall harness says `ray_eval_str` returns NULL
for void results and describes bare-NULL comparison semantics.
- `test/stress_eval.c:69`, the stress harness annotates the result with
“NULL = void/null result, fine”.

Three instances meet the project threshold of three.

## Validation

Re-ran the recorded census on 2026-07-22. It reproduced the two single-line
harness comments but missed the public-header instance because `ray_eval_str`
and “Returns NULL” are on separate lines. A supplementary exact-literal
census reproducibly finds all three recorded instances:

```sh
rg -n -i 'Returns NULL for void / null results|ray_eval_str returns NULL for void results|NULL = void/null result' \
include src docs test README.md examples fuzz bench
```

The public invariant in `include/rayforce.h` states that value-null is always
`RAY_NULL_OBJ`; `test_eval_println` and `test_eval_null_keyword` assert that
behavior directly. All three stale comments therefore remain substantively
confirmed.


## Root cause

The evaluator's null-result contract moved to the `RAY_NULL_OBJ` value
invariant, but comments in the public header and two harnesses were not migrated
with it.

## Global strategy

Rung (b): update all three comments to the `RAY_NULL_OBJ` contract and make
the public invariant the named source of truth. Retain defensive bare-NULL
checks where they protect against allocation failure, but do not describe bare
NULL as a successful evaluation result. Re-run the focused null-evaluation
test and the recorded census.

## Remediation

Planned in `audit/plans/RP-0003.md` using the human-accepted rung-(b)
strategy. The direction is the existing public `RAY_NULL_OBJ` invariant; no
new or different norm choice is introduced.

Updated the public `ray_eval_str` contract in `include/rayforce.h` and the
harness comments in `test/main.c` and `test/stress_eval.c` to identify
`RAY_NULL_OBJ` as the successful void/null result. Defensive bare-NULL paths
remain unchanged and are described only as no-result fallbacks.

Self-checks completed on 2026-07-22:

- The supplementary exact-literal census returned zero stale instances.
- The original regex returned one documented non-defect exception: the
corrected `test/main.c` comment, because its broad `void results` alternative
also matches `RAY_NULL_OBJ` wording.
- Focused tests `lang/eval/println` and `lang/eval/null_keyword` each passed
1/1 with no skips or failures.


## Verification

Pending independent Verifier review.
138 changes: 138 additions & 0 deletions audit/findings/CF-0003-null-encoding-comments-conflict.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
---
id: CF-0003
title: Null-encoding comments conflict across scalar and vector surfaces
severity: major
dimension: api-doc-consistency
unit:
- include/rayforce.h
- src/vec/atom.c
- src/vec/vec.c
- src/table/domain.h
- src/ops/pivot.c
- docs/docs/namespaces/csv.md
- test/stress_store.c
- test/test_dict.c
- test/test_format.c
- test/test_str.c
- test/rfl/integration/null.rfl
- test/rfl/strop/split.rfl
status: fixed
class: null
members:
- F-0004
attempts: 0
pass: P-01
created-by: RP-0001
updated: 2026-07-22
---

## Pattern

A comment or API-facing statement assigns null status to empty SYM/STR values,
or says F32 has no sentinel, while the public atom/vector predicates and
current focused tests say SYM/STR empty values are ordinary values and F32
uses NaN.

Reproduce the candidate census with:

```sh
rg -n -i '(SYM null\s*=|STR null\s*=|empty string IS.*null|empty symbol.*null|BOOL/U8/F32|types without a sentinel|global id 0.*null|id 0 is the SYM null)' \
include src docs test README.md examples fuzz bench
```

Classify each candidate against `ray_atom_is_null_fn` in
`include/rayforce.h`, `ray_vec_is_null` in `src/vec/vec.c`, and the explicit
`nil?` expectations in `test/rfl/null/sym_no_null.rfl`.

## Census

- `include/rayforce.h:441-442` assigns SYM id 0 and empty STR as null.
- `include/rayforce.h:451-452` incorrectly groups F32 with types lacking a
sentinel.
- `src/vec/atom.c:185-186` repeats the F32 no-sentinel claim.
- `src/table/domain.h:50-51` calls global SYM id 0 null.
- `src/ops/pivot.c:1268-1269` calls SYM id 0 the SYM null.
- `src/vec/vec.c:1156-1157` calls an empty STR descriptor a STR null.
- `src/vec/vec.c:1200` repeats “STR null = empty string”.
- `docs/docs/namespaces/csv.md:25` says empty strings are read as null and
marked `RAY_ATTR_HAS_NULLS`.
- `test/stress_store.c:118` labels the empty symbol as a SYM null.
- `test/test_dict.c:1177-1179` says empty STR is a null atom.
- `test/test_dict.c:1214` repeats the STR-null/empty-string conflation.
- `test/test_format.c:751-753` calls the empty string and “null string” the
same null-like value, despite the predicate returning false.
- `test/test_str.c:1830` says a STR null is stored as an empty string.
- `test/rfl/integration/null.rfl:8` says “STR null = empty string” immediately
before an expectation that `(nil? "")` is false.
- `test/rfl/strop/split.rfl:4-5` says empty string is the STR null immediately
before an expectation that the resulting empty value is not null.

Fifteen instances meet the project threshold of three.

## Validation

Re-ran the recorded candidate census on 2026-07-22 and manually classified
each result against `ray_atom_is_null_fn`, `ray_vec_is_null`,
`ray_vec_set_null_checked`, and the focused `nil?` expectations. All fifteen
recorded conflicting statements remain in their cited locations. The search
also returns correct counterexamples that explicitly say empty SYM/STR values
are not null; those are classification references, not defects.

The current executable behavior is internally consistent enough to expose the
norm choice but not to authorize it:

- F32 atoms and vectors use NaN as a null sentinel.
- SYM and STR atoms have no null distinct from their empty values;
`ray_typed_null` collapses to the ordinary empty value and
`RAY_ATOM_IS_NULL` returns false.
- SYM and STR vectors are likewise treated as non-nullable by
`ray_vec_is_null`; missing inputs collapse to empty payloads without
`RAY_ATTR_HAS_NULLS`.
- BOOL and U8 typed-null atoms use the auxiliary null bit, while BOOL and U8
vectors reject null insertion.

The conflict is therefore substantive and the finding is validated. Because
the Global strategy is rung (b) and explicitly requires the norm owner to
choose the cross-surface matrix, validation does not ratify either direction.


## Root cause

The project lacks one ratified nullability matrix that distinguishes typed-null
construction, payload sentinels, empty-value collapse, and the public null
predicates. Comments from incompatible historical models coexist.

## Global strategy

Proposed rung (b): first obtain norm-owner ratification for a single per-type
matrix, because the current normative and executable surfaces conflict. Then
fix all census instances and write the ratified matrix into the public API
contract. The norm ratification gate applies: no global edit should execute
until triage records which semantics own SYM/STR empty values and F32.

## Remediation

The human norm owner ratified the recommended preserve-behavior matrix on
2026-07-22. Under `audit/plans/RP-0004.md`, the public contract in
`include/rayforce.h` now publishes the cross-surface matrix; all fifteen
censused statements in the header, implementation comments, documentation,
and tests now describe empty SYM/STR values and F32 consistently. The new
`public/nullability_matrix` test in `test/test_public_api.c` pins ordinary and
typed-null atom behavior for SYM, STR, BOOL, U8, and F32. Executable null
representation was not changed.

Self-checks completed on 2026-07-22:

- The recorded class census returned seven matches, all manually classified
as correct counterexamples that explicitly say empty SYM values are not
null; it returned zero conflicting statements.
- The ASan/UBSan debug build completed cleanly with warnings as errors.
- The full test suite passed 3,639/3,639 with zero skips and zero failures,
including `public/nullability_matrix` and every touched focused area.
- `mkdocs build --strict` completed successfully.
- `git diff --check` reported no whitespace errors.


## Verification

Pending independent Verifier review.
Loading
Loading