Settle absent-main behavior for companion inputs

This commit is contained in:
2026-11-09 17:49:08 +00:00
parent e36740313d
commit 2ba61d5c7c

View File

@@ -1,7 +1,7 @@
# Main-relative companion imports and overlays
Status: accepted direction and public API structure; absent-main and remaining
filesystem-policy choices are open. Not implemented. Implementation baseline:
Status: accepted direction, public API structure, and absent-main behavior;
containment and main-source eligibility remain open. Not implemented. Baseline:
`191015e`.
## Purpose
@@ -138,11 +138,11 @@ precedence, and validation retain their existing semantics.
### Absent main and optional companions
Optional discovery may find no main file while defaults and CLI settings still
permit a successful application load. Support a declared absent-main policy for
dependent companion imports. Skipping optional companions is the intended default
for this workflow; applications can instead require a base or supply an explicit
fallback directory/context. The representation and exact skip scope remain in
OD-2, including inputs with required imports or additional application payload.
permit a successful application load. When no usable base is available, skip
optional companion import expansion while retaining the declaring input's
ordinary payload and validation. Required imports still fail. Applications can
require a base or supply an explicit fallback context on each derived binding.
OD-2 records the settled precedence, skip scope, and fallback behavior.
Do not infer a directory from unsuccessful candidates or silently use the working
directory. An application may explicitly choose the working directory as its
@@ -249,14 +249,14 @@ without an application directory walker, parser, or extra discovery pass.
Add a small, optional main-relative binding description to `Input`, retaining
the concrete `Input.Filesystem` field. A helper supplies the common default
description; explicit settings group any absent-main controls decided in OD-2.
description; explicit settings group the absent-main controls settled in OD-2.
Companion `Mapping` and `Bytes` inputs use native imports for fragment selection.
Preserve the input's source, placement, import enablement, and tier.
The proposed shape is an `Input.MainRelative` field of type
`*MainRelativeContext`, with a `MainRelative()` convenience helper. These names
illustrate the settled structure; final spelling and OD-2's settings can be
finished during API design. For example, this unimplemented API sketch assumes
illustrate the settled structure; final spelling can be finished during API
design. For example, this unimplemented API sketch assumes
`companionDeclarations` contains ordinary native import declarations:
```go
@@ -275,7 +275,7 @@ setup without clearing its binding declaration.
Layered overlays derive automatically when `OverlayFilesystem` is absent; no
additional opt-in flag is needed. An explicit overlay context wins as a whole.
If OD-2 calls for configurable overlay fallback behavior, reuse the small binding
Support an explicit overlay fallback under OD-2, reusing the small binding
settings where appropriate without requiring a general context-selection API.
Keep the binding on `Input`: `Source` still describes the supplied content and
@@ -285,32 +285,47 @@ a boolean and sibling fields, while keeping the addition smaller than a general
context selector. No source wrapper, deferred fields on `FilesystemContext`,
callback, or second file-selection API is needed for this design.
### OD-2: Scope and representation of absent-main handling — settled
Put absence behavior on each derived binding. When no usable base exists, the
default skips optional companion import expansion, retaining the declaring
input's ordinary configuration values. Required imports produce an error;
requiredness includes applicable application import defaults. Continue normal
input and directive validation, so absence does not excuse invalid declarations.
This preserves independent payload and existing required/optional distinctions
without treating the entire input as conditional on main presence.
Support a concrete fallback context and a require-base option within the binding
description. Illustrative fields are `Fallback *FilesystemContext` and
`RequireBase bool`; final spelling remains an API design detail. Select the
context in this order:
1. A supplied `Input.Filesystem` is the complete override.
2. Otherwise, use a usable main-derived context.
3. Otherwise, use the explicitly supplied fallback context, if any.
4. Without any usable context, skip optional imports unless the binding requires
a base. A require-base binding or required import produces an error.
A fallback can satisfy require-base: the option requires a usable context, not
an actual main file. Consumers requiring a main file can make discovery required.
An invalid selected context fails; it does not activate a lower-priority choice.
Fallback applies only when the main cannot provide a base, never after a failure
reading or processing a selected main, or after missing or invalid companion
files beside an existing main. Once bound, normal import selection and failure
rules apply. Do not guess from unsuccessful discovery candidates or implicitly
use the working directory; applications may explicitly choose it as a fallback.
A fallback uses `FilesystemContext.BaseDir` as its lookup directory, with `Root`
and `FS` retaining their containment and namespace roles. This also applies to
the new overlay fallback: look for `overlays/<name>.yml` beneath its base, while
preserving existing explicit `OverlayFilesystem` lookup behavior. An explicit
overlay context wins, followed by main derivation, then the declared overlay
fallback. When no overlay is selected, no overlay context is needed. An active
selection requires a usable context and the named file; never silently skip it.
Companion absence settings do not make a selected overlay optional.
## Open Decisions
### OD-2: Scope and representation of absent-main handling
**Settled:** optional companions should support defaults-only startup; a declared
fallback is useful, and guessed candidate directories or implicit working-directory
fallback are inappropriate. Selected-main failures remain terminal.
**Recommendation:** put absence behavior on each derived binding. Default to
skipping optional companion import expansion when no main base exists. Provide
an explicit require-base choice and a concrete fallback context; use a fallback
only when no main base is available, never to recover from a selected-file error.
Keep any independent payload in the underlay input, and do not silently waive
required import declarations. A supplied fallback for the overlay can likewise
provide its lookup base; an active overlay without any usable context fails.
This preserves useful absent-main behavior without silently discarding unrelated
configuration or conflating required imports with optional ones. Finalize how
these choices are represented and how a fallback declares lookup base and root.
**Alternative:** scope skip to the entire explicitly designated companion input.
This is simpler for the import-only mappings Audita describes and avoids partial
input processing, but also omits any payload or required imports in that input.
It needs clear semantics for that deliberate condition. A single load-wide
absence policy is another viable convenience, but cannot express different
requirements for separate companion inputs as directly.
### OD-3: Containment inheritance and symlink convention
**Settled:** derived companion imports and derived layered overlays use the main