KB-39B6

VPS-CLEAN-MINIMUM — Targeted Disk Reclaim With Zero Production Disruption (2026-07-24)

15 min read Revision 1
current-statereportvps-clean-minimumdisk-reclaimcleanupdockerbuilder-prunedelete-safequarantinezero-mutationpg-restore-testuptime-kuma-datamanifest-drivenPASS_VPS_CLEAN_MINIMUM_STABLE_HEADROOMVPS-ADMIN-SECURITY-R02026-07-24

VPS-CLEAN-MINIMUM — Targeted Disk Reclaim With Zero Production Disruption (2026-07-24)

VERDICT: PASS_VPS_CLEAN_MINIMUM_STABLE_HEADROOM Mission VPS-CLEAN-MINIMUM REV1 Host Contabo vmi3080463 (38.242.240.89) · disk /dev/sda1 · UTC window 2026-07-24 ~06:49Z → ~07:30Z Authorization accepts: PASS_VPS_RECOVERY_PREP_READY_FOR_MINIMUM_CLEAN + OFF_VPS_DECRYPTION_RECOVERY = PASS Canonical input: knowledge/current-state/reports/vps-recovery-prep-2026-07-24.md Mode: delete only the classified DELETE_SAFE set by exact path/ID; production otherwise untouched. Author: Claude Code (Opus 4.8, 1M ctx)


1. Verdict & PASS gate

PASS-gate condition (§11) Result
ALL_APPROVED_DELETE_SAFE_ITEMS_PROCESSED YES (Stage A 25 del + 1 held-with-reason · B cache · C 19 images · D 7 volumes · E both objects)
ROOT_FILESYSTEM_USED_PERCENT <= 75 YES — 61% (was 87%)
ROOT_FILESYSTEM_FREE_GB >= 24 YES — 39G (was 13G)
CORE_RUNNING_CONTAINERS = 10 YES
CORE_HEALTH = PASS YES (9 healthy + nginx 200/301)
ACTIVE_IMAGE_IDS_UNCHANGED YES (all 10 active image IDs present, restart counts unchanged)
DOCKER_SYSTEM/IMAGE/VOLUME/CONTAINER/NETWORK_PRUNE_USED NO (only docker builder prune --all --force was run)
OLD_AGENT_DATA_QUARANTINE_IMAGES_DELETED NO (5 present)
ROOT_CHECKPOINTS_DELETED NO (7 present)
ACTIVE_PG_ROTATION_DELETED NO (present, newest directus_2026-07-24_0027.sql.gz)
QDRANT_SNAPSHOTS_DELETED NO (8 present)
DRIVE_RECOVERY_ARTIFACTS_DELETED NO (Drive never touched)

Mutation ledger: PRODUCTION_CONTAINER_RESTARTED=0 · PRODUCTION_CONFIG_MUTATED=0 · PRODUCTION_DATA_MUTATED=0 · MAC_FILES_MUTATED=0 · ACTIVE_PRODUCTION_IMAGE_IDS_UNCHANGED=YES.

Total reclaimed: ~27.4 GB (used 84G→58G, free 13G→39G, 87%→61%). Target reached by Stage A+B+D alone; Stage C and E processed for completeness.


2. Before / after — disk & Docker

Root filesystem / (df -B1 → df -h):

Point Used Avail Use%
Session start (Gate 0) 89,381,089,280 (84G) 13,490,229,248 (13G) 87%
After Stage A (files) 80,536,158,208 (76G) 22,335,160,320 (21G) 79%
After Stage B (cache) 75,899,342,848 (71G) 26,971,975,680 (26G) 74%
After Stage C (images) 72,354,652,160 (68G) 30,516,666,368 (29G) 71%
After Stage D (volumes) 62,772,043,776 (59G) 40,099,274,752 (38G) 62%
After Stage E (final) 61,982,760,960 (58G) 40,888,557,568 (39G) 61%

Docker usage (docker system df):

Type Before After
Images (unique) 36 / 38.63GB (10 active) 17 / 30.46GB (10 active)
Build Cache 79 / 6.697GB (0 active) 0 / 0B
Local Volumes 9 / 10.37GB (1 active) 0 / 0B
Containers (running) 11 10

3. Exact deletion manifest (Gate 0)

Frozen at /root/vps-clean-minimum-delete-manifest.tsv (columns: type · exact_identifier_or_path · classification · estimated_bytes · reference_count · recovery_basis · planned_action). All delete commands used exact paths/IDs from this manifest — no wildcard was used in any delete command (wildcards only to enumerate candidates).

Gate 0 assertions (all PASS): none of the 10 protected image IDs (23f2f526599b directus · 72715a92885c nuxt · 9acd60503290 agent-data · 54df5be4d9fc agent-api-executor · 1d13701a5f9f nginx · 7c0096602a1c claude-mcp · 3cf3065bf66e claude-kb · 7337368a7787 uptime-kuma · 004f63c1e580 postgres · 0425e3e03e7f qdrant) appears in any delete row; no production bind mount / production volume appears; every Stage-C image had 0 running/stopped-container refs and 0 compose refs; build-cache active entries = 0.


4. Stage A — files deleted (exact paths, 25 items, 8,845,372,734 B ≈ 8.24 GiB; FS reclaim ~8.85 GB)

Per-file gate satisfied for each: exists · not open (lsof empty) · REFERENCE_COUNT=0 (script/cron/systemd) · NOT_CURRENT_ROTATION_ARTIFACT=YES · OFFSITE_RESTORE_PROVEN_REPLACEMENT=YES · classification DELETE_SAFE.

  • /tmp/c1_introspect.sql (305) · /tmp/c1_snapshot.sql (1369) · /tmp/snap_before.sql (1379)
  • /tmp/batch0-partA-2026-07-02 (442,239) · /tmp/batch0-staging-2026-07-02 (13,370,508)
  • /opt/incomex/backups/100000x (1,787,797,247)
  • /opt/incomex/backups/dot-iu-cutter-v0.4-prodtrial-2026-05-17 (1,366,903,771)
  • /opt/incomex/backups/dieu44_*14 of 15 dirs (REF=0): dieu44_exec_2026-05-15, dieu44_hb05_2026-05-15, dieu44_hb08_2026-05-15, dieu44_hb09_2026-05-15, dieu44_phase_alpha_2026-05-16, dieu44_phase_alpha_postexec_verify_20260516T030747Z, dieu44_phase_alpha_postexec_verify_20260516T030821Z, dieu44_phase_alpha_postexec_verify_kit, dieu44_phase_alpha_prod_20260516T022657Z, dieu44_v0_2_closeout_20260516T104634Z, dieu44_v0_3_closeout_20260516T233317Z, dieu44_v0_3_readobs_dryrun_20260516T152620Z, dieu44_v0_3_readobs_dryrun_rerun_20260516T230114Z, dieu44_v0_3_readobs_prod_20260516T232444Z (~4.15 GB total)
  • /root/p0-6-p0-5-dryrun (650,367,901) · /root/p0-6-p0-5-prod-exec (652,517,378) · /root/p0-6-p0-5-prod-exec-rerun (652,537,148)
  • /root/directus-pre-iucore-6000x-20260523T140636Z.dump (75,901,728)

Reference reconciliation (important, transparent): a broad recursive grep initially showed elevated match counts for p0-6-* (5/7/3) and most dieu44_* dirs (1–5). Investigation showed these are self-references inside the target directories (their own .log/.sh/.sql files naming their own paths) plus 5 inert, unscheduled /root/v0_2_closeout_*.sh / v0_3_*.sh one-off scripts (mtime May 16–17; not in cron/systemd; not invoked by anything). A targeted grep over script/config files only returned 0 external references for every deleted path — except the single dieu44_v0_3_readobs_dryrun_rerun_20260516T230306Z (REF=1, the dead prod_exec.sh SRC= line), which was HELD (see §8). dot-iu-cutter, 100000x, iucore-6000x, batch0 = 0 in both greps.


5. Stage C — unused images removed (19 unique IDs, docker image rm by ID, no --force)

Image ID Tag(s) Size (B)
f2a000c5214d nuxt-ssr-local:d28gmr-1778407456 60,539,397
105bd197347c nuxt-ssr-local:d2db418 60,538,617
c221fedd4875 nuxt-ssr-local:latest 60,410,391
8be1088b4c3b nuxt-ssr-local:p10d 60,525,027
072ccd861f30 nuxt-ssr-local:pre-d28-rollback-1778397192, :s174 (2 tags → removed via explicit tags) 60,516,369
474378da3538 nuxt-p10d-fix:c2ab61e 60,521,703
7c328c113dcc nuxt-p10d-layout:3d61e02 60,535,847
adec32087a62 nuxt-p10d-sidebar:704ff74 60,539,532
9476561c1af9 nuxt-p10d-sidebar:a8408ed 60,538,388
5387f2fa2bd0 docker-nuxt:latest 60,001,445
1bcfab54f6bc docker-agent-data:latest 331,678,640
99d774bf02a4 mysql:8.0 232,308,084
f598378b5240 node:20-alpine 48,369,806
a5b427ace490 python:3.11-slim 45,456,943
401f6e1a67da python:3.12-slim 43,204,694
ef54e839ef54 hello-world:latest 16,304
1487d0af5f52 busybox:latest 2,222,002
23b60dc412cd alpine/curl:latest 6,327,079
b3f1fb2a51d9 curlimages/curl:latest 10,630,939

19/19 removed, 0 skipped. Images 36→17 unique. Actual FS reclaim ~3.54 GB (nominal sum higher; shared layers). docker-agent-data:latest (1bcfab54f6bc) qualified because its ID is distinct from the active agent-data (9acd60503290) and from all 5 quarantined agent-data variants.


6. Stage B — build cache

ACTIVE_BUILD_CACHE_ENTRIES = 0 reconfirmed → ran only docker builder prune --all --force. Prune reported 6.697 GB total; actual disk reclaimed 4.64 GB (remaining cache layers were shared with kept images — consistent with the pre-run RECLAIMABLE 0B note). Build Cache now 0 entries / 0B. No other prune command was run.


7. Stage D + E — volumes & test container removed

Stage D — 7 orphaned DELETE_SAFE volumes (docker volume rm by exact name; all LINKS=0): 32b405…db15d (1,388,514,038) · 5838dc…6d31c (1,394,320,638) · d2e14f…52064 (1,394,279,678) · 886272…fb0aa (1,425,409,278) · pg-dry-run-hb05-2026-05-15-data (1,289,819,413) · pg-dry-run-v0.2-phase-alpha-2026-05-16-data (1,344,224,340) · pg-dry-run-v0.2-p0-2-2026-05-16-data (1,344,093,186). Reclaim ~9.58 GB (full; independent _data dirs). No docker volume prune used.

Stage E.1 — pg-restore-test-20260520T031054Z (0cbc668c76f9) + its data volume 46dbcc89…6b54bc (788,242,182 B): all promotion gates PASS — NOT_IN_COMPOSE (labels empty) · PUBLISHED_PORTS=0 (5432/tcp:null) · 0 script/cron/systemd refs · PRODUCTION_POSTGRES_VOLUME_MATCH=NO (prod uses bind /opt/workflow/postgres/data) · CREATION_PURPOSE=POSTGRES_DB=restore_test · UNIQUE_PRODUCTION_STATE=NO · OFFSITE_DB_RESTORE_PROVEN=YES. No client/job in the test PG (active=0, external clients=none; the 5 backends were internal PG processes — autovacuum launcher / bg writer / checkpointer / logical-rep launcher / walwriter). Container was started with --rm, so docker stop <exact CID> cascaded removal of both the container and its anonymous volume 46dbcc89. Production Postgres verified unchanged (same CID 22540b78de8f, same data bind, healthy, pg_isready accepting, SELECT 1→1). Result: 10 core running.

Stage E.2 — uptime-kuma-data orphan volume (1,120,632 B): all gates PASS — active uptime-kuma uses bind /opt/incomex/uptime-kuma → /app/data; named volume LINKS=0, not compose-referenced, no unique required state (content was a stale Feb-2026 kuma.db, superseded by the rescued bind-mount data). Removed by exact name. uptime-kuma container verified unchanged (same CID, healthy, still bind-mounted).


8. Items skipped / held (kept on purpose)

Item Classification Reason kept
/opt/incomex/backups/dieu44_v0_3_readobs_dryrun_rerun_20260516T230306Z (667,380,088 B) DELETE_SAFE_HELD REFERENCE_COUNT=1 — hard-coded SRC= in the (dead, unscheduled) /root/v0_3_readobs_prod_exec.sh. Held per the Stage-A REFERENCE_COUNT=0 gate.
5 agent-data variants: pre-b1 (5a7eb4e4e2a2), pre-c1-schema (b6154accb6d8), pre-s178-cutllm (bfe092449032), s178-cutllm ×2 tags (d53a11072c00), agent-data-test:latest (9421cd9c4303) QUARANTINE Explicitly out of scope for the minimum mission (lineage of a local-only image).
claude-mcp-local:rollback-pre-p2b (73f953f71632), claude-mcp-local:rollback (37098dc6ef6e) NOT_CLASSIFIED Not in the report's DELETE_SAFE list; claude-mcp (local-only) lineage — not promoted by inference.
~19× /opt/incomex/backups/directus-pre-iucore-*.dump (30x…5000x series) not classified Only the single /root/directus-pre-iucore-6000x-*.dump was in the DELETE_SAFE set; the /opt/incomex/backups iucore series was not — all kept.

No Stage A/C/D item was skipped for an unexpected live reference — every planned deletion succeeded.


9. Core service verification (read-only smoke — all PASS)

Check Result
DIRECTUS_HEALTH_INTERNAL {"status":"ok"} (nginx→directus:8055/server/health)
DIRECTUS_HEALTH_PUBLIC {"status":"ok"} (https://directus.incomexsaigoncorp.vn/server/health)
NUXT_HOME http 200, 256,999 B, <title>Home - Incomex AI Portal</title> (real render)
NUXT_API_HEALTH http 200 (/api/health)
AGENT_DATA_HEALTH docker health=healthy
AGENT_API_EXECUTOR_HEALTH docker healthcheck GET /healthz healthy, last_exit=0
CLAUDE_MCP_HEALTH / CLAUDE_KB_HEALTH docker health=healthy
UPTIME_KUMA_HEALTH docker health=healthy (127.0.0.1:3001 → 302)
POSTGRES_HEALTH pg_isready accepting · SELECT 1→1
QDRANT_HEALTH /readyz = all shards ready · /healthz passed (/collections 401 = API-key auth enforced)
NGINX_80_443 :80 → 301 (→https) · :443 → 200 OK
BALO_GUARD_37 `BALO_ONE_CLICK_GUARD
SHARED_MACHINE_IDENTITY machine-transition static token → /users/me user 73aa333b (stateless, 0 session)
ACTIVE_ADMIN_SESSIONS 0 live (query showed 1 row for admin@example.com but it is expiredexpires 2026-07-23 09:49:16, ~22h old, ip 172.18.0.1 curl/8.5.0; a pre-existing rotation remnant not yet GC'd, not created by this cleanup)

All 10 core containers: same CIDs, same restart counts as the start-of-session baseline (nuxt=2, claude-mcp=2, claude-kb=2 are the pre-existing self-restart pattern), same active image IDs.


10. Protected assets confirmed untouched

  • 10 active image IDs all present.
  • 5 QUARANTINE agent-data variants present (unique IDs 5a7eb4e4e2a2, b6154accb6d8, bfe092449032, d53a11072c00, 9421cd9c4303).
  • 2 claude-mcp rollback images present.
  • 7 /root/*-checkpoint-* dirs present (c0/c1/c2a/c2b1-hybrid-precut/c2bpre/nuxt-img-h1/wave-a1).
  • Active PG rotation /opt/incomex/backups/pg/ present (newest directus_2026-07-24_0027.sql.gz).
  • 8 Qdrant daily snapshots /opt/incomex/backups/qdrant/*.snapshot present.
  • 19 directus-pre-iucore-*.dump (in /opt/incomex/backups) kept; 1 HELD dieu44 dir kept.
  • Drive recovery artifacts never accessed.
  • No edit to compose / env / nginx / DOT / systemd / cron; no Directus, PostgreSQL, schema, or Qdrant write; no credential rotation; MacBook untouched.

Prohibited actions (§2) — NOT executed: docker system/image/container/volume/network prune, docker compose down, restart/recreate of any production container, rmi on any protected/quarantine image, delete of active volume/bind/network, delete of Drive/PG-rotation/Qdrant-snapshot/checkpoint, credential rotation, config edit, Mac access. Only docker builder prune --all --force (the single allowed prune) was used.

Additive artifact left on VPS: /root/vps-clean-minimum-delete-manifest.tsv (Gate 0 evidence; no secrets).


11. Next gate

VPS-ADMIN-SECURITY-R0 — the single next gate. Not started here (this mission stops after the report).

Observation forwarded (not acted on): the expired admin-session remnant and the still-admin-credentialed-but-failing dot-apr-execute cron (Failed to connect to localhost:8055) are pre-existing items appropriate for the security gate — outside the scope of this disk-cleanup mission.