| 2026-07-30 |

Close sweep: queued findings F1-F10, memory review, skill invariants
...
Sweep capture docs/audit/queued-findings-20260730-dc0-region-migration.txt.
Three items lived ONLY in the transcript and would have been lost on a
clear:
F1 -- this session's permission rules exist only in the GITIGNORED
.claude/settings.local.json, so their verbatim text is now recorded,
including a broad Bash(ssh vr1-dc0-rack *) that an interactive approval
auto-added and which deserves review.
F2 -- the Office1 region STILL registers a rack controller on the dc0 rack
(vvr1-dc0/7chphy) and still holds the dc0 region VM's machine record. Not
harmful (Office1's DHCP for that VLAN is off, verified by process) but
dual-registration the operator should rule on.
F10 -- the five instrument errors of this session as one pattern, with the
rule that catches them.
F9 carries the next session's first commands and every measured input the
carve tool needs.
GA-R7 memory review: sharpened the classifier memory with the profile-token
lesson (a rule pinning 'maas admin' would have matched step 1 of the DHCP
cutover and silently missed step 3), and added an instrument-currency
memory. Both graduate to repo surfaces; neither is the only copy.
Skill swept: the per-DC region migration invariants folded in -- region
identity by rack, ids do not cross regions, the per-node ordering, batches
of three, zero SSH keys, the role-dependent carve, the role-tags gate that
passes on an incomplete tag set, and the two scripts that must not be
pointed at a new region.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

octavia-pki: a hardened, tool-driven controller-cert REISSUE path (F9's remedy)
...
Operator: 'Let's reissue now. Engineer the artifact, variable, based workflow to
reduce the chance of errors.' Five GA-R5 rulings, one exchange each, quoted in
the changelog; ruling 5 was 'Full script minter now'.
THE TOOL IS BUILT; THE MINT IS NOT YET RUN (gated operator action, 1.0-REISSUE).
scripts/octavia-pki.sh gains 'reissue <site> [--force] [--dry-run]': controller
LEAF only, signed by the EXISTING controller CA (neither CA regenerated, amphora
trust domain untouched), fresh P-256 key, zone DERIVED from the site token and
never typed, printf-built config (the F8 payoff), stage-assert-promote, and a
single-value overlay surgery that never puts the bundle in argv.
SIX GATE DEFECTS FOUND BY VALIDATION AGENTS, ALL CLOSED. Mutation testing is
what earned this: deleting the three assertions I had just written left the
harness fully GREEN every time, so they were decoration until each got a
failing-direction fixture.
- A15 keyUsage/EKU on the ISSUED cert. A cert with NEITHER minted, promoted and
passed everything. keyUsage appeared once in the file: the printf writing it.
- A16 validity. openssl x509 -req defaults to -days 30, and checkend/notAfter/
enddate appeared ZERO times in verify -- a 30-day cert passed forever.
- A17 the overlay must decode to what the workspace holds. A10 graded shape,
A1-A16 graded the workspace, nothing joined them; a desynced overlay read
PASS 0-failed and the overlay is what reaches the charm.
- The re-run guard REFUSED to fix broken certs: names-correct + stale IP SAN
gave verify FAIL and reissue exit 4 'nothing to fix'. Now gated on verify.
- A8's negative proves its instrument loads first (openssl verify exits non-zero
for 'could not load the CA' too, so a corrupt CA passed it vacuously).
- Two pre-existing overlay defects moved pre-mint, so they stop producing a
false exit-5 with the workspace already promoted.
Harness 23/23 -> 48/48. Runbook Step 1.0-REISSUE appended AFTER GEN.e
deliberately (F10 line-anchored mint-refs; creds-matrix reports no S4 findings
after the append). Skill gains two standing invariants for future DC standups:
every per-DC secret needs a ROTATION tool not just a generation recipe -- a
REFUSE-IF-PRESENT generation gate makes the dangerous path the only path -- and
a hand-pasted openssl chain is a defect class, with F8 and F9 as the receipts.
Also corrected: D-137 fork 1 is NOT open (sub-ruling 1, 2026-07-25, ruled
'Blocking in preflight' and explicitly declined the PreToolUse guard), so the
queued Q2 premise is stale in the same way Q1 was.
gauntlet ALL GREEN (89); repo-lint 0 fail; creds-matrix 5 findings, all
pre-existing and named; ledger-scan unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
| 2026-07-27 |

Session close: GA-R4 bookend, skill sweep, ledger rotation, permission block removed
...
CLOSE SET, all executed and verified:
BOOKEND (GA-R4). The STAGE-5 GROUNDING AUDIT close bookend had already landed
while the operator was away, by design. They then returned and worked the queued
rulings, so this session's second entry is recorded as a POST-CLOSE ADDENDUM
rather than a second close -- the 2026-07-25/07-26 precedent, which states the
convention in terms: "The close bookend landed early by design; this addendum
records the work that followed it rather than re-opening the entry." Catching
that avoided leaving TWO close entries for one session. Addendum is 12 bullets
against the 15 cap.
LEDGER ROTATION (GA-R4 rule 3 / F1). The addendum took the live ledger to 321
lines against the 300 cap. One oldest-first pass left it at 307, still over, so a
SECOND pass was taken in the same close: both 2026-07-25 summaries (handoff-pack
execution, and MAAS admin-account recovery) moved VERBATIM to
docs/archive/session-ledger-rotated-20260727.md. Live ledger now 292 lines, five
entries, from the 2026-07-26 D-137 addendum onward.
SKILL SWEEP, done although NO STAGE CLOSED, on operator direction. Three new
invariants folded into SKILL.md, each earned this session:
- A FINDING IS AN OBSERVATION, NOT A CONCLUSION -- measure before putting it to
the operator. Four of the first six questions changed shape on measurement and
three were withdrawn or re-scoped.
- A CITATION IS AN EXISTENCE CLAIM; ONLY ITS CONTENT IS EVIDENCE -- both bugs
behind the v4-only lb-mgmt draft failed on reading and the conclusion inverted.
No gate reads prose, so nothing in a repo can catch this.
- RULED IS NOT BUILT -- D-134's bands and D-020's vault VIP were both properly
ruled and never implemented, and passed every gate for weeks.
Into references/script-authoring.md: the repo-lint L5 heading trap (a heading
LEADING with a D-number needs AMENDMENT or RESOLVED on the same line -- it bit
this session twice and was on no author-facing surface), the commit-gated-on-lint
pattern that then caught its second occurrence, and the space-aligned .tsv.
Into references/operating-discipline.md: the probe PATH determines the answer --
the office1 VMs read "unreachable" via voffice1 and NO-CLONE from vcloud, and only
the second is a finding.
Snapshot regenerated as openstack-cloud-ops-consolidated-20260727.md: 1695 lines,
ASCII/LF byte-verified, all five new items present. A stale snapshot is the
recorded failure mode of docs/audit/skill-divergence-20260725.md.
CHANGELOG extended with the full ruling table (14 ruled, 2 withdrawn, G18 opened)
and the sweep/skill sections, each carrying its revert.
PERMISSION BLOCK REMOVED as promised at grant time: allow 303 -> 248, ask 24 -> 7.
All 55 session-scoped allow rules deleted and the five original broad
`ssh voffice1 "maas admin <noun> *` ask rules restored in place of the 23
verb-scoped ones. JSON validated. The file is gitignored, so the scope doc's
section 6 and this changelog are its only durable record.
FINAL VERIFICATION: repo-lint 0 fail / 1 warn (the L1 legacy carve-out, expected);
gauntlet ALL GREEN (81 harnesses); ledger-scan reconciles at 21 open SEC rows and
next-free D 138 / DOCFIX 205 / BUNDLEFIX 053 -- UNCHANGED, correctly, because
fourteen rulings were recorded and nothing was remediated.
Revert: git revert this commit; the skill edits are additive, the snapshot is
derived, and the ledger rotation is reversible from the archive file.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

Stage 4 close-out set: GA-R2 consolidation, skill sweep, snapshot, GA-R7 review
...
Every substantive Stage 4 item is closed or split to gate row G17. This is the GA-R6 close-out
set; only the operator-gated merge to `main` remains.
GA-R2 CONSOLIDATION: the 7 stage changelogs archived to docs/archive/changelogs/ (top-level
docs/ 25 -> 18, 113 archived total) and the stage record written at
docs/archive/stage-records/vr1-stage4-record.md. It records what the stage actually delivered
(READY handoff, not deployed nodes), the three things a future session should read first, and
the false-green pattern this stage kept surfacing. 12 stale `docs/changelog-*` paths in live
surfaces rewritten to the archive -- including several already dangling from the G12 close, so
every changelog reference in CURRENT-STATE / session-ledger / security-ledger now resolves.
SKILL SWEEP: three new INVARIANTS folded in --
- per-DC ARTIFACT DELIVERY is a per-DC STRATEGY (dc0 full mirror / dc1 caching proxy, D-135
amendments); checking dc1 as a mirror fails BY DESIGN. Corollary, learned the hard way: a
per-DC utility service OWNS ITS OWN network prerequisites -- never let one strategy's
teardown be able to break the other's.
- Stage 4 hands off READY nodes, NOT deployed ones (DOCFIX-200). Any surface saying "nodes
Deployed" as a Stage-4 exit is a defect; four were found and fixed. Consequence: nothing
node-side is probeable in Stage 4, which is why G17 exists.
- "A CHECKER THAT CANNOT FAIL IS NOT A GATE", with the working rules that came out of two
measured false greens: assert on CONTENT not existence; an unrecognised state REFUSES;
"could not look" is never "nothing there"; ENUMERATE what exists rather than only auditing
what is declared, because a register cannot report the absence of a row it does not have;
and when a test asserts a literal finding string, REPLACE the assertion, never delete it.
Plus two routing rows (per-DC artifact checks; D-137 as the credential-lifecycle authority).
SNAPSHOT REGENERATED: .claude/skills/openstack-cloud-ops-consolidated-20260727.md (1589 lines,
ASCII + LF byte-verified, all 7 sections). The superseded 20260725 snapshot is REMOVED rather
than kept alongside -- a stale snapshot being uploaded is the exact failure
docs/audit/skill-divergence-20260725.md records (a failed clone + a mis-shaped handoff), and it
is a derived artifact regenerable from any commit.
GA-R7 MEMORY REVIEW: NO new memory written -- everything durable from this stage graduated to
the skill and the repo, which is the correct GA-R7 outcome, not an omission. Both existing
entries verified against the repo (the finding-class baseline they cite does exist) and extended
with the two reasoning traps this stage produced: the register cannot see a credential it has no
ROW for, so enumerate what exists; and diagnose a denied call by checking whether an existing
rule failed to MATCH before blaming the classifier (the measured 2026-07-26 root cause). Also
marked the ask-vs-allow precedence claim UNVERIFIED so no future session relies on it.
Noted, not actioned (hard rule 1): T24's finding-class baseline covers TIER 1 only, so tier-2/3
classes have no baselined red state and a future false green there would not be caught.
Gauntlet ALL GREEN (81), repo-lint 0-fail.
Revert: git revert this commit; the changelog moves are renames and the snapshot is derived.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
| 2026-07-25 |
skill: stage-close sweep keeps the authoritative dir current + regenerates the Chat snapshot
...
SKILL.md stage-close rule now states the authoritative, versioned skill is the
.claude/skills/openstack-cloud-ops/ dir (SKILL.md + references), kept current at each
stage-close sweep, and the dated single-file Chat-upload snapshot is REGENERATED from it
then (a derived artifact, never the source; the stale Chat mount is a known failure mode).
Regenerated openstack-cloud-ops-consolidated-20260725.md from the updated skill so the two
stay in sync. ASCII/LF verified; repo-lint 0 fail.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
| 2026-07-23 |
G12 dc1 close-out: consolidation + skill sweep + CURRENT-STATE (G12 CLOSED)
...
- GA-R2 consolidation: 3 dc1 session changelogs (07-21 authoring, 07-22 build,
07-23 edge) archived to docs/archive/changelogs/; Stage 3 record gains a
"G12 CLOSED 2026-07-23" section + table rows
- CURRENT-STATE: G12 gate CLOSED, section-1 stage narrative updated
- skill sweep: per-DC dedicated MAAS->libvirt power key (SEC-012/SEC-016)
added as a standing DC-standup invariant
- GA-R7 memory review: clean (no changes)
Close-out set complete; ready for operator-gated merge to main.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
| 2026-07-21 |
STAGE 3 CLOSE (operator-ruled): GA-R2 consolidation + skill sweep; gauntlet 76 ALL GREEN
...
- Four execution-session changelogs -> docs/archive/changelogs/;
vr1-stage3-record.md finalized (close summary + session table)
- CURRENT-STATE stage line CLOSED (vr1-dc0 scope; dc1 = HELD G12);
workflow Stage-3 State row + runbooks/README corrected
- Skill sweep: D-131 forwarder invariant + MAAS pod traps + merge
precedent folded; no stale facts found
- Close-out evidence: gauntlet 76 ALL GREEN, repo-lint 0 fail, GA-R7
memory review done (changelog items 11, 17)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013XRtm5sDQgUsZyTJk3k7dz
|
| 2026-07-19 |
Batch 5: skill sweep -- GA-R1..R7 implemented in openstack-cloud-ops (single commit)
...
New GA-rulings section reconciled against the RATIFIED text (draft
skill-additions cross-checked; the one draft-only item, the
reconciliation circuit-breaker, kept and marked as discipline). Stale
facts demoted to CURRENT-STATE delegation: the header's "current phase =
VR0 testcloud" and the deploy loop's "opentofu UNVALIDATED / no tofu
binary has ever run" (false since 2026-07-13). Session bookends + stage
close rewritten per GA-R4/GA-R6; change-delivery per GA-R2/D1; routing
rows re-pointed. Read-through checklist committed:
docs/audit/skill-sweep-checklist-20260719.md (every ratified rule ->
disposition). G3 cell updated same commit. repo-lint 0 fail.
Revert: git revert this commit (restores the pre-sweep skill).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZbUeRE8weySLSGY1odrCi
|

Batch 3 CLOSE: memory hygiene (GA-F05..F08 memory surfaces) + G1 review; GA-F16 registered
...
Per the recorded provenance rulings: review-after-each-step.md REMOVED
(GA-F06 -- one-time instruction, never standing) and project-posture-
closed-test.md REMOVED (GA-F07 -- "ruling" never ruled; posture NEUTRAL);
hostname -> vcloud in the Remote Control memory (GA-F05 last surface);
MEMORY.md index rebuilt (GA-F08). GA-R7 rule-6 skill line added to
SKILL.md bootstrap. First full G1 review (rules 1-4) found + fixed one
further violation: creds-folder-convention.md duplicated a repo-carried
convention and linked both removed files -- registered as GA-F16, reduced
to a pointer entry. Post-review: 3 memory files, zero violations, zero
stale refs (grep-verified). Pre-edit copies: docs/archive/memory-20260718/
(index copy ASCII-normalized, noted in the changelog). G3 cell updated
same commit (L10 satisfied).
Revert: restore files from docs/archive/memory-20260718/ (memory side);
git revert this commit (repo side).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZbUeRE8weySLSGY1odrCi
|
GA-F05: jumphost name corrected to vcloud on always-loaded surfaces
...
CLAUDE.md:4 + SKILL.md:46 per the finding, plus a fourth surface
discovered in the same sweep: references/environment.md:43 (same defect
class, same measured fact -- hostname -> vcloud, env snapshot). The
memory-file instance is Batch 3's item per the plan. Batch 2 item 2.4.
Revert: git revert this commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZbUeRE8weySLSGY1odrCi
|
| 2026-07-17 |
Gap register #20: durable host->site reachability CLOSED (Office1); skill carries the per-DC discipline
...
- docs/dc-dc-deployment-workflow.md: new tooling-gap item 20 -- the durable
host->isolated-site base leg had no owning tool; CLOSED for Office1 via
scripts/site-baseleg.sh (installed+enabled 2026-07-17; boot-race unproven until
a reboot). Documents the DC generalization so the gap does not reopen per-DC.
- SKILL.md: operating-model invariant extended -- durable host->site reach is
standing per-SITE tooling (DCs included): at each DC standup MEASURE the reach
and, if the DC net is ISOLATED, add a MEASURED site-baseleg.sh leg row + install
as part of standup DoD (never an inferred DC IP; harness enforces it).
Doc-only follow-up to 1958063. Nothing merged to main (stage-close).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QMKdXCquMnh1jKH2sWXPMg
|

D-126 base-leg oneshot (site-baseleg.sh) + D-128 operating model; post-restart sweep
...
vcloud post-restart health sweep all-green (host on 6.8.0-136, patch+reboot done;
libvirt/pools/autostart clean; Office1 stack self-recovered end-to-end). Sweep
surfaced a recurring break: office1-local is an ISOLATED libvirt net, so the host's
base L3 leg (10.10.0.10/24 on the bridge + compose route 10.10.1.0/24 via 10.10.0.20)
lives nowhere in the XML and drops on every reboot -- the un-persisted foundation
D-126 assumed but never owned.
- NEW scripts/site-baseleg.sh + tests/site-baseleg/ (24/24): root Type=oneshot unit,
After=libvirtd (+virtnetworkd for modular hosts; ordering MEASURED here = monolithic
libvirtd), re-adds the leg at boot. Bridge DISCOVERED from the stable net name (never
a baked virbrN, PATTERN-1); apply idempotent + root-guarded; check = session-verify.
INSTALLED + enabled this session; boot-race UNPROVEN until an actual reboot.
- docs/design-decisions.md: D-126 amendment (base-leg durability) + NEW D-128 (operating
model -- Claude on the vcloud jumphost; Plane-1 substrate on vcloud / Plane-2 executes
on voffice1; workstation tailnet is the human path; D-107 untouched).
- Skill invariant + routing row (SKILL.md), Cross-cutting bullet (dc-dc-deployment-workflow.md),
session-ledger + changelog.
Gauntlet ALL GREEN (67 harnesses), repo-lint 0-fail. Nothing merged to main (stage-close).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QMKdXCquMnh1jKH2sWXPMg
|
| 2026-07-15 |
stage-close discipline: add the operating-skill sweep as part of definition-of-done
...
Per operator: the skill-update sweep must itself be part of every stage close, so it
is never skipped. At stage close (alongside the branch->main merge + branch retire),
sweep .claude/skills/openstack-cloud-ops/ for any new INVARIANT the stage established
and reconcile divergence from repo HEAD. Recorded in both the workflow doc's
Cross-cutting discipline and the skill's own VR1 deploy-loop stage-close note.
repo-lint 0 fail.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015WgVrZE2ryY9aXP7JiBuwj
|
skill: add the standing merge-at-close discipline + the DOCFIX-195 apex pointer
...
The operating skill delegates facts (stage status, IPs) to the repo by design, so
Stage-2-merged/D-120/etc. need no skill edit. But two things are the skill's own
domain and were missing:
- The new INVARIANT: branch-per-stage + MERGE AT STAGE CLOSE (merge commit,
operator-gated, retire the branch, next stage off post-merge main). Added to the
VR1 deploy loop as part of a stage's definition-of-done. Precedent: Stage 2 -> PR #1.
- A DOCFIX-195 pointer on the IPAM routing row: during VR1 the WORKING apex is
office1-netbox (netbox.baldurkeep.com is a read-only v1 reference, write-back
deferred). This exact ambiguity cost time early this session.
repo-lint 0 fail (L8 guide<->skill coupling pins clientdocs, not this skill -- unaffected).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015WgVrZE2ryY9aXP7JiBuwj
|
| 2026-07-13 |

Office1 headend LIVE: MAAS 3.7.2 + LXD 5.21 on voffice1. D-114 PROVEN END TO END.
...
MAAS composed, PXE-booted and COMMISSIONED its first VM inside voffice1. The model works.
vcloud (L1 -- itself a KVM guest, measured)
+- voffice1 (L2) MAAS 3.7.2 region+rack + PostgreSQL 16.14 + LXD 5.21.5
+- office1-netbox (L3) LXD VIRTUAL-MACHINE, MAAS-composed, MAAS-PXE-booted,
leased 10.10.1.100 from MAAS, status READY, 2c/4096MiB detected
THE L3 PROOF IS NOW DEFINITIVE. Earlier today we could only say nested KVM was AVAILABLE
(/dev/kvm + svm present). Now a guest has actually BOOTED, PXE'd, COMMISSIONED and reported its
hardware three levels deep. D-114's Office1 gate is CLEARED. This reproduces VR0's `lxd` +
`tailscale` pattern exactly -- and the Juju-created LXD CONTAINERS remain invisible to MAAS, as in VR0.
THE DHCP SPLIT IS STRUCTURAL, NOT CONVENTIONAL:
10.10.0.0/24 (site LAN) -> Kea on the OPNsense edge MAAS dhcp_on=False
10.10.1.0/24 (lxdbr0) -> MAAS MAAS dhcp_on=True
Separate L2s; lxdbr0 is never bridged onto the site LAN, so they cannot see each other. The
installer asserts after configuring DHCP that MAAS owns NO other subnet, and hard-fails otherwise.
NEW: scripts/site-headend-install.sh + tests/site-headend-install/ (18/18 PASS). It is the sequence
we ACTUALLY EXECUTED, codified -- not written from docs -- and reusable verbatim for DC1/DC2. Its
--check mode was run against the live voffice1 and reports every item OK.
FOUR TRAPS, ALL HIT FOR REAL TODAY, ALL NOW ENCODED AND HARNESS-ASSERTED:
1. `lxd init --auto` FAILS on a MAAS host. It brings up lxdbr0 with LXD's own DHCP+DNS, which starts
a dnsmasq; dnsmasq binds the WILDCARD 0.0.0.0:53 and MAAS's bind9 already holds :53. The error
names the BRIDGE address ("failed to create listening socket for 10.10.1.1"), which sends you
hunting the wrong thing. `ipv4.dhcp=false` + `dns.mode=none` are NOT enough -- LXD still spawns
dnsmasq. The fix is raw.dnsmasq="port=0". Verified after: dnsmasq holds ZERO :53 and ZERO :67.
2. `lxc` READS CONFIG FROM STDIN. Piped to `bash -s` over ssh, the first unredirected `lxc` call
EATS THE REST OF THE SCRIPT as YAML and everything after it silently vanishes. Every lxc call now
ends in </dev/null. Same class as the OPNsense tcsh trap.
3. LXD snap track changes are ONE-WAY -- install DIRECTLY onto 5.21/stable, never via `latest`.
MAAS 3.6/3.7 is incompatible with LXD >= 6.7. (Bonus: core.trust_password exists in 5.21, gone in
6.x -- the pin also preserves the scriptable registration path.)
4. MAAS DHCP on the compose network ONLY. --compose-cidr is REQUIRED with no default so it can never
be picked by accident.
DISCIPLINE: every MAAS/LXD flag was read from the tool's own --help ON THE BOX before use (maas init,
createadmin, vm-host compose), not trusted from docs. All secrets (DB, admin, API key, LXD trust) are
generated on the target, stored 0600 under /root/maas-secrets/, and never printed into the session.
10.10.1.0/24 IS AN UNBLESSED ALLOCATION -- chosen deliberately (DC1=10.12.x, DC2=10.13.0.0/19, tenant
pool=10.20.0.0/16 per D-016; the obvious 10.20.x would have COLLIDED with tenant space), but NetBox
has not assigned it. Register once NetBox exists -- it is one of the VMs this headend composes.
Also: the ops skill is now tuned to this exact stack (new references/platform-traps.md with a
verbatim-error -> cause index; the OPNsense section that still routed sessions into the DELETED
config-ISO path is replaced). Upstream corroboration found for two of our own findings: the libvirt
provider's release notes document that an "in-place" domain update undefines and re-defines the
domain (our measured guest-bounce), and there is an upstream issue for the AppArmor denial.
Gauntlet ALL GREEN (53 harnesses). repo-lint 0 fail.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
| 2026-07-10 |
DOCFIX-177: make the skill and runbooks/README.md aware the VR1 DC-DC track exists
...
Found while the operator was heading to the vcloud host to begin real
execution: SKILL.md and runbooks/README.md (what its routing table points
to) had zero mentions of the entire VR1 DC-DC track, so a fresh session
would be routed to VR0's phase-01..08 runbooks with no indication today's
actual mission (dc-dc-phase0..6 + the new teardown runbook) exists.
Added a "VR1 DC-DC track" index to runbooks/README.md, VR1-specific rows
to SKILL.md's routing table and standard loops, and pointers in
references/environment.md and references/troubleshooting.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QrcJx8TUar7pYAvpGJw57A
|

DOCFIX-148: OpenTofu module audit pass + provider-docs skill reference
...
Audited every "UNVERIFIED"/"inferred"/"assumed" marker across all 9 modules
built this session rather than leaving them as-is. Found and fixed a real
documentation error: opnsense-edge's comments claimed devices.interfaces
list order directly sets OPNsense's LAN/WAN role. Researching OPNsense's own
interface-assignment model showed this conflates two things -- list order
plausibly controls which vtnetN device number a NIC gets (libvirt's own
docs: auto-assigned PCI addresses "usually match" XML order for a simple
topology), but the actual LAN/WAN role is a separate, explicit mapping set
inside config.xml itself ("vtnet0=WAN" is a convention some guides choose,
not an enforced rule). Corrected main.tf's comments and both
lan_network_name/wan_network_name variable descriptions -- no config.xml
exists in this repo yet, so this fixes documentation accuracy for whoever
writes it next, not current behavior.
Confidence upgraded (not just re-hedged) on three other items: node-vm's
boot={order=N} shape (confirmed the provider 1:1-mirrors libvirt's own XML,
and libvirt's own docs confirm the single-attribute shape), create.content.url
accepting local paths (second independent source), and the genisoimage
flags (confirmed standard, cleanly separated from the still-open question of
whether OPNsense's Importer actually reads the result). Confirmed safe:
maas_vm_host's zone/pool computed-if-unset behavior.
Added .claude/skills/openstack-cloud-ops/references/opentofu-provider-docs.md:
indexes every provider/doc source used this session with exact URLs and
confirmed versions, plus the fetch methodology that actually worked
(Registry doc pages are JS-rendered, use GitHub instead; branch names vary,
check default_branch via the API; real example .tf files beat doc-summarized
prose for syntax questions). Wired into SKILL.md's routing table,
cross-referenced from opentofu/README.md in both directions without
duplicating content.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QrcJx8TUar7pYAvpGJw57A
|
| 2026-07-09 |

DOCFIX-139..141: repo-rename sweep (ipv4->dc-dc) + repo-lint L9 self-reference guard
...
New repo openstack-caracal-dc-dc still had stale operational references to the
source repo it was seeded from (openstack-caracal-ipv4), plus, after the
mechanical fix, hardcoded references to its own new name -- both break on any
future fork/rename. Fixes:
- DOCFIX-139/140: repaired 8 stale clone-path/URL references across the skill
and 4 runbook RUN blocks; fixed a repo_lint.py Windows path-separator bug
that silently turned a documented WARN into a FAIL (rel comparison used
str() instead of as_posix()).
- DOCFIX-141: new repo-lint check L9 fails any script/RUN-block/skill file
that hardcodes the current repo's own directory name. Narrowed the
.claude exclusion in repo_lint.py to .claude/worktrees/ only (it was
blanket-hiding checked-in .claude/skills and .claude/hooks from all
lint checks). Established a $REPO session-variable convention
(runbooks/README.md Conventions) and converted the 8 hardcoded paths to
require it explicitly, fail loud if unset.
repo-lint: 0 fail / 1 documented legacy WARN. tests/repo-lint harness 34/34.
Full details + per-item revert instructions in the two changelogs.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QrcJx8TUar7pYAvpGJw57A
|
| 2026-07-04 |
|
| 2026-07-03 |
|