CLI Configuration
Note
Status: implemented. ddown compile and ddown visualize resolve a project's
CompilerOptions — from --config, or a dialogue.toml
found by walking up from the script — and build their compiler and report from it,
so configured speakers also reach the report editor's autocompletion.
Where it sits
flowchart LR
ARGS["--config / script"] --> R["ProjectConfiguration"]
TOML["dialogue.toml"] -.discovered.-> R
R -->|CompilerOptions| CMP["compile:<br/>Func<CompilerOptions, IScriptCompiler>"]
R -->|CompilerOptions| VIZ["visualize:<br/>CompilationVisualizer"]
VIZ --> SYM["report symbols → autocompletion"]
ProjectConfiguration is the only CLI type that references
DialogueDown.ConfigurationLoader. Everything downstream receives a plain
CompilerOptions, so the visualization assemblies never see TOML.
Resolution
Precedence: --config › nearest dialogue.toml walking up › CompilerOptions.Default.
| Case | Behavior |
|---|---|
No --config, none found |
CompilerOptions.Default. |
--config path missing |
Usage error naming the file; nothing compiles. |
| Malformed file (explicit or discovered) | The loader's located DialogueConfigurationException, exit 65. |
A dialogue.toml beside the script and a different --config |
--config wins. |
visualize with no script |
Walk up from the browse root. |
Nearest file above visualize --root |
Not found — the walk stops at --root; use --config. |
| Empty file | CompilerOptions.Default. |
The launcher resolves one CompilerOptions from its browse root and applies it to
every report it opens; per-file discovery inside a subtree with its own
dialogue.toml is not built.
Key design decisions
D1 — Resolve in the CLI; pass the core options down
Only the CLI knows the command line and working directory, so discovery and loading live there, and the TOML dependency stays at the outermost layer.
D2 — Discover by walking up from the script
Zero configuration is the common case. Like tsc, Prettier, Ruff, and EditorConfig,
the CLI searches upward and the nearest file wins, so one file at a project root
serves nested scripts. A dialogue.toml is itself the project marker, so there is no
root = true stop. For visualize, the served root is a security boundary, so the
walk never reads above --root.
D3 — compile takes a compiler factory
The compiler must be built after the options are resolved, so CompileCommand takes
Func<CompilerOptions, IScriptCompiler> (default ScriptCompilerFactory.CreateDefault)
instead of a startup-built compiler. A test substitutes the factory and asserts the
resolved options reached it.
D4 — One options value reaches every visualize path
CompilationVisualizer(CompilerOptions) builds a configured visualizer. The static
export and the served session receive an AppliedConfiguration (the options plus the
file they came from, which the Config tab shows); --emit receives the
CompilerOptions alone.
D5 — Configured speakers complete even when unused
Completions come from SymbolProjection over the semantic model. SpeakerTable.Symbols
exposes every bound speaker — from the script or configuration — and the projection
unions them after the script's speakers, so a cast declared up front completes before
anyone speaks.
Testability
ProjectConfiguration: explicit, discovered, and default resolution; the missing path; the malformed file — with a temporary directory and raw-string TOML.compile: the substituted factory receives the resolved options.visualize: each route receives the resolved options.SpeakerTable.Symbolslists configured and script speakers once each, and an unused configured speaker appears in the report'sSymbolSet.