KB-754E

03 - Deploy Plan & Rollback

6 min read Revision 1
dot-iu-cutterv0.6O6deploy-planrollbackG2

03 - Deploy Plan & Rollback

O6 · doc 3 of 8 · 2026-05-21 · Gate G2 — deploy plan lock. This plan is authored and locked but NOT executed — G3 is blocked on the source-availability gap (doc 04). The plan is the command-review-ready artifact for the macro that resolves the gap.

1. Prerequisite that must be satisfied BEFORE this plan can run

The v0.6 source tree at HEAD 6625f76 must be present on a Contabo-reachable path. See doc 04 §3 for the four accepted ways to deliver it. Until then, every step below is a plan, not a log.

2. Deploy target decision

Strategy Description Verdict
Replace in-place overwrite /opt/incomex/dot/iu-cutter (v0.4→v0.6) rejected for first deploy — destructive
Side-by-side new dir /opt/incomex/dot/iu-cutter-v0.6/; v0.4 left intact CHOSEN
Timestamped release /opt/incomex/deploys/iu-cutter-v0.6-6625f76-<stamp>/ + pointer acceptable alternative

Decision: side-by-side, non-destructive.

deploy_target:  /opt/incomex/dot/iu-cutter-v0.6/
backup_of_v0.4: not required to MOVE v0.4 — it stays in place untouched;
                additionally /opt/incomex/dot is a git repo (history = backup)
release_stamp:  record HEAD 6625f76 + UTC stamp in a DEPLOY-MANIFEST.txt
                inside the target dir
invocation:     orchestrator is a manual CLI — callers use an explicit
                path; no symlink/service switch needed
promotion:      replacing v0.4 in-place is deferred until AFTER O7
                post-deploy dry-run PASS (separate, reviewed step)

Rationale: iu-cutter is not a long-running service, so a new directory introduces zero runtime risk; rollback is a single rm -rf of a dir the macro itself created; v0.4 is never at risk.

3. Backup rule

v0.4_tree:   left in place, untouched; dot-repo git history is its backup
pre_state:   record sha256 of the deploy target's parent listing before
             creating the new dir; record that the new dir did not pre-exist
no overwrite of any pre-existing path

4. Rollback command (exact)

# side-by-side rollback — removes ONLY what O6 created:
rm -rf /opt/incomex/dot/iu-cutter-v0.6
# v0.4 at /opt/incomex/dot/iu-cutter is untouched → nothing else to undo
# no service to restart; no DB change; no .env change

If a later macro promotes v0.6 in-place, rollback becomes git -C /opt/incomex/dot checkout -- iu-cutter (or restore the timestamped backup) — out of scope for O6.

5. Smoke command set (to run in G5/G6 once deployed)

G5_static_and_unit:
  - py_compile:   python3 -m compileall /opt/incomex/dot/iu-cutter-v0.6
  - import:       python3 -c "import cutter_agent, cutter_agent.orchestrator"
  - version:      assert cutter_agent.__version__ startswith 0.6
  - kill_switch:  assert orchestrator.__execution_enabled__ is False
  - tests:        python3 -m pytest tests/ -q   (expect 366/366)
  - status:       python3 cli.py orchestrate inspect / status
                  → milestone O4/O6-ready, execution_enabled=False
G6_readonly_dryrun_smoke:
  - mode:         Mode.DRYRUN only
  - role:         context_pack_readonly  (read-only, proven in O3/O4)
  - txn:          BEGIN READ ONLY ... ROLLBACK around every live SQL
  - assert:       pre/post production counts identical; Mode.LIVE refused
  - forbidden:    no INSERT/UPDATE/DELETE; no fn_iu_create/fn_iu_enact;
                  no review_decision/verify_result write

6. No-secret logging rules

- no `set -x` in any deploy/smoke wrapper
- never read or print .env / .env.production VALUES; env-var NAMES only
- artifact dir: timestamped, chmod 700
- redact any DSN/password if a tool would echo it
- KB reports: secrets stripped on serialize (kb_reporter doctrine)

7. Runtime skeleton plan (G4 — deferred, not executed)

To be provisioned only after a successful deploy, non-secret only:

dirs:   /var/lib/cutter/runs , /var/lib/cutter/batches , /var/lib/cutter/locks
config: orchestrator.* keys (sidecar_root, batch_dir, global_locks_dir,
        expected_grant_matrix_sha = 45d25e38...e2d600 from O4,
        run_hard_cap_minutes, phase_soft_cap_minutes)
secrets: NONE written by O6; existing env-file secrets used read-only
         for read-only smoke if needed, values never logged
execution_enabled: stays False

O6 did not create these dirs — the host is left 100% untouched because the deploy is blocked (doc 04). They are planned here so the follow-up macro can provision them in one reviewed step.

8. STOP condition check

The G2 mandate says "If unsafe/ambiguous: STOP." The plan above is safe and unambiguous as a plan, but it cannot be executed: its §1 prerequisite (v0.6 source on a Contabo-reachable path) is not met. → Proceed to doc 04, which records the exact block.

9. G2 result

G2_deploy_plan: LOCKED (authored, command-review-ready)
G2_executable_now: NO — blocked on the §1 source-availability prerequisite
target:   /opt/incomex/dot/iu-cutter-v0.6/   (side-by-side, non-destructive)
rollback: rm -rf /opt/incomex/dot/iu-cutter-v0.6   (v0.4 untouched)
Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.6-o6-release-deploy-postdeploy-dryrun-readiness/03-deploy-plan-and-rollback-2026-05-21.md