# Development This document defines contributor workflow for Notarius. For architectural invariants and package boundaries, read [Architecture](architecture.md) first. ## Required Reading Before changing the repository, review: - [Architecture](architecture.md) - [Documentation Policy](documentation.md) Keep current-behavior documentation limited to implemented behavior. Put planned or deferred behavior under `docs/roadmap/`. ## Repository Layout - `cmd/notarius`: executable entry point. - `internal/cli`: CLI parsing, production catalog wiring, config loading, run command orchestration, output writes, and user-facing errors. - `internal/core`: deterministic models and policy for artifacts, source documents, config, and diagnostics. - `internal/framework`: reusable contracts, pipeline orchestration, prompt helpers, validation helpers, and LLM runtime plumbing. - `internal/modules`: concrete input, chunk, extract, merge, normalize, and output modules. - `docs`: policy, user/operator docs, internal docs, integration docs, and roadmap files. - `examples`: maintained, secret-free examples covered by tests where practical. ## Validation Commands Run focused tests for the area changed, then run the broader checks when the change affects shared contracts, CLI behavior, or documentation examples. ```sh go test ./... go vet ./... go build ./cmd/notarius ``` Useful focused checks: ```sh go test ./internal/cli go test ./internal/core/config go test ./internal/framework/pipeline go test ./internal/framework/llm go test ./internal/modules/input/seriatim go test ./internal/modules/extract/dnd/spells go test ./internal/modules/output/json ``` ## Prompt Asset Tests Tests should not assert the exact text of embedded prompt assets for production modules. Prompt wording is expected to change frequently during development, and tests should not fail solely because prompt prose was edited. Prefer assertions against prompt structure, prompt IDs and versions, declared inputs, schema wiring, input propagation, diagnostics redaction, and successful prompt preparation. Narrow exceptions: - generic or test-only modules may use fixed prompt text assertions when the text is part of the test surface; - test fixtures may supply their own prompt text and assert against that fixture text. ## Go Conventions - Prefer the standard library unless a dependency is justified by correctness, security, interoperability, or substantial complexity reduction. - Keep package names short, lowercase, and idiomatic. - Preserve import direction: framework and core code must not depend on concrete production modules. - Use `context.Context` for long-running operations and external calls. - Return contextual errors that name the operation and relevant module, path, or resource. - Do not include secrets in errors, logs, diagnostics, manifests, or docs. ## Adding Config Fields Config behavior is centralized under `internal/core/config`. When adding a file config field: 1. Update file config structs and YAML parsing in `file_config.go`. 2. Apply the field over defaults in config application code. 3. Add validation in `validation.go` when the field has constraints. 4. Add environment override support in `env.go` only for operational overrides. 5. Update redaction if the field can contain secrets. 6. Add focused config tests. 7. Update [Configuration](../config.md) and maintained examples when behavior changes. Pipeline composition should remain config-driven. Do not add command flags that silently replace structural pipeline definitions. ## Adding CLI Flags Or Commands CLI behavior lives in `internal/cli`. When adding CLI surface: 1. Keep syntax explicit and update usage text. 2. Validate arguments before running expensive work. 3. Convert internal errors into concise user-facing messages. 4. Add CLI tests for success, syntax errors, and failure modes. 5. Update [CLI Reference](../cli.md), and update [Operations](../operations.md) or [Troubleshooting](../troubleshooting.md) if run behavior changes. ## Adding Modules Or Adapters Concrete modules live under `internal/modules//...` and implement the interfaces in `internal/framework/contracts`. For a new production module: 1. Implement the relevant contract. 2. Expose a `ModuleSpec` with the correct module key, module kind, provided capabilities, and required capabilities. 3. Expose a `Register` function that registers the module with its registry. 4. Add focused module tests for contract behavior, registration, options, validation, and errors. 5. Register the module in `internal/cli/catalog.go` only when it is production ready. 6. Update internal docs and user-facing docs only for implemented behavior. Source-format behavior belongs in input modules and integration docs. Extraction-domain behavior belongs in extract modules and artifact docs. ## Updating Examples Examples must be valid, secret-free, and small. - Prefer environment-based secret configuration. - Keep `examples/dnd-spells.config.yml` loadable by CLI tests. - Keep `examples/seriatim-minimal-transcript.json` compatible with the Seriatim adapter. - Do not add expected-output fixtures unless they are validated or have a clear regeneration procedure. ## Documentation Updates Update docs in the same change when behavior changes. - CLI syntax: `docs/cli.md` - Config fields and defaults: `docs/config.md` - Output, diagnostics, retention, or recovery: `docs/operations.md` - Common user-facing failures: `docs/troubleshooting.md` - Internal architecture and contracts: `docs/internal/` - External file formats and durable integration contracts: `docs/integrations/` - Future or planned work only: `docs/roadmap/`