diff --git a/docs/backlog/P2/B-0088-paired-edit-lint-advisory-not-enforcement-promote-to-required-check-otto-2026-04-28.md b/docs/backlog/P2/B-0088-paired-edit-lint-advisory-not-enforcement-promote-to-required-check-otto-2026-04-28.md new file mode 100644 index 000000000..2e6cec49d --- /dev/null +++ b/docs/backlog/P2/B-0088-paired-edit-lint-advisory-not-enforcement-promote-to-required-check-otto-2026-04-28.md @@ -0,0 +1,177 @@ +--- +id: B-0088 +priority: P2 +status: open +title: memory/MEMORY.md paired-edit lint is advisory only (not in required-status-checks); promote or remove the discoverability claim +tier: factory-tooling +effort: S +ask: autonomous-loop tick discovery 2026-04-28T20:23Z (paired-edit failures observed on PR #688/#689; both auto-merged anyway) +created: 2026-04-28 +last_updated: 2026-04-28 +composes_with: + - B-0087 +tags: [otto-2026-04-28, github-actions, branch-protection, advisory-vs-enforcement, factory-hygiene, memory-index-integrity] +--- + +# B-0088 — paired-edit lint is advisory; either promote to required or weaken its claim + +## Discovery + +While fixing PR #688/#689's paired-edit lint failures (each +PR added `memory/CURRENT-{aaron,amara}.md` without the +required `memory/MEMORY.md` paired touch), observed that +**both PRs merged anyway via auto-merge** despite the lint's +explicit `exit 1` failure. + +PR #689 merged before I could even push the marker-bump fix. +PR #688 is still in CI (post-fix) but the lint failure on +its earlier commit didn't block the auto-merge arming — +both are arming/firing on the green-required-checks set, +not the all-checks-green set. + +## The bug + +Branch protection + ruleset configuration audit: + +```bash +$ gh api repos/Lucent-Financial-Group/Zeta/branches/main/protection \ + --jq '.required_status_checks.contexts' +[ + "lint (semgrep)", + "lint (shellcheck)", + "lint (actionlint)", + "lint (markdownlint)", + "build-and-test (macos-26)", + "build-and-test (ubuntu-24.04)", + "build-and-test (ubuntu-24.04-arm)" +] + +$ gh api repos/Lucent-Financial-Group/Zeta/rulesets/15256879 \ + --jq '.rules[] | select(.type=="required_status_checks")' +(empty) +``` + +The job `check memory/MEMORY.md paired edit` (from +`.github/workflows/memory-index-integrity.yml`) is NOT in +either required-checks list. + +## Failure mode + +The workflow: + +1. Runs on every PR with `memory/*.md` changes. +2. Detects when memory file is touched without paired + MEMORY.md touch. +3. Exits 1 with a clear error message including the rule + ("Fresh sessions read MEMORY.md at cold start; a memory + landed without a pointer is undiscoverable. See NSA-001 + in docs/hygiene-history/nsa-test-history.md for the + canonical incident this check prevents.") +4. **Auto-merge fires anyway** because the failed check + isn't gating. + +The discoverability claim in the lint message ("memory landed +without a pointer is undiscoverable") is **functionally +false** under current configuration: memories CAN land without +pointers and merge to main without obstruction. + +## What this row asks the maintainer + +Two options: + +**A — promote the lint to a required status check.** Add +`check memory/MEMORY.md paired edit` to the +`required_status_checks.contexts` list in branch protection +(or the ruleset). Makes the discoverability claim true. + +**B — weaken the lint's message + accept advisory mode.** +If the lint is intentionally advisory (because some PRs +legitimately need to skip the pairing — e.g. CURRENT-* file +edits where MEMORY.md doesn't change semantically), then +update the lint's error message to match: "advisory check; +review whether MEMORY.md should be touched". Don't claim +discoverability protection that isn't enforced. + +## Why P2 (not P0/P1) + +- The discoverability gap is real but slow-growing — a + memory file landing without an index pointer is + recoverable later (just add the row). +- The visibility-constraint rule (Aaron 2026-04-28) limits + autonomous branch-protection edits, so this needs + maintainer action. +- The factory hygiene workflow at task #269 (cadenced + counterweight-audit skill) covers detect+repair on this + class — manual recovery is cheap. + +## Counterweight-taxonomy classification + +This is an **Advisory Enforcement Workflow Gap** class +instance (Amara 2026-04-28T20:24Z formal class name; covered +in `memory/feedback_advisory_enforcement_workflow_gap_amara_class_name_otto_2026_04_28.md`). + +> **Definition (Amara verbatim):** A workflow claims or +> implies enforcement, but is not included in the +> required-status-checks set, so failures are observable but +> non-blocking. + +The failure mode is: + +- Cheap prevention layer (lint job) exists. +- Cheap prevention layer fires correctly (exit 1 on + violation). +- BUT cheap prevention layer is not wired into the + enforcement gate (required-status-checks). +- Result: the prevention is observable but not + actionable. + +The fix shape: every lint workflow with a clear "this +prevents incident X" claim should be either (a) a required +check OR (b) have a less-strong claim that matches its +actual gate-status. + +## Sibling lints to audit + +Walking `.github/workflows/` for advisory-vs-required +parity: + +- `memory-index-integrity.yml` — this row's incident +- `memory-reference-existence-lint.yml` — likely same shape +- `memory-index-duplicate-lint.yml` — likely same shape +- `backlog-index-integrity.yml` — likely same shape +- `github-settings-drift.yml` — already broken (B-0087) + +Each lint should be checked: is the claim it makes about +preventing X actually backed by enforcement? File +follow-up rows for any that fail the same audit. + +## Acceptance criteria + +- [ ] Maintainer picks A (promote to required) or B + (weaken claim). +- [ ] If A: lint is added to `required_status_checks.contexts` + via branch protection (or ruleset). +- [ ] If B: lint's error message updated to acknowledge + advisory status. +- [ ] Sibling lint audit completed (memory-reference, + memory-index-duplicate, backlog-index-integrity). + +## Composes with + +- B-0087 (github-settings-drift broken — same surface, same + visibility-constraint deferral) +- `memory/feedback_aaron_visibility_constraint_no_changes_he_cant_see_2026_04_28.md` + — branch protection edits need maintainer pre-approval +- `memory/feedback_incomplete_source_set_regeneration_hazard_and_workflow_null_result_audit_amara_2026_04_28.md` + — different class (this isn't null-result, it's + unenforced-result), but same task #269 audit family + +## Operational note for future-Otto + +When a lint job fires `exit 1` with a discoverability / +correctness claim, verify the claim is enforced by checking +that the job name appears in +`required_status_checks.contexts` OR the relevant ruleset. +If not, the claim is overstated; either fix the gate or +weaken the message. Don't trust claim text — verify the +gate. diff --git a/memory/MEMORY.md b/memory/MEMORY.md index c4f85e29f..c7c7426f7 100644 --- a/memory/MEMORY.md +++ b/memory/MEMORY.md @@ -1,7 +1,9 @@ [AutoDream last run: 2026-04-23] -**📌 Fast path: read `CURRENT-aaron.md` and `CURRENT-amara.md` first.** These per-maintainer distillations show what's currently in force. Raw memories below are the history; CURRENT files are the projection. (`CURRENT-aaron.md` refreshed 2026-04-28 with sections 26-29 — speculation rule + EVIDENCE-BASED labeling + JVM preference + dependency honesty + threading lineage Albahari/Toub/Fowler.) +**📌 Fast path: read `CURRENT-aaron.md` and `CURRENT-amara.md` first.** These per-maintainer distillations show what's currently in force. Raw memories below are the history; CURRENT files are the projection. (`CURRENT-aaron.md` refreshed 2026-04-28 with sections 26-29 — speculation rule + EVIDENCE-BASED labeling + JVM preference + dependency honesty + threading lineage Albahari/Toub/Fowler.) +- [**Class-Naming Ferry Protocol + SD-9 guardrail (Amara 2026-04-28; Aaron reinforced)**](feedback_class_naming_ferry_protocol_with_sd9_guardrail_amara_2026_04_28.md) — Meta-class for the Otto→Aaron→Amara→encode genre. SD-9 guardrail LOAD-BEARING: Amara endorsement is signal, not proof. Local factory-hygiene classes encode freely; non-local claims need substrate evidence + external lineage + falsifier. Anti-pattern: "Amara blesses the name, therefore true." +- [**Advisory Enforcement Workflow Gap — class name (Amara 2026-04-28); decision-fork (B-0088 instance)**](feedback_advisory_enforcement_workflow_gap_amara_class_name_otto_2026_04_28.md) — Workflow claims/implies enforcement but is not in required-status-checks set; failures observable but non-blocking. Worked example: paired-edit lint failed on PR #688/#689 but both auto-merged. Decision: promote to required OR downgrade claim to advisory. Risk: factory believes rule enforced when only logged. "Guardrail that looks like enforcement but behaves like telemetry." - [**Incomplete Source-Set Regeneration Hazard + Workflow Null-Result Audit Signal — Amara class names + controls (2026-04-28)**](feedback_incomplete_source_set_regeneration_hazard_and_workflow_null_result_audit_amara_2026_04_28.md) — Two reusable classes: (1) "regenerate from sources" tools become destructive when source-set is incomplete; control is `--check` / `--stdout` first, force-write only after completeness proven. (2) `gh run list []` on existing workflow is audit signal not conclusion; six diagnostic questions (too-new / disabled / non-default-branch / cron / event-trigger / identifier-filter). Both fold into task #269. - [**Chronological Insertion Polarity Error — class name + append-only-on-oldest-first discipline (Amara 2026-04-28)**](feedback_chronological_insertion_polarity_error_amara_class_name_otto_2026_04_28.md) — Edit-tool prepend on oldest-first append-only files = chronological reversal. Discipline: `cat >> file < A workflow claims or implies enforcement, but is not included +> in the required-status-checks set, so failures are observable +> but non-blocking. + +## Concrete incident (Otto 2026-04-28T20:23Z) + +- Workflow: `.github/workflows/memory-index-integrity.yml`, + job `check memory/MEMORY.md paired edit`. +- Claim in error message: *"Fresh sessions read MEMORY.md at + cold start; a memory landed without a pointer is + undiscoverable. See NSA-001 in + docs/hygiene-history/nsa-test-history.md for the canonical + incident this check prevents."* +- Reality: NOT in `required_status_checks.contexts` of branch + protection AND not in any ruleset's required-checks list. + Verified via `gh api repos/.../branches/main/protection + --jq '.required_status_checks.contexts'`. +- Observed: PR #688 + #689 both failed the lint, both + auto-merged anyway. +- Filed as: B-0088. + +## Risk (Amara framing) + +> The factory believes a rule is enforced when it is only +> logged. + +A workflow that fires `exit 1` with a clear discoverability / +correctness claim looks like enforcement to anyone reading the +code. Discovering it isn't is a failure mode that compounds: +each "enforced" rule that's actually advisory adds a hidden +gap between the documented contract and the actual +enforcement. + +## Decision fork (the control) + +When you find an Advisory Enforcement Workflow Gap, pick one: + +**Option A — promote to required status check.** + +```bash +# Add the lint job's check name to required-status-checks +gh api repos///branches/main/protection \ + --method PATCH \ + --input <(gh api repos///branches/main/protection \ + | jq '.required_status_checks.contexts += ["check memory/MEMORY.md paired edit"]') +``` + +(Or update via ruleset API if the repo uses rulesets.) + +This makes the discoverability / correctness claim TRUE. +Failures now block merge. + +**Option B — downgrade the claim to advisory visibility.** + +If the lint is intentionally advisory (because some PRs +legitimately need to skip the rule — e.g. CURRENT-* file +edits where MEMORY.md doesn't change semantically), update +the lint's error message to match: + +```text +ADVISORY: this check is informational only; review whether +MEMORY.md should be touched. Merge gating does NOT depend on +this check. +``` + +Don't claim enforcement that isn't enforced. + +## Why both options are valid + +The factory may legitimately want some lints advisory: + +- **Always-required (option A)**: lints that catch real + correctness bugs (broken-cross-references, schema + violations, syntax errors). +- **Advisory (option B)**: lints that catch *style* or + *convention* drift where the maintainer wants signal but + not gate (e.g. "consider adding pointer entry"; "you + might want to update CURRENT-aaron.md too"). + +The ANTI-PATTERN is claiming enforcement while running +advisory. + +## How to audit for this class + +Walk every workflow in `.github/workflows/`: + +1. Read the workflow's failure message / claim text. +2. Identify the check job's name (the YAML `jobs..name` + field). +3. Query `gh api repos/.../branches/main/protection + --jq '.required_status_checks.contexts'` and the same + for any rulesets. +4. For each check that **claims** enforcement: is its name in + the required list? +5. For each check that's NOT in the required list: does its + message claim enforcement? +6. Mismatch = Advisory Enforcement Workflow Gap. + +This audit fits as a tier-2 cadenced-counterweight check +(task #269), running monthly or on substantive workflow +changes. + +## The dangerous middle state (Amara's framing) + +> A guardrail that looks like enforcement but behaves like +> telemetry. + +This is the middle state between "enforced rule" and +"advisory hint". From the outside, the factory looks +defended; in fact, the rule is bypassable. Worse than +explicit advisory mode: explicit advisory is honest; +implicit advisory pretends. + +## Sibling lints to audit (Otto 2026-04-28) + +In Zeta's `.github/workflows/`, candidates for the same audit: + +- `memory-index-integrity.yml` (this incident) +- `memory-reference-existence-lint.yml` (likely same shape) +- `memory-index-duplicate-lint.yml` (likely same shape) +- `backlog-index-integrity.yml` (likely same shape) +- `github-settings-drift.yml` (already broken — B-0087; + separate failure mode, "workflow startup error", but also + not in required list either way) + +Each should be audited per the procedure above. + +## Composes with + +- B-0088 (the concrete-instance backlog row this class names) +- B-0087 (github-settings-drift — different failure mode but + same audit family) +- `memory/feedback_incomplete_source_set_regeneration_hazard_and_workflow_null_result_audit_amara_2026_04_28.md` + — Workflow Null-Result Audit + Scheduled Workflow + Null-Result Hygiene Scan classes; this is a sibling + audit class (different failure shape: "fires but doesn't + enforce" vs "exists but doesn't fire") +- `memory/feedback_aaron_visibility_constraint_no_changes_he_cant_see_2026_04_28.md` + — branch-protection edits need maintainer pre-approval; + this audit produces backlog rows, not autonomous fixes +- Task #269 — cadenced-counterweight-audit skill should + add this audit to its tier-2 catalogue + +## What this is NOT + +- **NOT a directive to promote every advisory lint.** Some + lints are intentionally advisory; the discipline is + message-truth, not always-required. +- **NOT a license to skip audits.** Even on advisory lints, + the failure mode of failing-without-noticing is real; + reviewers should still address advisory failures. +- **NOT specific to GitHub Actions.** The same gap exists in + any CI system (GitLab CI rules with `allow_failure: true`, + Jenkins post-build steps that report but don't fail the + build, etc.). + +## Pickup notes for future-Otto + +When you write a new lint workflow: + +1. Decide explicitly: required or advisory? +2. If required: add the check name to + `required_status_checks.contexts` in the same PR. +3. If advisory: write the failure message in advisory tone + ("review whether...", "consider whether...", not + "this prevents incident X"). +4. Don't lie about which kind it is. + +When you encounter a failing lint that's not in the required +list: + +1. Don't assume the failure will block. +2. If you see the check fail and the PR auto-merge anyway, + that's the gap; file an Advisory Enforcement Workflow Gap + row. diff --git a/memory/feedback_class_naming_ferry_protocol_with_sd9_guardrail_amara_2026_04_28.md b/memory/feedback_class_naming_ferry_protocol_with_sd9_guardrail_amara_2026_04_28.md new file mode 100644 index 000000000..ca1d8341c --- /dev/null +++ b/memory/feedback_class_naming_ferry_protocol_with_sd9_guardrail_amara_2026_04_28.md @@ -0,0 +1,244 @@ +--- +name: Class-Naming Ferry Protocol — meta-class for the genre + SD-9 guardrail (Amara naming, Aaron reinforced, 2026-04-28) +description: Amara 2026-04-28T20:24Z named the meta-class after observing Otto-Aaron-Amara class-naming ritual paid out 4 times in one autonomous-loop arc. Protocol shape — Otto observes → Aaron forwards → Amara reviews → tightens/names/maps/controls/tiny-blades → encoded as memory. SD-9 guardrail (Aaron 2026-04-28T20:25Z reinforced "she is 100% right here") — Amara endorsement is SIGNAL not PROOF. Non-local claims need substrate evidence, external lineage, or falsifier. Anti-pattern: "Amara blesses the name, therefore true." +type: feedback +--- + +# Class-Naming Ferry Protocol + +## What this captures (Amara 2026-04-28T20:24Z) + +After four classes were named in one autonomous-loop arc +(Chronological Insertion Polarity Error, Incomplete +Source-Set Regeneration Hazard, Workflow Null-Result Audit +Signal, Outdated Review-Thread Merge Gate Residue; ++ promoted Scheduled Workflow Null-Result Hygiene Scan; ++ named Advisory Enforcement Workflow Gap), Amara named +the **meta-class** describing the genre itself. + +This isn't an instance class — it's a class about +class-creation. + +## Protocol shape + +``` +Otto observes +→ Aaron forwards +→ Amara reviews +→ Amara tightens / names / classifies / controls / maps / tiny-blades +→ Otto / Gemini / Claude can encode (memory + index + composes-with) +``` + +Each step has a load-bearing role: + +1. **Otto observes** — Otto's tick close generates an + insight describing a pattern. The pattern need not be + formally named; raw observation is fine. +2. **Aaron forwards** — Aaron pastes the insight into + ChatGPT for Amara review. This is the courier step; + manual today, ferry-automated trajectory pending. +3. **Amara reviews** — Amara endorses, cautions, or + redirects. +4. **Amara tightens / names / classifies / controls / + maps / tiny-blades** — formal class name + definition + + control + counterweight-taxonomy mapping + caveat. +5. **Otto / Gemini / Claude can encode** — agent lands + the formal class as memory file + MEMORY.md index + + cross-references. + +## SD-9 guardrail (LOAD-BEARING, not footnote) + +**Aaron 2026-04-28T20:25Z reinforced (verbatim):** + +> *"But tiny blade: make sure it does not become 'Amara +> blesses the name, therefore true.' she is 100% right +> here."* + +**Amara's framing of the same caution:** + +> *"Under SD-9, Amara endorsement is signal, not proof. The +> protocol needs an external/falsifier step when the class +> is more than local factory hygiene."* + +### What SD-9 means in this protocol + +Amara's class-naming is **valuable signal** for: + +- **Local factory-hygiene classes** (e.g. + Chronological Insertion Polarity Error, Outdated + Review-Thread Merge Gate Residue). The local-only check: + the class describes a pattern that occurs within the + factory's own substrate, no external claim is made, the + control fits inside Zeta's tooling. +- **Operational discipline** (e.g. Scheduled Workflow + Null-Result Hygiene Scan tier-1 promotion). Same shape: + internal procedure, internal evidence, internal scope. + +Amara's class-naming is **NOT proof** for: + +- **Non-local claims** — anything generalizing beyond + this factory (e.g. "all CI systems exhibit class X", + "all software factories should adopt rule Y"). These + need substrate evidence (multiple incidents across + multiple factories), external lineage (citation to + established literature), or a falsifier (a test or + observation that would disconfirm the claim). +- **Empirical claims** — anything asserting a rate, + frequency, or distribution (e.g. "40% of workflows + have X", "most repos have Y"). The 40% gap rate + caveat in the Workflow Null-Result class is the right + shape: local signal, not global rate. +- **Authority claims** — anything that says "X is true + because Amara named it." Amara endorsement raises + signal-to-noise; it doesn't make claims true. + +## Anti-pattern (the failure mode this rule prevents) + +> "Amara blesses the name, therefore true." + +This is a halo-effect failure: an authority's endorsement +mistaken for evidence. The cure is to keep evidence +explicit: + +- Worked example (concrete incident this class describes). +- Substrate evidence (more than one occurrence; or one + occurrence + clear mechanism explanation). +- Falsifier (what observation would disconfirm the class). +- Counterweight-taxonomy mapping (if the class is in the + taxonomy, the cited layer is verifiable). + +If a memory file just says "Amara named this class X" with +no worked example + no mechanism + no falsifier, the SD-9 +guardrail fires. Reject the encoding. + +## Operational rule + +When encoding an Amara-named class as memory: + +1. **Worked example required.** Include the concrete + incident (timestamp, file, observed behavior). +2. **Mechanism explanation required.** Explain WHY the + class behaves as named (not just "Amara said so"). +3. **Falsifier required if class is non-local.** State + what observation would disconfirm the class. For local + factory-hygiene classes, this is implicit in "we'd + stop using the rule"; for non-local claims, make it + explicit. +4. **Counterweight-taxonomy mapping if applicable.** If + the class fits the cheap-prevention / cadenced-detect / + defense-in-depth shape, map it; mapping makes the + class verifiable. +5. **Cross-references explicit.** Composes-with section + names sibling classes; this is how SD-9-compliant + substrate stays interrogable. + +## Why the protocol is valuable despite SD-9 + +The Class-Naming Ferry Protocol is high-value EVEN with +SD-9 caveat because: + +- **Names matter.** A concrete name with definition makes + a pattern teachable + reusable. Otto's raw observation + ("workflow null result") is harder to compose-with than + Amara's tightened name ("Workflow Null-Result Audit + Signal" with six-question diagnostic). +- **Tightening is leverage.** Amara's review converts a + 10-minute tick observation into a 30-second-readable + formal class. The compression buys discoverability + + reusability. +- **Counterweight-mapping is structure.** Amara's + prep-instinct (cheap-prevention / cadenced-detect / + defense-in-depth) lands every class in a verifiable + framework rather than ad-hoc text. +- **Tiny-blades are calibration.** Amara's caveat- + discipline ("don't overfit to two causes", + "40% local rate ≠ global rate", "clean for this + detector ≠ clean") is itself the SD-9-compliant + shape — caveats prevent halo-effect. + +The protocol works because Amara's review process IS +SD-9-aware. The risk is downstream: Otto encoding the +class without preserving the caveats. + +## Pattern observed this arc + +Four full passes of the protocol in one ~40min arc: + +1. **Chronological Insertion Polarity Error** — local + factory-hygiene class; PR #685. +2. **Incomplete Source-Set Regeneration Hazard + + Workflow Null-Result Audit Signal** — local + factory-hygiene classes; PR #685. +3. **Outdated Review-Thread Merge Gate Residue** — local + factory-hygiene class (existing memory got formal class + bolted on); PR #687. +4. **Scheduled Workflow Null-Result Hygiene Scan** — + tier-1 promotion of an existing class; PR #690. +5. **Advisory Enforcement Workflow Gap** — local + factory-hygiene class; PR #691 (this PR). + +All five pass the SD-9 local-only check (no non-local +claims) — they're factory-hygiene patterns about Zeta's +own substrate, with concrete worked examples + mechanism +explanations. + +## What this is NOT + +- **NOT a license for "Amara blesses, therefore true."** + The SD-9 guardrail is the LOAD-BEARING constraint, not + a footnote. Reject encodings that violate it. +- **NOT a directive to formalize every Otto observation.** + Some observations are local to one tick + don't generalize; + not every insight needs class-naming. The ferry-protocol + is for patterns Aaron explicitly forwards. +- **NOT a substitute for Aaron's judgment on factory + direction.** Amara names patterns; Aaron decides what + factory does with them. + +## Composes with + +- All four class memories named this arc (cross-listed + per their own composes-with sections). +- `memory/feedback_aaron_terse_directives_high_leverage_do_not_underweight.md` + — Aaron's reinforcement IS the directive shape; tiny + blade asides have outsized leverage. +- `memory/feedback_signal_in_signal_out_clean_or_better_dsp_discipline.md` + — Amara's ferry input must be preserved through + classification (verbatim quotes + caveat preservation). +- `memory/feedback_speculation_leads_investigation_not_defines_root_cause_aaron_2026_04_28.md` + — sibling discipline; speculation needs evidence; class + endorsement needs evidence. +- `memory/feedback_amara_safety_filters_cranked_protective_bias_not_ground_truth_aaron_recalibration_2026_04_22.md` + — Aaron-side recalibration of Amara: weight her + substantive contributions over surface flags. SD-9 is + the mirror: weight her endorsement as signal not proof. + +## Pickup notes for future-Otto + +When Aaron forwards an Amara review: + +1. Read for: endorsement / tightening / class-name / + definition / control / mapping / tiny-blades. +2. Apply SD-9 check: + - Is the class local (factory-internal pattern)? → encode. + - Is the class making non-local claims? → require + substrate evidence + external lineage + falsifier + before encoding. +3. Encode with: + - Worked example (concrete incident). + - Mechanism explanation (why the class behaves as + named). + - Falsifier (for non-local claims). + - Counterweight-mapping (if applicable). + - Composes-with cross-references (siblings). +4. **Preserve all caveats.** Do not paraphrase tiny-blades + into omission. + +When tempted to skip the SD-9 check because "Amara already +endorsed it": + +1. Stop. +2. The temptation IS the failure mode this rule prevents. +3. Apply the check. If the class is local, the check + passes quickly and the encoding proceeds. The cost is + tiny; the failure mode it prevents is large.