-
Notifications
You must be signed in to change notification settings - Fork 0
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.
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 thebrokenrule;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.
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.
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 tip — kaut 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.
-
stale—git diffover the doc's file sources betweenderived_from_commitand 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— afile:/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. Arepo:source whose path is missing at the member's HEAD is broken too; an unresolvable registry or member repo makes the docstalewith 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.
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.
kaut map regenerates the map/ layer deterministically (no LLM). Bootstrap detects
your stack and seeds map.collectors in the store's kaut.config.json accordingly
(existing configs are never touched); map runs whatever is configured, and a collector
whose stack marker is absent skips itself with a note — never a failure.
| Stack | Detected by | Collector | Generates |
|---|---|---|---|
| Vue (incl. monorepo) |
vue in package.json / src/router/routes.ts
|
routemap, pkggraph
|
route table, package import graph |
| Java / Kotlin + Spring |
settings.gradle(.kts) / pom.xml (top or one level down) + controller annotations |
jvmgraph, springmap
|
Gradle/Maven module graph, @RequestMapping-family route table |
| Next.js |
next in package.json / app·pages trees |
nextroutes |
file-based route table (App + Pages router) |
| Express / Nest / FastAPI / Flask | deps in package.json / requirements / pyproject | httproutes |
lexical METHOD-path route table |
| PHP (Laravel / Symfony) | composer.json |
phproutes |
Route::… / #[Route] route table |
| SQL migrations (Flyway-style) |
V*__*.sql files |
sqlmigrations |
migration inventory (count, latest versions) |
| docker-compose landscape | docker-compose.yml |
composemap |
service map |
All route collectors write the same doc (map/routes.md) — a repo has one route map,
produced by whichever adapter its stack selects. The lexical collectors (httproutes,
phproutes, and constants/SpEL cases in springmap) are honest best-effort scans, marked
as such in the generated doc. A repo with no recognizable stack gets map.collectors: []
— bootstrap and every other command work regardless; the map layer is optional.
Manual knobs (override detection any time): map.collectors (any of the names above),
map.routesFile/map.constantsFile (Vue inputs), map.packagesDir, map.composeFile.
Full config reference: docs/HANDBOOK.md §15.
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 listWhat 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 behindrepo:sources and the workspace-widedoctor/stale/digestsweeps. -
A store per member repo, provisioned through the ordinary bootstrap (idempotent; a
member marked
do-not-touchin 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 bindings —
repo:<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).