Skip to content

Connecting Your Project

Yuriy Orlov edited this page Aug 27, 2026 · 2 revisions

Connecting Your Project

Every fact KAUT stores is bound to a data source — a code file, a glob, a ticket, a human statement, or a file in another repository — and anchored to the commit it was derived at. That binding is what makes freshness mechanical: when the bound sources change, the fact flips stale without any AI involved. This page explains the binding grammar, the store layers, what belongs in each, and how multi-repo workspaces extend the same model across repositories. The normative contract behind all of it is SCHEMA.md in the repo.

Typed sources

Each doc's frontmatter declares one or more typed sources (SCHEMA.md §2.1, §17):

file:src/router/routes.ts            one file, relative to the project repo root
file-glob:packages/core/src/**       a glob, relative to the project repo root
ticket:TICKET-16576                  a ticket reference (provenance only)
user:2026-06-10                      a human statement, dated (provenance only)
repo:billing:file:openapi/api.yaml   a file in another workspace member repo (see below)
  • Only file: / file-glob: participate in freshness diffing and the broken rule; ticket: / user: are provenance — they can never go stale or break.
  • repo:<name>:file:<path> is resolved through the workspace registry and checked existence-only at that member repo's HEAD: missing ⇒ broken; present ⇒ never stale.
  • An OpenAPI-style fragment (file:openapi/api.yaml#/components/...) is stripped to the file path for diffing; the fragment stays in the raw value for human reference.

No source — no claim. Unsourced text cannot enter the store.

Doc-level vs section-level bindings

The frontmatter sources: list binds the whole doc. A section can scope its own binding with a comment immediately after its ## heading:

## Pointers
<!-- sources: file:src/router/routes.ts -->
<!-- trust: T1 -->

A section with its own binding is evaluated against those sources; a section without one inherits the doc-level list. The doc's verdict is the worst section's; the affected-files list is the union. Section bindings are also what kaut touched matches when it names the docs a code change owes an update.

Anchoring: derived_from_commit

Every doc records the commit it was true at — always a commit on the main line (the tracked main branch), never a feature branch or the working tree. Freshness is evaluated against the merge base with main, so working on a branch never flaps stored verdicts; your branch's own edits surface only as an ephemeral branch-advisory at read time.

When re-deriving, anchor to the main branch tipkaut refresh names the exact target ref. The draft queue enforces this at the door: an anchor that is not a commit of the anchor repo, or not on its main line, is refused.

What flips a verdict

  • stalegit diff over the doc's file sources between derived_from_commit and the main-line anchor is non-empty; or (err-toward-stale) the anchor commit is unknown to the repo or not an ancestor of the main line.
  • broken — a file:/file-glob: source matches zero paths in the anchor tree. A broken pattern cannot be diffed, so it never reports fresh — renames and typos are caught, not hidden. A repo: source whose path is missing at the member's HEAD is broken too; an unresolvable registry or member repo makes the doc stale with an "unverifiable" note — the engine errs toward stale, never toward fresh.

The full verdict set and priority (tampered > disputed > broken > stale > branch-advisory) is in SCHEMA.md §11 and §16; exactly one verdict renders per answer.

Store layers

The directory a doc lives in is its layer (id = path without .md):

Layer What belongs there
map/ The project skeleton — route table, package graph, service map. Script-generated (T0), regenerated by kaut map, never hand-edited
domains/ Thin per-domain notes: pointers and invariants — where things live and what must hold, not retellings of code
decisions/ The "why": business rules, constraints, decisions with their reasons, ticket-anchored
flows/ End-to-end flows across components — how a request/feature traverses the system
contracts/ Interface agreements between components or repos (APIs, message shapes)
runbook/ Operational procedures verified by running them (startup, debug, environments)
bootstrap/ Orientation plans for working in a repo — where to start, what to read

The litmus test decides what may be stored at all:

If tomorrow's agent can get it from the code cheaply — don't store it.

KAUT stores what code cannot say: intent, business rules, constraints, decisions and their reasons. Everything cheaply derivable from code is derived on demand instead — a derived fact can go stale; a re-derived one cannot.

Map collectors

kaut map regenerates the map/ layer deterministically (no LLM). Which collectors run, and where they look, is configuration in the store's kaut.config.json:

  • map.collectors — any of routemap | pkggraph | composemap; default ["routemap", "pkggraph"]; [] disables map generation.
  • map.routesFile / map.constantsFile — route-map inputs (default is Vue-conventional src/router/routes.ts). If the file is absent, the collector is skipped with a note and the rest still run.
  • map.packagesDir — package-graph monorepo directory (default packages).
  • map.composeFile — compose-map input (default docker-compose.yml).

Each adapter refuses to write rather than emit a partial map when its input fails its self-check. Full config reference: docs/HANDBOOK.md §15.

Multi-repo workspaces

For a landscape of repositories, kaut workspace init derives everything from one manifest owned by your orchestration framework (e.g. TAUT):

node <engine>/kaut.mjs workspace init --manifest <conductor>/manifest.json
node <engine>/kaut.mjs workspace list

What it gives you (SCHEMA.md §21):

  • A workspace registry (~/.kaut/workspaces/<name>.json) — a derived copy of the manifest, regenerated wholesale on every init; the resolver behind repo: sources and the workspace-wide doctor/stale/digest sweeps.
  • A store per member repo, provisioned through the ordinary bootstrap (idempotent; a member marked do-not-touch in the manifest gets a registry entry and nothing else).
  • One system store for landscape-level knowledge (cross-repo flows, contracts, runbooks), anchored to a launcher repo via config project.anchorRepo — its freshness is checked against that repo no matter where it is read from.
  • Cross-repo bindingsrepo:<name>:file:<path> sources let a doc in one store cite files in sibling repos, resolved through the registry.

One MCP server then serves the whole workspace — each tool call names its repo (MCP Server).

Clone this wiki locally