The preceding workflow is already quite long.
From Generation, a piece of content goes through machine validation, independent review, revision, re-review, final confirmation, and package closure, and then enters the Integrated Surface review.
If all of these pass, it is easy to intuitively assume:
Since the content and the integrated site have both passed review, can’t we just activate it directly next?
I initially tended to think this way too.
But after actually implementing Activation, I realized a very important question was still missing:
Is the state seen when the review passed still the same state seen when actually preparing to write the activation state?
If we cannot prove this, then even if all previous reviews were correct, the final write could still overwrite changes someone else has legitimately made in the meantime.
Therefore, v2 ultimately did not design Activation as:
“Execute a single write after Surface PASS.”
Instead, it was split into:
First perform a read-only preflight to freeze the current prior state; when actually applying, verify that this prior state has still not changed.
This introduces three very key concepts:
activation-preflightprior_sha256- CAS
This article is specifically dedicated to organizing why they exist.
Surface PASS proves “review passed”, not “the state will never change again”
First, let’s separate the two stages.
The integrated site review primarily answers:
Is the content currently prepared for integration into the site correct within the full site context?
It focuses on:
- Links between pages;
- Local content overrides;
- structured content;
- glossary;
- carried content vs. fresh content;
- Semantics after integration;
- Whether conflicts appear between pages.
If it passes, it can prove:
The integrated site state formed by this set of inputs at the time of review is acceptable.
But it cannot prove:
That the activated authoritative state in the repository will never change again after the review ends.
For example:
10:00: Package A's Surface PASS
10:03: Another legitimate process activates Package B
10:05: Package A begins executing ActivationAt this point, the prior state Package A saw during the 10:00 review and the prior state when actually preparing to write at 10:05 might no longer be the same.
If Activation still directly writes based on the 10:00 assumption, it could overwrite the legitimate change from 10:03.
Therefore:
Surface PASS is a proof of language and integration quality, not a concurrent write lock.
What Activation actually modifies
There is another easily confused point here.
Activation does not mean:
Deploying the website directly to Production.
It is closer to:
Writing a content package that has completed its formal lifecycle into the current activated authoritative state.
That is, the workflow still contains:
Package Closure
→ Integrated Surface Review
→ Activation
→ Preview
→ ProductionActivation resolves:
Which set of proven content now officially belongs to the activated state.
Preview and Production continue to verify actual rendering, routing, browser behavior, and production release.
Therefore:
Activation is not the deployment endpoint, but the write point where the formal content state changes.
Precisely because it really does change the authoritative state, we must be more cautious here than with an ordinary read-only check.
Why we cannot just directly execute activation-apply
Assume the current activated state is:
Current state: S0Package A has completed:
Generation
→ validation
→ Independent QC
→ A-only finalization
→ package closure
→ Integrated Surface Review PASSNow we want to activate A.
The simplest design might be:
Read current state S0
→ Add Package A
→ Write as S1The problem is:
“Read S0” and “Write S1” do not happen in the same instant.
If another legitimate write occurs in between:
At read time: S0
Another process writes: S0 → SB
Current process still writes: S0 → SAThe final result might become:
SB is overwritten by SAAnd Package A itself might be completely fine.
Surface might also be completely fine.
The real problem is just:
The write used an outdated prior assumption.
So Activation cannot just ask:
“What am I preparing to write?”
It must also ask:
“Based on which current state am I preparing to write?”
This is the role of prior_sha256
v2’s Activation first executes:
activation-preflight
It is read-only.
The input is not a Surface receipt, nor a Surface scope, and certainly not a Reviewer Bundle.
Its formal input is:
package closure
From this closure, preflight automatically finds the currently bound Integrated Surface state and recalculates the current Activation plan.
One very important output is:
prior_sha256
You can understand this as:
The exact SHA-256 of “the current prior state I just checked”.
For example, conceptually:
package closure: Package A
current activated state: S0
prior_sha256: hash(S0)
planned result state: S1
result_sha256: hash(S1)At this point, preflight just tells the maintainer:
If the current state is still this
prior_sha256, then after applying this closure, the expected result should be thisresult_sha256.
It has not modified any formal state yet.
Why preflight must be read-only
This is very important.
If preflight itself modified state, then:
“Checking the current state” and “formally writing the state”
would be mixed together again.
After a failure, it would also be hard to answer:
Did it actually modify anything?
So v2 explicitly requires:
activation-preflightdoes not execute formal state changes.
It is responsible for:
- Reading the package closure;
- Finding the current Integrated Surface;
- Checking if the closure and Surface are still valid;
- Reading the current activation authority;
- Calculating the exact prior state;
- Calculating the expected result state;
- Determining if it is already in the target state.
Finally, it outputs a complete plan.
If this step fails, it should be able to explicitly state:
MUTATION=noneThat is:
A failed check should not leave half an Activation behind.
What problem does result_sha256 solve
prior_sha256 describes:
What should be seen before writing.
result_sha256 describes:
What should be obtained if this Activation completes correctly.
Thus, an Activation is no longer just:
“Ran a command.”
It can be expressed as:
Verified prior: prior_sha256
Planned result: result_sha256This turns Activation from:
A vague “switching action”
into:
A transition from one exact state to another exact state.
This way, subsequent checks can answer:
Is the current state actually the result produced by this plan?
Instead of just looking at:
“Whether a certain activation file exists.”
The real protection happens in activation-apply
After preflight completes, the maintainer gets the exact:
prior_sha256
When actually executing activation-apply, it’s not just passing the closure.
It must also simultaneously provide:
The exact
prior_sha256just obtained from preflight.
Conceptually, this is:
Input closure: Package A
Expected prior: prior_sha256=S0Then apply does not blindly trust the old preflight.
It re-reads the current state and performs another check.
If it is still:
current sha256 == prior_sha256It allows the write to proceed.
If not, it stops.
What exactly is CAS
The idea used here is essentially CAS.
CAS is generally called:
Compare-And-Swap
It can be simply understood as:
The replacement with a new value is only allowed if the current value still equals the value I previously saw.
Applied to Activation, this means:
If current == prior
→ Write result
If current != prior
→ Stop, do not writeThis is very similar to optimistic locking in databases.
Suppose you opened an article to edit it.
The version number when you read it was:
version = 20You edited for ten minutes.
During this time, someone else saved it once, and the version became:
version = 21If you just save directly, you might overwrite the other person’s recent edits.
A safer approach is:
Only if version still equals 20
→ Allow save
If it has become 21
→ Reject the old write, re-readActivation’s prior_sha256 plays a similar role.
Except here, what is being compared is not a simple integer, but:
The exact identity of the current authoritative state.
Why SHA is more reliable than “state names”
Suppose we only check:
Current package count = 3This is far from enough.
Two completely different states might both have 3 packages.
Even if the package names are the same, the bound closure, Surface, and identity inside might differ.
So Activation should not just compare:
- Counts;
- Filenames;
- Some loose status;
- A scope that “looks about right”.
Instead, it should bind:
The deterministic SHA-256 of the complete canonical state.
Thus, as long as the content actually participating in the authority changes, prior_sha256 should change.
Only then can it accurately detect:
Whether a concurrent state change occurred between preflight and apply.
A typical concurrency scenario
Assume the current activated state is:
S0Both Package A and Package B have completed their respective formal workflows.
The maintainer first does a preflight for A:
A preflight:
prior = S0
result = SAThen does a preflight for B:
B preflight:
prior = S0
result = SBIf A is applied first:
current S0 == A prior S0
→ A apply PASS
→ current becomes SANext, the old B apply is executed.
Without CAS, B might still write according to:
S0 → SBThis could overwrite the state A just activated.
But with CAS:
Current: SA
B old prior: S0
SA != S0So B must stop.
The correct way to handle this is:
Read current authority
→ Re-run preflight for B
→ Get new prior=SA
→ Recalculate new result
→ Then applyThis way, B will move forward based on the latest state where A already exists.
prior mismatch isn’t just “run it again”
This is an easy trap to fall into.
If activation-apply reports:
prior mismatch
What it actually means is:
The world you previously checked no longer exists.
The most dangerous reaction at this point is:
“It might just be an intermittent issue, I’ll run the original command again.”
Because the old command still carries the old prior_sha256.
The correct approach must be:
Stop
→ Read current authority
→ Re-run activation-preflight
→ Get new exact prior_sha256
→ Then decide whether to applyYou cannot:
Modify parameters to bypass CAS.
Nor can you:
Force a replay using the old prior.
Because a CAS failure itself is protecting a legitimate change that just happened.
Why apply needs to preflight again
Since we already have CAS, one might ask:
Isn’t it enough for apply to just compare
prior_sha256?
v2 still re-executes the preflight logic during apply.
The reason is:
Activation depends on more than just a prior file.
Between the first preflight and apply, other currentness factors might also change, for example:
- package closure is no longer current;
- Surface binding changes;
- authority order changes;
- dependencies change;
- current package state changes.
So apply cannot just do:
SHA matches → unconditional writeIt must reconfirm:
If we were to do a preflight again right now, would this plan still hold.
And then perform the prior/current CAS and concurrent change check.
Therefore:
The result of preflight is not a permanently valid write permit.
It is only an exact plan for the current moment.
Why already_active is not a failure
Activation also needs to handle another practical issue:
The command might be executed repeatedly.
For example, the first apply already succeeded.
But the terminal connection dropped, and the maintainer didn’t see the final PASS.
Later, preflight is executed again, and it finds:
The current active state is already the expected result.
At this point, it should not write again.
Nor should it report:
State conflict.
The formal result should be able to express:
already_active=trueWhich means:
The target state already exists, no further mutation is needed.
This is idempotency.
Idempotency and “repeated execution doesn’t matter” are not the same thing
Sometimes idempotency is understood as:
The same command can be executed as many times as you want.
The more accurate meaning is actually:
If the target state already exists correctly, executing it again will not create a second, different state change.
For example:
First time:
S0 → S1
Second time:
current is already S1
→ already_active=true
→ no repeated writeBut if current has already become:
S2Then you cannot say:
Since this command is idempotent, I’ll just run it again.
Because this is no longer the same prior state.
Therefore:
Idempotency cannot replace currentness.
Activation order also cannot be guessed by package name
When multiple packages are preparing for Activation, another problem arises:
Which one should be activated first?
The simplest manual method might be:
“Tour is older than Learn/Docs, so Tour first.”
Or:
“Sort by filename.”
None of these are reliable.
The formal order should come from:
The current sparse authority / package workflow authority.
That is:
The system explicitly declares which package is the next legitimate Activation target.
This is especially important because, in a transition state, some old coverage commands might become stale-sensitive because the current state has not fully switched yet.
So, to find the order, you cannot use a coverage result that itself depends on “all activations complete” to infer backwards.
The principle should be:
Activation order comes from the current authority, not from human intuition.
Why transition states are particularly dangerous
Assume a locale is currently in:
Package A: active
Package B: closure completed, pending activation
Package C: not yet completedAt this point it is neither:
The complete old state.
Nor:
The complete new state.
Many checks that are only suitable for stable states might return:
staleIf this stale-sensitive coverage is incorrectly used to decide:
Who should be activated next
It could create a loop:
coverage waits for activation
activation uses coverage to determine orderSo v2 makes the order authority explicit and separate.
This is also something I have increasingly valued later on:
Problems in different stages should read the authority belonging to that stage.
Do not use a checker for the “final completed state” to infer intermediate transition states.
Why a Surface receipt cannot be directly used as activation input
Another mistake that is easy to make is:
Surface has already PASSed, so
activation-preflight --inputshould just directly take the Surface receipt, right?
Actually, no.
The formal input is:
package closure.
The reason is that package closure is the formal lifecycle input for this content package to enter Activation.
Integrated Surface Review is a subsequent gate it needs to satisfy.
So Activation will:
Start from package closure
→ Automatically bind the current legitimate Integrated Surface
→ Then calculate the activation planInstead of having the maintainer manually piece together:
- closure;
- Surface receipt;
- scope;
- Reviewer Bundle;
This can reduce issues like:
Taking the wrong receipt, taking an old scope, manually binding the wrong Surface
and so on.
Why we still cannot immediately go to Production after Surface PASS
This is another boundary brought by the Activation design.
The complete path is:
package closure
→ Integrated Surface Review PASS
→ Activation
→ Preview
→ ProductionSurface primarily proves:
The combined content semantics and link relationships are acceptable.
Activation proves:
The current formal activated authority has safely transitioned to the new content state.
Preview then proves:
After this activated state actually passes through the renderer, routes, browser, and machine verification, the running result is also correct.
Only then does it enter Production.
Therefore:
Surface PASS ≠ activated.
Similarly:
Activation PASS ≠ Production ready.
Each gate proves different things.
Why mutation=unknown must immediately stop
Activation is a formal state change.
So the most dangerous thing is not:
An explicit failure.
But rather:
Not knowing whether the write actually succeeded.
For example:
Process interrupted
Disk error
Abnormal return
Write result cannot be confirmedIf at this point the system can only determine:
mutation=unknownIt cannot just be directly re-executed.
Because the actual state might be:
Case A: Actually nothing was written at all
Case B: The write succeeded, but the result was not returned
Case C: Partially written, state is abnormalIf you don’t know which one it is, blindly replaying could cause secondary damage.
So the principle here is:
Stop and diagnose first when mutation=unknown.
Only after re-proving the current authority can the recovery method be decided.
Explicit failures and unknown failures must be treated differently
For example, if preflight fails:
preflight FAILED
MUTATION=noneThis is relatively simple.
Because we can clearly know:
The formal state has not changed.
Just fix the issue and re-run preflight.
But if the following occurs during the apply phase:
mutation=unknownThe handling strategy is completely different.
At this point, the first thing to answer is:
What exactly is the current authority?
Not:
Why did the command exit non-zero?
In a formal state machine, the latter is just a technical error.
The former determines whether it is safe to recover.
This is the true meaning of fail-closed in Activation
The project frequently uses:
fail-closed
It used to be easy to understand this as:
Exit on error.
In fact, in a mutation phase like Activation, it is more specific:
As long as it cannot be proven that continuing to write is safe, do not write.
This includes:
- prior mismatch;
- insufficient currentness;
- uncertain Surface binding;
- uncertain authority order;
- concurrent mutation;
- mutation state cannot be confirmed.
All must stop.
The purpose is not to make the workflow seem stricter.
Rather, it is to avoid:
An otherwise completely legitimate old operation destroying a newer legitimate state because it was executed too late.
CAS does not protect “the current task”, but the work someone else just completed
I feel this point is particularly worth writing out.
When seeing a CAS failure, the first reaction is easily:
It blocked me.
But from another angle:
It might have just protected another Activation that has already successfully completed.
For example:
My prior: S0
Current state: S1CAS does not know who wrote S1.
It only knows:
The current world is no longer the world I originally checked.
So it refuses to overwrite it using an old assumption.
This is actually a very important engineering principle:
When unsure whether a new change is legitimate, you also cannot overwrite an updated state just because your own task was once legitimate.
Why “last write wins” cannot be used
There is another very simple concurrency strategy:
Whoever writes last takes effect.
Many ordinary configuration systems do indeed do this.
But it is not suitable for a translation lifecycle.
Because here, behind every activated state is bound:
- Generation;
- machine validation;
- Independent QC;
- A-only finalization;
- package closure;
- Integrated Surface Review.
If the last writer can unconditionally overwrite the previous legitimate state, it is equivalent to:
An old plan executed later can erase a new plan executed earlier.
This would destroy the entire chain of evidence.
So Activation is more suited for:
optimistic concurrency control
Which means:
Most of the time it does not hold a long-term lock, but when actually committing, it must confirm that the prior has not changed.
Why not use a very long global lock
Since concurrency is a concern, one might also think of:
Acquiring a lock at the start of preflight and holding it until apply ends.
Theoretically possible.
But in an actual workflow, the time between preflight and apply might include:
- Manual inspection;
- Terminal operations;
- handoff;
- Sequential processing of multiple packages.
Holding a global lock for a long time would bring:
- Blocking;
- Deadlock recovery;
- Interrupt cleanup;
- Uncertain lock states;
- More complex operations.
The advantage of CAS is:
It does not need to assume the world stands still during the entire check.
It allows others to proceed normally.
It just confirms at its own actual commit time:
“Is the prior I saw earlier still there?”
If not, it recalculates.
This better fits this current incremental workflow.
Activation is actually a very small transaction
Later on, I increasingly felt that Activation can be viewed as a small transaction.
Its logic is roughly:
Step 1: Read and validate closure
Step 2: Bind current Surface
Step 3: Read current activation authority
Step 4: Calculate prior_sha256
Step 5: Calculate result_sha256
Step 6: preflight returns, read-only ends
When actually applying:
Re-execute current checks
Verify current == prior_sha256
Confirm no concurrent mutation
Atomically commit new activation state
Verify resultWhat is most important here is not how many commands there are.
Rather, it is ensuring:
From a proven old state, it can only transition to a proven new state.
Activation principles I now endorse more
Having reached this point, I think Activation can be condensed into a few clearer principles.
First:
Surface PASS proves integration quality, not concurrency safety at the time of future writes.
Second:
activation-preflightmust be read-only, and explicitly stateMUTATION=noneon failure.
Third:
The formal input to Activation is package closure, and the system automatically binds the current Integrated Surface.
Fourth:
preflight must return the exact
prior_sha256andresult_sha256, giving the state transition a clear prior and result identity.
Fifth:
activation-applymust use the same closure and the exactprior_sha256obtained from a fresh preflight.
Sixth:
apply must re-verify currentness, and cannot treat an old preflight as a permanent permit.
Seventh:
prior mismatch or concurrent mutation is not a retry of the old command, but a re-read of authority and a fresh preflight.
Eighth:
already_active=trueis a normal idempotent result, and no further mutation should occur.
Ninth:
Activation order comes from the current authority, and cannot be guessed based on package names, historical experience, or stale-sensitive coverage.
Tenth:
mutation=unknownmust stop for diagnosis, and cannot blindly replay.
Ultimately, I think the most memorable sentence is:
Just because an operation was once legitimate does not mean it can still be safely written now.
What prior_sha256 and CAS truly protect is:
Whether the world has changed between “I just checked this state” and “I am now actually going to modify this state”.

