Describe generated components by logical path, not write location (v0.1.16) - #59
Merged
Volv-G merged 1 commit intoSep 18, 2026
Conversation
….1.16) Component provenance annotations were derived from wherever the YAML happened to be written. Two defects followed. Git provenance could vanish entirely. Repository details were read from the common ancestor of the source file and the output path; when a caller wrote outside the checkout that ancestor is not in the repository, so every git_* annotation was silently dropped. This is reachable today by configuring an output folder outside the checkout. Bytes were unstable. Because the physical path reached the annotations, the same source generated to two locations produced different content, and so a different digest. Repository details are now read from the source file's own directory, which is inside the checkout whenever the source is. A generated component also keeps its identity when written somewhere incidental: the optional logical_output_path records where the component is to be understood to live, while the bytes are written where the caller asked. The parameter is opt-in and forwarded only when set, so existing callers -- including overrides written against the previous signatures -- are unaffected, and the annotation path is kept unresolved so symlinked outputs still record the name they were given. Assisted-By: devx/6257e672-aaa7-443c-a4e1-a0150a485d9d
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
(AI-assisted)
A generated component carries annotations describing where it came from:
component_yaml_path,python_original_code_path, and thegit_*set. These were derived from wherever the YAML happened to bewritten, which turns an incidental choice by the caller into part of the component's identity.
Git provenance could disappear
Repository details were read from the common ancestor of the source file and the output path. That ancestor
is only inside the checkout when the output is. Generate to a directory outside the repository and the
lookup runs somewhere that is not a repository at all, so every
git_*annotation is dropped and thecomponent records no origin whatsoever.
This needs no unusual setup to hit -- the output folder is configurable, so pointing it outside the checkout
is enough.
Bytes depended on where the file was written
Because the physical path reached the annotations, generating identical source to two different locations
produced different content, and therefore a different digest. Anything treating the digest as an identity
for the same source saw two unequal results.
What changed
Repository details are now read from the source file's own directory. The source is what the provenance is
about, and its directory is inside the checkout whenever the source is -- including when the file is reached
through a symlink from outside.
A component can also now keep its identity when written somewhere incidental. The optional
logical_output_pathsays where the component is to be understood to live; the bytes still go where thecaller asked. Callers that stage output in a scratch location can describe the component truthfully without
publishing a path that is meaningless to anyone else.
Compatibility
The parameter is opt-in. When it is not supplied the emitted bytes are unchanged, and two tests exist purely
to pin that: omitting it, and passing it equal to the physical path, must both be indistinguishable from the
previous behaviour.
It is also forwarded only when actually set. Several hops here are overridable, and passing a new keyword
unconditionally would break an override written against the previous signature even though that caller never
asked for the feature. A test exercises a subclass carrying the exact prior signature.
The annotation path is deliberately kept unresolved. Legacy path annotation records the name it was given, so
resolving would rewrite it whenever the output is a symlink; only the common-ancestor computation resolves.
The container image is still read back from the physical output.
logical_output_pathis provenance only --reading content from a location that was never written would make a non-existent path behavioural. A caller
writing to a fresh output supplies the image, as before.
Verification
Tests drive the real generator end to end against a genuine repository, because the behaviour under test
is the path derivation; a stub cannot demonstrate it. They assert against real annotation keys and cover:
provenance surviving an output outside the checkout, the logical path being recorded instead of the physical
one, two writes to different locations producing identical bytes, no host or staging path appearing in any
annotation, a symlinked output keeping its lexical name, a symlinked source keeping its repository, and the
two compatibility cases above.
Each was confirmed to fail when the corresponding fix is reverted.