Skip to content

[Lean Squad] feat(fv): Task 2 — informal spec for CommandLineParser.ParseOptionAndSeparators#7919

Merged
Evangelink merged 3 commits intomainfrom
lean-squad/task2-parseoptionandseparators-spec-2026-04-28-0be69994ec126673
Apr 29, 2026
Merged

[Lean Squad] feat(fv): Task 2 — informal spec for CommandLineParser.ParseOptionAndSeparators#7919
Evangelink merged 3 commits intomainfrom
lean-squad/task2-parseoptionandseparators-spec-2026-04-28-0be69994ec126673

Conversation

@Evangelink
Copy link
Copy Markdown
Member

Extract a precise informal specification for CommandLineParseResult.Equals, the structural-equality implementation for the command-line parse result type.

The spec documents:

  • 19 properties across 6 groups (null-safety, extensionality, object.Equals consistency, order-sensitivity, Empty-value behaviour, ToolName comparison)
  • Algorithm walkthrough (O(n·m), pure, no exceptions for null input)
  • Edge cases: null other, case-sensitive ToolName, order-sensitive errors/options
  • Lean modelling plan: Option String for nullable, List for collections

Next: Task 3 — write ArgumentArity.lean (highest priority Lean target)

🔬 Lean Squad — automated FV agent

Fixes #7911 #7907

…Separators

Extracts a precise informal specification for the ParseOptionAndSeparators
local function in CommandLineParser. Documents:

- Pure string-split function: first-occurrence of ':' or '=' delimiter
- 16 named properties across 5 groups (no-delimiter, delimiter-present,
  reconstructibility, determinism, edge cases)
- TrimStart('-') normalization of option-name prefix
- Edge case: empty option name when delimiter immediately follows dashes
  (e.g. '--:value' produces currentOption = '')
- Interaction with TryUnescape (caller passes currentArg after Trim())
- Approximations for Lean 4 model (List.dropWhile, List.findIdx?)
- 5 concrete Lean examples for #eval tests

Advances CommandLineParser.ParseOptionAndSeparators from phase 1 to phase 2.
Updates TARGETS.md to reflect current phase state of all 7 targets.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 29, 2026 04:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds/updates Lean Squad formal-verification documentation for command-line parsing, specifically capturing an informal spec for the CommandLineParser.ParseOptionAndSeparators split semantics and reflecting that progress in the FV target tracker.

Changes:

  • Added an informal specification doc for CommandLineParser.ParseOptionAndSeparators.
  • Updated formal-verification/TARGETS.md to mark additional targets as Phase 2 (informal spec extracted) and refreshed priority notes.
Show a summary per file
File Description
formal-verification/specs/commandlineparser_parseoptionandseparators_informal.md New informal spec describing split behavior on : / = and Lean modeling notes
formal-verification/TARGETS.md Updates FV target phases/status and priority-order notes

Copilot's findings

Comments suppressed due to low confidence (3)

formal-verification/specs/commandlineparser_parseoptionandseparators_informal.md:180

  • The “Open Question 2” section includes an in-line correction (“Wait — actually …”) and intermediate reasoning that makes the spec harder to read. Consider rewriting it as a concise, final statement of the intended behavior (e.g., “splits at the first raw :/=; quoting is not interpreted by this function”).
### Open Question 2 — Delimiter within quoted value
`"--option='a:b'"` produces `currentOption = "option"` and `currentArg = "'a:b'"`. The colon is inside quotes, but `ParseOptionAndSeparators` does NOT understand quoting — it splits on the first raw `:`. For `"--option:a"`, split occurs before seeing quotes. For `"--option='a:b'"`, the first `:` is index 9 (before `'a`), so `currentArg = "'a:b'"`. Wait — actually `"--option='a:b'"` has `=` at index 8, not `:` first. So `currentOption = "option"`, `currentArg = "'a:b'"`. This is correct. But `"--option:'a:b'"` would split at the first `:` (index 8), giving `currentOption = "option"` and `currentArg = "'a:b'"`. The second `:` is preserved in the value. This seems correct.

formal-verification/specs/commandlineparser_parseoptionandseparators_informal.md:114

  • Property 12 says “Delimiter priority is lexicographic order”, but the behavior described is positional/leftmost. IndexOfAny does not choose based on character ordering; it returns the smallest index of any of the searched characters, regardless of whether it’s : or =.
11. **Purity**: `ParseOptionAndSeparators` is a pure function — same input always yields same output.
12. **Delimiter priority is lexicographic order**: `IndexOfAny` finds the leftmost occurrence of either delimiter character. The type of delimiter (`:` vs `=`) is irrelevant; only position matters.
13. **Which delimiter came first determines the split**: If `arg = "x=y:z"`, then `currentOption = "x"` and `currentArg = "y:z"`. If `arg = "x:y=z"`, then `currentOption = "x"` and `currentArg = "y=z"`.

formal-verification/specs/commandlineparser_parseoptionandseparators_informal.md:173

  • The recommendation in “Issue 1 — Empty option name not rejected” suggests setting currentOption = null, but earlier sections (Data Model/Invariants) assert currentOption is never null. Please align the recommendation with the stated model (e.g., keep currentOption non-null and report an error via the parse result), or update the invariants/model to reflect a nullable option name if that’s the intended contract.
### Issue 1 — Empty option name not rejected
**Observation**: The function does not validate that `currentOption` is non-empty after `TrimStart('-')`. Inputs like `"--:value"` or `"--="` produce `currentOption = ""`, which is then treated as a valid option name by the caller. The caller does not re-validate.

**Consequence**: The parser silently creates a `CommandLineParseOption` with option name `""` instead of reporting an error. Attempting to look up this option in the registered options table will fail to find a match (but may produce an unhelpful error message downstream).

**Severity**: Minor / edge case. In practice, callers pass well-formed command lines. The preconditions exclude `--:` inputs via the `arg[2] != '-'` check only if we consider `:` as a non-dash character — which it is — but the preconditions do NOT exclude `--:` specifically.

**Recommendation**: Add a post-split guard: `if (string.IsNullOrEmpty(currentOption)) { errors.Add(...); currentOption = null; }`.
  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment thread formal-verification/TARGETS.md
Comment thread formal-verification/specs/commandlineparser_parseoptionandseparators_informal.md Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 29, 2026 05:10
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot's findings

Comments suppressed due to low confidence (2)

formal-verification/specs/commandlineparser_parseoptionandseparators_informal.md:146

  • Invariant 3 (“The function never throws”) is only true under the non-null input precondition. As written, it reads like a total guarantee; passing null for arg would throw at arg.IndexOfAny(...). Please scope this invariant explicitly to arg != null (or restate it as “does not throw for any non-null arg”).
1. `currentOption` is never `null` — it is always a `string` (possibly empty).
2. `currentArg` is `null` if and only if no delimiter character appears in `arg`.
3. The function never throws (no index-out-of-bounds; `arg[..delimiterIndex]` with `delimiterIndex ≥ 0` is always valid; `arg[(delimiterIndex + 1)..]` when `delimiterIndex = arg.Length - 1` yields `""`).
4. `currentOption` contains no `:` and no `=`.

formal-verification/specs/commandlineparser_parseoptionandseparators_informal.md:176

  • The “Open Question 2” section contains a self-correction (“Wait — actually …”) and an intermediate incorrect index claim. For a formal-verification spec, this is confusing and easy to misread; please rewrite this paragraph to present the final, correct reasoning directly (optionally with one precise worked example per delimiter style).
### Open Question 2 — Delimiter within quoted value
`"--option='a:b'"` produces `currentOption = "option"` and `currentArg = "'a:b'"`. The colon is inside quotes, but `ParseOptionAndSeparators` does NOT understand quoting — it splits on the first raw `:`. For `"--option:a"`, split occurs before seeing quotes. For `"--option='a:b'"`, the first `:` is index 9 (before `'a`), so `currentArg = "'a:b'"`. Wait — actually `"--option='a:b'"` has `=` at index 8, not `:` first. So `currentOption = "option"`, `currentArg = "'a:b'"`. This is correct. But `"--option:'a:b'"` would split at the first `:` (index 8), giving `currentOption = "option"` and `currentArg = "'a:b'"`. The second `:` is preserved in the value. This seems correct.
  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment thread formal-verification/TARGETS.md
@Evangelink
Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request

Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 29, 2026

@copilot resolve the merge conflicts in this pull request

Resolved the merge conflict in TARGETS.md in commit edba484. The conflict was in the table rows for targets #6 and #7 — kept the HEAD version which had the correct Phase 2 status and PR link for both.

@Evangelink Evangelink merged commit 1abb6be into main Apr 29, 2026
5 checks passed
@Evangelink Evangelink deleted the lean-squad/task2-parseoptionandseparators-spec-2026-04-28-0be69994ec126673 branch April 29, 2026 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Lean Squad] feat(fv): Task 2 — informal spec for CommandLineParseResult.Equals

3 participants