Skip to content

feat(grounding-wrapper): validate keyword input on initSession#98

Merged
LanNguyenSi merged 1 commit into
masterfrom
fix/init-session-input-validation
May 27, 2026
Merged

feat(grounding-wrapper): validate keyword input on initSession#98
LanNguyenSi merged 1 commit into
masterfrom
fix/init-session-input-validation

Conversation

@LanNguyenSi
Copy link
Copy Markdown
Owner

Summary

initSession silently emitted degenerate ids and resolved_scopes for edge-case keywords:

Input id resolved_scope
"" gs--<ts> ""
1000-char string slug truncated to 16, ts full 1000-char scope
"クラウド" gs---<ts> "" (Unicode stripped, nothing left)
"クラウド-monitor" gs---monitor-<ts> "--monitor" (leading double-dash)

Reviewer of PR #91 (task 839b51f9) called out that the README's "Public API for enforcement" section claims initSession is deterministic in keyword+problem, which is technically true (same input → same degenerate output) but the input domain wasn't pinned anywhere.

Fix

  • New exported helper validateKeyword(keyword: unknown): void that throws a typed Error when the keyword is:
    • non-string,
    • empty,
    • longer than KEYWORD_MAX_LENGTH (64) chars, or
    • slug-normalised to an empty string (toLowerCase[^a-z0-9]+ collapse → trim leading/trailing -).
  • initSession calls validateKeyword(input.keyword) as its first statement.
  • README "Public API for enforcement" gains an "Input invariants" bullet naming the rules + the exported helper.
  • 13 new tests (29 → 42 passing): both validateKeyword directly and initSession covered.

The rule preserves friendly mixed-Unicode keywords: "クラウド-monitor" normalises to "monitor" and is still accepted. Only pure-Unicode / pure-symbol / pure-whitespace / oversize / empty inputs are rejected.

Backward compatibility

Grep confirmed every existing initSession( caller in the monorepo uses a valid ASCII slug (clawd-monitor, github-api, agent-tasks, etc.). handleScopeChange has no production caller outside lib.ts, so the new throw is contained.

Test plan

  • npm test in grounding-wrapper: 42/42 pass.
  • Review subagent: APPROVE, including live verification of the slug-regex boundary cases.
  • Ledger fact logged for the CI merge-approval gate.
  • CI green.

initSession silently emitted degenerate ids and resolved_scopes for
edge-case keywords:

- ""               → id "gs--<ts>", resolved_scope ""
- 1000-char input  → ID slug truncated to 16 chars, scope full-length
- "クラウド"        → resolved_scope "" (Unicode stripped, nothing left)
- "クラウド-monitor" → resolved_scope "--monitor" (leading double-dash)

Add `validateKeyword(keyword)` (exported) that throws a typed Error
when the keyword is non-string, empty, longer than KEYWORD_MAX_LENGTH
(64), or its slug-normalised form has no ASCII alphanumerics. Mixed
inputs that still contain at least one [a-z0-9] after normalisation
remain accepted (e.g. "クラウド-monitor" → "monitor").

`initSession` now calls validateKeyword first so the README contract
("Public API for enforcement") matches reality. Contract section
updated to name the input invariants explicitly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@LanNguyenSi LanNguyenSi added review:tests-pass merge-approval prereq review:checklist-complete merge-approval prereq review:comments-resolved merge-approval prereq review:scope-matches-task merge-approval prereq review:evidence-logged merge-approval prereq labels May 27, 2026
@LanNguyenSi LanNguyenSi merged commit 51e0269 into master May 27, 2026
2 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review:checklist-complete merge-approval prereq review:comments-resolved merge-approval prereq review:evidence-logged merge-approval prereq review:scope-matches-task merge-approval prereq review:tests-pass merge-approval prereq

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants