You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit f97d147
Browse filesBrowse the repository at this point in the historyBrowse files
feat(init): name a package.json pin older than the running CLI
An upgrade through a launcher leaves the project's own pins alone, and
those pins are what CI, scripts and git hooks run. After a migration, a
pin that predates the new schema refuses the project with
SCAFFOLD_VERSION_MISMATCH, so CI breaks on the push carrying the
migrated files.
init (batch and wizard) now names every bounded pin of @taskless/cli or
@taskless/cli-nightly that cannot reach the running version, in the
dependency fields or spelled out in a script, and offers the bump
without editing package.json. After a migration the notice states the
breakage as certain and ties the bump to the same commit as .taskless/.
init --json carries the pins as pinnedCli, and the update recipe (topic
v11) tells an agent to offer the bump.
`taskless init` names any `package.json` pin of `@taskless/cli` (a dependency entry, or a script spelling out `@taskless/cli@<version>`) that cannot resolve to the CLI that just ran, and offers bumping it as part of the upgrade. Scripts, CI and git hooks run that pin, and a CLI older than the project's `.taskless/` refuses the layout. The install does not edit `package.json`. `init --json` carries the pins as `pinnedCli`, and the `update` recipe (topic v11) tells an agent to offer the bump.
### Requirement: Init names a package.json pin older than the running CLI
4
+
5
+
After a successful install, `taskless init` SHALL read `package.json` in the working directory and report every pin of `@taskless/cli` or `@taskless/cli-nightly` that cannot resolve to the running CLI's version or later. A pin is:
6
+
7
+
- an entry in `dependencies`, `devDependencies`, or `optionalDependencies`; or
8
+
- a script in `scripts` that spells out `@taskless/cli@<spec>` or `@taskless/cli-nightly@<spec>`.
9
+
10
+
A pin SHALL be reported only when its spec is bounded and its bound sits below the running version: an exact version (optionally prefixed `=` or `v`), or a `^` or `~` range whose exclusive ceiling is at or below the running version, with caret ranges holding the left-most non-zero part as npm does. Versions SHALL be compared on their numeric core, ignoring a prerelease suffix. A spec the CLI cannot bound (`latest`, `*`, a comparator range, `workspace:`, a URL or git spec) SHALL NOT be reported. An absent or unparseable `package.json` SHALL produce no report and SHALL NOT fail the install.
11
+
12
+
The install SHALL NOT modify `package.json`. The report SHALL offer the bump rather than claim it.
13
+
14
+
On the human path (batch and wizard), when at least one pin is reported, the CLI SHALL print a notice naming each pin's location (the dependency field, or `scripts.<name>`), package and spec, stating that what runs those pins runs a CLI older than the project, and offering to update them to the running version. The notice SHALL print whether or not the run changed anything. On the batch path it SHALL print after the upgrade trailer, and the onboarding trailer SHALL remain the final line.
15
+
16
+
When the same run migrated `.taskless/`, the notice SHALL NOT hedge. It SHALL name the schema version the run wrote, state that a CLI predating that schema refuses the project with `SCAFFOLD_VERSION_MISMATCH` so CI running the pins will break on the push carrying the migrated files, and say the bump belongs in the same commit as `.taskless/`. Without a migration the notice SHALL describe the failure as likely, not certain.
17
+
18
+
Under `--json`, the envelope SHALL carry `pinnedCli`: an array of `{ location, name, spec }`, present on every successful run and empty when nothing is stale.
19
+
20
+
#### Scenario: A stale dependency and script pin are named and left alone
21
+
22
+
-**WHEN**`taskless init` runs at version `V` in a project whose `package.json` has `devDependencies["@taskless/cli"]` set to a version below `V`, and a script running `npx @taskless/cli@<older>`
23
+
-**THEN** stdout SHALL name both pins with their location and spec, and offer updating them to `V`
24
+
-**AND**`package.json` SHALL be byte-identical afterwards
25
+
-**AND** the notice SHALL appear after the upgrade trailer, with the onboarding trailer still the final line
26
+
27
+
#### Scenario: A pre-1.0 caret range that cannot reach the running version is stale
28
+
29
+
-**WHEN**`package.json` pins `@taskless/cli` at `^0.10.2` and the running CLI is `0.11.2`
30
+
-**THEN** the pin SHALL be reported
31
+
32
+
#### Scenario: A floating or current pin is not reported
33
+
34
+
-**WHEN**`package.json` pins `@taskless/cli` at `latest`, `*`, `>=0.10.0`, `workspace:*`, or a range that admits the running version, or a script runs `@taskless/cli@latest`
35
+
-**THEN** no pin SHALL be reported
36
+
37
+
#### Scenario: A migration makes the breakage definite
38
+
39
+
-**WHEN**`taskless init` migrates `.taskless/` to schema version `N` in a project with a stale pin
40
+
-**THEN** the notice SHALL name schema version `N` and `SCAFFOLD_VERSION_MISMATCH`
41
+
-**AND** SHALL state that CI running the pins will break, and that the bump belongs in the same commit as `.taskless/`
42
+
-**AND** SHALL NOT describe the failure as merely likely
43
+
44
+
#### Scenario: A stale pin is named on a re-install that changed nothing
45
+
46
+
-**WHEN**`taskless init` runs against a project that is already current and whose `package.json` holds a stale pin
47
+
-**THEN** stdout SHALL NOT contain the upgrade trailer
48
+
-**AND** stdout SHALL name the stale pin
49
+
50
+
#### Scenario: The JSON envelope carries the pins
51
+
52
+
-**WHEN**`taskless init --json` runs
53
+
-**THEN** the envelope SHALL contain `pinnedCli`, an array with one `{ location, name, spec }` entry per stale pin
54
+
-**AND**`pinnedCli` SHALL be an empty array when there is no `package.json` or nothing in it is stale
Copy file name to clipboardExpand all lines: openspec/specs/cli-init/spec.md
+53Lines changed: 53 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -825,3 +825,56 @@ The `migrated` field is unchanged: present with the migration report when a migr
825
825
-**WHEN**`taskless init --json` runs
826
826
-**THEN** the envelope SHALL contain `cliVersion.previous` (a string or `null`), `cliVersion.installed`, a `targets` array with one entry per install target, and a boolean `changed`
827
827
-**AND**`changed` SHALL be `true` exactly when `migrated` is present, any target's written or removed list is non-empty, or `cliVersion.previous` is non-null and differs from `cliVersion.installed`
828
+
829
+
### Requirement: Init names a package.json pin older than the running CLI
830
+
831
+
After a successful install, `taskless init` SHALL read `package.json` in the working directory and report every pin of `@taskless/cli` or `@taskless/cli-nightly` that cannot resolve to the running CLI's version or later. A pin is:
832
+
833
+
- an entry in `dependencies`, `devDependencies`, or `optionalDependencies`; or
834
+
- a script in `scripts` that spells out `@taskless/cli@<spec>` or `@taskless/cli-nightly@<spec>`.
835
+
836
+
A pin SHALL be reported only when its spec is bounded and its bound sits below the running version: an exact version (optionally prefixed `=` or `v`), or a `^` or `~` range whose exclusive ceiling is at or below the running version, with caret ranges holding the left-most non-zero part as npm does. Versions SHALL be compared on their numeric core, ignoring a prerelease suffix. A spec the CLI cannot bound (`latest`, `*`, a comparator range, `workspace:`, a URL or git spec) SHALL NOT be reported. An absent or unparseable `package.json` SHALL produce no report and SHALL NOT fail the install.
837
+
838
+
The install SHALL NOT modify `package.json`. The report SHALL offer the bump rather than claim it.
839
+
840
+
On the human path (batch and wizard), when at least one pin is reported, the CLI SHALL print a notice naming each pin's location (the dependency field, or `scripts.<name>`), package and spec, stating that what runs those pins runs a CLI older than the project, and offering to update them to the running version. The notice SHALL print whether or not the run changed anything. On the batch path it SHALL print after the upgrade trailer, and the onboarding trailer SHALL remain the final line.
841
+
842
+
When the same run migrated `.taskless/`, the notice SHALL NOT hedge. It SHALL name the schema version the run wrote, state that a CLI predating that schema refuses the project with `SCAFFOLD_VERSION_MISMATCH` so CI running the pins will break on the push carrying the migrated files, and say the bump belongs in the same commit as `.taskless/`. Without a migration the notice SHALL describe the failure as likely, not certain.
843
+
844
+
Under `--json`, the envelope SHALL carry `pinnedCli`: an array of `{ location, name, spec }`, present on every successful run and empty when nothing is stale.
845
+
846
+
#### Scenario: A stale dependency and script pin are named and left alone
847
+
848
+
-**WHEN**`taskless init` runs at version `V` in a project whose `package.json` has `devDependencies["@taskless/cli"]` set to a version below `V`, and a script running `npx @taskless/cli@<older>`
849
+
-**THEN** stdout SHALL name both pins with their location and spec, and offer updating them to `V`
850
+
-**AND**`package.json` SHALL be byte-identical afterwards
851
+
-**AND** the notice SHALL appear after the upgrade trailer, with the onboarding trailer still the final line
852
+
853
+
#### Scenario: A pre-1.0 caret range that cannot reach the running version is stale
854
+
855
+
-**WHEN**`package.json` pins `@taskless/cli` at `^0.10.2` and the running CLI is `0.11.2`
856
+
-**THEN** the pin SHALL be reported
857
+
858
+
#### Scenario: A floating or current pin is not reported
859
+
860
+
-**WHEN**`package.json` pins `@taskless/cli` at `latest`, `*`, `>=0.10.0`, `workspace:*`, or a range that admits the running version, or a script runs `@taskless/cli@latest`
861
+
-**THEN** no pin SHALL be reported
862
+
863
+
#### Scenario: A migration makes the breakage definite
864
+
865
+
-**WHEN**`taskless init` migrates `.taskless/` to schema version `N` in a project with a stale pin
866
+
-**THEN** the notice SHALL name schema version `N` and `SCAFFOLD_VERSION_MISMATCH`
867
+
-**AND** SHALL state that CI running the pins will break, and that the bump belongs in the same commit as `.taskless/`
868
+
-**AND** SHALL NOT describe the failure as merely likely
869
+
870
+
#### Scenario: A stale pin is named on a re-install that changed nothing
871
+
872
+
-**WHEN**`taskless init` runs against a project that is already current and whose `package.json` holds a stale pin
873
+
-**THEN** stdout SHALL NOT contain the upgrade trailer
874
+
-**AND** stdout SHALL name the stale pin
875
+
876
+
#### Scenario: The JSON envelope carries the pins
877
+
878
+
-**WHEN**`taskless init --json` runs
879
+
-**THEN** the envelope SHALL contain `pinnedCli`, an array with one `{ location, name, spec }` entry per stale pin
880
+
-**AND**`pinnedCli` SHALL be an empty array when there is no `package.json` or nothing in it is stale
0 commit comments