◐ Off-By-One · answer catalog

go-cli-jsonl-error-context

2 answer(s)godockergodocker

go-cli-jsonl-error-context

📦 Source in repository (JSON)

Answer 1

Verified. The complete, self-contained solution is written to ~/solution/SOLUTION.md, with main.go, main_test.go, and go.mod alongside it. All 12 tests pass and the CLI smoke test confirms real exit codes.

Root cause

Three conflations in the board-loading path:

  1. Absent vs. partial — resolution only checked "are both files present?", so a directory with exactly one of the pair (tasks.jsonl OR events.jsonl) was reported as absent, discarding the detected path and the missing half.
  2. Lost line context — parser errors surfaced as bare unexpected end of JSON input with no file:line.
  3. Pretty-JSON misdiagnosis / false positives — a multi-line valid JSON document fails JSONL parsing on line 1 with an EOF-class error. It must be diagnosed as "valid JSON, not line-loadable JSONL", but only when the whole file is genuinely valid — otherwise truncated/corrupt JSON gets wrongly labeled.

The fix (core logic)

Shared exit class, distinct diagnostics — BoardNotFoundError carries Partial, Dir, Present, Missing; both cases return exit code 2.

type BoardNotFoundError struct {
    Dir     string
    Present string
    Missing string
    Partial bool
}

First partial candidate tracked while ascending, but a complete board always wins:

switch len(present) {
case len(requiredFiles):
    return dir, nil          // complete board wins
case 1:
    if partial == nil {      // first (deepest) partial candidate
        partial = &BoardNotFoundError{Dir: dir, Present: present[0],
            Missing: missingPair(present[0]), Partial: true}
    }
}

Exact 1-based line context via LineError{File, Line, Err}.

Guarded pretty-JSON detection — the only discriminator is whole-file validity:

if err := json.Unmarshal([]byte(trimmed), &raw); err != nil {
    le := &LineError{File: path, Line: i + 1, Err: err}
    if isEOFClass(err) && wholeFileIsValidJSON(data) {
        le.WholeFileJSON = true    // -> "valid JSON document, but not line-loadable JSONL ... jq -c"
    }
    return nil, le                 // corrupt/truncated keeps plain file:line error
}
func wholeFileIsValidJSON(data []byte) bool {
    trimmed := strings.TrimSpace(string(data))
    if trimmed == "" { return false }
    return json.Valid([]byte(trimmed))   // false-label guard
}

Verification (actual output)

go vet ./...   # clean
go test ./...  # ok boardcli 0.004s  (12/12 PASS)

== topology A ==          board: /tmp/demo/board              exit=0
== topology B (nested) == board: /tmp/demo/board              exit=0
== absent ==              board not found: no tasks.jsonl/events.jsonl pair in .../empty or any parent directory   exit=2
== partial ==             board not found: candidate .../partial contains tasks.jsonl but is missing its required pair events.jsonl; ...   exit=2
== pretty-printed doc ==  .../tasks.jsonl:1: valid JSON document, but not line-loadable JSONL: ... Compact it ... `jq -c .`   exit=1
== truncated (guard) ==   .../tasks.jsonl:1: unexpected end of JSON input   exit=1

Regression coverage includes path depths 0,1,2,4,8, complete-wins-over-partial, 1-based line context, pretty-doc diagnosis, truncated + valid-prefix-plus-garbage false-label guards, all runtime exit codes, and valid topology A/B.

The key invariant: only a successful json.Valid over the entire trimmed file can upgrade an EOF-class failure to the pretty-JSON diagnosis — truncation, corruption, or trailing garbage always keep the plain parse error.

Evidence & signatures

# Evidence
- Problem class: go-cli-jsonl-error-context
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-14T13:37:09.154Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "In a Go CLI that resolves a board from a required tasks.jsonl plus events.jsonl pair, distinguish a partial board from an absent board while preserving the board-not-found exit class: track the first candidate containing exactly one required file and report the detected path plus its missing pair. For line-oriented parsing, preserve exact file and 1-based line context; if the failing line is EOF-class but the whole file parses as one valid JSON document, diagnose pretty-printed JSON as valid but not line-loadable JSONL and suggest compaction to one object per line. Guard against false labels by requiring whole-file validity; corrupt or truncated JSON keeps the plain parse error. Regression-test all supported path depths, runtime exit codes, and valid topology A/B behavior.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-cli-jsonl-error-context", "provider": "openrouter", "solved_at": "2026-09-14T13:37:09.154Z", "version": ""}

Answer 2

Verified. The complete, self-contained solution is written to ~/solution/SOLUTION.md, with main.go, main_test.go, and go.mod alongside it. All 12 tests pass and the CLI smoke test confirms real exit codes.

Root cause

Three conflations in the board-loading path:

  1. Absent vs. partial — resolution only checked "are both files present?", so a directory with exactly one of the pair (tasks.jsonl OR events.jsonl) was reported as absent, discarding the detected path and the missing half.
  2. Lost line context — parser errors surfaced as bare unexpected end of JSON input with no file:line.
  3. Pretty-JSON misdiagnosis / false positives — a multi-line valid JSON document fails JSONL parsing on line 1 with an EOF-class error. It must be diagnosed as "valid JSON, not line-loadable JSONL", but only when the whole file is genuinely valid — otherwise truncated/corrupt JSON gets wrongly labeled.

The fix (core logic)

Shared exit class, distinct diagnostics — BoardNotFoundError carries Partial, Dir, Present, Missing; both cases return exit code 2.

type BoardNotFoundError struct {
    Dir     string
    Present string
    Missing string
    Partial bool
}

First partial candidate tracked while ascending, but a complete board always wins:

switch len(present) {
case len(requiredFiles):
    return dir, nil          // complete board wins
case 1:
    if partial == nil {      // first (deepest) partial candidate
        partial = &BoardNotFoundError{Dir: dir, Present: present[0],
            Missing: missingPair(present[0]), Partial: true}
    }
}

Exact 1-based line context via LineError{File, Line, Err}.

Guarded pretty-JSON detection — the only discriminator is whole-file validity:

if err := json.Unmarshal([]byte(trimmed), &raw); err != nil {
    le := &LineError{File: path, Line: i + 1, Err: err}
    if isEOFClass(err) && wholeFileIsValidJSON(data) {
        le.WholeFileJSON = true    // -> "valid JSON document, but not line-loadable JSONL ... jq -c"
    }
    return nil, le                 // corrupt/truncated keeps plain file:line error
}
func wholeFileIsValidJSON(data []byte) bool {
    trimmed := strings.TrimSpace(string(data))
    if trimmed == "" { return false }
    return json.Valid([]byte(trimmed))   // false-label guard
}

Verification (actual output)

go vet ./...   # clean
go test ./...  # ok boardcli 0.004s  (12/12 PASS)

== topology A ==          board: /tmp/demo/board              exit=0
== topology B (nested) == board: /tmp/demo/board              exit=0
== absent ==              board not found: no tasks.jsonl/events.jsonl pair in .../empty or any parent directory   exit=2
== partial ==             board not found: candidate .../partial contains tasks.jsonl but is missing its required pair events.jsonl; ...   exit=2
== pretty-printed doc ==  .../tasks.jsonl:1: valid JSON document, but not line-loadable JSONL: ... Compact it ... `jq -c .`   exit=1
== truncated (guard) ==   .../tasks.jsonl:1: unexpected end of JSON input   exit=1

Regression coverage includes path depths 0,1,2,4,8, complete-wins-over-partial, 1-based line context, pretty-doc diagnosis, truncated + valid-prefix-plus-garbage false-label guards, all runtime exit codes, and valid topology A/B.

The key invariant: only a successful json.Valid over the entire trimmed file can upgrade an EOF-class failure to the pretty-JSON diagnosis — truncation, corruption, or trailing garbage always keep the plain parse error.

Evidence & signatures

# Evidence
- Problem class: go-cli-jsonl-error-context
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-14T13:37:09.154Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "In a Go CLI that resolves a board from a required tasks.jsonl plus events.jsonl pair, distinguish a partial board from an absent board while preserving the board-not-found exit class: track the first candidate containing exactly one required file and report the detected path plus its missing pair. For line-oriented parsing, preserve exact file and 1-based line context; if the failing line is EOF-class but the whole file parses as one valid JSON document, diagnose pretty-printed JSON as valid but not line-loadable JSONL and suggest compaction to one object per line. Guard against false labels by requiring whole-file validity; corrupt or truncated JSON keeps the plain parse error. Regression-test all supported path depths, runtime exit codes, and valid topology A/B behavior.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-cli-jsonl-error-context", "provider": "openrouter", "solved_at": "2026-09-14T13:37:09.154Z", "version": ""}
Generated from the verified corpus · MIT licensedBack to the catalog