The previous articles kept discussing one question:
When content changes, which existing results can still be reused, and which must be invalidated?
But recently, _content/learn/books.yaml encountered an even more specific situation.
This time, the original file did not change.
No heading was modified.
No new book was added.
No English content was updated.
In terms of file bytes, it remained the exact same books.yaml.
However, after the workflow reread it, it found:
Previously, only 10 semantic units were identified as needing to enter the language workflow; now there are 12.
The two new additions are display text slots that previously did not fall within the scope of formal language semantic inputs. Their current source values are PDF and GitHub.
This easily raises a question:
GitHubwere likely to remain unchanged in Simplified Chinese anyway, so why add them to the language input?
This question actually reveals exactly what this design truly aims to solve.
The point of the change is not:
These two words must now be translated into Chinese.
Rather, it is:
These two user-facing display texts have now formally entered the language workflow.
In other words:
Entering the language workflow does not mean the text must change.
For Simplified Chinese, the final result could very well still be:
PDF → PDF
GitHub → GitHubBut now, this “unchanged” state is the result of formal language processing, rather than being coincidentally left as-is simply because the parser failed to recognize them.
This article organizes this issue, along with what was later added to address it:
A re-entry mechanism for structured semantic input expansion.
At first, I also placed too much importance on “whether the source file changed”
Many incremental workflows first check:
Source file unchanged → reuse existing results
Source file changed → recalculate affected scopeThis logic is usually fine.
For example, after a Markdown page is actually modified, you can compare source identities and then determine which translation units need to re-enter the workflow.
But structured content adds an extra layer:
The original file does not directly equal the translation input the model actually receives.
There is a parser in between.
Take books.yaml as an example: the workflow does not just throw the entire YAML as-is to the model.
It first reads the structure, then identifies which fields belong to:
- User-facing language content;
- Machine structure;
- URLs;
- Identifiers;
- Technical values that should not be modified;
- Display text that can enter the formal language processing scope.
Ultimately, what actually enters Generation is the language semantics extracted by the parser from the original structure.
This can be simply understood as:
Original YAML
→ Parser parses structure
→ Extracts formal language semantic inputs
→ Generation
→ Rebuilds complete YAML according to original structureSo what determines the model’s task is not only:
What the original file is.
It also includes:
What the current parser considers to be formal language input.
This time, the change is not in the raw source, but in the semantic input
The actual state of books.yaml this time is clear.
The old state can be summarized as:
Original file: unchanged
Old semantic units: 10
Current semantic units: 12
Added: 2
Removed: 0
Old unit changes: 0The additions are not two “words that must be translated into another language”.
More accurately, they are:
Two display text slots that previously did not enter the formal language semantic input, but are now recognized by the parser.
Their current source values are:
PDF
GitHubThe original 10 semantic units are all still present.
Their:
- Unit ID;
- locator;
- source;
- source SHA;
- coordinates;
- protection metadata;
have not changed.
What actually happened is simply:
The current parser recognizes more display content that should be explicitly handled by the language workflow than before.
Why PDF and GitHub also deserve to enter the language workflow
This is the most confusing part this time.
For Simplified Chinese:
PDF
GitHubMost likely do not need modification.
So why not just leave them outside the language workflow?
The reason is:
The parser should determine whether a field is user-facing language content based on its structural semantics, rather than deciding based on whether the current English value “looks like it needs translation”.
Suppose a structured field has the value today:
PDFTomorrow, upstream might change it to:
Download PDFAnother one displays today:
GitHubLater it might become:
View on GitHubIf the parser’s logic is:
“This field looks like a technical term right now, so it doesn’t enter the language workflow.”
Then it might continue to be overlooked when the field content changes in the future.
A more robust design should be:
Is this field itself user-visible display text?
If the answer is “yes”, then it should enter the language semantic input.
Whether the final target language changes the text is decided by subsequent language processing.
Therefore:
Entering the language workflow ≠ must rewrite the stringThis is a very important distinction in this design.
“Keeping it as-is” can itself be a correct localization result
Previously, it was easy to understand “localization” as:
English must be changed into another language.
But in reality, not all user-visible content must change.
For example:
- Brand names;
- Product names;
- Abbreviations;
- Standard names;
- API names;
- Certain common technical terms;
In many locales, these should remain as-is.
So:
source = PDF
target = PDFdoes not automatically mean:
Not translated.
It could also mean:
This display text has entered the formal language workflow, and it has been confirmed that it should remain as-is.
The real question is not whether the characters changed.
But rather:
Whether it has been formally processed.
This is actually very similar to the issue encountered in the previous article about code comment completeness.
The final page “looking fine” does not mean the workflow has proven:
All content that should have been processed actually went through the workflow.
If you only look at the source SHA, you will reach the wrong conclusion
Suppose the system only checks:
old source SHA == current source SHAThe result holds.
Then the easiest conclusion to make is:
The file hasn’t changed, so the old translation remains valid.
But the old Generation actually only faced 10 formal semantic inputs.
The current formal inputs have become 12.
Thus:
Current formal semantic inputs: 12
Old Generation coverage: 10
Current new inputs: 2At this point, if the old Generation is still deemed the current complete result, it is equivalent to saying:
An output that does not cover all current formal inputs can continue to be recognized as current.
This is clearly not true.
Therefore:
Currentness cannot be bound solely to the original file; it must also be bound to the formal semantic inputs produced by the parser.
The original file hasn’t changed, so why do the parser results change?
Because the parser itself is also part of the workflow.
Early implementations might have considered certain fields to be:
Technical tags that do not need to enter localization.
Later, during actual page and structural semantic checks, it was discovered that:
These fields are actually display text that users will see.
As a result, the parser’s formal semantic rules changed.
The same:
_content/learn/books.yamlThe old parser yielded:
10 formal language semantic unitsThe current canonical parser yields:
12 formal language semantic unitsSo:
Unchanged raw source bytes do not mean the Generation’s semantic inputs haven’t changed.
Furthermore:
How the parser interprets the source is itself part of the model’s task.
This is not an ordinary “file invalidation”
At first, this situation is easily classified simply as:
staleThis is not entirely wrong, of course.
The old result has indeed become invalid relative to the current semantic inputs.
But just saying it’s “invalid” is not enough.
Because there could be many different reasons for the old result becoming invalid:
- Source change;
- Glossary change;
- Unified Review change;
- Parser protection rule change;
- Authority change;
- Expansion of the formal semantic input scope.
These situations cannot all use the same recovery method.
The most important fact this time is:
The old 10 semantic units are not wrong, nor have they changed.
They are simply:
No longer the entirety of the current complete input.
This requires a more accurate expression than “invalidate everything”.
But you also can’t just carry over the old result as current
Since the old 10 units have all remained unchanged, another natural thought is:
Then just inherit the old 10 results directly, and add the 2 new ones, right?
That sounds reasonable.
But there is another important boundary in the formal workflow.
books.yaml is a complete structured asset.
The formal Generation corresponds to:
The language output of the current complete structured asset.
The internal 10 or 12 slots are mainly used for:
- parser;
- protection;
- comparison;
- reconstruction;
- impact analysis.
They are not 12 independent formal TranslationUnits.
So you cannot secretly turn the workflow into:
Old 10 results
+ Newly generated 2 results
→ Automatically stitched into a new formal GenerationOtherwise, a problem arises:
The new formal result does not correspond to a real, complete Generation input and output relationship.
This makes the provenance inaccurate.
Therefore:
The old result can serve as predecessor context, but it cannot masquerade as the current complete Generation.
This is also not ordinary structured recovery
The project already has structured recovery.
It is suited for handling another class of problems.
For example:
The model has actually completed Generation for the correct, complete semantic inputs, but the Bundle later became stale due to transport, authority representation, or compatibility changes.
If it can be strictly proven that:
- The original model input truly exists;
- The original output is complete;
- The current semantic inputs have not changed;
- The current validator still accepts them;
- The change is only in transport or compatibility authority;
Then that already completed real work can be recovered.
The essence of this recovery is:
Proving that work done in the past still holds true today.
But books.yaml 10→12 is not this situation.
Because the old model invocation never faced the two newly added formal semantic inputs at all.
So:
You cannot use structured recovery to patch an old Generation that truly lacks current inputs into being current.
This is not a transport issue.
It is:
semantic input expansion.
So later a new formal state was added: semantic input expansion
What ultimately needs to be expressed is this kind of situation:
raw source unchanged
→ old semantic units all exactly preserved
→ current semantic inputs are a strict superset of the old set
→ at least one new formal language semantic unit added
→ need to re-execute complete structured GenerationThe project later explicitly defined this as:
Structured semantic-input-expansion reopen
Which is:
Structured semantic input expansion re-entry.
The “re-entry” here is very important.
It is not declaring:
The old translation was wrong.
Nor is it declaring:
The old Generation was invalid at the time.
What it truly expresses is:
The old Generation remains a valid historical fact for the 10 formal inputs at that time, but it can no longer prove the complete result of today’s 12 formal inputs.
Why it must be proven to be a “strict superset”
Suppose the old state was:
A
B
CAnd the current state becomes:
A
B
C
DThis can be considered a pure expansion.
All old content is preserved, only D is added.
But if the current state becomes:
A
B'
C
DThen the situation is different.
Because B has changed.
Or for instance, if the current state becomes:
A
C
DThen the old B has disappeared.
None of these can be called:
Pure semantic input expansion.
So the formal check requires:
The old set must be entirely exact preserved, and the current set can only be added to the original basis.
Expressed as a set relationship:
old semantic inputs ⊂ current semantic inputsAnd it must be a true strict superset.
It cannot be just:
- ID algorithm changes;
- Coordinate changes;
- Parser remap;
- Renumbering of old units;
- Unprovable old-new mappings.
If it cannot be strictly proven, stop.
Why a read-only preflight must be done first
This kind of re-entry cannot just see:
10 → 12and immediately create a new task.
Because first it must be proven that:
This is truly a semantic input expansion, and not some other change misjudged as an expansion.
So the formal mechanism first does a read-only preflight.
It needs to confirm at least:
- historical completion is still verifiable;
- baseline Generation is still verifiable;
- baseline closure is still verifiable;
- accepted output still exists;
- locale, package, asset, path bindings are correct;
- raw source bytes have not changed;
- contributor identity has not changed;
- non-slot Document context and dependencies have not changed.
Most critically:
Every old Unit must exist exactly as it was.
Including:
- ID;
- locator;
- source;
- source SHA;
- coordinate;
- protection metadata.
At the same time, it must be confirmed that:
removed = 0
changed = 0
added > 0Only then can it be formally classified as:
semantic-input-expansion.
Why books.yaml meets these conditions
The actual result this time exactly meets these requirements.
It can be condensed into:
raw source bytes changed: no
old semantic units: 10
current semantic units: 12
added: 2
removed: 0
old unit changes: 0The two display text slots newly entering the formal language semantic input have current source values of:
PDF
GitHubIt needs to be specially emphasized that:
“Added” here means newly added to the language workflow, not newly added to the original YAML file.
It also does not mean:
GitHubmust be translated into Chinese.
For zh-CN, they can perfectly well continue to remain:
PDF
GitHubThe real change is:
They are now explicitly handled by the formal language workflow, and are no longer in an area uncovered by the parser.
Why this “unchanged” state is more reliable than before
In the old state, PDF and GitHub might have ultimately appeared on the page just the same.
On the surface, it looked like:
There is no problem with the page.
But what the system could actually prove at that time was only:
The parser did not send them into the language workflow.
It could not answer:
Should they have remained as-is in the first place?
Are they user-visible text?
Were they missed?
After the new parser incorporates these display texts into the formal semantic input, the system can finally express:
This field belongs to the language workflow
→ After processing by the current target language, it still retains its original valueThis is different from:
This field never entered the language workflow
→ Therefore it coincidentally retained its original valueThese are two completely different states.
The final bytes might be the same.
But the strength of evidence is completely different.
Why generate a reopen receipt
The read-only preflight can prove that:
The current state indeed matches semantic-input-expansion.
But subsequent Generation Bundles, closures, and other readers still need to know:
Why is this structured asset, which had already become stale, now formally allowed to re-enter Generation?
So the apply phase will generate a formal reopen receipt.
It will bind:
- Old Document identity;
- Current Document identity;
- structure/source/raw SHA;
- Old Unit inventory;
- Current Unit inventory;
- Complete newly added semantic atoms;
- accepted target SHA;
- baseline Generation;
- baseline closure;
- baseline Surface;
- Current glossary;
- Current Unified Review.
This receipt is not a manual note saying:
“This can be retranslated here.”
It is machine-verifiable causal evidence:
Why re-entry is needed, and what exactly the newly added formal inputs are.
The receipt does not translate anything for you
This is also very important.
Having a reopen receipt does not mean:
PDF processed
GitHub processedIt will not:
- write target;
- automatically fill slots;
- create language quality levels;
- create package closure;
- create Surface PASS;
- execute activation;
- enter Production.
It only provides a formal authority:
This structured asset indeed needs to re-enter Generation now, and the reason for re-entry has been strictly proven.
After that, the real language work still has to continue.
Why the new Generation still requires a complete output of 12 units
Here is another question that easily arises:
Since the old 10 have not changed, why can’t the new Generation just return the two items
GitHub?
The reason is still the formal asset boundary.
The formal object of books.yaml is:
The complete structured asset.
Not two patches.
So the new Generation Bundle will carry:
- Current complete Document;
- Current raw source;
- baseline accepted output;
- predecessor context;
- reopen receipt;
- current glossary;
- current relevant authority.
The model can see the old state as context.
But ultimately it still needs to output:
The target corresponding to the complete current asset.
This ensures that:
- provenance is authentic;
- reconstruction is complete;
- schema still holds;
- current exact set is fully covered.
Why not upgrade all 12 slots to formal TranslationUnits
This is very similar to the issue mentioned in the previous article about code comment completeness.
Just because the internal granularity is fine, does not mean the formal governance unit should also become finer.
For books.yaml:
12 semantic slotsare mainly used for:
- parser;
- protection;
- exact comparison;
- reconstruction;
- stale detection;
- impact analysis.
But the formal asset is still:
_content/learn/books.yamlIf every display field were upgraded to an independent TranslationUnit, it would introduce:
- more Generation states;
- more review states;
- more closure combinations;
- more recovery branches;
- more complex currentness relationships.
And these fields are inherently part of the same structured resource.
So the current design still insists that:
Internal granularity is for proof, while the formal asset boundary is for governance.
After re-Generation, not a single subsequent gate can be skipped
semantic-input-expansion reopen is easily misunderstood as:
Since it’s been proven that only two fields were added, the regenerated output should be able to go live directly.
That is not actually the case.
After the new complete Generation is finished, it still has to go through:
Structured Generation
→ import
→ current validation
→ package closure
→ Integrated Surface Review
→ activation
→ preview
→ ProductionBecause the new output is, after all, a new formal target.
It must re-prove that:
- current schema is correct;
- glossary is valid;
- reconstruction is correct;
- structured output is complete;
- there are no site integration issues after page assembly;
- activation binds to current authority;
- Preview behavior is correct;
- Production display is normal.
So:
“The reason for re-entering Generation has been proven” does not equal “the new Generation has been proven correct”.
This also made me rethink stale
Before, when I saw stale, it was easy to understand it as:
The old thing is now wrong.
But now I prefer to understand it as:
The old evidence is no longer sufficient to prove the current state.
The difference between these two concepts is significant.
The old Generation of books.yaml did not suddenly become a wrong translation.
What it faced at that time was:
10 formal semantic inputsFor those 10 inputs, it remains a valid historical fact.
It cannot continue to be treated as current today because:
Current formal inputs = 12
Old Generation proof scope = 10So the old result is not:
Wrong.
But rather:
The scope of proof is no longer sufficient.
Historical validity does not mean it is still complete today
This is another boundary that v2 has been emphasizing.
Now that the parser has become more complete today, you cannot retroactively say:
The old Generation was invalid at the time.
That is using today’s rules to retroactively rewrite history.
The old Generation was bound at the time to:
The semantic inputs formally accepted at that time.
It should continue to exist as a historical fact.
The new parser can only show that:
From the current state onwards, the old result can no longer satisfy current eligibility.
So we need to distinguish between:
historical validity: whether it was valid historically.
And:
current eligibility: whether it is still sufficient as a current result today.
Historical validity does not mean it is still complete today.
Being incomplete today also does not mean history should be deleted.
This is very similar to database schema migration
Later, I felt this problem could be understood using database migration.
Suppose an old record previously only had:
name
url
descriptionThe system correctly processed these three fields at the time.
Later, the business model formally added:
pdf
githubThe old record would not suddenly become:
Wrong data.
But it can no longer fully satisfy the new schema.
At this point, the system needs to:
Clearly identify the schema expansion, and then enter migration.
Instead of:
Database original file unchanged
→ So nothing needs to be doneThe semantic input expansion in structured translation is essentially a similar issue.
The parser itself is actually also a formal dependency
This issue further exposed a fact that was not obvious enough before:
Translation results depend not only on source and glossary, but also on how the parser interprets the source.
The same source bytes:
parser v1 → 10 formal semantic inputs
parser v2 → 12 formal semantic inputsFor the model, these are already two different tasks.
So currentness cannot just look at:
source SHAIt must also be able to answer:
Is the formal semantic projection of this source by the current canonical parser still exactly the same as the old Generation?
This is also why “dependencies” in modern incremental workflows cannot be understood merely as:
File dependencies.
They also include:
Dependencies on the rules that interpret these files.
But you also can’t redo everything just because there is any code change in the parser
Here we also cannot go to the other extreme.
If the rule becomes:
parser code changed
→ all structured translations invalidatedThat is equally too crude.
The parser internals might just be:
- performance optimizations;
- refactoring;
- error message improvements;
- implementation adjustments that do not affect a certain asset.
What should really be judged is:
Whether the final formal semantic inputs have changed.
If, after the parser update, an asset’s:
- Unit set;
- source;
- coordinates;
- protection metadata;
all remain exactly the same, then there is no need to force a re-translation just because the implementation code changed.
What should truly trigger invalidation propagation is:
A change in the formal semantic results.
Not:
The parser file has a diff.
So what really matters is not “whether the file changed”, but “whether the model’s task changed”
Writing up to here, this article can actually be condensed into one question:
Is the task required of the model today still the same as that original model task?
For this books.yaml, the answer is:
No.
Although:
raw source = sameBut:
old semantic input count = 10
current semantic input count = 12The scope of formal inputs the model actually faces has changed.
So the old Generation cannot continue to serve as current.
A more accurate currentness model
If understood in a very simplified way, it might have started as:
current =
source unchangedLater it gradually became:
current =
source correct
+ semantic inputs correct
+ glossary correct
+ review authority correct
+ output corresponds correctly
+ current validator still acceptsIf a real semantic change occurs in any of these layers, it could cause the old result to lose its current validity.
This design is indeed more complex.
But it avoids many:
The page looks fine, so the workflow is assumed to be complete.
false positives like this.
The most worthwhile principles to retain from this time
Through books.yaml 10→12, I think this design can be condensed into a few principles.
First:
Unchanged raw source does not mean unchanged Generation semantic inputs.
Second:
Entering the language workflow does not mean the target string must change.
Display text like PDF and GitHub can perfectly well remain as-is after formal processing in Simplified Chinese.
Third:
The parser should determine whether a field is language input based on its structural semantics, rather than deciding based on whether the current English value looks like it needs translation.
Fourth:
If the current semantic inputs are a strict superset of the old inputs, it can be clearly identified as semantic-input-expansion, rather than broadly categorized as ordinary stale.
Fifth:
The old units must all be exact preserved; when there are deletions, modifications, or ambiguous mappings, it cannot masquerade as a pure expansion.
Sixth:
The old Generation is retained as a historical fact, but being historically valid does not mean it is still sufficient to prove completeness today.
Seventh:
The reopen receipt is only responsible for proving the authority to re-enter the workflow; it is not responsible for generating translations, nor does it grant closure, Surface, activation, or Production permissions.
Eighth:
structured recovery can only recover real work that has already been completed for complete and correct inputs; it cannot be used to patch truly newly added semantic inputs.
Ninth:
Internal semantic slots are used for proof and reconstruction, and are therefore not upgraded into new formal TranslationUnits.
Ultimately, I think the most memorable sentence from this time is:
To determine whether a translation can still be reused, you cannot just ask “has the source file changed”; you must also ask “is the task required of the model today the same task as the original one”.
And this seemingly small case of PDF and GitHub exactly proves that:
Even if the final text has not changed by a single character, as long as it previously did not enter the formal language workflow and has formally entered today, then the workflow semantics itself has already changed.

