Skip to content

fix(init): install a nightly beside the release, and retire it on a release install - #572

Merged
theCodeDrift merged 2 commits into
mainfrom
fix/nightly-alongside-release
Oct 22, 2026
Merged

theCodeDrift merged 2 commits into
mainfrom
fix/nightly-alongside-release

Conversation

@theCodeDrift

Copy link
Copy Markdown
Member

Moving a production project from the nightly back to mainline showed the two channels don't behave as a pair. A nightly should install beside the release without switching what scripts, CI, and hooks run, and installing the release should clean the nightly up.

A nightly installs beside the release

  • init no longer offers to move @taskless/cli pins in package.json scripts, CI files, or hooks onto @taskless/cli-nightly.
  • If the nightly migrated an existing .taskless/, a release pin is still listed, marked "leave as is", with a warning that a release older than the new schema refuses the project.
  • Fixes a gap where a manifest from before install.launchers recorded the release only as install.cliVersion. A nightly init overwrote it, and .taskless/bin/cli.mjs was left with no version to run. That version is now carried into install.launchers.

A release install retires the nightly

  • Removes .taskless/bin/cli-nightly.mjs and cli-nightly.lock.json, and drops the nightly's install.launchers entry, so its cached build gets pruned. init --json gains retired, listing the files it removed.
  • Removes @taskless/cli-nightly rules from harness permission files. This reverses the symmetric "keep each other's rules" behavior for the release direction only.
  • Flags every leftover @taskless/cli-nightly pin in scripts, CI, or hooks, including one newer than the release.
  • Leaves the user-level global trust entry alone, since other projects may still use the nightly.

Dependencies on the CLI

Any package.json dependency on @taskless/cli or @taskless/cli-nightly is now flagged for removal in favor of the project launcher, whatever its version. Each pinnedCli entry now carries a reason: dependency, stale, nightly, or unreleased. The notice gives each entry its action.

Recipes updated: init v15, update v20, info v4. The OpenSpec change nightly-alongside-release is archived in this PR.

Verification

  • pnpm typecheck, pnpm lint, and the full CLI suite pass (2651 tests, including the nightly project).
  • Ran the built release CLI against a scratch project carrying a nightly launcher, lockfile, permission rule, dependency, and nightly script. It retired both files, removed the rule, and flagged the dependency (dependency) and the script (nightly).

…elease install

A nightly init no longer offers to move @taskless/cli pins onto the nightly,
and keeps the release's version when only install.cliVersion recorded it. A
release init removes the nightly's launcher, lockfile, recorded version, and
permission rules, and raises nightly pins left in scripts, CI, or hooks. Any
package.json dependency on the CLI is raised for removal in favour of the
project launcher, and pinnedCli entries carry a reason.
@theCodeDrift

Copy link
Copy Markdown
Member Author

@claude /review

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @theCodeDrift's task in 3m 57s —— View job


Review complete

Review mode: incremental — read 0 prior review thread(s) before reviewing. .prior-review.json held no prior review threads, review summaries, or top-level comments beyond the trigger comment itself, so this is the first review pass on this PR.

Todo list

  • Read .prior-review.json (nothing to carry forward)
  • Fetch PR diff and metadata (gh pr diff, gh pr view --json commits,headRefOid,files)
  • Review core logic: pinned-cli.ts, launcher.ts, install.ts, permissions.ts
  • Review command/schema/wizard changes
  • Review test coverage
  • Review OpenSpec docs for consistency

Assessment

I read the full diff and the current contents of the touched source files (install/pinned-cli.ts, install/launcher.ts, install/install.ts, install/permissions.ts, commands/init.ts, commands/info.ts, wizard/index.ts, schemas/info.ts) against the OpenSpec requirements this PR adds/modifies, plus the test suites that exercise them. I found nothing to raise. Specifically I traced:

  • channelVerdict/scriptPinReason (pinned-cli.ts:71-357) against every "channels"/"nightly ordering" scenario in the archived spec — the nightly-leaves-release-alone, release-raises-nightly-whatever-its-version, and migration→unreleased paths all match the spec text and the corresponding tests in pinned-cli.test.ts.
  • getPinnedCliNotice's paragraph selection (pinned-cli.ts:589-613) — the has("stale") || (has("dependency") && migration !== undefined) condition looked suspicious in isolation (mixing two reasons into one breakage paragraph), but it's exactly what the "asks for a reinstall only when a dependency is raised" / "points a removed dependency at the launcher" tests pin down: a bare dependency with no migration correctly gets no "will likely fail" claim, while stale always does. Matches spec and tests.
  • Launcher retirement (install.ts:597-692, launcher.ts:190-217) — recordedLauncherVersion correctly carries a pre-install.launchers release version into the new field before a nightly overwrites cliVersion; retiredLauncherPackage only fires for a release build; pruneLauncherCache runs against the already-retired nextState.launchers, so the nightly's cache entry is correctly pruned. Verified against install-launcher.test.ts and install-launcher-nightly.test.ts.
  • Permission rule asymmetry (permissions.ts:869-964) — isRetired/isOther correctly exclude the nightly's rules from the "other package, leave alone" set only when the installed invocation is the release, including the "harness no longer selected" and "file Taskless created becomes empty" paths. Verified against the new/renamed tests in permissions.test.ts.
  • Doc/schema consistency — agent/init.md, agent/update.md, agent/info.md, schemas/info.ts, and the non-archived openspec/specs/* all describe the reason field and retired array consistently with the implementation; no leftover references to the old findStalePins name or old notice headers (UPDATE PINNED TASKLESS VERSIONS, "pins a Taskless CLI older") anywhere in packages/cli/src or openspec/specs.

No correctness, security, performance, or test-adequacy issues found. The regex-based pin detection (SCRIPT_PIN, BOUNDED_SPEC) uses only fixed-length lookbehind and simple negated-character-class quantifiers, so there's no ReDoS exposure. The workspace-glob expansion caps reads at MAX_WORKSPACE_MANIFESTS and excludes node_modules/.git, matching the spec's bound on tree traversal.
· Branch: fix/nightly-alongside-release

@theCodeDrift

Copy link
Copy Markdown
Member Author

Re: @github-actions — "Claude finished @theCodeDrift's task in 3m 57s — Review complete…"
#572 (comment)

Thanks — the review raised no findings, so there is nothing to change. CI is green on the current head.

— AI Coding Agent

@theCodeDrift
theCodeDrift merged commit 772a542 into main Oct 22, 2026
8 checks passed
@theCodeDrift
theCodeDrift deleted the fix/nightly-alongside-release branch October 22, 2026 00:30
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