22e1c95e6a
gates / gates (push) Failing after 17s
R-410. golden_currency_gate.py matched EVIDENCE_RE against os.listdir and read nothing inside, so `mkdir documentation/tests/golden-9.9.9-2026-01-01` turned it green with no bake behind it - noticed while the 0.230.0 bake was running, when the evidence directory existed before the bake finished. It now reads the GOLDEN_SHA256= line out of that directory's bake log: a directory name is a label, that line is a fact only a completed publish produces. Still offline, still --fast, one file read. Directories that look right and hold nothing are printed by name rather than silently ignored, so a half-finished bake is visible. test_golden_currency_gate.py ships the red-proof with a POSITIVE CONTROL, without which "it fails on an empty directory" would be satisfied by a gate that fails on everything: CASE 1 empty directory -> rejected and named CASE 2 log with no GOLDEN_SHA256 -> rejected CASE 3 real bake log -> counted, and its sha read <- the control CASE 4 the tree is left byte-identical Red-proofed: reverting the gate to name-matching fails cases 1, 2 and 3. R-406. Citations MEASURED before choosing, which is what the row asked for: hub-uniqueness had 3 references (all inside one audit doc), plaintext-break-glass had 5 (CONTEXT.md, break-glass.md, hub/CHANGELOG.md, the capability map, a spike). The FEWER-cited one moved - hub uniqueness is now R-415 - and all three citations were rewritten to "R-415 (was R-133)" rather than silently swapped. THIS IS THE OPPOSITE OF THE TASK'S LITERAL INSTRUCTION, which said renumber the second row on the stated ground that "the older number has the longer reference trail". Measured, that ground points the other way. The principle was followed and the letter was not, and the row says so rather than leaving an unexplained diff. R-416 filed: the within-register duplicate rule was deliberately NOT added in the same commit that removed its only subject - a guard whose red-proof can only be a planted fixture is not this project's standard. Now that the register is clean it can ship with the next real duplicate as its first subject.
73 lines
3.6 KiB
Markdown
73 lines
3.6 KiB
Markdown
# Part 2.1 — was the scratch resolver missed, or excluded on purpose?
|
|
|
|
**ANSWER: neither label fits exactly. It was consciously OUT OF SCOPE for R-356, and it was never
|
|
ruled out on the state-only grounds. The rule in §6.3 already covers it. → BRANCH (a).**
|
|
|
|
## The evidence, in the order it settles the question
|
|
|
|
### 1. R-356 itself says the scratch resolver was left alone — and says why
|
|
|
|
From R-356's own commit (`08eb1a6`, 2026-08-22), in its test file, twice:
|
|
|
|
> *"the prepared scratch **still resolves** to the registered storage path (`offboxRestoreScratchDir`
|
|
> step 2), so the srcs the fixture laid down are still where the code looks for them; **only the
|
|
> DESTINATION moves**, which is precisely what this change is about."*
|
|
|
|
> *"The scratch was laid out against the drive namespace, which is where `offboxRestoreScratchDir`
|
|
> **still resolves** (the drive stays a registered storage path). Only the DESTINATION moves."*
|
|
|
|
R-356 was about **where restored data LANDS**. It changed `PlaceOffsiteRestore` and
|
|
`ReconstituteFromOffsite`. It did not consider the scratch resolver a subject — and it assumed, in
|
|
every fixture, that **step 2 succeeds because a registered storage path exists**.
|
|
|
|
**`demo-felhom` is the case R-356 never had: zero registered storage paths.**
|
|
|
|
### 2. The one comment about a `systemDataPath` fallback was about a DIFFERENT function, and R-356 OVERRULED it
|
|
|
|
R-356's diff **deleted** this line from `PlaceOffsiteRestore`:
|
|
|
|
> *"NOT AppNamespaceRoot — its systemDataPath fallback would merge **userdata** onto the SSD system
|
|
> namespace."*
|
|
|
|
That concern was about placing the customer's **bulk userdata** on the SSD, and R-356 decided against
|
|
it deliberately. It was never a statement about a **scratch**.
|
|
|
|
### 3. The scratch resolver's own comment forbids a different path
|
|
|
|
> *"NEVER `cfg.Paths.DataDir` (the rootfs — the F-A1 filler)."*
|
|
|
|
`cfg.Paths.DataDir` is the controller's data dir on the **rootfs**. `cfg.Paths.SystemDataPath`
|
|
(`/mnt/sys_drive`) is a different filesystem. **The documented exclusion is the rootfs, not the system
|
|
data path.**
|
|
|
|
### 4. And the decisive one: a driveless app's unit ALREADY lives there, permanently, by design
|
|
|
|
`07-backup-architecture.md` §7, **[FACT]**:
|
|
|
|
> *"`GetAppDrivePath` returns the app's `HDD_PATH` if it has one and **`systemDataPath` otherwise** —
|
|
> what `appbackup/paths.go:26-27` calls the SSD-only system-data fallback. Nothing deletes a unit
|
|
> after it is copied onward … so for every app without a data drive, `mp1` holds the kept copy
|
|
> indefinitely."*
|
|
|
|
and:
|
|
|
|
> *"the same-device placement is **intended, not a defect**."*
|
|
|
|
**So a unit-only scratch on the system data path is at most a second copy of a unit that already sits
|
|
there permanently and by design.** Nothing anywhere states a restore scratch must not land there.
|
|
|
|
## Therefore
|
|
|
|
**Branch (a)** — apply the rule that already exists, **scoped by what is being restored**, which is
|
|
the distinction the register row did not carry and §2.2's state-only concern genuinely requires:
|
|
|
|
| restore | scratch fallback | why |
|
|
|---|---|---|
|
|
| **unit-only** (the nightly proof, and the customer's default) | **may fall back to the system data path** | the unit already lives there permanently (§7); the scratch is bounded by the unit's own size |
|
|
| **full** (bulk userdata) | **keeps today's behaviour and refuses** | this is the case the deleted `PlaceOffsiteRestore` comment worried about, and the SSD is a state-only tier |
|
|
|
|
**One resolver answering two questions is the R-356 defect itself.** Splitting it by restore scope is
|
|
the same separation R-356 made between *"installed?"* and *"where?"*.
|
|
|
|
§6.3's *"one expression"* sentence gains a **fourth** consumer and becomes true.
|