diff --git a/docs/roadmap/configkit.md b/docs/roadmap/configkit.md index 2b1cf73..dde162f 100644 --- a/docs/roadmap/configkit.md +++ b/docs/roadmap/configkit.md @@ -124,8 +124,10 @@ file remain terminal. effective settings. Apply its [selected scope and fallback rules](glossary-stages.md#configuration-scope--resolved) and [compound-value and clearing rules](glossary-stages.md#compound-values-and-explicit-clearing--resolved), together with its [CLI precedence and native-support boundary](glossary-stages.md#cli-overrides-and-stage-precedence--resolved). + Use its [separate glossary and protection selections](glossary-stages.md#glossary-selection-and-protected-vocabulary--resolved), + including root protection defaulting through recorded application resolution. Complete its required durable decision record. The glossary roadmap owns - the remaining path and attribution decisions. This + the remaining path, list-input, combined-entry, and attribution decisions. This application scope model does not change native source composition or sibling-inheritance semantics. diff --git a/docs/roadmap/glossary-stages.md b/docs/roadmap/glossary-stages.md index 90384c8..03d543b 100644 --- a/docs/roadmap/glossary-stages.md +++ b/docs/roadmap/glossary-stages.md @@ -15,7 +15,7 @@ but does not select a different glossary input for each occurrence. Allow operators to run ordered glossary stages against different glossary inputs within one processing run. For a D&D transcript, the first glossary stage can use `party.yml` and the second can use `spells.yml`. Each stage uses its selected -glossary and processes the transcript resulting from earlier stages. Operators +glossaries and processes the transcript resulting from earlier stages. Operators need not combine those inputs into one glossary or run Audita separately for each pass. @@ -34,12 +34,17 @@ separate variable-substitution language. The selected glossary configuration is: ```yaml version: 3 -glossary: party.yml +glossaries: + - party.yml + - spells.yml pipeline: stages: - module: glossary + glossaries: + - party.yml - module: glossary - glossary: spells.yml + glossaries: + - spells.yml - module: grammar ``` @@ -49,12 +54,13 @@ Preserve meaningful false, zero, and empty values under each setting's validatio rules rather than treating them as omission. A stage override does not alter the root settings or the defaults seen by later stages. -In this example, the first glossary stage uses `party.yml`, the second uses -`spells.yml`, and grammar inherits `party.yml` wherever it or its validators -consume the glossary. Transcript changes carry forward between stages; -configuration overrides do not. A stage's module and associated validators -receive its effective stage settings consistently. Whether protected vocabulary -needs a broader selection remains an open domain decision below. +In this example, the first glossary stage uses `party.yml` as its correction +input, the second uses `spells.yml`, and grammar inherits both glossary inputs. +All three stages inherit protection from both files through the root default +described below. Transcript changes carry forward between stages; configuration +overrides do not. Each consumer receives the appropriate selection from the +stage's effective settings, keeping correction/context inputs and protection +inputs distinct. Apply this model to settings governing stage processing. Invocation-wide concerns such as configuration discovery, output destinations, and reporting @@ -74,7 +80,8 @@ must preserve these scope decisions. | Setting | Scope and rationale | | --- | --- | -| Glossary input | Stage: vocabulary supplied to the module and its validators. | +| `glossaries` | Stage: ordered glossary files supplying correction and context vocabulary. | +| `protected_terms` | Stage: independently selected glossary files supplying protected vocabulary; defaults from root `glossaries` before stage inheritance. | | Applicable confidence threshold | Stage: acceptance of that stage's proposals. | | Proposal and validation profile selection | Stage: models and generation settings appropriate to each role. | | `context.description` | Stage: prompt context shared by proposals and validators. | @@ -98,6 +105,54 @@ backend admission. Do not rebuild or mutate shared backend configuration for each stage. Per-stage validation batching does not change transcript chunking; per-stage rechunking would be a separate feature decision. +### Glossary Selection and Protected Vocabulary — Resolved + +Use `glossaries` at the root and on stages for an ordered sequence of glossary +file paths, including when only one file is selected. Combine the entries from +the selected files in declared order for the stage's glossary input. A glossary +module stage without an override receives the combined root selection; an +explicit stage list selects the files for a focused pass. Paths are direct file +selections, with no named catalog or variable-reference language. + +Use `protected_terms` at both scopes for a separate ordered sequence of glossary +file paths, not literal term strings. Its entries supply the protected vocabulary. +Each list specifies the complete selection and replaces the inherited list; +`protected_terms` is not an additive list of extra glossaries. Do not implicitly +union it with correction inputs or with files selected by other stages. + +Resolve these settings in this order: + +1. Load configuration and apply explicit CLI assignments through ConfigKit. +2. If root `protected_terms` is omitted, derive it from a copy of the effective + root `glossaries`. Preserve any explicit root protection selection, including + `[]`. +3. Independently inherit the effective root `glossaries` and `protected_terms` + into each stage wherever that stage omits the corresponding setting. A stage + override replaces only its own selected list. + +Protection therefore defaults at the root before stage inheritance. It does not +fall back to a focused stage's glossary list. In the example above, no operator +protection configuration is needed: + +| Stage | Glossary input | Protected vocabulary | +| --- | --- | --- | +| Party glossary pass | Party | Party + spells | +| Spell glossary pass | Spells | Party + spells | +| Grammar | Party + spells | Party + spells | + +A stage can supply a narrower or different `protected_terms` list. Explicit +`protected_terms: []` disables glossary-derived protection for that stage without +clearing its correction/context inputs or disabling other validators. Explicit +`glossaries: []` clears correction/context inputs without changing protection. +A glossary-correction stage requires a nonempty effective glossary selection; +other stages may operate without glossary context where supported. A glossary +selected only by a stage is not automatically added to root protection. + +Protection must retain module-appropriate allowances for legitimate glossary +corrections and spoken-word cleanup. Carry both selections through execution and +validation rather than passing a single combined glossary to every consumer. +Combined-entry conflicts and overlapping protected identities remain open below. + ### Validation-Profile Fallback — Resolved Combine root and stage selections, including explicit clearing, before deriving @@ -125,15 +180,18 @@ Resolve eligible settings field by field. A partial settings group overrides only its supplied children; an empty mapping such as `llm: {}` contributes no overrides. For example, a stage setting `llm.repair_attempts: 0` inherits the root proposal profile and operation timeout while explicitly selecting no repairs. -Omitted fields inherit root settings and then receive any applicable fallback. +Omitted fields inherit root settings, with derived defaults applied at the scope +specified for each setting. Root protection defaulting precedes stage inheritance; +validation-profile fallback follows the combination of root and stage selections. False, zero, and empty values remain explicit and follow per-field validation: zero repairs is valid, while a zero operation timeout is invalid. | Explicit input | Meaning | | --- | --- | | `context.description: ""` | Clear the inherited description. | -| `glossary: null` | Clear the inherited glossary selection. | -| `glossary: ""` | Error: an empty string is not a valid glossary path. | +| `glossaries: []` | Clear correction/context inputs; a glossary-correction stage then lacks its required input. | +| `protected_terms: []` | Disable glossary-derived protection without changing correction/context inputs. | +| Empty file-path entry in either list | Error: an empty string is not a valid glossary path. | | `llm.validation_profile: null` | Clear the inherited selection, then use the effective proposal profile. | | `llm.validation_profile: ""` | Error: use null to clear the selection deliberately. | | Empty or null proposal profile | Invalid for a stage requiring model execution. | @@ -141,10 +199,11 @@ zero repairs is valid, while a zero operation timeout is invalid. Declare genuinely optional selectors nullable and preserve omission versus explicit null through resolution. Null is not a universal reset operation; -settings groups are not nullable. A glossary-correction stage requires a glossary -and rejects a missing selection before execution. Other stages may operate -without glossary context where their operation supports it. The separate -protected-vocabulary decision below still governs its consumers. +settings groups are not nullable. The glossary settings are sequences with `[]` +as their explicit-clearing form; list-null handling remains open below. +Reject a glossary-correction stage's missing or empty effective input +before execution. Other stages may operate without glossary context where their +operation supports it, independently of their protection selection. Lists replace the entire inherited list where list-valued stage settings apply; `[]` explicitly selects an empty list. Do not append or union implicitly. @@ -161,12 +220,15 @@ values and clearing remain authoritative for that stage. Apply validation-profil fallback after combining these selections. This preserves deliberate differences between stages while allowing invocation-specific changes to their defaults. -For the pipeline example above, `--glossary revised-party.yml` changes the -effective glossary for the first glossary stage and the grammar stage to -`revised-party.yml`; the second glossary stage still uses `spells.yml`. A stage -with `glossary: null` remains cleared. Apply this precedence consistently to all -stage-capable settings. Submit only explicitly supplied CLI values to ConfigKit; -preserve false, zero, and empty values under their per-field rules rather than +For the pipeline example above, a CLI assignment replacing root `glossaries` +with `[revised-party.yml, spells.yml]` changes grammar's inherited input and, +with root `protected_terms` omitted, the derived protection inherited by all +three stages. The explicit party and spell correction selections stay unchanged. +An explicit root protection list is not changed by a root glossary assignment; +an explicit stage protection list or `[]` remains authoritative for that stage. +Apply this precedence consistently to all stage-capable settings. Submit only +explicitly supplied CLI values to ConfigKit; preserve false, zero, and empty +values under their per-field rules rather than allowing parser defaults to override configuration. Keep CLI functionality within ConfigKit's native capabilities. ConfigKit v1.1.0 @@ -196,6 +258,19 @@ in `Definition.Resolve`, using `Resolution.IsExplicit` for presence and `configkit.Default` for omitted stage fields and record root-field dependencies. Do not treat a derived root validation fallback as an explicit selection. +Implement root protection defaulting in the same `Definition.Resolve` callback: +use `configkit.Default` for root `protected_terms`, copying effective root +`glossaries` and recording that path as its dependency. Then default each omitted +stage protection list from the effective root protection list, even when that +root value was derived. Preserve source context through both steps and avoid +shared mutable list storage. Explicit empty lists must suppress defaulting. + +Leave `protected_terms` absent from the bundled configuration underlay. ConfigKit +does not express this live list-to-list dependency as a declarative underlay +reference: native `extends` concerns sibling mappings and runs before CLI +assignment. Use the public recorded-resolution lifecycle, which sees final CLI +assignments, rather than static duplicated lists or custom reference machinery. + An explicitly null validation selection needs deliberate application fallback: `configkit.Default` correctly leaves explicit null alone. Apply the chosen fallback and use `Resolution.RecordDerivedDefault` to record the assignment and @@ -234,12 +309,13 @@ adopted configuration and CLI conventions and avoids adapting it twice. Keep the requirement visible during library design without expanding those migrations into feature implementation. -1. Apply the selected scope, compound-value, clearing, CLI precedence, and - validation-profile fallback rules. Finalize path resolution. Incorporate +1. Apply the selected scope, glossary/protection selection, compound-value, + clearing, CLI precedence, and validation-profile fallback rules. Finalize path + resolution and remaining list-input details. Incorporate these into the version-3 schema rather than retain the old module-name list. 2. Resolve effective stage settings and carry them through stage execution, - proposal generation, and validation. Carry selected glossary inputs through - loading and settle the protected-vocabulary behavior for all consumers. + proposal generation, and validation. Load correction/context and protection + selections separately and settle combined-entry and identity conflicts. 3. Make repeated stages and their selected inputs understandable in inspection, diagnostics, and reports. Account for all consumed glossary files in input handling and output-collision protection. @@ -251,17 +327,22 @@ into feature implementation. ## Acceptance Direction Use distinct party and spell fixtures with controlled model responses to show -that each stage receives the intended glossary, that one stage's input does not -leak into another, and that the second stage sees the first stage's accepted -transcript changes. Verify meaningful errors for invalid selections or inputs, -and retain the selected domain validation and partial-success behavior. Exact +that each stage receives its intended correction and protection selections, +that overrides do not leak into other stages, and that the second stage sees +the first stage's accepted transcript changes. Verify meaningful errors for +invalid selections or inputs, and retain the selected domain validation and +partial-success behavior. Exact test cases follow the design; live provider calls are unnecessary. Verify root fallback, per-stage override isolation, and explicit-value presence for the selected stage settings. Include the grammar stage after the overridden -glossary stage to establish that it inherits the root glossary. Verify that each -stage's module and validators receive consistent effective settings, including -their recorded source origins. Cover repeated modules and an empty stage list. +glossary stage to establish that it inherits both root glossary inputs. Verify +that all three stages inherit root protection derived from those inputs despite +the focused correction selections. Cover explicit root and stage protection +lists, independent empty-list clearing, a glossary stage with no override using +both inputs, and a file selected only on a stage not entering root protection. +Verify that modules and validators receive their respective effective selections +and recorded source origins. Cover repeated modules and an empty stage list. Exercise the selected request and validation overrides through stage consumers, including independent budgets without changing shared backend admission or the @@ -276,6 +357,10 @@ history as well as effective values. Verify that explicit CLI flags change root defaults and inherited stage values while preserving explicit stage settings and clearing. Cover profile fallback after CLI assignment, explicit false/zero/ empty CLI values where valid, and the absence of overrides from parser defaults. +Cover root protection defaulting after CLI assignment, explicit root protection +surviving glossary overrides, and recorded root-to-stage protection dependencies. +Verify module-appropriate protection using terminology from both files, including +legitimate corrections and cleanup; test the selected overlap/conflict behavior. Confirm that the durable policy, configuration contracts, and contributor guidance are in place before declaring this feature complete. @@ -287,28 +372,45 @@ The recommendations below are proposals, not selected contracts. **Recommendation:** use ConfigKit's supported source context to resolve a configuration path relative to the document supplying that value, and resolve -CLI paths relative to the working directory. A stage inheriting a root glossary -also inherits that value's source context. This supports reusable imported -configuration; verify the native facilities before selecting implementation. +CLI paths relative to the working directory. Each inherited glossary or protection +path retains its source context, including protection derived from root glossary +paths. This supports reusable imported configuration; verify the native +facilities before selecting implementation. **Alternative:** resolve all relative glossary paths from the working directory. This has one simple base and suits invocation-local inputs, but makes reusable configuration dependent on where Audita is launched. Decide the base explicitly for no-main-file operation as well. -### Glossary Selection and Protected Vocabulary +### Combined Entries and Protected Identities -**Recommendation:** start from each stage's effective glossary for its module -and validators, with no implicit carryover or union of other stage inputs. This -matches the selected scope model and keeps each stage understandable in isolation. -Review whether protecting terms corrected by earlier stages requires a separate, -explicit protected-vocabulary selection; overlapping terms need deliberate rules. +**Recommendation:** preserve declared file and entry order, coalesce identical +entries, and diagnose conflicting definitions rather than silently choosing by +file order. Define identity handling for overlapping names, aliases, and plurals +across the correction and protection selections, including legitimate glossary +corrections. This keeps protection explainable but requires distinguishing true +conflicts from harmless repetition or legitimate shared spellings. -**Alternative:** protect vocabulary from all configured glossary inputs while -using the effective stage glossary for proposal generation. This could preserve -party names during later spell or grammar work, but makes stage behavior depend -on other stages' inputs and requires conflict and overlap semantics. Ordinary -input selection alone does not decide this protection policy. +**Alternative:** use documented ordered precedence for conflicting entries. This +supports intentional local overrides and is straightforward to apply, but can +hide disagreements and make protection depend on list order. Neither approach +should accidentally inherit the existing single-glossary lookup's first-match +behavior as a new multi-file contract. + +### List Inputs and CLI Representation + +**Recommendation:** accept explicit null as an empty selection, preserving native +ConfigKit slice decoding and presence without an additional rejection rule. Keep +`[]` as the primary documented clearing form. This requires documenting a second +clearing form and ensuring null suppresses protection defaulting just as `[]` +does. Select CLI syntax for supplying each complete root list using native +ConfigKit overrides. + +**Alternative:** reject null for the two glossary-file lists and require `[]` for +clearing. This offers one explicit empty-list spelling but adds application +validation beyond ConfigKit's nullable slice decoding. CLI spelling remains to +be selected; it does not reopen root-versus-stage precedence or imply +targeted-stage overrides. ### Stage Identity and Attribution