feat(query): resolve --pipeline names client-side in audit/snapshot (v1.6.2)#12
Merged
Merged
Conversation
…v1.6.2)
Why
- v1.6.1 query audit / query snapshot only accept opaque pipeline IDs.
Passing a name (e.g. 'Sales - Flex - Triage') silently returned
rows: [], pushing the agent to drop into raw query sql to look up the
ID and then re-run audit. That's the v1.6.1 -> v1.6.2 loophole shape:
primitive forces a wrapper round-trip the skill rules can't bind.
What
- New resolvePipelineID() runs before the audit/snapshot SQL:
- Opaque 20-char ID (e.g. CLUy1QapsrEeBiNrmQiL) passes through.
- Otherwise tokens are AND'd as case-insensitive LIKEs against the
pipelines table.
- 1 match -> use it, surface matchedId/matchedName/matchedBy.
- 0 match -> error lists every available pipeline.
- >1 match -> error lists the candidates.
- Audit JSON gains pipelineResolution so the agent (and humans) see how
the input was matched. matchedBy = "id" | "name".
- Skill docs (hermes + claude-code) bumped to v1.6.2:
- --pipeline now reads PIPELINE_ID_OR_NAME.
- New banned-in-default-flow rule: don't run raw query sql to resolve
a pipeline name to its ID.
- Pitfall #17 documents the v1.6.1 failure trace and the v1.6.2 fix.
Tests
- TestQueryAuditResolvesPipelineByName: 'flex triage' -> Triage ID,
resolution echo'd in JSON, audit SQL uses opaque ID.
- TestQueryAuditUnknownPipelineListsCandidates: 'no such pipeline'
errors with the candidate list.
- TestQueryAuditAmbiguousPipelineErrors: 'flex' errors with both
Flex pipelines and an "ambiguous" hint.
- TestQuerySnapshotResolvesPipelineByName: same resolver path for
query snapshot.
All resolver and existing tests pass; go build ./... clean.
alexskatell
added a commit
that referenced
this pull request
May 14, 2026
PR #12's selectIDNamePairs assumed rows came back as positional arrays ([]any aligned with `columns`), but the live hosted warehouse query API returns rows as column-keyed maps (map[string]any with "id" and "name" keys). The unit-test fixture also returned positional arrays, so the mismatch slipped through — verified against prod by running: topline --agent query audit --pipeline 'flex triage' ... which returned `no pipeline matched ... Available pipelines: (none found)` even though `SELECT id, name FROM pipelines` returned rows fine. Fix - selectIDNamePairs now switches on row type: - map[string]any: read row["id"] / row["name"] by column name. - []any: read by positional index (preserved for parity with any deployment that returns array rows). - Test fixture in pipelineLookupServer rewritten to emit the real column-keyed object shape ({"id":"...","name":"..."}), so the resolver tests now exercise the actual wire format. Verified live: `topline --agent query audit --pipeline 'flex triage' ...` resolves to bna6e9DoPgRchNsjeYS3 (Sales - Flex - Triage) and runs the audit cleanly. All existing resolver tests still pass. Co-authored-by: Alex Skatell <alex@topline.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
query auditandquery snapshotin v1.6.1 only accept opaque 20-char pipeline IDs. Passing a human-readable name (e.g.'Sales - Flex - Triage') silently returnedrows: []because the literal string got jammed intoWHERE pipeline_id = '...', which never matches.Live failure trace (Paul, 2026-05-14):
topline --agent query doctor✓topline --agent query audit --pipeline 'Sales - Flex - Triage' --since this-week-et→rows: []topline --agent query sql --sql "SELECT id, name FROM pipelines WHERE LOWER(name) LIKE '%flex%' OR LOWER(name) LIKE '%triage%'"— the agent correctly diagnoses "wrong identifier" and writes raw SQL to translate the nametopline --agent query audit --pipeline bna6e9DoPgRchNsjeYS3 --since this-week-et— now it worksThat third call is the loophole shape: a primitive gap that forces a raw-SQL wrapper round-trip the skill rules can't bind. Per the auto-memory rule of thumb that landed during the earlier audit-contract work — after three failed skill iterations, build the primitive instead of writing another rule — we're moving the lookup into the CLI rather than tightening pitfall #N+1.
What
resolvePipelineID()runs before the audit/snapshot SQL:CLUy1QapsrEeBiNrmQiL) passes through unchanged.pipelines.name.pipelineResolution: {input, matchedId, matchedName, matchedBy: "name"}in the JSON envelope.Available pipelines: A (id), B (id), …).pipelineResolution, so agents (and humans) see exactly how--pipelinewas matched.skills/hermes/SKILL.md+skills/claude-code/SKILL.md) bumped to v1.6.2:--pipelinenow reads asPIPELINE_ID_OR_NAME.query sqlto resolve a pipeline name to its ID —query audit/snapshothandle it.Tests
TestQueryAuditResolvesPipelineByName—'flex triage'resolves to the Triage opaque ID;pipelineResolution.matchedId/matchedName/matchedByare echoed; audit SQL uses the resolved ID.TestQueryAuditUnknownPipelineListsCandidates—'no such pipeline'errors with the available-pipelines list.TestQueryAuditAmbiguousPipelineErrors—'flex'errors listing both Flex pipelines with an "ambiguous" hint.TestQuerySnapshotResolvesPipelineByName— same resolver path forquery snapshot.go build ./...clean; fullgo test ./...green.Expected agent trace after this lands
For
What activity happened this week in our flex triage pipeline?:No intermediate
query sql, nopython3 -<<'PY', no bash heredoc. The third tool call is gone.Non-goals
os-mcpviews.query sql(separate, larger change).