--- id: importer kind: architecture title: Source Importer Behavior status: active depends_on: - folder-contract - runtime-architecture --- # Source Importer Behavior An importer maps one local source selection into normalized shared project rows. It should be deterministic, boring, and hard to accidentally make clever. ## Local selection A local controller owns source roots, individual files, include/exclude globs, watches, materialization paths, and absolute path mappings. Those machine facts do not enter shared Jazz rows. The current filesystem adapter accepts one root and defaults to `spec/**/*.md`. This is the first source adapter, not the project boundary. The controller model permits multiple selections and other adapters without changing shared document identity. ## Scan and normalize For each selected Markdown file, the scanner records relative projection path, raw Markdown, YAML frontmatter, body, heading outline, content hash, byte size, filesystem mtime, and import timestamp. Normalization rules: 1. Use `frontmatter.id` when present; otherwise derive identity from stable source id plus relative path. 2. Use `frontmatter.title`, then first H1, then filename title case. 3. Preserve unknown frontmatter in `frontmatterJson`. 4. Hash raw content, including frontmatter. 5. Sort by source id and relative path for deterministic output. Absolute local paths never define shared identity. ## Sync Sync writes through `CharterDatabase` into native Jazz 2 tables: 1. Upsert normalized document rows by portable key. 2. Retain immutable semantic document-version rows keyed by document id and content hash. 3. Delete current document rows removed from the selected projection while retaining version history. 4. Write semantic `spec.document.upserted` and `spec.document.deleted` events. 5. Create queued work items for actionable events. 6. Wait for the runtime's configured durability tier. Jazz is authoritative. `.spec/state/jazz.sqlite` is its native local store. `.spec/state/jazz-runtime.json` is an inspection receipt. `.spec/state/index.json` is a disposable lexical cache. None is a JSON bootstrap mirror of shared project state. `CHARTER_DB_ADAPTER=json` selects a separate local fallback/test adapter and writes `.spec/state/spec-db.json`. JSON mode has no Jazz runtime to inspect. ## CLI - `charter scan`: parse the current filesystem selection and print normalized ids. - `charter sync`: ingest the selection into the configured runtime. - `charter sync --dry-run`: print planned changes without writing. - `charter sync --jazz-runtime`: print native Jazz row ids and durability configuration. - `charter events`: query semantic project events. - `charter work`: query durable work items. The next importer milestone is to make source add/list/remove and multi-source watch use the local controller mapping directly rather than passing one `--spec-dir` through every command.