Skip to content

LLP 0264: hyp query grep mirrors the server's grep search (LLP-only) - #856

Merged
bgmcmullen merged 1 commit into
masterfrom
llp/0264-grep-search-mirrors-the-server
Aug 18, 2026
Merged

LLP 0264: hyp query grep mirrors the server's grep search (LLP-only)#856
bgmcmullen merged 1 commit into
masterfrom
llp/0264-grep-search-mirrors-the-server

Conversation

@bgmcmullen

@bgmcmullenbgmcmullen commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

LLP-only PR, no code changes. Status: Accepted, so the implementation agent can pick it up.

What it decides

  • hyp query grep ships as a read-class verb in CORE_VERBS, tool: 'grep_search' with a schema compatible with the server's, so --remote <target> reaches the server's existing archive-backed search with zero server feature work.
  • The mechanism mirrors hypaware-server LLP 0127/0128/0130/0157 tier for tier: mutable data is scanned (spool + not-yet-compacted files, never indexed), immutable compacted cache files carry hypgrep .index.parquet sidecars built during maintenance on the server's proven worker-thread / poison-quarantine / sidecar-existence patterns.
  • The searchable-column allowlist, matcher/snippet, and hit shapes hoist into hypaware core; the server (which already depends on hypaware) imports them in a follow-up PR, so local and remote grep can never disagree on coverage.
  • Client-only delta: the local scan wraps in the existing withLocalOnlyVisibility (LLP 0105 applies on the MCP-host surface; the server never holds local-only rows).
  • hypgrep becomes a hard root dependency, with overrides for the LLP 0222 hyparquet 1.28.2 floor (hypgrep pins 1.27.1).

Coordination hazard (called out in the doc)

hypaware-server's daemon defers if grep_search is already registered, so shipping the kernel verb alone silently replaces the server's archive-backed tool with a local-cache one on every server host. The kernel verb and a small server-side registration fix must land as a pair.

Also records

The rejected first draft (substring pushdown into the SQL scan via an icebird row-range hook), so the alternative isn't re-litigated.

🤖 Generated with Claude Code

@bgmcmullen

Copy link
Copy Markdown
ContributorAuthor

The server half of the coordinated pair is up: hyparam/hypaware-server#364 (LLP 0178, displace the kernel twin instead of deferring). It is inert against today's kernel, so it can merge first; the implementation of this LLP owes the verb registry an unregister(name) for it to call. Sequencing constraint: server#364 must be merged before hypaware-server bumps its hypaware dependency to the version that ships the grep_search twin.

LLP-only PR: no code changes. Accepted so the implementation agent can
pick it up.
Full-text search over recorded sessions ships as a read-class 'query
grep' verb whose tool is the server's existing grep_search, so --remote
reaches the archive-backed service unchanged. The mechanism mirrors
hypaware-server LLP 0127/0128/0130/0157 tier for tier: mutable data
(spool + uncompacted files) answers by direct scan and is never indexed;
immutable compacted files carry hypgrep .index.parquet sidecars built at
maintenance. The searchable-column allowlist, matcher, and hit shapes
hoist into core so both repos import one copy. The client-only delta is
LLP 0105 visibility on the local scan. Names the grep_search
registration collision in the server daemon as a coordinated-release
requirement, and records the rejected pushdown-into-the-scan draft.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@bgmcmullen
bgmcmullenforce-pushed the llp/0264-grep-search-mirrors-the-server branch from 2d55765 to 96faa91CompareAugust 18, 2026 22:26
@bgmcmullen
bgmcmullen merged commit 4bc1a15 into masterAug 18, 2026
9 checks passed
@bgmcmullen
bgmcmullen deleted the llp/0264-grep-search-mirrors-the-server branch August 18, 2026 22:28
bgmcmullen added a commit that referenced this pull request Aug 18, 2026
Two parallel sessions both claimed 0264 as the next free number; the
grep-search decision (#856) claimed it first and is green, so this
branch's query-status decision takes 0265. File rename plus every LLP
0264 reference in the branch's own diff (llp/0033 forward-ref, the
query.js @refs, the test header).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
bgmcmullen added a commit that referenced this pull request Aug 19, 2026
…ong host (LLP 0265) (#859)
* LLP 0264: `hyp query status` refuses --remote, and the query skill records what recorded runs got wrong
## The code change
LLP 0033 #flag-compat settles that a local-cache operation under --remote is
a hard error, never a silent ignore, and names one instance: --refresh.
`hyp query status` is the same kind of operation and was not covered, so it
accepted the flag, printed this machine's cache, and exited 0.
That silent ignore is worse than a dropped --refresh. A dropped refresh is
self-announcing: work was asked for and nothing happened. A dropped --remote
on status is self-consistent, because status already returns the recording
root, cache freshness, and dataset list, which is the exact shape of the
answer "what does the server have?" expects. The caller gets a plausible,
server-shaped inventory of the wrong host with nothing on stderr, and no
later signal contradicts it.
Not hypothetical: recorded sessions on 2026-08-03 show
`hyp query status --remote hyperparam` issued in four distinct sessions, each
an agent enumerating the server's datasets, each answered with the laptop's.
status now rejects --remote (all three spellings, including LLP 0062's bare
--remote sentinel) with exit 2 before any cache work, so no partial local
inventory reaches stdout, and names the probe that answers the real question:
`hyp query sql "select 1 from <dataset> limit 1" --remote <target>`.
There is no remote status to fill this gap with. Only query_sql and
graph_neighbors cross the wire; registration state is the server's own and is
not exposed. 0033 is Active, so the extension is a new doc plus a forward-ref
on 0033's header rather than an edit to what it settled.
## The skill changes
Both hypaware-query SKILL.md copies (claude, codex) get the same edits. Each
one is a failure measured in recorded sessions, not a style pass:
- The status/--remote rule above, stated with the *old* behavior spelled out,
because a stale `hyp` still answers locally and that asymmetry is the hazard.
- `2>&1` and `| head` are the same mistake as `2>/dev/null` wearing a
disguise: merging the streams breaks --format json parsing and a pager then
cuts whichever half falls past the limit.
- `hyp query overview` reframed from "totals are windowed" to "a map, not a
source of figures", with --json (window.days / rows / narrowed) as the
agent-facing form, since the period is otherwise only prose under the title.
- A transport failure is not a query to retry. HTTP 502/504, `fetch failed`,
and connect timeouts are about the path to the host, so identical SQL
cannot fix them; sessions have burned 25 to 32 consecutive calls on this.
- SQL traps, each one observed: the column-name misses (`conversation_source`
not `source`, `message_created_at` not `timestamp`/`ts`), more absent
functions, UNION needing identical column *names*, an aggregate in HAVING
or ORDER BY needing to appear in the SELECT list, and that a memory-budget
refusal is deterministic (one session re-ran the same rejected query 12
times).
- The graph section splits local from remote: a local graph needs projecting
first, a remote one cannot be projected from here and is the server's to
keep current. On `hyperparam` the graph is also the cheap surface, ~0.3s for
node aggregates against 16-34s for the equivalent message scan, so falling
back to SQL is the expensive mistake rather than the safe one.
## Checks
npm test: 4417 pass, 29 fail, all 29 identical to the pre-change tree (parquet
predicate pushdown, report render, gateway listener; none touched here). The 3
new tests are in that pass count. Refusal also exercised through the real CLI
for both `--remote <target>` and bare `--remote`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* LLP 0264 collision: query-status decision renumbers to 0265
Two parallel sessions both claimed 0264 as the next free number; the
grep-search decision (#856) claimed it first and is green, so this
branch's query-status decision takes 0265. File rename plus every LLP
0264 reference in the branch's own diff (llp/0033 forward-ref, the
query.js @refs, the test header).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Review fixes: renumber LLP to 0273, correct CLI help and SQL dialect notes
Three defects found reviewing c47aec1.
LLP 0265 is already claimed on master by
`llp/0265-grep-search-implementation.plan.md`, so merging as-is fails
`test/core/llp-ref-hygiene.test.js` ("no LLP number is claimed by two
documents") and leaves the three `@ref LLP 0265#...` annotations
ambiguous. Renumbered to 0273, free on master and on every open branch,
and updated the refs in `query.js`, the new test, and the
`Extended-by:` line on LLP 0033.
`hyp query --help` still told the reader that `status` is "local-only
and ignore[s] --remote", which the refusal makes false: the CLI
documented the behavior it now immediately contradicts. The group help
names the refusal instead, and the LLP's Consequences bullet no longer
claims the flag was nowhere documented.
The new SQL dialect bullets in both `hypaware-query` SKILL.md copies
state as absent several functions that squirreling 0.15.3 (the pinned
engine) runs. Verified directly against it: `DATE_TRUNC`, `DATE_PART`,
`EXTRACT`, `DATEDIFF`, `EPOCH`, `CURRENT_DATE`, `CAST(x AS TIMESTAMP)`,
`json_extract_string`, and `split_part` all execute, so "there are no
date/time functions at all" would send an agent hand-rolling string
arithmetic for a query the engine answers. `STRING_AGG` is named as the
`group_concat` stand-in. The column-name traps are scoped to
`ai_gateway_messages`, since the otel `logs`/`metrics` datasets do have
the `timestamp` column the bullet says does not exist.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Review fixes: query status rejects every stray argument, not one flag spelling
The `--remote` refusal only caught the flag spelled correctly. `--remot prod`,
`-r prod`, `--format json`, and a bare `prod` all still printed the full local
cache inventory with exit 0 - the exact wrong-host answer LLP 0273 exists to
withhold, reached by a typo on the flag the doc tells agents not to use.
`status` takes no arguments, so the rest of argv now goes through the shared
command codec (the pattern `runQueryOverview` already documents), which
rejects unknown flags and stray positionals with exit 2.
Two skill-doc corrections, both verified against the pinned engine:
- The transport-failure bullet cited `could not reach <url> (timed out after
30000ms)`, which no remote path emits: the MCP client sets no timeout and
produces `MCP tools/call failed: HTTP <status>` or a bare `fetch failed`.
The only match in the tree is the local gateway control request at 5000ms,
so an agent following the bullet would report a remote target unreachable
when the fault was on 127.0.0.1.
- `ANY_VALUE` and `REGEXP_LIKE` do exist in squirreling 0.15.3 (both parse and
both have implementations); the bullet next to the one this PR corrected
still said they did not.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: neutral <neutral@hyperparam.app>
Co-authored-by: test <test@example.com>
Sign up for freeto 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.

1 participant

@bgmcmullen