Skip to content

Configuration

The contract between karajan-watch (generic, the product repo) and each organization’s deployment repo (private, theirs). EVERYTHING concrete about an organization lives in this file, in its deployment repo — never in the product.

Load it with loadConfig(path) / validate with validateConfig(object) (exported from the package). Validation is strict: an unknown key or an out-of-range value = ConfigError with the exact path ($.corpus.code.store), no silent fallbacks. Full example in karajan-watch.config.example.json.

Non-empty array. Each entry declares an observed repo:

KeyTypeRequiredDefaultNotes
namestringyesUnique; namespaces its paths in the corpus (name/…)
branchstringnomainBranch whose merges trigger ingestion
sensitivityenumnointernalSee Sensitivity

Exactly two entries: code and docs (separate tables/corpora).

KeyTypeRequiredDefaultValues
storeenumyeslancedb | pgvector | in-memory
embedderenumyeshash | transformers (local: the code never travels to a third-party embedder)
sensitivityenumnointernalSee Sensitivity

You install the store backend yourself: @lancedb/lancedb for lancedb, pg for pgvector. The engine declares neither, so whoever uses one does not pay for the other’s binary; if it is missing, the ingestion fails red naming which one.

With lancedb the corpus is a directory on disk: no server and nothing to host, but only whoever holds that disk can see it. If ingest and impact run on different machines — or on ephemeral runners that keep nothing between jobs — the corpus must be persisted separately or the store must be pgvector. The two impact thresholds are calibrated against the store you use: scores are not comparable across backends.

Thresholds of the cross-repo impact pipeline (F2). If the section is present, thresholds is required:

KeyTypeConstraint
thresholds.minSimilaritynumberin [0, 1]
thresholds.maxCandidatesint>= 1

Notification targets. If the section is present, targets is a non-empty array. Supported types:

  • { "type": "pr-comment" } — a comment on the merged PR.
  • { "type": "webhook", "url": "https://…" } — POST to the webhook (https only).

Controls the contract signal (see impact):

{
"contracts": { "enabled": true, "types": ["http", "event", "sql"] }
}
KeyTypeDefaultNotes
enabledbooleantruefalse disables the signal entirely
typesarrayall threesubset of http | event | sql

Without this section the signal runs with all three types. An unknown type is an error with the exact path ($.contracts.types).

The deployment’s own sensitivity policy: a level → allowed-LLM-adapters map, validated with karajan-rag’s validateSensitivityPolicy (all three levels are mandatory):

{
"policy": {
"confidential": ["ollama"],
"internal": ["ollama", "azure-openai"],
"public": ["claude", "codex"]
}
}

Without this section the engine’s createDefaultSensitivityPolicy() rules. An explicitly requested adapter the policy does not allow for the effective level is an error — it is never silently downgraded to another adapter.

Levels and their default inherit karajan-rag’s model (SENSITIVITY_LEVELS, DEFAULT_SENSITIVITY): public | internal | confidential, safe default internal. The effective level governs which LLM adapters the policy allows in F2/F3 judgments.