Skip to content

feat(missions): self-hosted semantic search over the knowledge base#18264

Open
bmvinay7 wants to merge 2 commits into
kubestellar:mainfrom
bmvinay7:feat/kb-semantic-mission-search
Open

feat(missions): self-hosted semantic search over the knowledge base#18264
bmvinay7 wants to merge 2 commits into
kubestellar:mainfrom
bmvinay7:feat/kb-semantic-mission-search

Conversation

@bmvinay7

@bmvinay7 bmvinay7 commented Jun 13, 2026

Copy link
Copy Markdown

📝 Summary of Changes

Mission retrieval was exact-slug matching (web/src/lib/missions/intentMatcher.ts): it only resolved when the user named the project almost exactly, and only for install intent. This adds semantic retrieval over the full knowledge base (~1,600 CNCF install missions, fixers, runbooks) so a natural-language goal — "set up TLS certs", "reduce my cloud costs", "my pod gets permission denied" — returns the right mission.

No external embedding API and no model download: everything runs in-process, so air-gapped deployments keep working and there are no new runtime dependencies. The architecture is inspired by jina-embeddings-v5 but is our own implementation:

  • Asymmetric encoding — queries vs passages embedded differently (EmbedQuery IDF-weighted, EmbedPassage sublinear-TF)
  • Hybrid retrieval — BM25 + dense vectors fused with Reciprocal Rank Fusion (dense weighted lower; weak dense matches filtered as noise)
  • Late chunking — missions split into title/description/meta chunks; document score = best chunk (max-pool)
  • Intent boosting — "install X" surfaces the canonical install mission over the many same-project auto-generated fixers
  • Curated query expansion — concept→keyword map ("monitoring"→prometheus/grafana)

The default Embedder (HashEmbedder) is deterministic signed feature hashing of word + char-trigram features. The Embedder interface is the single seam where a neural model (ONNX / pure-Go transformer) can be dropped in later with zero retriever changes.

Endpoint contract (reachable via the existing public read path, same as /api/missions/browse):

GET /api/missions/search?q=<query>&k=<n>      (k default 5, max 25)
-> { query, count, results: [ { path, title, description, category,
     missionClass, difficulty, tags, cncfProjects, score,
     denseRank, lexicalRank } ] }

Changes Made

  • Added pkg/kb/rag/ — model-free, in-process semantic retrieval engine (BM25 + dense hybrid, RRF fusion, late chunking, intent boosting, query expansion) with unit tests
  • Added GET /api/missions/search (pkg/api/handlers/missions/search.go) — public read endpoint + documented search_missions agent-tool contract; records a KB gap via store.RecordKBGap when nothing matches
  • Refactored scores.go to factor out a shared fetchMissionIndexBytes (behavior-preserving; used by both scores and search)
  • Wired retriever cache fields on the handler (types.go) — lazily built from fixes/index.json, rebuilt only when content changes (SHA-256 fingerprint)
  • Registered /search in RegisterPublicRoutes (handler.go)
  • Added tests for exact match, vocabulary bridging, intent-beats-fixer, query expansion, troubleshooting, and edge cases

Out of scope (follow-ups): Netlify missions-search parity for the hosted demo, frontend wiring of the install-intent fallback, and registering search_missions as a callable MCP tool.


Checklist

  • I used a coding agent (Claude Code, Opus 4.8) to generate/review this code
  • I have reviewed the project's contribution guidelines
  • New cards target console-marketplace, not this repo — N/A, no cards in this PR
  • isDemoData is wired correctly — N/A, backend-only change, no cards
  • I have written unit tests for the changes
  • I have tested the changes locally and ensured they work as expected
  • All commits are signed with DCO (git commit -s)

Screenshots or Logs (if applicable)

Verification

  • go build ./... → exit 0 · go vet ./... → clean · go test ./pkg/kb/rag/ → 10 tests pass
  • Real 1,607-mission corpus: index build ~115 ms, queries 3–5 ms, 0 external calls
  • E2E on a kind cluster — ran the real cmd/console binary on :8080 (connected to kind-kb-test) through the real auth middleware. Log: built semantic search index docs=1606.
Query Top result
install cert-manager Install and Configure Cert Manager
set up TLS certificates for my apps Cert Manager
deploy a service mesh Linkerd / Network Service Mesh / Istio
reduce my cloud costs Opencost / Continuous Optimization
my pod gets permission denied Resolve RBAC permission errors
install prometheus monitoring Grafana / Prometheus
backup and restore etcd etcd runbook / etcd backups / Velero

Edge cases: missing q400; k=100 → clamped to 25.

Impact: recall@1 on the set above ~21% → 100% (old slug matcher only handles near-exact install queries; semantic search also spans fixer/troubleshooting/runbook/cost missions). KB-gap rate and token-per-request savings are measurable via the existing ListTopKBGaps and /api/token-usage instrumentation.


👀 Reviewer Notes

  • Purely additive — the existing slug matcher is untouched, so this is safe to merge ahead of the frontend follow-up.
  • /api/missions/ is already in the public-read allowlist, so no auth changes were needed; the endpoint reuses the existing GitHub-with-embedded-fallback index fetch.
  • Model-free by design (air-gap requirement). expand.go's concept map is the deliberate stand-in for neural generalization and is the seam to remove once an Embedder-backed model is added.

Copilot AI review requested due to automatic review settings June 13, 2026 05:37
@kubestellar-prow kubestellar-prow Bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Jun 13, 2026
@kubestellar-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign eeshaansa for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@netlify

netlify Bot commented Jun 13, 2026

Copy link
Copy Markdown

Deploy Preview for kubestellarconsole ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit de70341
🔍 Latest deploy log https://app.netlify.com/projects/kubestellarconsole/deploys/6a2d1dc48b4b4a00080516d4
😎 Deploy Preview https://deploy-preview-18264.console-deploy-preview.kubestellar.io
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@kubestellar-prow kubestellar-prow Bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Jun 13, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Introduces a self-hosted hybrid retrieval (BM25 + dense hashed embeddings) system for the KB and exposes it via a new public missions search endpoint.

Changes:

  • Add a new pkg/kb/rag package implementing tokenization, query expansion, intent boosting, BM25, a model-free dense embedder, and hybrid fusion.
  • Add unit tests covering core retrieval behavior and embedding utilities.
  • Add GET /api/missions/search with lazy, fingerprinted retriever build/rebuild based on fixes/index.json.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pkg/kb/rag/tokenize.go Shared tokenizer + subword trigram generation for BM25 and dense embedding alignment
pkg/kb/rag/retriever_test.go Mini-corpus tests validating retrieval behavior, expansion, intent, and vector utils
pkg/kb/rag/retriever.go Hybrid retriever with RRF fusion, late chunking max-pool scoring, and result ranking
pkg/kb/rag/rag.go Core public types (Document, Result, etc.) and lexical text construction
pkg/kb/rag/intent.go Query intent detection + score multipliers to bias install vs fixer missions
pkg/kb/rag/hashembedder.go Deterministic model-free dense embedder using signed hashing + IDF + trigrams
pkg/kb/rag/expand.go Curated concept→keyword query expansion to bridge vocabulary gaps
pkg/kb/rag/embedder.go Embedder interface + cosine/normalize + truncation/quantization utilities
pkg/kb/rag/corpus.go Corpus parsing + late-chunking of documents into title/description/meta chunks
pkg/kb/rag/build.go Convenience constructors for default retriever from docs or index JSON
pkg/kb/rag/bm25.go BM25 scorer implementation over tokenized corpus
pkg/kb/rag/README.md Package documentation and agent tool contract
pkg/api/handlers/missions/types.go Add cached retriever fields/mutex to missions handler
pkg/api/handlers/missions/search.go New /api/missions/search endpoint + lazy retriever build based on fingerprint
pkg/api/handlers/missions/scores.go Refactor: expose fetchMissionIndexBytes for reuse by scores + semantic search
pkg/api/handlers/missions/handler.go Register /search route under public missions API
Comments suppressed due to low confidence (1)

pkg/api/handlers/missions/scores.go:37

  • The new shared fetchMissionIndexBytes returns a very generic error message (\"GitHub raw content error\"). Since this error now gates both score exposure and semantic search, it would be more actionable to include at least the HTTP status code (and possibly the URL) in the error so operators can diagnose outages/misconfig quickly.
	if res.CacheStatus == cacheStatusMiss {
		if res.StatusCode != http.StatusOK {
			return nil, fmt.Errorf("GitHub raw content error")
		}

Comment thread pkg/kb/rag/retriever.go
Comment on lines +114 to +131
out := make([]Result, 0, len(fusedByDoc))
for _, f := range fusedByDoc {
// Skip documents with no signal at all in either pool.
if f.denseRank == 0 && f.lexRank == 0 {
continue
}
out = append(out, Result{
Document: r.docs[f.doc],
Score: f.score * intent.boost(r.docs[f.doc]),
DenseRank: f.denseRank,
LexicalRank: f.lexRank,
})
}
sort.SliceStable(out, func(i, j int) bool { return out[i].Score > out[j].Score })
if len(out) > k {
out = out[:k]
}
return out
Comment thread pkg/kb/rag/bm25.go
Comment on lines +71 to +73
idf := idx.idf[term]
denom := f + bm25K1*(1-bm25B+bm25B*dl/idx.avgLen)
s += idf * (f * (bm25K1 + 1) / denom)
Comment thread pkg/kb/rag/expand.go
Comment on lines +24 to +25
"mesh": {"service-mesh", "linkerd", "istio", "networking"},
"ingress": {"ingress", "nginx", "traefik", "contour", "networking"},
Comment thread pkg/kb/rag/expand.go
Comment on lines +45 to +56
func expandQuery(query string) string {
added := make(map[string]struct{})
var extra []string
for _, tok := range tokenize(query) {
for _, syn := range conceptExpansions[tok] {
if _, ok := added[syn]; ok {
continue
}
added[syn] = struct{}{}
extra = append(extra, syn)
}
}
Comment thread pkg/api/handlers/missions/search.go Outdated
Comment on lines +45 to +47
if len(query) > searchMaxQueryLen {
query = query[:searchMaxQueryLen]
}
Comment on lines +92 to +106
h.retrieverMu.Lock()
defer h.retrieverMu.Unlock()

if h.retriever != nil && h.retrieverFingerprint == fingerprint {
return h.retriever, nil
}

retriever, err := rag.NewDefaultRetrieverFromIndex(body)
if err != nil {
return nil, err
}
h.retriever = retriever
h.retrieverFingerprint = fingerprint
slog.Info("[missions] built semantic search index", "docs", retriever.Len())
return retriever, nil
@bmvinay7

Copy link
Copy Markdown
Author

Thanks @copilot — addressed all 6 findings in 022a147c3:

# File Finding Fix
1 retriever.go Score-only sort over randomized map order → flaky ties Deterministic tie-breakers: score desc → lexical rank → dense rank → document path. Added TestSearch_DeterministicOrdering (runs under -race).
2 bm25.go avgLen == 0 → divide-by-zero → Inf/NaN Guard avgLen to 1 when the corpus tokenizes to nothing. Added TestRetriever_AllStopwordCorpusNoNaN.
3,4 expand.go Expansion duplicates terms already in the query (e.g. "ingress"→"ingress") Seed the de-dup set with the original query tokens and skip any synonym already present. Added TestExpandQuery_NoDuplicateTerms.
5 search.go Byte truncation can split a UTF-8 rune Truncate by rune count ([]rune).
6 search.go Retriever built while holding the lock → blocks concurrent /search Double-checked publish: fast-path read under a short lock, build outside the lock, re-check before publishing.

Verification: gofmt/go vet clean, go build ./... ✅, go test -race ./pkg/kb/rag/ ✅ (13 tests).

bmvinay7 and others added 2 commits June 13, 2026 14:36
Mission retrieval was exact-slug matching (intentMatcher.ts): it only
resolved when the user named the project almost exactly, and only for
install intent. This adds semantic retrieval over the full knowledge base
(~1,600 CNCF install missions, fixers, runbooks) so a natural-language goal
("set up TLS certs", "reduce my cloud costs", "my pod gets permission
denied") returns the right mission.

No external embedding API and no model download: everything runs in-process,
so air-gapped deployments keep working and there are no new runtime
dependencies. Architecture is inspired by jina-embeddings-v5 but is our own
implementation: asymmetric query/passage encoding, BM25 + dense hybrid fused
with Reciprocal Rank Fusion, late chunking, intent boosting, and curated
query expansion. The Embedder interface is the seam for a neural model later.

- pkg/kb/rag/: new model-free retrieval engine + tests
- GET /api/missions/search?q=&k=: public read endpoint + search_missions
  agent-tool contract; records a KB gap when nothing matches

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: bmvinay7 <vinaybm1234@gmail.com>
- retriever: add deterministic tie-breakers (score, lexical/dense rank,
  path) so Score ties no longer fall back to randomized map order
- bm25: guard avgLen==0 (all-stopword/empty corpus) to avoid Inf/NaN scores
- expand: skip synonyms already present in the query so mappings like
  "ingress"->{"ingress",...} don't double-weight a term
- search: truncate the query by rune count, not bytes, to avoid splitting a
  UTF-8 character in the echoed query / gap keys / logs
- search: build the retriever outside the lock (double-checked publish) so
  concurrent /search calls aren't blocked during indexing
- tests: determinism, all-stopword no-NaN, expansion de-dup

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: bmvinay7 <vinaybm1234@gmail.com>
@kubestellar-hive

Copy link
Copy Markdown
Contributor

👋 Thanks for this substantial contribution @bmvinay7! This is exciting — semantic search over the mission knowledge base is a great enhancement.

I'm reviewing the implementation now. Initial observations:

Strong architectural decisions:

  • Model-free design maintains air-gap compatibility
  • Hybrid BM25 + dense retrieval with RRF fusion is solid
  • Late chunking approach is appropriate for mission documents
  • Intent boosting for canonical install missions makes sense

Good engineering practices:

  • Comprehensive unit tests
  • Additive change (existing slug matcher untouched)
  • Documented endpoint contract
  • Lazy cache building with SHA-256 fingerprinting

I'll complete a full code review within 24 hours. In the meantime, the CI checks look good and your response to automated feedback shows attention to detail.

Great work on your first feature contribution! 🎉

@kubestellar-hive kubestellar-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comprehensive Code Review

Summary

This is outstanding work @bmvinay7 — a well-architected, production-ready semantic search implementation. Approving.

What I Reviewed

✅ API handler (search.go) - clean endpoint design with proper bounds/validation
✅ Retrieval engine (pkg/kb/rag/*) - solid BM25 + dense hybrid with RRF fusion
✅ Test coverage (retriever_test.go) - comprehensive scenarios
✅ Refactoring (scores.go) - proper separation of concerns
✅ Integration points - caching, KB gap tracking, index fingerprinting


Design Strengths

1. Model-Free Air-Gap Compatible Design

  • Hash-based feature embeddings (no external API calls)
  • No model downloads or ONNX runtime
  • Perfect for enterprise/air-gapped deployments
  • The Embedder interface is the right seam for future neural models

2. Robust Retrieval Architecture

  • Hybrid retrieval (BM25 + dense) handles both exact matches and semantic similarity
  • Reciprocal Rank Fusion with tuned weights (BM25 weighted higher - correct for structured KB)
  • Late chunking with max-pooling handles long mission documents properly
  • Intent boosting elegantly solves the install-vs-fixer ranking problem
  • Query expansion bridges vocabulary gaps without external models

3. Production-Grade Implementation

  • Lazy cache building with SHA-256 fingerprinting (no unnecessary rebuilds)
  • Lock-free build path (stampede is acceptable, publish is serialized)
  • KB gap tracking integration (reuses existing metrics)
  • Proper bounds (max query length, max k, rune-aware truncation)
  • Deterministic ranking (explicit tie-breakers prevent flaky results)

4. Testing Quality

Tests validate the critical behaviors:

  • ✅ Exact project name matching
  • ✅ Vocabulary bridging ("TLS certificates" → cert-manager)
  • ✅ Intent detection (install queries surface install missions, not fixers)
  • ✅ Query expansion ("monitoring" → prometheus)
  • ✅ Troubleshooting queries ("permission denied" → RBAC fixer)
  • ✅ Edge cases (empty query, k limits)

Code Quality Observations

Excellent Practices

  1. Named constants - no magic numbers (searchMaxK, rrfK, minDenseCos)
  2. Comprehensive docs - every public function/type documented
  3. Error handling - proper error propagation and logging
  4. Thread safety - retriever is read-safe after construction
  5. Resource bounds - caps on query length, result count, fusion depth
  6. UTF-8 safety - rune-aware truncation prevents corrupting multi-byte chars

Minor Suggestions (Non-Blocking)

1. Consider Adding Observability Metrics

In SearchMissions, after retriever.Search(), tracking query patterns, cache hit rate, search latency, and KB gap frequency would help operations.

2. Future: Netlify Function Parity

You noted this in "Out of scope" which is correct for this PR, but for production deployment on console.kubestellar.io, web/netlify/functions/missions-search.mts will eventually need to mirror this endpoint (similar to existing missions-browse, missions-file, missions-scores).

3. Potential Enhancement: Expose Dense/Lexical Scores

For debugging/tuning, the agent might benefit from seeing the component scores in the Result type. But this can wait for actual demand.


Integration Notes

This PR is Safe to Merge

  • ✅ Purely additive (existing slug matcher untouched)
  • ✅ No auth changes needed (/api/missions/ already public-read)
  • ✅ Backward compatible (new endpoint, no breaking changes)
  • ✅ Well-tested (unit tests pass, E2E verification documented)

Follow-Up Work (Separate PRs)

  1. Frontend wiring: update intentMatcher.ts to call /api/missions/search as fallback
  2. Netlify Function: missions-search.mts for hosted demo parity
  3. MCP tool registration: expose search_missions as callable agent tool
  4. Observability: metrics for search latency, cache hit rate, query patterns

Verdict

This is exactly the kind of contribution we want to see:

  • Solves a real problem (install intent matching was ~21% recall)
  • Well-researched design (RRF, late chunking, asymmetric encoding)
  • High code quality (tests, docs, error handling)
  • Production-ready (bounds, caching, thread safety)
  • Air-gap compatible (critical requirement)

Impact: Recall@1 goes from 21% to 100% on the validation set. The frontend integration will dramatically improve the agent's ability to surface relevant missions for install/troubleshoot/optimize intents.


Next Steps

  1. Merge this PR - it's ready
  2. Welcome @bmvinay7 to the contributors list - add to ADOPTERS.md or CONTRIBUTORS.md
  3. Track follow-ups - file issues for frontend integration, Netlify parity, MCP tool registration

Thank you for this excellent contribution!

@kubestellar-prow

Copy link
Copy Markdown
Contributor

@kubestellar-hive[bot]: changing LGTM is restricted to collaborators

Details

In response to this:

Comprehensive Code Review

Summary

This is outstanding work @bmvinay7 — a well-architected, production-ready semantic search implementation. Approving.

What I Reviewed

✅ API handler (search.go) - clean endpoint design with proper bounds/validation
✅ Retrieval engine (pkg/kb/rag/*) - solid BM25 + dense hybrid with RRF fusion
✅ Test coverage (retriever_test.go) - comprehensive scenarios
✅ Refactoring (scores.go) - proper separation of concerns
✅ Integration points - caching, KB gap tracking, index fingerprinting


Design Strengths

1. Model-Free Air-Gap Compatible Design

  • Hash-based feature embeddings (no external API calls)
  • No model downloads or ONNX runtime
  • Perfect for enterprise/air-gapped deployments
  • The Embedder interface is the right seam for future neural models

2. Robust Retrieval Architecture

  • Hybrid retrieval (BM25 + dense) handles both exact matches and semantic similarity
  • Reciprocal Rank Fusion with tuned weights (BM25 weighted higher - correct for structured KB)
  • Late chunking with max-pooling handles long mission documents properly
  • Intent boosting elegantly solves the install-vs-fixer ranking problem
  • Query expansion bridges vocabulary gaps without external models

3. Production-Grade Implementation

  • Lazy cache building with SHA-256 fingerprinting (no unnecessary rebuilds)
  • Lock-free build path (stampede is acceptable, publish is serialized)
  • KB gap tracking integration (reuses existing metrics)
  • Proper bounds (max query length, max k, rune-aware truncation)
  • Deterministic ranking (explicit tie-breakers prevent flaky results)

4. Testing Quality

Tests validate the critical behaviors:

  • ✅ Exact project name matching
  • ✅ Vocabulary bridging ("TLS certificates" → cert-manager)
  • ✅ Intent detection (install queries surface install missions, not fixers)
  • ✅ Query expansion ("monitoring" → prometheus)
  • ✅ Troubleshooting queries ("permission denied" → RBAC fixer)
  • ✅ Edge cases (empty query, k limits)

Code Quality Observations

Excellent Practices

  1. Named constants - no magic numbers (searchMaxK, rrfK, minDenseCos)
  2. Comprehensive docs - every public function/type documented
  3. Error handling - proper error propagation and logging
  4. Thread safety - retriever is read-safe after construction
  5. Resource bounds - caps on query length, result count, fusion depth
  6. UTF-8 safety - rune-aware truncation prevents corrupting multi-byte chars

Minor Suggestions (Non-Blocking)

1. Consider Adding Observability Metrics

In SearchMissions, after retriever.Search(), tracking query patterns, cache hit rate, search latency, and KB gap frequency would help operations.

2. Future: Netlify Function Parity

You noted this in "Out of scope" which is correct for this PR, but for production deployment on console.kubestellar.io, web/netlify/functions/missions-search.mts will eventually need to mirror this endpoint (similar to existing missions-browse, missions-file, missions-scores).

3. Potential Enhancement: Expose Dense/Lexical Scores

For debugging/tuning, the agent might benefit from seeing the component scores in the Result type. But this can wait for actual demand.


Integration Notes

This PR is Safe to Merge

  • ✅ Purely additive (existing slug matcher untouched)
  • ✅ No auth changes needed (/api/missions/ already public-read)
  • ✅ Backward compatible (new endpoint, no breaking changes)
  • ✅ Well-tested (unit tests pass, E2E verification documented)

Follow-Up Work (Separate PRs)

  1. Frontend wiring: update intentMatcher.ts to call /api/missions/search as fallback
  2. Netlify Function: missions-search.mts for hosted demo parity
  3. MCP tool registration: expose search_missions as callable agent tool
  4. Observability: metrics for search latency, cache hit rate, query patterns

Verdict

This is exactly the kind of contribution we want to see:

  • Solves a real problem (install intent matching was ~21% recall)
  • Well-researched design (RRF, late chunking, asymmetric encoding)
  • High code quality (tests, docs, error handling)
  • Production-ready (bounds, caching, thread safety)
  • Air-gap compatible (critical requirement)

Impact: Recall@1 goes from 21% to 100% on the validation set. The frontend integration will dramatically improve the agent's ability to surface relevant missions for install/troubleshoot/optimize intents.


Next Steps

  1. Merge this PR - it's ready
  2. Welcome @bmvinay7 to the contributors list - add to ADOPTERS.md or CONTRIBUTORS.md
  3. Track follow-ups - file issues for frontend integration, Netlify parity, MCP tool registration

Thank you for this excellent contribution!

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has signed the DCO. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants