Skip to content

fix(init): stop --force wiping config.toml; guard skill overwrites#135

Merged
markovejnovic merged 1 commit into
mainfrom
relprep/9-fix-init-force-preserve-config
Jun 10, 2026
Merged

fix(init): stop --force wiping config.toml; guard skill overwrites#135
markovejnovic merged 1 commit into
mainfrom
relprep/9-fix-init-force-preserve-config

Conversation

@markovejnovic

Copy link
Copy Markdown
Contributor

Summary

hm init --force used to remove_dir_all the entire .hm/ directory before
rewriting a single template. In a repo with multiple pipelines (e.g.
pipeline.py + deploy.py, as examples/elixir-phoenix ships) plus a cloud
config.toml, --force silently destroyed everything but the one regenerated
template — silent data loss. This PR makes --force overwrite only the
target template file (std::fs::write clobbers just that path; .hm/ already
exists, so create_dir_all is a no-op), so config.toml, .gitignore, and
co-resident pipelines survive.

It also hardens write_skills, which previously clobbered each SKILL.md
unconditionally — destroying local edits on any re-run of hm init. It now
takes a force flag (threaded from args.force):

  • absent file → installed,
  • present but unchanged from the bundled copy → silent no-op,
  • present with local edits → skipped with a tracing::warn! pointing at --force.

The info log now distinguishes "installed" (new) from "overwrote" (force) for
honest feedback.

Findings addressed

  • init-force-wipes-dir-1--force no longer wipes the whole .hm/ dir.
  • init-skills-overwrite-1write_skills no longer silently clobbers customized skills.

Verification

Worktree /tmp/hmfix/9, branch rebased onto current origin/main so the PR
contains only the fix commit (3 files: init.rs, cmd_init.rs, CHANGELOG.md).

  • cargo test -p harmont-cli --lib commands::init4 passed, 0 failed
    (new unit tests: install-when-absent, preserve-without-force,
    force-overwrites, unchanged-no-op).
  • cargo test -p harmont-cli --test cmd_init init_force_preserves_coresident_files1 passed
    (asserts config.toml + deploy.py survive while the template is rewritten).
  • cargo test -p harmont-cli --test cmd_init23 passed, 1 failed. The
    single failure, init_ts_templates_roundtrip_render, is a pre-existing,
    environment-level
    failure (Bun cannot resolve the pipeline export in the
    bundled @harmont/hm/index.mjs). It reproduces identically with origin/main's
    copy of the touched files and is untouched by this change — not a regression.
  • cargo clippy -p harmont-cli --lib → clean, no warnings.

Judge verdict

Approved. Blocking issues: none.


Generated by the Harmont release-readiness workflow (automated; needs human review before merge). 🤖

`hm init --force` called `remove_dir_all` on the whole `.hm/` directory
before recreating it and writing a single template. A repo with multiple
pipelines (e.g. `pipeline.py` + `deploy.py`, as examples/elixir-phoenix
ships) plus a cloud `config.toml` lost everything but the one template on
`--force` — silent data loss. Now `--force` overwrites only the target
template file; `config.toml`, `.gitignore`, and co-resident pipelines
survive (the `.hm/` dir already exists, so `create_dir_all` is a no-op).

`write_skills` also unconditionally clobbered each `SKILL.md`, destroying
local edits whenever a user re-ran `hm init` and confirmed skills. It now
takes `force` (threaded from `args.force`): an absent file is installed,
an unchanged bundled file is a silent no-op, and a customized file is
skipped with a `tracing::warn!` pointing at `--force`. The info log now
distinguishes "installed" (new) from "overwrote" (force) for honest
feedback.

Tests: rewrote init_force_overwrites_existing -> init_force_preserves_
coresident_files (asserts config.toml + deploy.py survive while the
template is rewritten); added unit tests for write_skills covering
install / preserve-without-force / force-overwrite / unchanged-no-op.

Fixes: init-force-wipes-dir-1, init-skills-overwrite-1
@markovejnovic markovejnovic merged commit a65fcb7 into main Jun 10, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant