openmillas 0.4.0 — installer UX + TD-21 + TD-26 + workflow convention #14

Open
MillasAgent wants to merge 4 commits from feat/installer-interactive-ux into main
Owner

openmillas 0.4.0 — installer UX + lib/cli.sh extraction + TD-26 + workflow convention

This is PR 1 of 3 in the installer-interactive-ux-and-mit-license umbrella improvement. PR 2 (add-mit-license) and PR 3 (readme-cli-usage) follow on separate branches.

Resolves

  • TD-21 (install.sh + openmillas duplicate subcommand bodies) — closed.
  • TD-26 (cmd_doctor git-check missing) — closed.

Installer UX (AC-1..AC-5)

cmd_install rewritten with a 4-step guided flow: (1) prereqs with version capture (bash 4+, python3 3.6+, git, OS), (2) local-vs-remote openmillas version compare via fetch_remote_version, (3) optional integrations one-at-a-time with [1/3]/[2/3]/[3/3] section markers, (4) applying. Banner + ================================================== header on every install path. Pure bundle install (--yes --no-interaction) preserves the existing short-circuit.

delegate_context7 switched from npx ctx7 setup (which hung on the agent-selection prompt in --no-interaction) to CTX7_TELEMETRY_DISABLED=1 npx -y ctx7 setup --opencode --yes with a manual mcp.context7 heredoc fallback. Verified against the npmjs ctx7 README + @upstash/context7-mcp "Install in Opencode" section.

TD-21 — lib/cli.sh extraction

New workspace/opencode/lib/cli.sh (~325 lines) with 6 public functions: prompt_yn, cmd_uninstall, cmd_doctor (with M19 JSONC fallback baked in as explicit if declare -F jsonc_strip branch), cmd_update, cmd_version, fetch_remote_version. Both install.sh and openmillas source it.

Deploy model (resolves the deploy / de-adapter asymmetry flagged by the arch-quality-reviewer): install_openmillas_cli now deploys lib/cli.sh, lib/jsonc.sh, lib/_jsonc_strip.py to ${HOME}/.local/lib/. cmd_uninstall symmetrically removes those 3 files (new regression test do_test_uninstall_removes_local_lib_files proves it).

TD-26 — doctor git check

9th check added to cmd_doctor: git available (>= 2.x). Asserts presence and captures the version. New regression test do_test_doctor_checks_git.

Workflow convention (.internal/, gitignored)

Formalized three-role convention for the orchestrator's working memory: specs/<branch-slug>.md (architect-drafted implementation spec), plans/<branch-slug>.md (orchestrator-drafted to-do), reports/<flow>-<slug>-<role>.md (raw subagent output). Documented in AGENTS.md §6 and shipped via the orchestrator + /init flow updates in this PR. Same convention this PR itself uses (artifacts at .internal/specs/installer-interactive-ux.md, .internal/plans/installer-interactive-ux.md, .internal/reports/feature-installer-interactive-ux-{analyzer,diff-context,security,arch}.md).

Test suite

38 PASS / 0 FAIL (stable across 8 of 10 runs; the 2 occasional failures are the pre-existing do_test_install_idempotent mtime flake documented in test_install.sh comments). deploy.sh --check PASS.

Six new tests: do_test_cli_sh_sourced_by_both_scripts, do_test_doctor_checks_git, do_test_install_prints_prereq_versions, do_test_install_prints_local_vs_remote_version, do_test_install_prompts_are_sectioned, do_test_install_context7_delegation_uses_opencode_flag, do_test_uninstall_removes_local_lib_files. Plus a stub fix for do_test_install_curl_pipe_stdin_bundle_clone (git stub now creates a fake lib/cli.sh in the cloned bundle).

Double-blind review

  • security-auditor: APPROVED (3 info-level findings: TD-20 SHA-256 pin deferred, curl redirect scheme pinning deferred, jsonc_patch_global_config perm-relaxation pre-existing in main).
  • arch-quality-reviewer: needs-changes → M1 fixed in the review commit (chore(review): address arch-quality-reviewer findings). 1 MAJOR + 8 MINOR + 4 NIT. MAJOR closed. Minor findings m5-m9 (constants-to-lib/config.sh refactor, lib/cli.sh rename, XDG path) deferred to a follow-up PR — they require a separate refactor outside the scope of this UX improvement.

Commits

5725df9 chore(review): address arch-quality-reviewer findings (M1 + m2 + m3 + m4)
50f240a chore(workflow): formalize .internal/ three-role convention in orchestrator + /init
db8ebfa chore(docs): AGENTS.md version bump + Internal artifact convention
85381cc chore(release): openmillas 0.4.0 — installer UX + lib/cli.sh extraction + TD-26

User-known caveats (out of PR scope)

  • AGENTS.md §9 still references "See §5.8" for L-036, but the user's local §5.8↔§5.9 swap (committed as part of chore(docs)) renumbered §5.9 → §5.8. The §9 cross-reference is now broken (§5.8 is Local-only host setup). User to fix in a follow-up.
## openmillas 0.4.0 — installer UX + lib/cli.sh extraction + TD-26 + workflow convention This is **PR 1 of 3** in the `installer-interactive-ux-and-mit-license` umbrella improvement. PR 2 (`add-mit-license`) and PR 3 (`readme-cli-usage`) follow on separate branches. ### Resolves - **TD-21** (`install.sh` + `openmillas` duplicate subcommand bodies) — closed. - **TD-26** (`cmd_doctor` git-check missing) — closed. ### Installer UX (AC-1..AC-5) `cmd_install` rewritten with a 4-step guided flow: (1) prereqs with version capture (bash 4+, python3 3.6+, git, OS), (2) local-vs-remote openmillas version compare via `fetch_remote_version`, (3) optional integrations one-at-a-time with `[1/3]/[2/3]/[3/3]` section markers, (4) applying. Banner + `==================================================` header on every install path. Pure bundle install (`--yes --no-interaction`) preserves the existing short-circuit. `delegate_context7` switched from `npx ctx7 setup` (which hung on the agent-selection prompt in `--no-interaction`) to `CTX7_TELEMETRY_DISABLED=1 npx -y ctx7 setup --opencode --yes` with a manual `mcp.context7` heredoc fallback. Verified against the npmjs `ctx7` README + `@upstash/context7-mcp` "Install in Opencode" section. ### TD-21 — `lib/cli.sh` extraction New `workspace/opencode/lib/cli.sh` (~325 lines) with 6 public functions: `prompt_yn`, `cmd_uninstall`, `cmd_doctor` (with **M19 JSONC fallback baked in** as explicit `if declare -F jsonc_strip` branch), `cmd_update`, `cmd_version`, `fetch_remote_version`. Both `install.sh` and `openmillas` source it. **Deploy model** (resolves the deploy / de-adapter asymmetry flagged by the arch-quality-reviewer): `install_openmillas_cli` now deploys `lib/cli.sh`, `lib/jsonc.sh`, `lib/_jsonc_strip.py` to `${HOME}/.local/lib/`. `cmd_uninstall` symmetrically removes those 3 files (new regression test `do_test_uninstall_removes_local_lib_files` proves it). ### TD-26 — doctor git check 9th check added to `cmd_doctor`: `git available (>= 2.x)`. Asserts presence and captures the version. New regression test `do_test_doctor_checks_git`. ### Workflow convention (`.internal/`, gitignored) Formalized three-role convention for the orchestrator's working memory: `specs/<branch-slug>.md` (architect-drafted implementation spec), `plans/<branch-slug>.md` (orchestrator-drafted to-do), `reports/<flow>-<slug>-<role>.md` (raw subagent output). Documented in AGENTS.md §6 and shipped via the orchestrator + `/init` flow updates in this PR. Same convention this PR itself uses (artifacts at `.internal/specs/installer-interactive-ux.md`, `.internal/plans/installer-interactive-ux.md`, `.internal/reports/feature-installer-interactive-ux-{analyzer,diff-context,security,arch}.md`). ### Test suite **38 PASS / 0 FAIL** (stable across 8 of 10 runs; the 2 occasional failures are the pre-existing `do_test_install_idempotent` mtime flake documented in `test_install.sh` comments). `deploy.sh --check` PASS. Six new tests: `do_test_cli_sh_sourced_by_both_scripts`, `do_test_doctor_checks_git`, `do_test_install_prints_prereq_versions`, `do_test_install_prints_local_vs_remote_version`, `do_test_install_prompts_are_sectioned`, `do_test_install_context7_delegation_uses_opencode_flag`, `do_test_uninstall_removes_local_lib_files`. Plus a stub fix for `do_test_install_curl_pipe_stdin_bundle_clone` (git stub now creates a fake `lib/cli.sh` in the cloned bundle). ### Double-blind review - **security-auditor**: APPROVED (3 info-level findings: TD-20 SHA-256 pin deferred, `curl` redirect scheme pinning deferred, `jsonc_patch_global_config` perm-relaxation pre-existing in `main`). - **arch-quality-reviewer**: needs-changes → M1 fixed in the review commit (`chore(review): address arch-quality-reviewer findings`). 1 MAJOR + 8 MINOR + 4 NIT. **MAJOR closed**. Minor findings m5-m9 (constants-to-lib/config.sh refactor, `lib/cli.sh` rename, XDG path) deferred to a follow-up PR — they require a separate refactor outside the scope of this UX improvement. ### Commits ``` 5725df9 chore(review): address arch-quality-reviewer findings (M1 + m2 + m3 + m4) 50f240a chore(workflow): formalize .internal/ three-role convention in orchestrator + /init db8ebfa chore(docs): AGENTS.md version bump + Internal artifact convention 85381cc chore(release): openmillas 0.4.0 — installer UX + lib/cli.sh extraction + TD-26 ``` ### User-known caveats (out of PR scope) - AGENTS.md §9 still references "See §5.8" for L-036, but the user's local §5.8↔§5.9 swap (committed as part of `chore(docs)`) renumbered §5.9 → §5.8. The §9 cross-reference is now broken (§5.8 is Local-only host setup). **User to fix in a follow-up.**
### Installer UX (AC-1..AC-5)
- `install.sh` `cmd_install` rewritten with a 4-step guided flow: (1) prereqs
  with version capture (bash 4+, python3 3.6+, git, OS), (2) local-vs-remote
  openmillas version compare, (3) optional integrations one-at-a-time with
  [1/3]/[2/3]/[3/3] section markers, (4) applying.
- Banner + section headers on every install path. Pure bundle install
  (--yes --no-interaction) short-circuits to a single header + bundle copy.
- `delegate_context7` switched from `npx ctx7 setup` (which hung on the
  agent-selection prompt) to `CTX7_TELEMETRY_DISABLED=1 npx -y ctx7
  setup --opencode --yes` with a manual mcp.context7 heredoc fallback.
  Verified against npmjs.com/package/ctx7 + @upstash/context7-mcp.

### TD-21: lib/cli.sh extraction (resolves)
- New `workspace/opencode/lib/cli.sh` (~455 lines) with the 6 public
  functions: prompt_yn, cmd_uninstall, cmd_doctor, cmd_update,
  cmd_version, fetch_remote_version. M19 JSONC fallback baked into
  cmd_doctor as explicit `if declare -F jsonc_strip` branch.
- install.sh and openmillas now source lib/cli.sh (3-way fallback in
  install.sh; 4-path lookup in openmillas).
- install_openmillas_cli deploys lib/cli.sh, lib/jsonc.sh, lib/_jsonc_strip.py
  to ~/.local/lib/ (deploy model per openmillas comment line 31-35).
- Net: ~446 duplicated lines removed.

### TD-26: doctor git check (resolves)
- 9th check added to cmd_doctor: `git available (>= 2.x)`.
  Asserts presence and captures the version.

### Python minimum enforced
- require_prereqs now enforces Python 3.6+ (binding minimum per PEP 498
  f-strings used in lib/jsonc.sh and deploy.sh heredocs).

### fetch_remote_version helper
- New public function in lib/cli.sh — `curl -fsSL --max-time 10 --retry 2`
  + strict-semver awk regex. Used by cmd_install (AC-3), cmd_update,
  cmd_version --remote.

### Tests (added in this commit)
- do_test_cli_sh_sourced_by_both_scripts (verifies lib/cli.sh exists +
  install.sh/openmillas source it)
- do_test_doctor_checks_git (verifies the 9th doctor check)
- do_test_install_prints_prereq_versions (AC-1, AC-2)
- do_test_install_prints_local_vs_remote_version (AC-3)
- do_test_install_context7_delegation_uses_opencode_flag (AC-4)
- do_test_install_prompts_are_sectioned (AC-4)
- Plus stub fix for do_test_install_curl_pipe_stdin_bundle_clone
  (git stub now creates a fake lib/cli.sh in the cloned bundle).

Test suite: 37 PASS / 0 FAIL. `bash workspace/opencode/deploy.sh --check` PASS.

Resolves: TD-21, TD-26
- **Version** line bumped from 0.3.5 to 0.4.0 on `main`.
- **§6 (Architectural notes)** gains the "Internal artifact convention
  (`.internal/`, gitignored)" bullet, formalizing the three-role
  convention (specs / plans / reports) plus the workflow steps.
- **§9 (Operational checklist)** gains the "If this change produced
  `.internal/` artifacts, they follow the three-role convention" item.

Note: this commit also includes a pre-existing local edit (user's
§5.8↔§5.9 swap and `.opencode/agents.md`→`.opencode/AGENTS.md`
case fix) that was already dirty in the working tree when PR 1 work
started. The §9 cross-reference to "§5.8 for L-036" is now broken
(§5.8 is Local-only host setup) — the user will address this in a
follow-up.
Aligns the orchestrator's Persistence discipline + `/init` flow with
the actual three-role convention (specs = architect-drafted; plans =
orchestrator-drafted to-do; reports = raw subagent output) that is
already documented in the project's root AGENTS.md §6 and used by
this very PR.

### agents/orchestrator.md
- §Persistence discipline rewritten: three-role convention spelled out
  with branch-slug naming, the workflow steps (write spec, dispatch
  code-analyzer → reports, dispatch architect → spec, persist spec →
  plans, draft plan → approval → implementer).
- `/init` flow gains a step that requires the generated AGENTS.md to
  include the §6 Internal artifact convention section (so future
  `/init` on other repos inherits the convention).
- `/feature` and `/bugfix` flows' step 6a simplified: persist a single
  `.internal/plans/<slug>.md` (no JSON wrapper). The spec is persisted
  to `.internal/specs/<slug>.md`.

### command/init.md
- Bullet for AGENTS.md generation expanded with the mandatory §6
  Internal artifact convention reference.

Resolves the spec/plan metaspec gap: the orchestrator's own prompt
now matches the repo convention that PR 1 itself uses.

Follow-up (out of scope here): the `agents/orchestrator.md` itself ships
with the bundle — this PR makes the deployed orchestrator consistent
with the convention PR 1 established.
Double-blind review by `arch-quality-reviewer` flagged 1 MAJOR + 8 MINOR + 4 NIT.
This commit resolves the MAJOR (deploy / de-adapter asymmetry) and the 3 cheap
MINORS that are tied to the lib/cli.sh extraction. The remaining minors (m5-m9)
are deferred — they require moving shared globals to a new `lib/config.sh`
(separate refactor, out of scope for PR 1).

### M1: cmd_uninstall now removes ~/.local/lib/ files (deploy / de-adapter symmetry)
- `lib/cli.sh:cmd_uninstall` adds a third loop over `$OPENMILLAS_LIB_DIR`
  removing `cli.sh`, `jsonc.sh`, `_jsonc_strip.py`, then `rmdir`s the directory
  if empty. Mirrors the deploy loop in `install.sh:install_openmillas_cli`
  (was install.sh:430-436).
- After `openmillas uninstall`, no files from the bundle remain in
  `~/.local/lib/`. The deploy and the de-adapter are now symmetric.
- New regression test: `do_test_uninstall_removes_local_lib_files` — runs
  install, asserts the 3 files are at `~/.local/lib/`, runs uninstall, asserts
  they are gone + the directory is empty.
- Test suite: 38 PASS / 0 FAIL (37 prior + 1 new).

### m2: AGENTS.md §3 layout tree updated to list `lib/cli.sh`
- Added `│   │   ├── cli.sh          shared subcommand bodies (TD-21; sourced by install + openmillas)`
  between `jsonc.sh` and `_jsonc_strip.py`. Doc was out-of-sync with reality
  after the TD-21 extraction.

### m3: Removed dead `_CLI_LIB_DIR` from `lib/cli.sh:58`
- The variable was set but never referenced anywhere — the comment claimed it
  mirrored the `_JSONC_LIB_DIR` pattern, but no consumer existed.
- 6-line comment + assignment deleted.

### m4: Removed unreachable third branch in `install.sh:51-68` source block
- The BASH_SOURCE[0] fallback was unreachable: if BASH_SOURCE[0] is a real file,
  line 27 already set SCRIPT_DIR from it, and the first branch
  (`-f "${SCRIPT_DIR}/lib/cli.sh"`) succeeds with the same file.
- 8 lines deleted; the comment now states the two reachable branches only.

Deferred (tracked as follow-ups in the arch review report):
- m5: OPENMILLAS_VERSION duplicated in install.sh + openmillas
- m6: BACKUP_ROOT dead in openmillas
- m7: implicit globals coupling (move to lib/config.sh)
- m8: `lib/cli.sh` name (rename to `lib/commands.sh`?)
- m9: `~/.local/lib/` non-XDG (documented non-convention)
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/installer-interactive-ux:feat/installer-interactive-ux
git switch feat/installer-interactive-ux

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff feat/installer-interactive-ux
git switch feat/installer-interactive-ux
git rebase main
git switch main
git merge --ff-only feat/installer-interactive-ux
git switch feat/installer-interactive-ux
git rebase main
git switch main
git merge --no-ff feat/installer-interactive-ux
git switch main
git merge --squash feat/installer-interactive-ux
git switch main
git merge --ff-only feat/installer-interactive-ux
git switch main
git merge feat/installer-interactive-ux
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MillasDev/memory!14
No description provided.