feat: implement render engine with resolution decay (#39) #41

Closed
xiaoju wants to merge 1 commits from fix/39-render-resolution-decay into main
Owner

What

Implements Phase 3 render engine for json-cas nodes with resolution-based decay and default YAML rendering.

Why

Issue #39 requested a rendering mechanism where:

  • Child nodes receive decayed resolution (parent × decay)
  • Nodes with resolution ≤ epsilon render as opaque cas: references
  • Default YAML output format for human-readable display

Changes

Core Implementation (packages/json-cas)

  • render.ts (221 lines): Core render engine with resolution decay model

    • render(): Main API with RenderOptions
    • renderNode(): Recursive node traversal with cycle detection
    • renderValue(): Type-specific value rendering
    • toYamlString(): YAML escaping and formatting
    • Defaults: resolution=1.0, decay=0.5, epsilon=0.01
    • Floating-point tolerance handling (FLOAT_TOLERANCE = 1e-10)
  • render.test.ts (935 lines): Comprehensive test suite

    • 38 tests across 8 suites:
      1. Basic rendering (primitives, objects, arrays)
      2. Resolution decay propagation
      3. Complex graphs (cycles, DAGs, deep trees)
      4. Epsilon boundary conditions
      5. YAML output format validation
      6. Schema integration (cas_ref detection)
      7. Error handling (missing nodes, invalid parameters)
      8. Performance & edge cases

CLI Integration (packages/cli-json-cas)

  • index.ts: New ucas render <hash> command

    • Flags: --resolution, --decay, --epsilon
    • Numeric parameter validation with NaN checking
    • Raw YAML output to stdout
    • Updated help text
  • cli.test.ts: 3 CLI integration tests

    • Missing hash argument validation
    • Graceful handling of missing nodes
    • Invalid numeric flag error handling

Exports

  • Updated packages/json-cas/src/index.ts to export render API

Key Features

  1. Resolution Decay Model: Children receive resolution = parent × decay
  2. Epsilon Threshold: Nodes pruned to cas:<hash> when resolution ≤ epsilon
  3. YAML Format: 2-space indentation, proper escaping of special characters
  4. Cycle Detection: Visited set prevents infinite loops
  5. Missing Node Handling: Graceful degradation to cas:<hash> references
  6. Schema Integration: Uses existing schema.refs() for cas_ref detection
  7. Floating-Point Tolerance: Handles FP precision issues (e.g., 0.1 × 0.1 ≈ 0.01)

Test Results

✓ 276 tests pass (38 new render tests + 3 CLI tests)
✓ bun run build: Clean compilation
✓ bun run check: No linting errors

Ref

Fixes #39

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

## What Implements Phase 3 render engine for json-cas nodes with resolution-based decay and default YAML rendering. ## Why Issue #39 requested a rendering mechanism where: - Child nodes receive decayed resolution (parent × decay) - Nodes with resolution ≤ epsilon render as opaque cas:<hash> references - Default YAML output format for human-readable display ## Changes ### Core Implementation (packages/json-cas) - **render.ts** (221 lines): Core render engine with resolution decay model - `render()`: Main API with `RenderOptions` - `renderNode()`: Recursive node traversal with cycle detection - `renderValue()`: Type-specific value rendering - `toYamlString()`: YAML escaping and formatting - Defaults: resolution=1.0, decay=0.5, epsilon=0.01 - Floating-point tolerance handling (`FLOAT_TOLERANCE = 1e-10`) - **render.test.ts** (935 lines): Comprehensive test suite - 38 tests across 8 suites: 1. Basic rendering (primitives, objects, arrays) 2. Resolution decay propagation 3. Complex graphs (cycles, DAGs, deep trees) 4. Epsilon boundary conditions 5. YAML output format validation 6. Schema integration (`cas_ref` detection) 7. Error handling (missing nodes, invalid parameters) 8. Performance & edge cases ### CLI Integration (packages/cli-json-cas) - **index.ts**: New `ucas render <hash>` command - Flags: `--resolution`, `--decay`, `--epsilon` - Numeric parameter validation with NaN checking - Raw YAML output to stdout - Updated help text - **cli.test.ts**: 3 CLI integration tests - Missing hash argument validation - Graceful handling of missing nodes - Invalid numeric flag error handling ### Exports - Updated `packages/json-cas/src/index.ts` to export render API ## Key Features 1. **Resolution Decay Model**: Children receive `resolution = parent × decay` 2. **Epsilon Threshold**: Nodes pruned to `cas:<hash>` when `resolution ≤ epsilon` 3. **YAML Format**: 2-space indentation, proper escaping of special characters 4. **Cycle Detection**: Visited set prevents infinite loops 5. **Missing Node Handling**: Graceful degradation to `cas:<hash>` references 6. **Schema Integration**: Uses existing `schema.refs()` for `cas_ref` detection 7. **Floating-Point Tolerance**: Handles FP precision issues (e.g., 0.1 × 0.1 ≈ 0.01) ## Test Results ``` ✓ 276 tests pass (38 new render tests + 3 CLI tests) ✓ bun run build: Clean compilation ✓ bun run check: No linting errors ``` ## Ref Fixes #39 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
xiaoju added 1 commit 2026-05-31 04:28:49 +00:00
Implement Phase 3: render core engine with resolution-based decay and
default YAML rendering.

Core Features:
- Resolution decay model: child nodes receive resolution = parent × decay
- Epsilon threshold: nodes with resolution ≤ epsilon render as cas:<hash>
- Default YAML output format with 2-space indentation
- Cycle detection via visited set
- Floating-point tolerance for epsilon comparisons

Implementation:
- packages/json-cas/src/render.ts: Core render function
- packages/json-cas/src/render.test.ts: 38 comprehensive tests
- packages/cli-json-cas: ucas render command with --resolution, --decay, --epsilon flags
- CLI integration tests for render command

Tests: All 276 tests pass (38 new render tests, 3 CLI tests)
Build: Clean compilation with tsc
Lint: Passes biome check

Fixes #39

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
xiaoju reviewed 2026-05-31 04:44:56 +00:00
xiaoju left a comment
Author
Owner

Review: Phase 3 — Render Core Engine

Reviewer: 小橘 🍊(NEKO Team)

Verdict: APPROVED

Clean, well-structured implementation of the resolution decay render model. All 38 tests pass, biome lint clean, TypeScript builds without errors.

Strengths

  • Decay model is correct: childResolution = currentResolution * decay applied at each level, with epsilon cutoff rendering cas:<hash> references. Float tolerance (1e-10) handles boundary cases properly.
  • Schema-aware traversal: Uses refs() to identify cas_ref fields, correctly handles anyOf nullable references, arrays of refs, and non-ref strings.
  • DAG support: visited.delete(hash) after rendering allows shared nodes to be expanded in multiple branches while still preventing infinite loops on cycles.
  • Excellent test coverage (8 suites, 38 tests): primitives, nesting, epsilon boundaries, complex graphs, error handling, performance, and edge cases.
  • CLI integration is clean — proper flag parsing, validation, and help text.
  • Follows project conventions: import type, .js extensions, named exports, kebab-case files, 2-space indent, re-exported from index.ts.

Minor Observations (Non-blocking)

  1. Test 7.2 missing — numbering jumps from 7.1 to 7.3. Cosmetic only.
  2. Test 3.3 Cycle Detection acknowledges it cannot create a true cycle in CAS — the visited guard is defensive. Consider noting this in a code comment.
  3. Hand-rolled YAML — works for the current scope but may need a library if output fidelity becomes important (e.g., multi-line strings, anchors). Fine for now.
  4. RenderOptions.resolution type comment says (0, 1] but validation allows [0, 1] — resolution=0 is valid and forces reference output. The comment could be updated to [0, 1].

Ship it! 🚀

## Review: Phase 3 — Render Core Engine **Reviewer:** 小橘 🍊(NEKO Team) ### ✅ Verdict: APPROVED Clean, well-structured implementation of the resolution decay render model. All 38 tests pass, biome lint clean, TypeScript builds without errors. ### Strengths - **Decay model is correct**: `childResolution = currentResolution * decay` applied at each level, with epsilon cutoff rendering `cas:<hash>` references. Float tolerance (1e-10) handles boundary cases properly. - **Schema-aware traversal**: Uses `refs()` to identify `cas_ref` fields, correctly handles `anyOf` nullable references, arrays of refs, and non-ref strings. - **DAG support**: `visited.delete(hash)` after rendering allows shared nodes to be expanded in multiple branches while still preventing infinite loops on cycles. - **Excellent test coverage** (8 suites, 38 tests): primitives, nesting, epsilon boundaries, complex graphs, error handling, performance, and edge cases. - **CLI integration** is clean — proper flag parsing, validation, and help text. - **Follows project conventions**: `import type`, `.js` extensions, named exports, kebab-case files, 2-space indent, re-exported from `index.ts`. ### Minor Observations (Non-blocking) 1. **Test 7.2 missing** — numbering jumps from 7.1 to 7.3. Cosmetic only. 2. **Test 3.3 Cycle Detection** acknowledges it cannot create a true cycle in CAS — the `visited` guard is defensive. Consider noting this in a code comment. 3. **Hand-rolled YAML** — works for the current scope but may need a library if output fidelity becomes important (e.g., multi-line strings, anchors). Fine for now. 4. **`RenderOptions.resolution` type comment** says `(0, 1]` but validation allows `[0, 1]` — resolution=0 is valid and forces reference output. The comment could be updated to `[0, 1]`. Ship it! 🚀
xiaoju closed this pull request 2026-05-31 05:29:13 +00:00
This repo is archived. You cannot comment on pull requests.
No Reviewers
No Label
1 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: uncaged/json-cas#41