diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md index 93a3fd1..aedbb72 100644 --- a/docs/roadmap/remediation.md +++ b/docs/roadmap/remediation.md @@ -1,15 +1,15 @@ # Release tooling review findings -Status: R1 complete; R2 open. Review baseline: +Status: R1 and R2 complete; no open findings. Review baseline: `124a9fa57fb3f815bedbafe2d4819f6aa265ee7d`, covering the implementation commits -after `cb40f1d`. This record requests corrections; no implementation was changed -during review. +after `cb40f1d`. The findings below preserve the review evidence; completion +markers record the subsequent corrections. No implementation was changed during +the original review. The selected architecture is substantially present: three declarative profiles, one host-normalized registered-tool helper, separate publication and page-only delivery, retained credential-directory ignoring, and focused wiring tests. -The following issues should be addressed before considering the refactor fully -complete. +Both issues identified by the review have been addressed. ## R1 — P2: Reject raw helper command names as legacy module selectors @@ -52,6 +52,16 @@ it adds no new accepted-version restriction. ## R2 — P2: Restore the tests' optional POSIX-shell execution boundary +**Completed.** Launcher execution tests now discover `sh`, invoke it explicitly +with the script path, and skip when it is unavailable. Profile assertions remain +independent of shell availability. A regression case removes the fixture +script's executable permission to verify interpreter invocation; it failed +before the correction and passes afterward. The focused scripts suite and shell +syntax checks passed with Go 1.26.8 on the available POSIX host. Running the +compiled test binary with an empty `PATH` confirmed that every launcher +execution case skips while all three profile assertions pass. Native Windows +execution was not tested and no new platform guarantee is introduced. + **Location:** [scripts/release_test.go](../../scripts/release_test.go), especially `fixture.run` at line 63 and the launcher test setup. diff --git a/scripts/release_test.go b/scripts/release_test.go index b70e92a..59d6fe6 100644 --- a/scripts/release_test.go +++ b/scripts/release_test.go @@ -60,12 +60,16 @@ esac func (f fixture) run(t *testing.T, script string, status int, args ...string) (string, string, int) { t.Helper() - cmd := exec.Command(filepath.Join(f.root, "scripts", script), args...) + shell, err := exec.LookPath("sh") + if err != nil { + t.Skip("POSIX shell is unavailable") + } + cmd := exec.Command(shell, append([]string{filepath.Join(f.root, "scripts", script)}, args...)...) cmd.Dir = f.outside cmd.Env = append(os.Environ(), "PATH="+filepath.Dir(f.root)+string(os.PathListSeparator)+os.Getenv("PATH"), "CALLS="+f.log, fmt.Sprintf("TOOL_STATUS=%d", status), "CDPATH=/tmp", "GOOS=windows", "GOARCH=arm64", "GOWORK=auto", "GOTOOLCHAIN=auto", "GOFLAGS=-trimpath -mod=mod") var stdout, stderr strings.Builder cmd.Stdout, cmd.Stderr = &stdout, &stderr - err := cmd.Run() + err = cmd.Run() if err == nil { return stdout.String(), stderr.String(), 0 } @@ -183,6 +187,17 @@ func TestStatusAndStreams(t *testing.T) { } } +func TestLauncherUsesShell(t *testing.T) { + f := newFixture(t) + if err := os.Chmod(filepath.Join(f.root, "scripts", "releasekit"), 0644); err != nil { + t.Fatal(err) + } + _, _, status := f.run(t, "releasekit", 0, "version") + if status != 0 { + t.Fatal(status) + } +} + func TestInvalidForms(t *testing.T) { for _, tc := range []struct { script string