Skip to content

Define and safely handle unsafe or ambiguous Model Group names #18

Description

@grzegorznowak

Context

Deferred from the Model Groups review on PR #14 because the concern is valid but not a blocker for that PR:

#14 (review)

Model Group names can currently contain whitespace, #, commas, control characters, and other grammar-significant characters. Their handling is inconsistent across persistence, TUI entry, prompt rendering, and autocomplete.

Current behavior

At PR #14 HEAD 2a3654abac575b71097659c4a87175ce8f61a161:

  • model-groups/names.ts:1-3 only trims names.
  • model-groups/store.ts:56-73,124-167 accepts any nonempty trimmed key during load, save, and CRUD operations.
  • model-groups/tui.ts:174-194 decodes escaped control characters into raw names.
  • index.ts:210-216 interpolates raw names into a comma-separated prompt section.
  • model-groups/autocomplete.ts:28-42 emits every name raw even though its token grammar cannot represent names containing whitespace or #.
  • Existing prompt and autocomplete tests cover ordinary names only.

Risks

  • Control or separator characters can alter the structure of generated prompt content.
  • Commas make the prompt's name list ambiguous.
  • Whitespace and # produce names autocomplete cannot represent faithfully.
  • Exact-name routing and completion can disagree about which names are addressable.
  • Tightening validation without a migration policy could make previously valid persisted configurations unloadable or uneditable.

OpenSpec contract conflict

The review proposes rejecting whitespace, #, commas, and control characters across load, save, and TUI entry. However, PR #14's data-layer OpenSpec deliberately specifies trim-only identity and treats control-bearing names as valid (proposal.md:18,27; story.md:168,346,439,499,501,543). It instead calls for reversible prompt quoting/serialization, omission of grammar-unrepresentable names from autocomplete, and continued access through structured tools.

This contract conflict must be resolved explicitly rather than by silently tightening validation.

Scope and acceptance criteria

  • Choose and document one canonical policy:
    • Restricted names: reject grammar-significant or unsafe characters using one shared validator; or
    • Arbitrary names: retain trim-only identity while making every textual consumer safe and unambiguous.
  • Update the affected OpenSpec proposal/story to match the chosen policy.
  • Apply the policy consistently across config load/save, CRUD operations, TUI entry and escape decoding, prompt rendering, and autocomplete.
  • Ensure a name cannot inject into or ambiguously restructure prompt content.
  • Ensure autocomplete never emits a suggestion its token grammar cannot represent correctly.
  • Document exact-routing and structured-tool behavior for names unavailable through autocomplete.
  • If names become restricted, define migration/recovery behavior for already-persisted invalid names.
  • Return deterministic, actionable errors for rejected names.

Test expectations

Add a shared hostile-name table covering at least:

  • line feed (LF)
  • escape (ESC)
  • bell (BEL)
  • Unicode line separator (U+2028)
  • comma
  • internal whitespace
  • #

Exercise it across load, save, CRUD, and TUI paths, with defensive prompt/autocomplete tests.

For a restricted-name policy, verify consistent rejection at every entry point, documented recovery for invalid persisted data, and defensive consumers if malformed data still reaches them.

For an arbitrary-name policy, verify identity-preserving round trips, reversible and structurally safe prompt serialization, omission of unrepresentable autocomplete entries, and unambiguous exact structured-tool routing.

Migration and design questions

  • Which characters belong in canonical names versus being unsafe only in textual consumers?
  • Should validation use an ASCII allowlist, Unicode-aware rules, or an explicit denylist?
  • Are internal spaces intended to remain valid?
  • Should invalid persisted names be renamed, quarantined, surfaced for recovery, or reject the whole file?
  • What prompt quoting/escaping format is reversible and unambiguous?
  • Should autocomplete omit unrepresentable names or gain a quoting grammar?
  • Must structured tools continue to support names unavailable through text completion?
  • How should normalization collisions be detected and reported?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions