Skip to content

fix(query): reject truncated dictionary keys as parse errors - #191

Open
TimeToBuildBob wants to merge 2 commits into
ActivityWatch:masterfrom
TimeToBuildBob:fix/truncated-dictionary-key
Open

TimeToBuildBob wants to merge 2 commits into
ActivityWatch:masterfrom
TimeToBuildBob:fix/truncated-dictionary-key

Conversation

@TimeToBuildBob

Copy link
Copy Markdown
Contributor

Summary

  • Treat an empty post-key remainder like other missing-colon errors instead of indexing an empty string.
  • Add parser and RETURN-query regressions for key-only, whitespace-after-key, later-entry and nested truncation; retain valid and existing-error controls.

Closes #190.

Verification

  • Fetched master c7821899ab38c1a39c87d7bf011c22a78de9b205: new cases 5 failed, 7 passed before the fix (IndexError); 68 query2 tests passed after.
  • Package-native make test: 374 passed, 5 skipped. This repository has no test-fast target.
  • make typecheck: clean across 37 source files. Pinned Ruff check/format and hook-enabled commit passed.
  • Actual offline Flask POST /api/0/query/ against aw-server master 994ea988ca30af36e08cef71ce6046e8c3391584, synthetic MemoryStorage, query caching disabled, no listener or personal data: five truncated forms return 500 on master → 400 with QueryParseException on this head. Missing-value/nonempty missing-colon controls stay 400; empty/single/multi-entry/nested complete dictionaries stay 200 with exact expected bodies.
  • Combined source replay with fix(query): accept whitespace-only empty collections #187 (37eb865): 149 passed across both query2 test modules, including whitespace-only empty collections. The adjacent repair is not copied into this PR.

Scope

One predicate change: startswith(":") is equivalent to indexing for nonempty strings and safely rejects an empty remainder. No blanket IndexError handler, parser rewrite, missing-comma policy change, or Rust/deployed-release claim. The offline route harness and raw RED/GREEN receipts are retained at /home/bob/data/aw-dictionary-replay-ebe3/; they are local evidence, not repository test dependencies.

The optional delegated review was unavailable (Claude subscription access disabled), not a passing review. Hosted CI/review will be recorded after opening.

Git-Session-Id: e7890338-d6fc-4b47-843e-a159a67ce343
@greptile-apps

greptile-apps Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Low impact] This PR appears safe to merge.

Summary

QDict.parse now rejects a dictionary key without a following colon using QueryParseException, rather than raising IndexError.

  • Dictionary keys without a colon now produce a parse error.

TimeToBuildBob explicitly excludes the adjacent empty-collection parsing repair from this PR. Those issues are unchanged here.

Reviews (1) · Last reviewed commit: "fix(query): reject truncated dictionary ..." · Reviewed by Greptile

Git-Session-Id: e7890338-d6fc-4b47-843e-a159a67ce343
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

All six checks pass on head 784c271, including Linux/macOS/Windows tests, lint and CodeQL; the PR is mergeable. Greptile reports 5/5 on parser commit 9af9b71 (before the CI runner-only follow-up). No outstanding review threads or human questions. Waiting only on a maintainer merge; Bob has triage, not push access.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

CI-green and mergeable (Greptile 5/5) — waiting only on a maintainer click.

This PR is ready to merge, but the bot has pull-only access to this repo and can't self-merge — surfacing it here so it isn't lost. The monitoring loop will stop re-flagging it now that this note is posted.

@TimeToBuildBob

TimeToBuildBob commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 AI code review

Safe to merge — 1 P1 disposed (rejected)

Updated after inline dispositions on finding threads — this is the current state; the verdict below is frozen at review time and is kept as the historical record of that pass.

Finding disposition
Finding Severity State
tests/test_query2.py:131 P1 rejected — The reviewer says: Traced aw_query/query2.py lines 243-249 through _parse_token at lines 349-355 and QString.check at li

QDict.parse in aw_query/query2.py replaces the post-key indexing check with startswith(":"). The PR adds dictionary parsing and RETURN-query cases in tests/test_query2.py and pins the Ubuntu build matrix entry to ubuntu-22.04.

Not safe to merge — 1 P1 open

Confidence 3/5

1 finding · ❌ 1 P1

❌ P1 high — tests/test_query2.py:131

The added '{"a": }' case raises IndexError rather than the QueryParseException expected by this test. QDict.parse removes the colon and passes three spaces to _parse_token; its initial length check passes, then strip() produces an empty string. The first checker, QString.check, immediately indexes string[0]. The changed startswith check runs before colon removal and cannot prevent this path, so this new parameter fails the test suite instead of providing a passing missing-value control.

How this was verified: Traced aw_query/query2.py lines 243-249 through _parse_token at lines 349-355 and QString.check at line 110: whitespace is stripped only after the empty-input check, leaving string[0] to raise IndexError.

Files changed (3) — the diff as I read it
  • .github/workflows/build.yml — Changes the Ubuntu matrix entry from ubuntu-latest to ubuntu-22.04 and adds a Python 3.8 availability comment.
  • aw_query/query2.py — Changes QDict.parse to reject missing colons using startswith(":") instead of indexing entries_str.
  • tests/test_query2.py — Adds parametrized tests for truncated dictionary keys, missing colons or values, and valid dictionary literals.

Reviewed 784c271da9e1 · panel: codex:gpt-6.1-sol · subscription engine · 31s · about this reviewer

Maintainer commands

@TimeToBuildBob review (own line) — fresh review · @TimeToBuildBob fix — a worker acts on the findings. Once per comment; 👀 = received.

Outage coverage: 1-pass, not merge evidence. Subscription review supplied findings while full consensus capacity was unavailable. The consensus merge gate remains unsatisfied.

The optional OpenRouter verifier was unavailable. Findings retain their original severity.

Comment thread tests/test_query2.py Resolved
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.

Truncated AQL dictionary keys raise IndexError instead of a parse error

1 participant