Skill Wiki v0.1.0

Docs / implementation / runtime

On this page

Runtime — loader & resolver

@skill-wiki/runtime reads compiled artifacts on disk and serves metadata + projection paths to the MCP server. It never reads chunk bodies.

Modules

ModuleRole
atom-loader.tsReads atom.yaml + graph.yaml per atom; never reads chunks.
index-loader.tsParses _index.xml, builds the in-memory atom map.
projection-resolver.tsReturns the on-disk path for a (atom, level) pair.
domain-config.tsRecursive domain.yaml discovery + DomainRegistry.
edge-walker.tsBFS / DFS over the in-memory edge graph.

Boot sequence

async function boot(primeDir: string) {
  // 1. Discover domain plugins.
  const domains = await discoverDomains(primeDir);
  for (const d of domains) DomainRegistry.register(d);

  // 2. Parse the index.
  const index = await loadIndex(`${primeDir}/_index.xml`);

  // 3. Build the in-memory graph.
  //    Atoms map id → metadata; no chunk content read here.
  const graph = buildGraph(index);

  return { domains, index, graph };
}

The "never read chunk content" rule

The runtime contract says that chunks/{summary,core,full}.md is not the runtime's job. Why?

  • Consistent with how the agent works. The agent has a Read tool. Doubling it in the runtime invites format drift and caching bugs.
  • Memory bound. Chunk content scales with corpus size. Metadata + the index do not (~50 KB even for 1k atoms).
  • Hot reload. The runtime can hot-reload the index without invalidating the agent's view of any specific atom.
// packages/runtime/src/atom-loader.ts
//
// IMPORTANT: This module NEVER reads chunks/*.md content.
// It only reads _index.xml and atom.yaml (metadata).
// Chunk content is exclusively for the agent to pull via the Read tool.

Edge walker

Used by the MCP server to satisfy contract resolution and walk requires chains:

function walkRequires(seed: AtomMeta, depth = 5): AtomMeta[] {
  const out: AtomMeta[] = [];
  const seen = new Set<string>([seed.id]);
  const queue: [AtomMeta, number][] = [[seed, 0]];
  while (queue.length > 0) {
    const [atom, d] = queue.shift()!;
    if (d >= depth) continue;
    for (const edge of atom.edges) {
      if (edge.verb !== 'requires' || seen.has(edge.target)) continue;
      const target = byId.get(edge.target);
      if (!target) continue;
      seen.add(target.id);
      out.push(target);
      queue.push([target, d + 1]);
    }
  }
  return out;
}

Public API

import { Runtime } from "@skill-wiki/runtime";

const rt = await Runtime.boot({ primeDir: "/path/to/compiled" });

// Lookup
const atom = rt.lookup("@recipes/method-pan-sauce");

// Resolve a projection (returns a path, NOT content)
const path = rt.resolveProjection(atom.id, "core");

// Walk
const deps = rt.walkRequires(atom);

// Domains
console.log(rt.domains);                  // [DomainConfig, ...]