diff --git a/docs/adr/0012-resolve-opaque-entity-identifiers-deterministically.md b/docs/adr/0012-resolve-opaque-entity-identifiers-deterministically.md index 82e2ca3..c93b740 100644 --- a/docs/adr/0012-resolve-opaque-entity-identifiers-deterministically.md +++ b/docs/adr/0012-resolve-opaque-entity-identifiers-deterministically.md @@ -12,9 +12,9 @@ an opaque implementation detail. A plain name is likewise insufficient where multiple supplied records share that name. The LLM boundary must preserve the typed artifact and durable-schema ownership -of [ADR-0003](0003-strongly-typed-stage-interfaces.md) and the distinction +of [ADR-0003](0003-typed-interfaces-with-two-zone-data-model.md) and the distinction between disambiguating references and source evidence in -[ADR-0009](0009-prefer-minimal-evidence-grounded-extraction-artifacts.md). +[ADR-0009](0009-minimal-evidence-grounded-extraction-artifacts.md). ## Decision diff --git a/internal/modules/dnd/shared/unit_refs.go b/internal/modules/dnd/shared/unit_refs.go index 84b4c63..5727aea 100644 --- a/internal/modules/dnd/shared/unit_refs.go +++ b/internal/modules/dnd/shared/unit_refs.go @@ -21,11 +21,6 @@ type SourceRefResponse struct { EndUnitID UnitRef `json:"end_unit_id"` } -func UnitRefFromString(value string) UnitRef { - parsed, _ := parseUnitRefNumber(value) - return UnitRef{value: parsed} -} - func UnitRefFromInt(value int) UnitRef { return UnitRef{ value: value, diff --git a/internal/modules/generic/chunk/units/chunker.go b/internal/modules/generic/chunk/units/chunker.go index 0125a66..1c59080 100644 --- a/internal/modules/generic/chunk/units/chunker.go +++ b/internal/modules/generic/chunk/units/chunker.go @@ -2,10 +2,7 @@ package units import ( "context" - "encoding/json" "fmt" - "math" - "strconv" "gitea.maximumdirect.net/eric/notarius/internal/core/source" "gitea.maximumdirect.net/eric/notarius/internal/framework/contracts" @@ -158,67 +155,11 @@ func nonNegativeIntOption(name string, value any) (int, error) { } func intOption(name string, value any) (int, error) { - switch typed := value.(type) { - case int: - return typed, nil - case int8: - return int(typed), nil - case int16: - return int(typed), nil - case int32: - return int(typed), nil - case int64: - if typed > maxInt() || typed < minInt() { - return 0, chunkerErrorf("%s is outside supported integer range", name) - } - return int(typed), nil - case uint: - if uint64(typed) > uint64(maxInt()) { - return 0, chunkerErrorf("%s is outside supported integer range", name) - } - return int(typed), nil - case uint8: - return int(typed), nil - case uint16: - return int(typed), nil - case uint32: - if uint64(typed) > uint64(maxInt()) { - return 0, chunkerErrorf("%s is outside supported integer range", name) - } - return int(typed), nil - case uint64: - if typed > uint64(maxInt()) { - return 0, chunkerErrorf("%s is outside supported integer range", name) - } - return int(typed), nil - case float64: - if typed != math.Trunc(typed) { - return 0, chunkerErrorf("%s must be an integer", name) - } - if typed > float64(maxInt()) || typed < float64(minInt()) { - return 0, chunkerErrorf("%s is outside supported integer range", name) - } - return int(typed), nil - case json.Number: - parsed, err := typed.Int64() - if err != nil { - return 0, chunkerErrorf("%s must be an integer", name) - } - if parsed > maxInt() || parsed < minInt() { - return 0, chunkerErrorf("%s is outside supported integer range", name) - } - return int(parsed), nil - default: + got, ok := value.(int) + if !ok { return 0, chunkerErrorf("%s must be an integer", name) } -} - -func maxInt() int64 { - return int64(1<<(strconv.IntSize-1) - 1) -} - -func minInt() int64 { - return -maxInt() - 1 + return got, nil } func chunkerErrorf(format string, args ...any) error { diff --git a/internal/modules/generic/chunk/units/chunker_test.go b/internal/modules/generic/chunk/units/chunker_test.go index 73d35e8..8e1aaf1 100644 --- a/internal/modules/generic/chunk/units/chunker_test.go +++ b/internal/modules/generic/chunk/units/chunker_test.go @@ -121,6 +121,22 @@ func TestPlanRejectsInvalidOptions(t *testing.T) { } } +func TestDecodeOptionsRejectsNonNativeIntegers(t *testing.T) { + for _, value := range []any{ + int8(2), int16(2), int32(2), int64(2), + uint(2), uint8(2), uint16(2), uint32(2), uint64(2), + float32(2), float64(2), json.Number("2"), + } { + _, err := DecodeOptions(map[string]any{"max_units": value}) + if err == nil { + t.Fatalf("DecodeOptions(max_units: %T) error = nil, want error", value) + } + if !strings.Contains(err.Error(), "max_units must be an integer") { + t.Fatalf("DecodeOptions(max_units: %T) error = %q, want integer type error", value, err) + } + } +} + func TestPlanRejectsEmptySource(t *testing.T) { doc := testSource(1) doc.Units = nil diff --git a/internal/modules/generic/output/json/encoder.go b/internal/modules/generic/output/json/encoder.go index 79982e6..06c079b 100644 --- a/internal/modules/generic/output/json/encoder.go +++ b/internal/modules/generic/output/json/encoder.go @@ -494,38 +494,6 @@ func cloneWarnings(warnings []contracts.Warning) []contracts.Warning { return append([]contracts.Warning(nil), warnings...) } -func cloneMetadata(metadata map[string]any) map[string]any { - if len(metadata) == 0 { - return nil - } - out := make(map[string]any, len(metadata)) - for key, value := range metadata { - out[key] = cloneJSONMetadataValue(value) - } - return out -} - -func cloneJSONMetadataValue(value any) any { - switch typed := value.(type) { - case map[string]any: - return cloneMetadata(typed) - case []any: - out := make([]any, len(typed)) - for i := range typed { - out[i] = cloneJSONMetadataValue(typed[i]) - } - return out - case stdjson.RawMessage: - return append(stdjson.RawMessage(nil), typed...) - case []byte: - return append([]byte(nil), typed...) - case []string: - return append([]string(nil), typed...) - default: - return value - } -} - func encoderErrorf(format string, args ...any) error { return fmt.Errorf("json output encoder: "+format, args...) }