You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Build shell completion, fuzzy selection, and query-builder metadata on top of the same query grammar, AST, action contracts, and read-view metadata used by CLI, MCP, daemon, Python, and web routes.
Completion is not a separate language. It is a read-only projection of the parser/lowerer/action/view registries, plus bounded archive-backed value providers.
Why this exists
The query language is now powerful enough that mistyped fields, stale examples, and unsupported future syntax are expensive. Completion should make valid fields, structural units, operators, values, read views, formats, and then actions discoverable without adding a natural-language layer or a second parser.
The product outcome is fewer invalid commands, fewer hidden surface mismatches, and a shared metadata feed that future MCP/web query builders can consume without reimplementing query semantics.
polylogue/cli/shell_completion_values.py contains static and archive-backed completion providers.
polylogue/archive/query/fields.py defines QueryFieldDescriptor, CompletionSource, and query_completion_sources() for spec-field metadata.
polylogue/archive/query/expression.py owns the Lark-backed query grammar, EXPRESSION_FIELD_REGISTRY, and structural query-unit metadata for exists message(...), exists action(...), and exists block(...).
Public action contracts live in polylogue.operations.action_contracts; the CLI re-exports them for compatibility. CliActionContract.completion_context and action_completion_contexts() expose action-contract completion contexts.
Stale wording to avoid: there is no long-lived "flat compiler floor." Current compact queries and explicit Boolean/structural predicates are being absorbed into #2006's Lark grammar and AST/lowering path. Completion should follow that canonical path as it lands, not preserve a parallel grammar.
Source-of-truth rule
Completion metadata must come from existing parser/action/view registries wherever possible:
query field names and examples from EXPRESSION_FIELD_REGISTRY;
structural units and structural fields from STRUCTURAL_QUERY_UNIT_REGISTRY / structural_query_units() / structural_query_fields();
completion value source names from QueryFieldDescriptor.completion_source / query_completion_sources();
action and danger metadata from ACTION_CONTRACTS / CliActionContract;
read views from SessionViewProfile / read_view_profile_payloads() rather than ad hoc lists;
If completion needs to duplicate a command, field, view, or output contract by hand, treat that as a design smell and either move the metadata to the owning registry or make the duplication mechanically checked.
Query-substrate boundary
Completion must expose the shared query grammar. It may inspect incomplete text to decide what kind of candidate to offer, but it must not implement a second grammar or accept syntax the real parser/lowerer rejects.
Unknown-field suggestions should be derived from the grammar field registry.
Structural-unit and structural-field suggestions should be derived from the grammar's structural registry.
Value suggestions should be tied to the field's declared completion source.
Unsupported parser/lowerer errors should be surfaced as "why not" messages where the adapter can show them.
Completion should suggest
fields: origin, repo, tag, title, since, until, tool, action, words, messages, has, near, lineage, etc., as they are supported by the parser/lowerer;
structural units: message(, action(, block( after exists;
structural fields inside exists <unit>(...), such as role:, text:, type:, path:, tool:, and command: when supported by that unit;
values from the live archive: origins, repos, tags, tools, actions, session ids, and path-like values where there is a real projection;
operators supported by the field and lowerer;
then actions and valid action-specific options from action contracts;
read views and formats from view-profile metadata;
degraded/unavailable states when the archive cannot answer dynamic values;
danger/confirmation metadata for destructive actions such as delete/mark variants.
Completion candidate record
Candidate records should carry enough structure for shells, fuzzy pickers, and future query builders:
value
insert
replace_start / replace_end
display
kind
group
description
score
source
stale
danger
unsupported_reason optional
preview_command optional
Completion is read-only. It may suggest destructive actions with danger metadata, but it must not execute them or bind them to single-key fuzzy shortcuts.
Implementation program
Implement completion as a usable query/action affordance, not as DTO ceremony.
Expose query field candidates directly from EXPRESSION_FIELD_REGISTRY, plus readable count/date field metadata from COUNT_QUERY_FIELD_REGISTRY and DATE_QUERY_FIELD_REGISTRY, including descriptions and examples.
Keep parser-context completion for common partial query states: empty query, partial field name, after field:, after exists, inside exists <unit>(...), after then, and after read --view. Already-covered states must stay tested rather than reimplemented.
Keep dynamic archive value providers bounded and graceful: missing/locked/stale archive returns stale or empty candidates, never a traceback.
Add action candidates from ACTION_CONTRACTS, carrying destructive/danger metadata.
Keep read-view and read-format candidates sourced from SessionViewProfile metadata.
Keep the read-only select verb wired through the existing query-backed selector and action contract. Future picker work should enrich candidate metadata rather than bypassing that path.
Reuse query_completions / QueryCompletionCandidate payloads from any future interactive query-builder UI; CLI, Python API, MCP, and the daemon web API already consume the shared contract, so new consumers should not reimplement query metadata.
The implementation should keep landing surfaced behavior. Do not stop at a registry or model with no shell/API/MCP consumer.
Acceptance criteria
Field-name completions are generated from EXPRESSION_FIELD_REGISTRY.
At least one test proves a deleted/renamed field, read view, action, structural unit, or structural field disappears from completion automatically through the shared registry.
Completion metadata is consumable by Python API, MCP, daemon web API, and future query-builder clients without reimplementing query semantics.
Non-goals
Do not build a separate query parser.
Do not implement natural-language search here.
Do not expose write actions through a fuzzy picker without explicit confirmation.
Do not add a web/query-builder facade that bypasses the shared metadata contract.
Readiness: ~80% already in code · scope M · conflict risk medium · depends on: #2006
Assessment & remaining work: The core completion infrastructure is complete: polylogue/archive/query/completions.py provides QueryCompletionCandidate and registry-driven candidates from EXPRESSION_FIELD_REGISTRY, QUERY_UNIT_DESCRIPTORS, and ACTION_CONTRACTS; polylogue/cli/shell_completion_values.py wraps these for shells with graceful empty/locked archive degradation; GET /api/query-completions, MCP query_completions, and Polylogue.query_completions() all expose the shared payload. Two ACs remain unimplemented: (1) "unknown field typos produce useful suggestions" requires adding a difflib/levenshtein nearest-match helper in completions.py and surfacing it from query_field_candidates when no candidates match; (2) an explicit registry-binding test in tests/unit/archive/test_query_metadata.py (or a dedicated file) must prove that removing a field from EXPRESSION_FIELD_REGISTRY causes it to disappear from query_field_candidates() output — the design guarantees this but no test currently asserts it. The structural-unit AC referencing "#2006 grammar metadata" is blocked on issue #2006 (open Lark DSL work); current QUERY_UNIT_DESCRIPTORS-backed implementation satisfies the spirit but not the exact letter until #2006 lands.
Purpose
Build shell completion, fuzzy selection, and query-builder metadata on top of the same query grammar, AST, action contracts, and read-view metadata used by CLI, MCP, daemon, Python, and web routes.
Completion is not a separate language. It is a read-only projection of the parser/lowerer/action/view registries, plus bounded archive-backed value providers.
Why this exists
The query language is now powerful enough that mistyped fields, stale examples, and unsupported future syntax are expensive. Completion should make valid fields, structural units, operators, values, read views, formats, and
thenactions discoverable without adding a natural-language layer or a second parser.The product outcome is fewer invalid commands, fewer hidden surface mismatches, and a shared metadata feed that future MCP/web query builders can consume without reimplementing query semantics.
Current implementation reality
Polylogue already has useful completion plumbing:
polylogue completionsemits bash/zsh/fish completion setup.polylogue/cli/shell_completion_values.pycontains static and archive-backed completion providers.polylogue/archive/query/fields.pydefinesQueryFieldDescriptor,CompletionSource, andquery_completion_sources()for spec-field metadata.polylogue/archive/query/expression.pyowns the Lark-backed query grammar,EXPRESSION_FIELD_REGISTRY, and structural query-unit metadata forexists message(...),exists action(...), andexists block(...).polylogue.operations.action_contracts; the CLI re-exports them for compatibility.CliActionContract.completion_contextandaction_completion_contexts()expose action-contract completion contexts.SessionViewProfileand the read-view profile APIs from Define evidence-linked session view profiles #1997 expose read-view metadata to CLI, Python, and MCP.read --viewchoices and completion come fromREAD_VIEW_PROFILES;read --formatchoices and completion come fromSessionViewProfile.formats(feat(cli): complete read formats from view profiles (#1844) #2034).polylogue/cli/select.pyowns the read-only query-backed selector with fzf/UI fallback;selectis now registered as a query verb and action contract (feat(cli): expose query-backed select verb (#1844) #2036).polylogue.archive.query.completionsowns the sharedQueryCompletionCandidatepayload and registry-backed candidate providers.polylogue query-completions,Polylogue.query_completions(...), MCPquery_completions, andGET /api/query-completionsall expose the same structured query/action completion metadata (feat(cli): expose query completion metadata (#1844) #2037/feat(query): share completion metadata across API and MCP (#1844) #2038/feat(daemon): expose query completion metadata endpoint (#1844) #2039), including registry provenance, danger/stale fields, replacement fields, full descriptions, and readable count/date field discoverability.Stale wording to avoid: there is no long-lived "flat compiler floor." Current compact queries and explicit Boolean/structural predicates are being absorbed into #2006's Lark grammar and AST/lowering path. Completion should follow that canonical path as it lands, not preserve a parallel grammar.
Source-of-truth rule
Completion metadata must come from existing parser/action/view registries wherever possible:
EXPRESSION_FIELD_REGISTRY;STRUCTURAL_QUERY_UNIT_REGISTRY/structural_query_units()/structural_query_fields();QueryFieldDescriptor.completion_source/query_completion_sources();ACTION_CONTRACTS/CliActionContract;SessionViewProfile/read_view_profile_payloads()rather than ad hoc lists;If completion needs to duplicate a command, field, view, or output contract by hand, treat that as a design smell and either move the metadata to the owning registry or make the duplication mechanically checked.
Query-substrate boundary
Completion must expose the shared query grammar. It may inspect incomplete text to decide what kind of candidate to offer, but it must not implement a second grammar or accept syntax the real parser/lowerer rejects.
Rules:
Completion should suggest
origin,repo,tag,title,since,until,tool,action,words,messages,has,near,lineage, etc., as they are supported by the parser/lowerer;message(,action(,block(afterexists;exists <unit>(...), such asrole:,text:,type:,path:,tool:, andcommand:when supported by that unit;thenactions and valid action-specific options from action contracts;Completion candidate record
Candidate records should carry enough structure for shells, fuzzy pickers, and future query builders:
Completion is read-only. It may suggest destructive actions with danger metadata, but it must not execute them or bind them to single-key fuzzy shortcuts.
Implementation program
Implement completion as a usable query/action affordance, not as DTO ceremony.
polylogue.archive.query.completions; CLI shell completion should only adapt that metadata into ClickCompletionItems, whilepolylogue query-completions --format json,Polylogue.query_completions(...), and MCPquery_completionsexpose the shared payload for non-shell consumers (feat(cli): expose query completion metadata (#1844) #2037/feat(query): share completion metadata across API and MCP (#1844) #2038).EXPRESSION_FIELD_REGISTRY, plus readable count/date field metadata fromCOUNT_QUERY_FIELD_REGISTRYandDATE_QUERY_FIELD_REGISTRY, including descriptions and examples.field:, afterexists, insideexists <unit>(...), afterthen, and afterread --view. Already-covered states must stay tested rather than reimplemented.ACTION_CONTRACTS, carrying destructive/danger metadata.SessionViewProfilemetadata.selectverb wired through the existing query-backed selector and action contract. Future picker work should enrich candidate metadata rather than bypassing that path.query_completions/QueryCompletionCandidatepayloads from any future interactive query-builder UI; CLI, Python API, MCP, and the daemon web API already consume the shared contract, so new consumers should not reimplement query metadata.The implementation should keep landing surfaced behavior. Do not stop at a registry or model with no shell/API/MCP consumer.
Acceptance criteria
EXPRESSION_FIELD_REGISTRY.Non-goals
Related issues
Current state (audited 2026-06-27)
Readiness: ~80% already in code · scope
M· conflict riskmedium· depends on: #2006Assessment & remaining work: The core completion infrastructure is complete:
polylogue/archive/query/completions.pyprovidesQueryCompletionCandidateand registry-driven candidates fromEXPRESSION_FIELD_REGISTRY,QUERY_UNIT_DESCRIPTORS, andACTION_CONTRACTS;polylogue/cli/shell_completion_values.pywraps these for shells with graceful empty/locked archive degradation;GET /api/query-completions, MCPquery_completions, andPolylogue.query_completions()all expose the shared payload. Two ACs remain unimplemented: (1) "unknown field typos produce useful suggestions" requires adding a difflib/levenshtein nearest-match helper incompletions.pyand surfacing it fromquery_field_candidateswhen no candidates match; (2) an explicit registry-binding test intests/unit/archive/test_query_metadata.py(or a dedicated file) must prove that removing a field fromEXPRESSION_FIELD_REGISTRYcauses it to disappear fromquery_field_candidates()output — the design guarantees this but no test currently asserts it. The structural-unit AC referencing "#2006 grammar metadata" is blocked on issue #2006 (open Lark DSL work); currentQUERY_UNIT_DESCRIPTORS-backed implementation satisfies the spirit but not the exact letter until #2006 lands.Primary files:
polylogue/archive/query/completions.py,polylogue/archive/query/metadata.py,polylogue/cli/shell_completion_values.py,polylogue/cli/commands/completions.py,tests/unit/archive/test_query_metadata.py,tests/unit/cli/test_completions_contract.py,tests/unit/cli/test_completion_matrix.pyGrounded re-assessment from the 2026-06-27 backlog triage; verify against source before acting.