Repository navigation
[feat] Deepen a team's knowledge: relations across every asset, delivered to every tool, proved on the task bank #1552
Description
Goal
Teamai gives every tool the team's assets: the skills, rules, instruction blocks and agents are written into the places each tool reads them from, and a session can recall the rest. That is presence. It is not association and it is not structure: nothing says that a rule, a doc, a learning and the code page they describe are about the same thing, and nothing restructures them when one of them changes.
The relation model exists — for code only:
teamwiki/.indices/graph-index.jsonholds typed edges between code pages:DEPENDS_ON,IMPLEMENTS,MAPS_TO,CONTAINS,REFERENCES,CONFLICTS_WITH,SUPERSEDES(src/wiki-engine/core/graph-index.schema.ts:16). Recall already walks them: a code hit is boosted by its neighbours (RELATION_WEIGHT,src/code-knowledge-recall.ts:52).- Everything else — learnings, docs, rules, skills — is related by nothing but a namespace, which is a path segment (
src/manifest-schema.ts:112), and indexed flat: one TF-IDF index over the texts (src/recall.ts:438).
So a team's knowledge is a pile of files with a code graph beside it. Two things follow, and both are what a member feels as "teamai initialized it and stopped":
- The relations never reach a model.
docs,learningsandwikiare never written into a tool's own directory — their pull is a no-op (src/resources/repo-resource.ts:218) — and the graph itself stays in the team clone. A tool gets flat Markdown and has to rediscover the relations by reading. - The deepening that exists is neither published nor structured.
teamai codebase --deep-enrichwrites one document per component (src/deep-enrich.ts:421), each page independent of the others, into the clone — and never commits or pushes it, so a team repo never gets it ("Only an import publishes to the team repo",src/import-codebase.ts:606; [bug] codebase --deep-enrich in a team repo reports success but never publishes, and leaves the team clone dirty #1537). The method we already have for the structure — the wiki skill's G1–G9 graph documents, its confidence labels, its consistency check and its end-to-end question set (skill-data/wiki/SKILL.md:190) — is not wired into the CLI at all: its own table says "Compile into the wiki after K3 | Skip" (skill-data/wiki/SKILL.md:308).
This proposes the missing half: one relation graph over the whole team's knowledge, delivered to every tool in a form a model can use, and measured on the task bank, so a deepening change is proved instead of asserted.
Example
A team has a rule, a doc, a learning and the code:
rules/payments.md "every payment goes through ledger receipts; no direct writes to ledger"
docs/payments-overview.md how the payment flow works
learnings/ops/2026-10-12-ledger-timeout.md "the receipt write times out at 3s; retry once"
teamwiki/evidence/code/pay/…/modules/ledger-receipts.md
Today, a session that asks "why did the payment job fail?" recalls the pages that match the words: the learning and the module. It does not learn that the rule governs the module, that the learning corrects the module's doc, or that the doc is stale since the learning. The agent re-derives the relation by reading three files, or misses one.
With relations, the recall result carries the relation, so the session starts with it:
ledger-receipts (code) ← IMPLEMENTS — rule:payments
ledger-receipts (code) ← MAPS_TO — docs/payments-overview
docs/payments-overview ← SUPERSEDES — learning:2026-10-12-ledger-timeout
The session applies the rule and the correction without working out that three files are about one thing.
And the team that added the relation can say what it bought: the relation is an asset in the graph, and the task bank can tell whether the tasks that touch payments stopped failing.
Scope
1. One relation vocabulary for the whole team
Keep RelationType as it is (src/wiki-engine/core/graph-index.schema.ts:16) and widen the node kinds from code pages to the team's assets: skill, rule, doc, learning, agent, workflow, scorer, code. The edge already carries what an audited edge needs: evidence, weight, source, origin (src/wiki-engine/core/graph-index.schema.ts:95).
A first vocabulary, every relation of it already meaningful for code and reused as it is:
| relation | between | example |
|---|---|---|
IMPLEMENTS |
code ↔ rule / doc | the ledger module implements the payments rule |
REFERENCES |
any ↔ any | the rule references the doc |
SUPERSEDES |
learning ↔ doc / rule | the learning corrects the doc |
CONFLICTS_WITH |
rule ↔ rule | two rules give opposite answers |
MAPS_TO |
doc ↔ code | the doc describes the module |
CONTAINS |
namespace ↔ asset | the directory structure itself |
No new relation type is needed for the first slice.
2. Where the edges come from — deterministic first
Three sources that need no model and can be audited:
- Explicit. A
see also:/applies to:line in a skill's or rule's frontmatter. Human-written, team-reviewed, reviewed like any other change. - Derived from the records the team already keeps. A label records the team skills a session loaded (
used.skills,src/scorers/label.ts:77) and the sessions that hit a friction reminder. A skill loaded in exactly the sessions where a rule's rule fired is an edge with evidence behind it. - Derived from the existing code graph. The reconciler already maps a product page onto a code page by term overlap, with a confidence (
MAPS_TO,src/wiki-engine/knowledge-reconciler.ts:324). The same pass maps a rule or a doc onto a code page, under the same honesty rule the wiki skill states: "every relation in the graph must have an explicit basis in a component document; never guess from names" (skill-data/wiki/SKILL.md:293).
A model-assisted pass stays optional and off by default, as the skill is today: it proposes edges with a confidence, and a human accepts them into a review branch, the way teamai recall promote does for a promoted learning (docs/guide/knowledge.md:127).
3. The relations reach every tool
This is the part that makes it deepening rather than more files in the clone:
- Deliver the map, not the map's contents. A tool gets a compact knowledge map — the pages and the edges between them — in the place that tool reads, declared once in the descriptor (
src/tools.ts), so every tool's shape is written down once ([feat] One descriptor per tool, and one resolver for where teamai writes and where the tool reads #1221). The map is bounded (the top edges per node, the relations of the assets a session actually touches), so it does not grow with the team's knowledge. - Relations ride with the asset. A delivered skill or rule carries its edges as a short "related" block, so the model sees the relation next to the thing it must act on, not in a second file it has to find.
- Recall answers with relations. A hit carries its neighbours and the relation that links them, so the agent gets the association and not only the text.
- Nothing is delivered that the team did not write. The map is derived from the team's assets and the graph in the team clone: no new content, no second copy of the corpus.
4. The knowledge is restructured, not only deepened
- The deepening that exists has to reach the team repo:
codebase --deep-enrichand--reconcilecommit and push the wayimportdoes ([bug] codebase --deep-enrich in a team repo reports success but never publishes, and leaves the team clone dirty #1537). Until then the richest knowledge teamai builds never leaves the clone. - The structure the wiki skill describes (the G1–G9 graph documents, the router, the confidence labels) becomes the CLI's own, so the pages of one component reference the pages of the others instead of standing alone (
src/deep-enrich.ts:421). - The lint that exists becomes a gate over the whole knowledge, not only over the code:
codebase --lintalready measuresnodeCount,edgeCount,orphanNodesandconnectivity(src/codebase-wiki-lint.ts:166). An asset nobody relates to is an orphan, and the team sees it.
5. The deepening is proved on the task bank
This is what makes the proposal worth doing, and it is what the task bank buys:
- [feat] session-to-task: turn a session's bug fix into a benchmark task #1402 turns a session into a task; [feat] Run benchmark suites as workflows #1180 runs a suite as a workflow. The run record already has a
benchmarkslot, reserved and never written (src/dashboard/scorers.ts:60), and the dashboard already leaves benchmark labels out of the session page. - The cohort machinery already splits labels at a team commit:
before/after/notRecorded(src/scorers/results.ts:94). A deepening commit is such a commit. - So the measurement is: the tasks that pass after the deepening commit and failed before it — the same tasks, the same judge, the same rubric, one team revision apart. That is the number Proposal: Dashboard 统一承载 Team Execution / Team Context / Team Improvement #407 asks for ("某个团队 Skill、Rule 或知识上线后,是否真的改善了 AI 执行效果?"), and the number
teamai recall promoteguesses today with its confidence formula. - Without relations, the task bank can only measure with a team against without a team — presence. With relations it can measure deep against shallow, which is the claim this proposal makes.
First slice
Small enough to land on its own, and each part of it visible:
- A read-only pass that reads the team's assets and prints the relations it can derive deterministically — explicit frontmatter, the reconciler's term overlap, the delivery records — before anything is written.
- The edges land in the same graph the code pages use;
codebase --lintcounts orphans over the assets too, andteamai recallshows a hit's neighbours with the relation that links them. - One team's deepening commit, measured on the task bank: the tasks that pass after it that failed before.
Not in this proposal
- Not a new storage format: the graph the code pages use is the graph the assets use.
- Not per-tool knowledge formats written by hand: the descriptor decides where each tool's map goes ([feat] One descriptor per tool, and one resolver for where teamai writes and where the tool reads #1221).
- Not a model that rewrites a team's knowledge unattended: edges are proposed, the team accepts them.
- Not a new scoring method: the task bank and the judge already exist; this only records which run was a benchmark.
Dependencies
- [feat] Run benchmark suites as workflows #1180 (benchmark suites as workflows) and [feat] session-to-task: turn a session's bug fix into a benchmark task #1402 (session-to-task) for the measurement half.
- [bug] codebase --deep-enrich in a team repo reports success but never publishes, and leaves the team clone dirty #1537 (
--deep-enrichpublishes) for the restructuring half. - [feat] One descriptor per tool, and one resolver for where teamai writes and where the tool reads #1221 (one descriptor per tool) for the delivery half.
- Proposal: Team Context Assets Health — Skills / Rules / CLAUDE.md 多维质量与效果评估 #408 and [feat] Judge whether team skills load when they should, without writing a scorer #1469 for the assets-health and skill-routing view of the same assets.
Open questions
- Is the map delivered as a file per tool, or as an index the tool reads on demand? The first is simple; the second costs a lookup per session.
- Does a relation between two assets count as knowledge the team owns — reviewable in a PR — or as a derived fact that can only be rebuilt?
- Which assets are worth relating first: rules to code, or learnings to docs? Learnings are what a team writes daily; rules are what it forgets.
Activity
SaulMoro commentedon Oct 29, 2026
Triage: worth building, starting with a first slice narrower than the proposal.
In this slice:
teamai review --branch.Moved to four issues, each blocked only by what actually blocks it:
codebase --lint, the same counts in the dashboard's knowledge-base health view, and how often sessions open a file from a relation.codebase --reconcile --dry-run.deep-enrich.Two premises of the proposal are out of date:
deep-enrichalready writes G1, G2, G3, G5 and G6 (src/deep-enrich.ts:547-549,:675,:704).locateare on main (src/tools.ts,src/locate.ts).Nothing measured yet shows that agents fail for lack of relations. #1564 is where that gets measured.
How relations reach the model
Automatic recall is off by default (
getRecallSharing,src/types.ts:241). When it is on, the main conversation sees the summary from theteamai-recallsubagent, not recall's raw output (agents/teamai-recall.md:266). So the subagent is part of this slice.A tool without that subagent runs
teamai recallitself and reads the raw output.The subagent's LOW shortcut through
--check(agents/teamai-recall.md:75-81) stays as it is and carries no relations.Vocabulary and what may be declared
An edge reads "from RELATION to". This is the same direction the code graph already uses, where
IMPLEMENTSstarts at the implementing file (src/wiki-engine/code-knowledge/ast/index.ts:184).This slice uses four of the seven existing
RelationTypenames (src/wiki-engine/core/graph-index.schema.ts:16). The other three relate code to code, so they cannot be declared on an asset.Which assets can declare which relation, and towards which targets:
MAPS_TOREFERENCESSUPERSEDESCONFLICTS_WITHDEPENDS_ON,CONTAINS,IMPLEMENTS"Any asset" means a rule, doc, learning, skill or teamwiki page.
Skills and teamwiki pages are targets only. They never declare relations:
metadata, which maps strings to strings.review --branchalso warns about links that leave a skill directory (src/review-branch.ts:820-856).src/recall.ts:560). Their raw text is also printed as a snippet (src/code-knowledge-recall.ts:620-625), so a relation declared on a page could print a path from a withheld codebase.A learning cannot supersede a rule.
contributepublishes learnings with no review, so a learning that disagrees with a rule declaresCONFLICTS_WITHinstead.A declaration outside the table never becomes a relation, wherever the file came from. This holds for
contribute,importandimport --from-mr. The checks below report it, but no check is what blocks it.Format
A path is the asset's place in the team's tree:
rules/<path>.mddocs/<path>.mdlearnings/<id>, where the id is the filename the index uses, namespace included (src/utils/search-index.ts:711)skills/<path to the skill directory>, taken from the entry's path becausefilenamedrops the namespace (src/utils/search-index.ts:805)teamwiki/evidence/code/<slug>/<path>.mdMalformed and edge-case declarations:
review --branch(rules, docs)contribute(learnings)GOVERNSDEPENDS_ON,CONTAINS,IMPLEMENTS, or a pair outside the tablerelatedis not a mapping..after normalising, or has no known prefixMarkdown links
Links are read with the existing parser,
localLinkTargets(src/review-branch.ts:780), moved to a shared module so there is only one link parser. It skips code, schemes and leading/, and strips#anchorand?query.A link from a rule, doc or learning is resolved against that file's place in the team's tree, never against its location on disk. For example, from
learnings/<id>,../docs/x.mdisdocs/x.md.If the link lands on an asset, it becomes
REFERENCES. Anything else is ordinary prose and is not reported. Links in skills are not read.Resolution and visibility
SEARCH_INDEX_VERSIONis bumped. That also invalidates the per-file cache, becauseFILE_DERIVATIONincludes the version (src/utils/search-index.ts:446). Incoming relations are worked out from the outgoing ones and are never cached, because a cached target would keep a relation its source has since removed.src/recall.ts:551-557). A doc this directory does not receive is never a target, even though it is in the clone.src/recall.ts:755-771). That shadowing runs before relations are worked out, so a hidden entry contributes none.src/utils/learnings-roots.ts:202).withheldCodebases(src/recall.ts:805). If that list cannot be read, no teamwiki target resolves. Today's code turns an unreadable list into[](?? []atsrc/recall.ts:806); relations must not do that.teamwiki/.indices/graph-index.json. It already has four write paths (graph-aggregate.ts:410,codebase-extract.ts:1023,import-iwiki.ts:342,knowledge-reconciler.ts:499).Recall output
File:, a hit gets oneRelated:line per relation.→means this hit declared it, and←means the other asset did.File:line would print it. For a skill that is itsSKILL.md, and for a learning it is the file in the root that won.rules/payments.md), not by its absolute path. At most 5 lines per hit.Scorestay the same, and so do--checkand "Candidate change files". The ranking is tuned against question sets that are not in this repo (src/recall.ts:876,:923).In
agents/teamai-recall.mdStep 5, each kept entry carries itsRelated:lines under the summary, and so does each module under "Codebase context". The summary keeps at most 2 per entry, declared relations first, and they count towards the response size cap (agents/teamai-recall.md:385):Checks
teamai review --branch. It adds arelationscheck over every rule and doc in the materialized branch tree, as its other checks already do (src/review-branch.ts:1410-1438). It does not compare against a base.learnings/target is checked for shape only, because learnings live onteamai-learnings.fail(src/review-branch.ts:1548).teamai contribute. It prints the same findings as warnings for the learning it publishes, and still publishes it. A target exists if it is in the team clone on disk (rules, docs, skills, teamwiki) or in the learnings roots.Example
The team repo (
main) and the learnings branch:Recall output for this example. Lines marked
+are new; paths and scores are illustrative:If
payis withheld for this directory, hit 3 does not appear, and the rule'sMAPS_TOline does not appear either.A learning published with a declaration outside the table, and a typo:
The learning is published anyway, and recall shows neither relation.
teamai review --branch fix/payments, where the branch changes the rule's frontmatter to:Acceptance criteria
→on the declaring hit and←on the target hit. (feat(recall): declared asset relations on recall hits, checked by review --branch (#1552 first slice) #1629)SUPERSEDESa rule and was published bycontributeorimport.REFERENCES, resolved from the file's tree path. This includes a learning whose file lives in the learnings worktree.Score,--checkand "Candidate change files" are identical.←line on B after the next index build, even when B's file did not change.agents/teamai-recall.mdcarriesRelated:lines in Step 5 as shown, at most 2 per entry, and the LOW shortcut is unchanged.review --branchreports each row of the malformed-input table at its level, over the whole branch tree, and does not check that alearnings/target exists.contributewarns on the same rows and still publishes. (feat(recall): declared asset relations on recall hits, checked by review --branch (#1552 first slice) #1629)Definition of done
teamai recalloutput,review --branchfindings andcontributeoutput, including the visibility case, the unchanged-ranking case and the removed-relation case.npm run build,npx tsc --noEmit,npm run lint,npx vitest run, andnpx vitest run commands-reference(no help text changes).teamai.yaml. Paste the output ofteamai recallandteamai review --branchinto the PR. (feat(recall): declared asset relations on recall hits, checked by review --branch (#1552 first slice) #1629)docs/guide/knowledge.mdanddocs/guide/zh-CN/knowledge.md:related:and theRelated:line.docs/guide/sharing.mdand its Chinese page: therelationscheck.skill-data/share/references/doc-template.mdreplaces its free-text## Related Skillssection with arelatedrow in the frontmatter table. The import-MR prompts (src/import-mr.ts:145,:183) do not change: they have no list of the team's assets, so the model would invent paths. (feat(recall): declared asset relations on recall hits, checked by review --branch (#1552 first slice) #1629)graph-index.json. (feat(recall): declared asset relations on recall hits, checked by review --branch (#1552 first slice) #1629)Walternater commentedon Oct 31, 2026
I'd like to pick up the first slice from the triage comment above: declared relations via a
related:frontmatter block,Related:lines on recall hits, and therelationscheck inteamai review --branch/ warnings inteamai contribute.I'll implement strictly to the spec in the triage comment (vocabulary table, direction convention, visibility rules, unchanged ranking, cap of 5, malformed-input matrix) and the acceptance criteria listed there. Starting now; PR to follow.
feat(relations): derived rule-path edges and reconcile candidates (Te…
feat(recall): declared asset relations on recall hits, checked by rev…
feat(relations): derived rule-path edges and reconcile candidates (Te…
fix(lint,stats): count page relations, declared-beats-link by target,…
fix(lint,stats): count page relations, declared-beats-link by target,…