Skip to content

t1k:knowledge-retrieval

FieldValue
Modulet1k-extended
Version3.5.0
Effortmedium
ToolsAskUserQuestion, Bash, Glob, Grep, Read

Keywords: assembly lookup, corpus search, doc_get_member, doc_search, does this exist, have we built this, knowledge-retrieval, prior art, rag query, reuse check, semantic search, studio docs

/t1k:knowledge-retrieval
<capability or need> [--engine unity|cocos] [--json <out>]

Studio Knowledge Retrieval — Prior-Art Lookup That Actually Returns the Answer

Section titled “Studio Knowledge Retrieval — Prior-Art Lookup That Actually Returns the Answer”

Retired 2026-08-26 — you may now query a bare symbol name. This skill previously required every query to contain an all-lowercase word, because a query of only capitalized tokens returned a fixed junk set at ~0.79 similarity. That was a deployment defect (AIPGDS#9/#16), it is fixed (AIPGDS#18), and the corpus has been rebuilt. IObjectPoolManager now returns TheOne.Pooling.ObjectPoolManager at 0.7302 on the vector arm.

Correction 2026-08-26 — “fixed” is premature. PR AIPGDS#18 merged, but issues #9 and #16 are both still OPEN, and the symptoms remain measurable. Bare-symbol search now works for some types (RingSpawnRequest 0.7745, DraftPool 0.6925) and still fails for others (DotDamageAccumulator, CombatTarget, CurrencyId all miss their own record on a bare-name query). Root cause of the residue: the lexical arm is a full-text index over summary only (002_init_rag_docs.sql:63 — to_tsvector('english', coalesce(summary, ''))); simple_name has a separate btree that the hybrid search does not use. A type is therefore lexically findable only if its own summary happens to repeat its name — while its members’ summaries routinely do name the parent, which is why members outrank their own type. Measured: of 40 types known to be indexed, 8 could not be found by typing their own name (100% coverage, 80% reachability), and rank 1 in only 8 of 32 successful lookups.

It is called out here, not only in references/query-technique.md §0, because anyone who internalised the old rule has no reason to re-open the reference that retired it. The lexical arm is still conjunctive (AIPGDS#10), so the 2–3-content-word guidance stands — for that reason, not this one.

Ask the studio corpus “do we already have this?” against one MCP that indexes both engine worlds — and get an answer scoped to the engine you are actually working in.

The whole problem in one line: the corpus is overwhelmingly Unity/.NET, so the same unscoped query is correct for a Unity question and confidently wrong for a Cocos one. Scope is not an optimization here; it decides whether the answer is usable at all.

Query mechanics and corpus facts are the SSOT in references/doc-search-contract.md. How to shape the query — the part that most changes result quality — is references/query-technique.md. Cite them; do not restate them.

Nameknowledge-retrieval (HTTP MCP, https://mcp.the1studio.org/mcp)
Toolsdoc_search, doc_get_member, doc_list_assemblies
Authyour own gh auth token; needs active The1Studio org membership
Install~/.claude/skills/t1k-mcp-management/scripts/install-knowledge-retrieval.sh
Declaredmcp.required[] with autoInstall: true in both t1k-config-unity.json and t1k-config-cocos.json

Registration, credentials, and the auto-install policy belong to t1k-mcp-management. This skill owns only what to do once the tools are loaded.

When to invoke — the second half of prior art, not the first

Section titled “When to invoke — the second half of prior art, not the first”

Sweep the corpus FIRST — grep only confirms what you already know to ask for.** The discovery protocol is corpus-first, grep-second (theonekit-unity#533): the corpus is the default entry point for “does this already exist?”, and local grep is the step that turns a corpus hit into an actionable path. For a need you can name as a symbol, grep is fast and authoritative (real file path, on-disk version, actual implementation, reference count) — but a clean grep is not a miss; it is the corpus that answers a capability not checked out here, a sibling project’s source, or a need phrased as behaviour.

That verdict generalizes only to needs you can name. Grep answers the questions you knew to ask in the folder you knew to open. A need phrased as behaviour — “cancel a looping hint safely” — names no symbol, has no grep target, and remains a corpus question even when the answer is already installed locally. The skip is licensed by a nameable symbol, never by “it was installed” (the Cocos drift log carries the worked case where that exact reasoning lost a hit).

Invoke for the three things grep structurally cannot answer:

CaseWhy grep fails
Capability not checked out hereYou cannot grep a file that is not on disk. Confirm that is really the situation first — package count is not capability count.
Design precedent from another projectSibling projects are indexed. You cannot grep a repo you do not have.
You do not know what to grep forSemantic search answers “does anything solve X?” when you cannot name the symbol.

Not for: package names and versions (Cocos → CPM, https://cpm.playablelabs.ai/); needs a grep you could actually phrase already answers; a question about a third engine — the corpus indexes Unity/.NET and Cocos only, and a React-Native or web question returns confident nonsense from both.

  1. Establish the engine. Unity, Cocos, or neither. This picks the scoping profile in § Scoping and it is not optional — the same query needs opposite handling.
  2. Name the needs as capabilities, not class names. "combo multiplier score streak", not "ComboMeterController". The index is semantic; a local symbol name is the one string guaranteed not to appear in another project.
  3. Shape the query as an answer, not a question — see references/query-technique.md § Write the answer. This is the single highest-leverage step and it is free.
  4. Retrieve with the engine’s budget (§ Scoping). One call per need.
  5. Filter, then apply the positive test before citing anything. A name predicate is not proof; confirm the hit’s language and types match the engine you are in.
  6. Deepen survivors worth citing: doc_get_member({ id }) for the real signature.
  7. Tag and emit the prior-art table. Every ○ is new work someone will be asked to pay for — be sure the miss is real, and not a filter artefact or an absent MCP.
  8. Promote genuinely new, charter-generic work upstream. A corpus-miss on code carrying no project-specific token is a contribute-back case, not just a ○ in the table — see § Contribute back. This is the other half of the same sweep, not a separate task.

Scoping — the same corpus, two opposite problems

Section titled “Scoping — the same corpus, two opposite problems”

Do not quote a corpus count from memory or from this prose. The exact split lives in references/doc-search-contract.md’s pointer to assets/corpus-summary.json — regenerate it via scripts/refresh-corpus-summary.cjs before citing a number in a report. What stays true regardless of the exact count on any given day: Unity/.NET is the large majority of the corpus, Cocos is a small minority split between a fixed set of foundation subsystems and a growing list of projects. Your engine decides which failure mode you are fighting.

UnityCocos
Share of corpusthe large majoritya small minority
Failure modeToo many valid hits — 20 near-identical overloads, no wrong-language noiseRight answers outranked — C# APIs a playable can never import take the top slots
Default limit1025 (mandatory)
Primary mechanismassembly_prefix to disambiguate a known subsystemfilter-after-search against the committed allowlist
Main riskpicking a deprecated or internal overloadfiltering your way to an empty result on a capability the studio demonstrably has

The rule underneath both columns: filter-after-search is post-filtering, and post-filtering loses recall in proportion to how little of the corpus survives your filter. Retrieve budget must scale inversely with filter selectivity. Cocos keeps only a small slice of the corpus, so it must over-retrieve; Unity keeps nearly all of it, so it need not. Derivation, the measured ranking proof, and the ceiling rule: references/query-technique.md § Over-retrieve.

When limit: 25 still is not enough, the answer is not a bigger limit — 25 is the schema maximum. Switch mechanisms: an assembly_prefix drill-down is pre-filtering, which has no oversampling problem because the filter is applied before the search rather than after it. Broad-at-25 → prefixed drill-down is the intended shape.

⛔ assembly_prefix at FAMILY level is a truncation switch, not a narrowing aid

Section titled “⛔ assembly_prefix at FAMILY level is a truncation switch, not a narrowing aid”

Measured 2026-08-26 against unity-dots-library. assembly_prefix is a raw string prefix over assembly names, and this library ships two naming conventions — only 9 of ~97 indexed assemblies begin com.the1studio.; the other ~88 are bare CLR names (DOTSCore, DOTSCombat.Spawning, DOTSEconomy.Runtime, DOTSProgression.*, DOTSBridges.*, DOTSUiKit). The tell: com.the1studio.dots-core.Editor carries the prefix while its own runtime DOTSCore does not.

So assembly_prefix: "com.the1studio" hides ~91% of the library and reports success. It destroyed the correct answer in 7 of 20 benchmark queries and then backfilled each page to 10 rows with no signal. Cleanest case: a fertilizer query returned 10/10 correct DOTSFarming.Runtime rows unfiltered and zero farming content filtered — ten confident decoys from other packages.

Rule: only pass assembly_prefix an assembly name you have already seen in a result. Never a package family, never a guess. And note a prefix is not a boundary — assembly_prefix: "DOTSCombat.Spawning" silently also matches DOTSCombat.Spawning.Authoring, while scoping to DOTSProgression spans several distinct assemblies.

Cocos callers: the committed allowlist and the ranking proof live in the Cocos kit (t1k-cocos-base-knowledge-sweep), which cites this file for everything above. Use that skill directly in a Cocos project — it adds the generated allowlist, the project detector, and the prior-art table shape its four consumers read.

⚠️ Two of the three criteria below were measured non-functional (2026-08-26)

Section titled “⚠️ Two of the three criteria below were measured non-functional (2026-08-26)”
  • summary_quality: "high" discriminates nothing. It was high on 100% of 200 measured hits, on every hit returned for three deliberate nonsense queries, and on a member that does not exist in any source file. Corpus-wide it is 96.6% high. It rates prose completeness, never correctness or lifecycle. Treat it as metadata, never as a gate.
  • similarity ≳ 0.65 admits confirmed junk. A wrong Cocos hit ranked #1 at 0.760; an entirely irrelevant page sat at 0.720–0.729. Meanwhile the nonsense floor is 0.535–0.616 (a query about Vietnamese trademark law scored 0.616 — higher than a page containing a real, shipped capability at 0.599–0.623). The bands overlap, so no threshold separates them; 0.65 screens literal gibberish and nothing else.
  • Only the engine/assembly check actually works — and see the assembly_prefix warning above before trying to enforce it with a filter.

Use instead: does the returned summary describe the capability you asked for, in an assembly that belongs to your engine? That judgement is the gate. A score and a quality label are not.

Treat a hit as real prior art only when the assembly belongs to your engine and the summary actually answers your question (the two struck criteria above are unreliable). Then tag it:

TagMeaning
● inheritedThe member does the whole job — reuse as-is, bill nothing.
◐ framework-assistedA base exists; you build on it.
○ customNothing upstream — genuinely new work.

Record the verdict as reuse-search: found <Type>@<path> — byte-exact, its own line, nothing appended to it (§ Reporting a miss covers the miss form and why the line must stay pristine).

Sizing effort from these tags — hours and points, not just a symbol — is § Sizing the delta.

Record the hit’s kind alongside the tag. A foundation/package hit is genuinely importable. A project hit is another project’s own source, indexed for reference — nothing to install, and reuse means copying the pattern or extracting it first. Tagging a project hit ● tells the reader to import something that does not exist.

similarity is a ranking signal, not a correctness one. It orders candidates within one query; it does not transfer across queries, and it cannot tell a right-language hit from a wrong-language one. Filter by assembly and by the positive test — never by score alone.

When the MCP is absent — reconnect first, degrade second, never fake

Section titled “When the MCP is absent — reconnect first, degrade second, never fake”

If mcp__knowledge-retrieval__doc_search is not loaded this session:

  1. claude mcp list | grep -i knowledge (and claude mcp get knowledge-retrieval).
  2. Not registered or broken → run the kit installer, in the background so nothing blocks: ~/.claude/skills/t1k-mcp-management/scripts/install-knowledge-retrieval.sh
  3. Tell the user it was re-registered and a Claude Code restart is required for the tool to load — the registry is snapshotted at session start.
  4. Only then degrade to a fallback, and say so in the output (discovery: fallback).

Never report “nothing found” because the MCP was down. A miss caused by an absent tool is not evidence of absence; reporting it as one turns every subsystem into false greenfield.

A miss is a claim about your search, not about the studio. Every reported miss carries two lines — the verdict, then the scope on a separate adjacent line, never merged into it:

reuse-search: not-found-after-corpus-and-grep
scope: <what was actually searched> | swept: <date>

reuse-search: is the canonical cross-kit verdict token — it shipped first from theonekit-unity (PR #496) and is reviewer-gated (t1k-unity-dots-core-reviewer checklist item 14 treats a missing reuse-search: line as CRITICAL). Keep that line byte-exact and pristine; the scope: line beneath it is what actually satisfies rules/negative-result-scope.md — reuse-search: alone records the verdict, not what was swept, so the scope line is not optional and must never be appended to the gated line above it.

no hit across 21 Cocos assemblies is a finding. greenfield is an unverifiable assertion that every downstream estimate inherits. rules/negative-result-scope.md treats the bare form as the single highest-cost planning error.

⛔ A corpus miss is NOT evidence of absence — measured false-absence 20–60%

Section titled “⛔ A corpus miss is NOT evidence of absence — measured false-absence 20–60%”

Ten capabilities known to ship were probed in design vocabulary (2026-08-26):

sweep shapefoundfalse-absence
unfiltered only4/1060%
com.the1studio filtered only5/1050%
both passes, union8/1020%

The two passes are near-disjoint and mutually destructive, and no single configuration exceeded 5/10. Worse, a false negative and a true negative are indistinguishable: every call returns a full page — there is no empty result, even for gibberish — and over the sample the similarity signal ran backwards, with the true negative scoring highest and a false negative near the bottom. Score-gap does not discriminate either; do not build a heuristic on either number.

Two independent causes of a phantom miss, both verified:

  1. Reachability, not coverage — the type is indexed and simply cannot be ranked by its own name (see the lexical-arm note at the top of this file).
  2. The member was deleted at extraction — a trailing // comment on a documented C# field makes docgen-unity.py drop it and index a phantom named from the comment text. 65 documented members in unity-dots-library alone. AuraEffect.AffectAllies, OnHitEffect.Chance and AILeash.LeashRadius all return not_found while existing in source.

So: a miss downgrades a claim to unverified, never greenfield. Before writing any absence claim about a Unity member, grep the source — and check the declaration line for a trailing comment.

Contribute back — the other half of the sweep

Section titled “Contribute back — the other half of the sweep”

The corpus sweep (§ Workflow) only tells you what is already upstream; on its own it says nothing about pushing your own generic work the other direction. That direction has been absent from this skill — every section above looks upstream→down (does upstream have X for me to consume). This section closes it.

Trigger — generic by charter, immediately. Not rule-of-two. If the code you just wrote carries no project-specific token per rules/library-quality-mandate.md’s naming charter, it belongs upstream the moment it is written — do not wait for a second consumer to need it first. That rule’s own framing is why: “a concrete dependency that ships is concrete forever” applies exactly as hard to not extracting reusable, charter-generic code as it does to hard-coupling a vendor dependency. Every day it stays local is a day the next project re-solves the same problem instead of importing it.

Gate — the full five-part pass-test, no lighter variant. Before promoting, the code must clear ALL FIVE checks rules/library-quality-mandate.md already defines: domain-neutral, data-driven, tested, charter-conformant, documented. That rule is the SSOT for what each check means — cite it, do not restate the five items here, or the two copies will drift apart.

Where the corpus sweep comes in — run it BEFORE promoting, not after:

  • Hit — upstream already has this or something close to it. Do not promote a rival implementation; extend or reuse what’s there instead (rules/development-principles.md § “SSOT — No Duplicates”). Promoting anyway duplicates the exact thing this skill exists to stop you from duplicating.
  • Miss, and the code is charter-generic per the trigger above — that is the promote case. Push it through your kit’s normal contribute-back path (e.g. /t1k:sync-back for a .claude/-owned fragment; an upstream PR for a library package).

Treat this as the natural second half of one sweep, not a separate task: every corpus sweep you run already tells you whether to reuse, extend, or promote — decide which while the context is still loaded, not later from memory.

Sizing the delta — the flow, not a general estimator

Section titled “Sizing the delta — the flow, not a general estimator”

This sizes ONLY the delta a corpus-sweep result reveals for one need. It is not a general-purpose estimation method; do not use it in place of your team’s normal process, and do not present it as one.

Cite the flow, don’t reinvent it — theonekit-cocos already runs this in production. The t1k-cocos-playable-preproduction skill (repo The1Studio/theonekit-cocos, private module playable) carries an estimation-rules.md § 1 defining a two-point Base/Worst-case model driven by the same ●/◐/○ tags this skill already emits (its own reuse-sweep reference tags identically). That flow is the SSOT for how a reuse tag becomes an effort number; this section states only the shape every engine’s estimate follows, not a restatement of Cocos’s numbers as if they were universal.

The flow (shared, engine-agnostic):

  1. A reuse tag is a price claim, not decoration — it must cite the corpus hit that grounds it. An uncited discount defaults to ○. (Same rule as the Cocos reuse sweep’s own justification threshold.)
  2. Estimate Base directly per need — the lean, realistic number, with no rosy floor below it. Base is not derived by multiplying a tag against some hypothetical from-scratch figure; it is the actual estimate for the actual work, informed by what the tag says is left to build.
  3. Derive Worst-case = Base + a risk premium, and the premium is tag-driven, not uniform — inherited (●) work carries the smallest premium (little can go wrong), custom (○) work carries the largest (highest uncertainty). Only the Worst-case side scales with the tag; Base does not.
  4. Report two figures — Base and Worst-case — never a single number.

The values — engine/domain-specific, not baked in here. Cocos’s production numbers (cited, not asserted as universal): ● → Worst-case ≈ Base (near-flat); ◐ → Worst-case ≈ Base × 1.25; ○ → Worst-case ≈ Base × 1.4–1.6. No equivalent multiplier set exists yet for Unity or any other engine — inventing one here would repeat the exact mistake this section replaces. If you need Unity-specific numbers, that is a gap for the owning Unity kit to fill, following this same flow; do not improvise multipliers in the meantime and present them as settled.

Units — ideal engineering hours, Cocos’s basis exactly: 8h = dev-day, 5 dev-days = week. No story points, no Fibonacci — a points layer only one engine used would have been a second contract wearing the first one’s name, not the shared flow “the same flow, like IoC” asks for. The unit basis is cited from Cocos’s estimation-rules.md, not restated as independent arithmetic.

Seven rules from a 10-pair A/B plus ~150 probes: lead with the mechanic noun an engineer would type, include a MECHANISM word, never paste a designer’s player-facing sentence, and read rrf as an arm counter, not a score. Implementation phrasing beat design phrasing 7 of 10; design won none. Rules + measurements: references/query-technique.md § 9.

  • Never call doc_list_assemblies in a workflow — ~110K chars, it will blow the context. It is a maintenance-only call. (It is also unusable for inventory: 419 of 709 assemblies carry a null assembly_suffix and match no suffix_filter value, so no call sequence enumerates the DOTS gameplay assemblies at all.)
  • doc_get_member ids do not round-trip from source for Unity. Every id referencing a top-level Unity.Entities type carries a bogus The1Studio.DOTS.Analyzers.Tests.DOTSLIB002… prefix baked into the primary key. The correct cref returns not_found; only the corrupt one resolves. Copy ids from doc_search output — never construct them.
  • cross_refs.resolved_id is wrong about half the time (6 of 12 measured), resolved by unscoped simple-name match. DamageEvent’s own summary says “Use Create”, and Create resolves to DOTSBridges.Analytics.AnalyticsEvent.Create. Verify a cross-ref before following it.
  • siblings is an alphabetical head of the assembly, not a relatedness set — three unrelated queries into dots-combat returned byte-identical lists. Noise for the 88% of members in assemblies larger than 31 members.
  • Reject wrong-engine assemblies by name, never by score. Unity’s GameFoundation.* is not the Cocos @playablelabs/game-foundation and scores ~0.73 on behaviour queries — above any sane threshold. Score-based filtering lets it straight through.
  • doc_get_member’s siblings are assembly-wide, not class members. You get ~30 alphabetically-adjacent members from unrelated classes. To see one class’s real surface, run a second doc_search with assembly_prefix set instead.
  • Existence ≠ package name. A hit proves the capability exists upstream; the owning package comes from the folder map or CPM, not from the hit.
  • Existence ≠ reuse. The local copy may be ahead of upstream. Run a divergence check before swapping anything out.
  • A local symbol name is the worst possible query. It is the one string guaranteed not to appear in another project’s code.
  • The corpus is thin outside Unity. A handful of Cocos projects plus the foundation — check assets/corpus-summary.json for the current count, do not assume it is still three. A Cocos miss is weak evidence of absence and must be reported with its scope.
  • references/doc-search-contract.md — SSOT: corpus composition, tool signatures and limits, result shape, MCP-absence protocol.
  • references/query-technique.md — SSOT: how to shape a query (HyDE, multi-query + RRF, step-back, decomposition) and how much to over-retrieve, with the retrieval literature each rule comes from.
  • t1k-cocos-base-knowledge-sweep — the Cocos consumer; adds the generated 21-assembly allowlist, a project detector, and the prior-art table its four consumers read.
  • t1k-mcp-management — registration, credentials, auto-install policy for this server.
  • rules/negative-result-scope.md — why a miss must state its scope.
  • rules/library-quality-mandate.md — the five-part pass-test § Contribute back gates on; the zero-tech-debt-budget framing behind the “generic by charter, immediately” trigger.
  • rules/development-principles.md — § “SSOT — No Duplicates”, why a corpus hit blocks promoting a rival implementation.
  • rules/pinned-baseline-test-companion.md — why § Sizing the delta’s multipliers and hours-per-point anchor are stated as defaults with a review trigger, not facts.