Closes#1390. One commit on top of next @ ae58482b-era tip.
Measured BEFORE (node 24, next@b2d40dad):uninstall < /dev/null prints the prompt, takes the default No, exits 0 having removed nothing — success-by-silence for every scripted caller. The issue's second symptom (piped-y ERR_USE_AFTER_CLOSE) does NOT reproduce on this runtime: readline yields '' at EOF and the flow aborts cleanly — documented as not-reproduced rather than claimed fixed.
Measured AFTER (fixture meta + data, all three shapes):
uninstall </dev/null (no flags) → refuse, rc=1, remediation text naming --yes/--remove-data, nothing touched
uninstall --yes </dev/null → proceeds, data KEPT (verified on disk), rc=0
uninstall --yes --remove-data </dev/null → proceeds, data REMOVED (verified on disk), rc=0
Design: --remove-data is never implied by --yes (destructive recursion is explicit opt-in); non-TTY WITHOUT consent fails loud rather than defaulting; interactive TTY behavior unchanged (both prompts as before). MOSAIC_ASSUME_YES=1 honored as headless consent, consistent with install.ts.
Tests: uninstall.spec.ts — 4 specs (fail-loud, keep-data, remove-data, clean no-op without meta). Build/lint/prettier clean via pre-push gates. Reviewer: rev-code-02 per commission.
Closes #1390. One commit on top of next @ ae58482b-era tip.
**Measured BEFORE (node 24, next@b2d40dad):** `uninstall < /dev/null` prints the prompt, takes the default No, exits 0 having removed nothing — success-by-silence for every scripted caller. The issue's second symptom (piped-y ERR_USE_AFTER_CLOSE) does NOT reproduce on this runtime: readline yields '' at EOF and the flow aborts cleanly — documented as not-reproduced rather than claimed fixed.
**Measured AFTER (fixture meta + data, all three shapes):**
- `uninstall </dev/null` (no flags) → refuse, **rc=1**, remediation text naming --yes/--remove-data, nothing touched
- `uninstall --yes </dev/null` → proceeds, **data KEPT** (verified on disk), rc=0
- `uninstall --yes --remove-data </dev/null` → proceeds, **data REMOVED** (verified on disk), rc=0
Design: --remove-data is never implied by --yes (destructive recursion is explicit opt-in); non-TTY WITHOUT consent fails loud rather than defaulting; interactive TTY behavior unchanged (both prompts as before). MOSAIC_ASSUME_YES=1 honored as headless consent, consistent with install.ts.
Tests: uninstall.spec.ts — 4 specs (fail-loud, keep-data, remove-data, clean no-op without meta). Build/lint/prettier clean via pre-push gates. Reviewer: rev-code-02 per commission.
Measured BEFORE (next @ b2d40dad, node 24): stdin </dev/null prints the
prompt, takes default No, exits 0 having removed nothing — success-by-
silence to every scripted caller. (The issue's piped-y ERR_USE_AFTER_CLOSE
crash does NOT reproduce on this runtime: readline yields '' at EOF and the
flow aborts cleanly; documented rather than claimed fixed.)
AFTER (all measured):
uninstall </dev/null -> refuse, rc=1, remediation text, nothing touched
uninstall --yes </dev/null -> proceeds, data KEPT, rc=0
uninstall --yes --remove-data -> proceeds, data REMOVED, rc=0
--remove-data is never implied by --yes (destructive recursion is opt-in);
interactive TTY behavior unchanged (both prompts as before).
APPROVED at head d0a17362 (pinned). PR #1422, #1390 uninstall headless. Reviewer rev-code-02 (usc); author ops-deploy-01 — Gate-16 clean. Merge per homelab orch-01 lane. CI status pending at post time — merge gate needs terminal green at this head.
== MEASURED BY ME (real CLI process, real disk, built tree) ==
Arm A (the #1390 symptom): gateway uninstall </dev/null no flags → rc=1, refuses with remediation naming --yes/--remove-data, data intact. The silent success-by-no-op is dead.
Arm B: --yes alone → proceeds rc=0, data KEPT on disk (verified). --remove-data is never implied — confirmed against the code (removeData = Boolean(opts.removeData), prompt only in the TTY branch).
Arm D: MOSAIC_ASSUME_YES=1 honored as headless consent, data kept — consistent with install.ts as claimed.
Arm E (not-installed no-op): rc=0, "Gateway is not installed."-family flow, nothing thrown — unchanged courtesy behavior.
Arm F (TTY preservation, real PTY via python pty.fork): prompts appear, answer "n" → "Aborted.", exit 0, data intact. Interactive path unchanged.
Spec 4/4 green under me (fail-loud, keep-data, remove-data, clean no-op).
The piped-y ERR_USE_AFTER_CLOSE non-reproduction on node 24 matches my runtime too; documenting it as not-reproduced (rather than claiming a fix) is the honest evidence bar — no change requested.
== SURFACE ==
3 files exactly (gateway.ts wiring, uninstall.ts, uninstall.spec.ts) +148/-15 matches; the force-reset transparency note checks out — d0a17362's tree carries no #1394 files (verified by name-only diff; only gateway.ts is shared with #1423, and it is wiring-only in both).
== NOTE (non-blocking) ==
Arm B/E run uninstallGatewayPackage() (npm uninstall) even when the package was never installed / data kept — harmless (npm reports up-to-date), just noisy output in scripted runs.
APPROVED at head d0a17362 (pinned). PR #1422, #1390 uninstall headless. Reviewer rev-code-02 (usc); author ops-deploy-01 — Gate-16 clean. Merge per homelab orch-01 lane. CI status pending at post time — merge gate needs terminal green at this head.
== MEASURED BY ME (real CLI process, real disk, built tree) ==
- Arm A (the #1390 symptom): `gateway uninstall </dev/null` no flags → rc=1, refuses with remediation naming --yes/--remove-data, data intact. The silent success-by-no-op is dead.
- Arm B: `--yes` alone → proceeds rc=0, data KEPT on disk (verified). --remove-data is never implied — confirmed against the code (removeData = Boolean(opts.removeData), prompt only in the TTY branch).
- Arm C: `--yes --remove-data` → proceeds rc=0, GATEWAY_HOME removed recursively (sentinel file gone, directory gone).
- Arm D: MOSAIC_ASSUME_YES=1 honored as headless consent, data kept — consistent with install.ts as claimed.
- Arm E (not-installed no-op): rc=0, "Gateway is not installed."-family flow, nothing thrown — unchanged courtesy behavior.
- Arm F (TTY preservation, real PTY via python pty.fork): prompts appear, answer "n" → "Aborted.", exit 0, data intact. Interactive path unchanged.
- Spec 4/4 green under me (fail-loud, keep-data, remove-data, clean no-op).
- The piped-y ERR_USE_AFTER_CLOSE non-reproduction on node 24 matches my runtime too; documenting it as not-reproduced (rather than claiming a fix) is the honest evidence bar — no change requested.
== SURFACE ==
3 files exactly (gateway.ts wiring, uninstall.ts, uninstall.spec.ts) +148/-15 matches; the force-reset transparency note checks out — d0a17362's tree carries no #1394 files (verified by name-only diff; only gateway.ts is shared with #1423, and it is wiring-only in both).
== NOTE (non-blocking) ==
Arm B/E run `uninstallGatewayPackage()` (npm uninstall) even when the package was never installed / data kept — harmless (npm reports up-to-date), just noisy output in scripted runs.
Gate-16: author ops-deploy-01; reviewer rev-code-02.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #1390. One commit on top of next @ ae58482b-era tip.
Measured BEFORE (node 24, next@b2d40dad):
uninstall < /dev/nullprints the prompt, takes the default No, exits 0 having removed nothing — success-by-silence for every scripted caller. The issue's second symptom (piped-y ERR_USE_AFTER_CLOSE) does NOT reproduce on this runtime: readline yields '' at EOF and the flow aborts cleanly — documented as not-reproduced rather than claimed fixed.Measured AFTER (fixture meta + data, all three shapes):
uninstall </dev/null(no flags) → refuse, rc=1, remediation text naming --yes/--remove-data, nothing toucheduninstall --yes </dev/null→ proceeds, data KEPT (verified on disk), rc=0uninstall --yes --remove-data </dev/null→ proceeds, data REMOVED (verified on disk), rc=0Design: --remove-data is never implied by --yes (destructive recursion is explicit opt-in); non-TTY WITHOUT consent fails loud rather than defaulting; interactive TTY behavior unchanged (both prompts as before). MOSAIC_ASSUME_YES=1 honored as headless consent, consistent with install.ts.
Tests: uninstall.spec.ts — 4 specs (fail-loud, keep-data, remove-data, clean no-op without meta). Build/lint/prettier clean via pre-push gates. Reviewer: rev-code-02 per commission.
210e516cd8tod0a17362ecAPPROVED at head
d0a17362(pinned). PR #1422, #1390 uninstall headless. Reviewer rev-code-02 (usc); author ops-deploy-01 — Gate-16 clean. Merge per homelab orch-01 lane. CI status pending at post time — merge gate needs terminal green at this head.== MEASURED BY ME (real CLI process, real disk, built tree) ==
gateway uninstall </dev/nullno flags → rc=1, refuses with remediation naming --yes/--remove-data, data intact. The silent success-by-no-op is dead.--yesalone → proceeds rc=0, data KEPT on disk (verified). --remove-data is never implied — confirmed against the code (removeData = Boolean(opts.removeData), prompt only in the TTY branch).--yes --remove-data→ proceeds rc=0, GATEWAY_HOME removed recursively (sentinel file gone, directory gone).== SURFACE ==
3 files exactly (gateway.ts wiring, uninstall.ts, uninstall.spec.ts) +148/-15 matches; the force-reset transparency note checks out — d0a17362's tree carries no #1394 files (verified by name-only diff; only gateway.ts is shared with #1423, and it is wiring-only in both).
== NOTE (non-blocking) ==
Arm B/E run
uninstallGatewayPackage()(npm uninstall) even when the package was never installed / data kept — harmless (npm reports up-to-date), just noisy output in scripted runs.Gate-16: author ops-deploy-01; reviewer rev-code-02.