@zalom/plastic 1.0.0-alpha.18 → 1.0.0-alpha.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ # frozen_string_literal: true
4
+
5
+ # Plastic — `uninstall` verb. Runs via `npx @zalom/plastic uninstall` (bin/plastic.js) or directly.
6
+ # Usage: ruby scripts/uninstall.rb [--claude|--codex|--hermes|--all] [--help]
7
+ #
8
+ # Manifest-driven removal of installed files + legacy-plugin migration. Leaves ~/.plastic/
9
+ # (intent store, config, and the versions.json ledger) in place — the ledger is permanent.
10
+
11
+ require_relative "lib/installer_core"
12
+
13
+ class Uninstall < InstallerCore
14
+ def cli(argv = ARGV)
15
+ if argv.include?("--help") || argv.include?("-h")
16
+ show_help
17
+ return 0
18
+ end
19
+
20
+ selected = agent_keys_from(argv)
21
+ selected = ["claude"] if selected.empty?
22
+
23
+ puts "\n\u{1f9e0} Plastic v#{version} — uninstall\n\n"
24
+ handle_uninstall(selected)
25
+ 0
26
+ end
27
+
28
+ private
29
+
30
+ def show_help
31
+ puts <<~HELP
32
+
33
+ plastic uninstall — remove Plastic from an agent
34
+
35
+ Usage:
36
+ npx @zalom/plastic uninstall [options]
37
+
38
+ Agent options:
39
+ --claude Uninstall from Claude Code (default)
40
+ --codex Uninstall from Codex CLI
41
+ --hermes Uninstall from Hermes
42
+ --all Uninstall from all supported agents
43
+
44
+ Other options:
45
+ -h, --help Show this help
46
+
47
+ Leaves your intent store, config, and version ledger (~/.plastic/) in place.
48
+
49
+ HELP
50
+ end
51
+ end
52
+
53
+ exit(Uninstall.new(package_root: ENV["PLASTIC_PACKAGE_ROOT"] || File.expand_path("..", __dir__)).cli(ARGV)) if $PROGRAM_NAME == __FILE__
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ # frozen_string_literal: true
4
+
5
+ # Plastic — `update` verb. Runs via `npx @zalom/plastic update` (bin/plastic.js) or directly.
6
+ # Usage: ruby scripts/update.rb [--beta|--latest|--alpha] [--claude|--codex|--hermes|--all] [--help]
7
+ #
8
+ # Forward-only version transitions, sourced from npm dist-tags:
9
+ # - no flag = next version on the CURRENT channel (derived from VERSION)
10
+ # - --beta/--latest/--alpha = switch channel. Toward stability (alpha->beta->latest) is
11
+ # frictionless; toward bleeding edge requires confirmation.
12
+ # "Already up to date" is a clean no-op. Performs the switch by delegating the file-sync to
13
+ # `install --reinstall --ledger-action update` for the chosen version via npx.
14
+
15
+ require_relative "lib/installer_core"
16
+
17
+ class Update < InstallerCore
18
+ PKG = "@zalom/plastic"
19
+
20
+ def cli(argv = ARGV)
21
+ if argv.include?("--help") || argv.include?("-h")
22
+ show_help
23
+ return 0
24
+ end
25
+
26
+ iv = installed_version
27
+ unless iv
28
+ warn "Plastic is not installed. Run: npx #{PKG} install --claude"
29
+ return 1
30
+ end
31
+
32
+ requested = requested_channel(argv)
33
+ tags = fetch_dist_tags
34
+ unless tags
35
+ warn "Could not query npm dist-tags. Are you online?"
36
+ return 1
37
+ end
38
+
39
+ res = compute_target(installed_version: iv, dist_tags: tags, requested_channel: requested)
40
+
41
+ case res[:status]
42
+ when :up_to_date
43
+ puts "\u{2705} Plastic v#{iv} is already up to date on the #{channel_for(iv)} channel."
44
+ return 0
45
+ when :unknown_channel
46
+ warn "No published version on the #{requested} channel."
47
+ return 1
48
+ when :ok
49
+ if res[:kind] == :cross_bleeding && !confirm_bleeding(iv, res[:target])
50
+ puts "Aborted."
51
+ return 1
52
+ end
53
+ puts "\u{2b06}\u{fe0f} Updating Plastic #{iv} \u{2192} #{res[:target]}"
54
+ perform_switch(res[:target], agent_args(argv))
55
+ end
56
+ end
57
+
58
+ # Pure decision logic (hermetically testable). Returns a status hash.
59
+ def compute_target(installed_version:, dist_tags:, requested_channel: nil)
60
+ installed_ch = channel_for(installed_version)
61
+ target_ch = requested_channel || installed_ch
62
+ cand = dist_tags[target_ch]
63
+ return { status: :unknown_channel } unless cand
64
+
65
+ if target_ch == installed_ch
66
+ return { status: :up_to_date } unless semver_gt?(cand, installed_version)
67
+ { status: :ok, target: cand, kind: :in_channel }
68
+ else
69
+ bleeding = stability_rank(target_ch) < stability_rank(installed_ch)
70
+ { status: :ok, target: cand, kind: bleeding ? :cross_bleeding : :cross_stable }
71
+ end
72
+ end
73
+
74
+ def installed_version
75
+ path = File.join(plastic_home, "VERSION")
76
+ File.exist?(path) ? File.read(path).strip : nil
77
+ end
78
+
79
+ private
80
+
81
+ def requested_channel(argv)
82
+ return "alpha" if argv.include?("--alpha")
83
+ return "beta" if argv.include?("--beta")
84
+ return "latest" if argv.include?("--latest")
85
+ nil
86
+ end
87
+
88
+ # Agent flags to pass through to the delegated install (default --claude).
89
+ def agent_args(argv)
90
+ flags = agents.map { |a| a[:flag] }.select { |f| argv.include?(f) }
91
+ flags << "--all" if argv.include?("--all")
92
+ flags.empty? ? ["--claude"] : flags
93
+ end
94
+
95
+ def fetch_dist_tags
96
+ raw = `npm view #{PKG} dist-tags --json 2>/dev/null`
97
+ return nil if raw.nil? || raw.strip.empty?
98
+ JSON.parse(raw)
99
+ rescue JSON::ParserError, StandardError
100
+ nil
101
+ end
102
+
103
+ def confirm_bleeding(current, target)
104
+ return false unless $stdin.tty?
105
+ print "Switch from #{current} to the less-stable #{target}? [y/N]: "
106
+ ($stdin.gets&.strip || "").downcase.start_with?("y")
107
+ end
108
+
109
+ # Thin npx-exec glue (not unit-tested; the decision above is). Delegates the file-sync to
110
+ # the target version's install verb, recording the ledger action as `update`.
111
+ def perform_switch(target, agent_flags)
112
+ cmd = ["npx", "#{PKG}@#{target}", "install", "--reinstall", "--ledger-action", "update", *agent_flags]
113
+ puts " $ #{cmd.join(" ")}"
114
+ system(*cmd) ? 0 : 1
115
+ end
116
+
117
+ def show_help
118
+ puts <<~HELP
119
+
120
+ plastic update — upgrade Plastic to a newer version
121
+
122
+ Usage:
123
+ npx @zalom/plastic update [options]
124
+
125
+ Channel options (default: stay on the current channel):
126
+ --latest Switch to / advance the stable channel
127
+ --beta Switch to / advance the beta channel
128
+ --alpha Switch to / advance the alpha channel (bleeding edge — confirmed)
129
+
130
+ Agent options (default: --claude):
131
+ --claude --codex --hermes --all
132
+
133
+ Behaviour:
134
+ No flag advances to the next version on your current channel. Switching toward a
135
+ more stable channel is frictionless; switching toward bleeding edge is confirmed.
136
+ Use `versions` to roll back to a previously-installed version.
137
+
138
+ HELP
139
+ end
140
+ end
141
+
142
+ exit(Update.new(package_root: ENV["PLASTIC_PACKAGE_ROOT"] || File.expand_path("..", __dir__)).cli(ARGV)) if $PROGRAM_NAME == __FILE__
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ # frozen_string_literal: true
4
+
5
+ # Plastic — `versions` verb. Runs via `npx @zalom/plastic versions` (bin/plastic.js) or directly.
6
+ # Usage: ruby scripts/versions.rb [--downgrade [--version <v>] | --upgrade] [--help]
7
+ #
8
+ # Local time-machine over the append-only versions.json ledger. Navigates ONLY versions you
9
+ # have actually run (the ledger), never npm's full list — fetching brand-new versions is
10
+ # `update`'s job. Lets you roll back to a known-good build after a bad release.
11
+ # - no flag print the ledger table (and offer to continue a rollback)
12
+ # - --downgrade step back one version in your history
13
+ # - --downgrade --version V jump to a specific previously-run version
14
+ # - --upgrade step forward one version (after a rollback)
15
+
16
+ require_relative "lib/installer_core"
17
+
18
+ class Versions < InstallerCore
19
+ PKG = "@zalom/plastic"
20
+
21
+ def cli(argv = ARGV)
22
+ if argv.include?("--help") || argv.include?("-h")
23
+ show_help
24
+ return 0
25
+ end
26
+
27
+ ledger = ledger_read
28
+ if ledger.empty?
29
+ puts "No version history yet (versions.json is empty). Install or update first."
30
+ return 0
31
+ end
32
+
33
+ timeline = version_timeline(ledger)
34
+ current = installed_version || timeline.last
35
+
36
+ if argv.include?("--downgrade")
37
+ explicit = flag_value(argv, "--version")
38
+ target = explicit || step_target(timeline, current, :back)
39
+ return no_target("No earlier version in your history.") unless target
40
+ unless timeline.include?(target)
41
+ warn "#{target} is not in your version history. Choose one of: #{timeline.join(", ")}"
42
+ return 1
43
+ end
44
+ return switch_to(target, current)
45
+ elsif argv.include?("--upgrade")
46
+ target = step_target(timeline, current, :forward)
47
+ return no_target("No later version in your history. Use `update` for new releases.") unless target
48
+ return switch_to(target, current)
49
+ end
50
+
51
+ # No flag: show the table, and detect an in-progress rollback.
52
+ print_table(ledger, current)
53
+ if ledger.last && ledger.last["action"] == "downgrade"
54
+ prev = step_target(timeline, current, :back)
55
+ if prev && $stdin.tty?
56
+ print "\nYou recently rolled back. Go back further to #{prev}? [y/N]: "
57
+ return switch_to(prev, current) if ($stdin.gets&.strip || "").downcase.start_with?("y")
58
+ end
59
+ end
60
+ 0
61
+ end
62
+
63
+ # Unique versions in first-seen (chronological) order — the user's personal timeline.
64
+ def version_timeline(ledger)
65
+ ledger.map { |e| e["version"] }.compact.uniq
66
+ end
67
+
68
+ # Neighbour of `current` in the timeline. direction :back (older) or :forward (newer).
69
+ def step_target(timeline, current, direction)
70
+ i = timeline.index(current)
71
+ return nil if i.nil?
72
+ j = direction == :back ? i - 1 : i + 1
73
+ return nil if j < 0 || j >= timeline.length
74
+ timeline[j]
75
+ end
76
+
77
+ # Direction-derived ledger action for moving current -> target.
78
+ def action_for(target, current)
79
+ cmp = semver_compare(target, current)
80
+ cmp == -1 ? "downgrade" : "update"
81
+ end
82
+
83
+ def installed_version
84
+ path = File.join(plastic_home, "VERSION")
85
+ File.exist?(path) ? File.read(path).strip : nil
86
+ end
87
+
88
+ private
89
+
90
+ def flag_value(argv, name)
91
+ i = argv.index(name)
92
+ return nil unless i && argv[i + 1]
93
+ argv[i + 1]
94
+ end
95
+
96
+ def no_target(msg)
97
+ puts msg
98
+ 0
99
+ end
100
+
101
+ def switch_to(target, current)
102
+ action = action_for(target, current)
103
+ puts "#{action == "downgrade" ? "\u{23ea}" : "\u{23e9}"} #{current} \u{2192} #{target} (#{action})"
104
+ cmd = ["npx", "#{PKG}@#{target}", "install", "--reinstall", "--ledger-action", action, "--claude"]
105
+ puts " $ #{cmd.join(" ")}"
106
+ system(*cmd) ? 0 : 1
107
+ end
108
+
109
+ def print_table(ledger, current)
110
+ puts "\nPlastic version history (versions.json — append-only):\n\n"
111
+ puts " %-22s %-10s %s" % ["version", "action", "at"]
112
+ ledger.each do |e|
113
+ marker = e["version"] == current ? "\u{2192} " : " "
114
+ puts " #{marker}%-22s %-10s %s" % [e["version"], e["action"], e["at"]]
115
+ end
116
+ puts "\n \u{2192} = currently installed (v#{current})\n\n"
117
+ end
118
+
119
+ def show_help
120
+ puts <<~HELP
121
+
122
+ plastic versions — manage and roll back your local Plastic versions
123
+
124
+ Usage:
125
+ npx @zalom/plastic versions [options]
126
+
127
+ Options:
128
+ (none) Show the version-history table
129
+ --downgrade Roll back one version in your history
130
+ --downgrade --version V Roll back to a specific previously-run version
131
+ --upgrade Step forward one version in your history
132
+ -h, --help Show this help
133
+
134
+ Navigates only versions you have already run (the append-only ledger). To move to a
135
+ brand-new release, use `update`.
136
+
137
+ HELP
138
+ end
139
+ end
140
+
141
+ exit(Versions.new(package_root: ENV["PLASTIC_PACKAGE_ROOT"] || File.expand_path("..", __dir__)).cli(ARGV)) if $PROGRAM_NAME == __FILE__
@@ -107,7 +107,7 @@ digraph brainstorming {
107
107
 
108
108
  ## After the Design
109
109
  **Documentation:**
110
- - Write the validated design (spec) to `{intent_dir}/spec.md`
110
+ - Write the validated design (spec) to `{intent_dir}/spec.md` using the `${CLAUDE_PLUGIN_ROOT}/templates/spec.md` form
111
111
  - Use elements-of-style:writing-clearly-and-concisely skill if available
112
112
  - Commit to the store repo:
113
113
  ```
@@ -70,7 +70,7 @@ After all tasks complete, dispatch a final reviewer for the entire implementatio
70
70
  ### Step 4: Update Intent and Complete
71
71
  Capture observations in `## Insights`. When ALL checklist items are checked:
72
72
 
73
- 1. Write `outcome.md` with detailed results in the intent directory
73
+ 1. Write `outcome.md` with detailed results in the intent directory, using the `${CLAUDE_PLUGIN_ROOT}/templates/outcome.md` form
74
74
  2. Write `## Outcome` summary in the intent file (1-2 sentences)
75
75
  3. Move intent from `## Active` to `## Completed` in INDEX.md (with today's date)
76
76
  4. Update cluster entries to show `_(completed)_`
@@ -95,7 +95,7 @@ For each task:
95
95
  ### Step 3: Update Intent and Complete
96
96
  Capture observations in `## Insights`. When ALL checklist items are checked:
97
97
 
98
- 1. Write `outcome.md` with detailed results in the intent directory
98
+ 1. Write `outcome.md` with detailed results in the intent directory, using the `${CLAUDE_PLUGIN_ROOT}/templates/outcome.md` form
99
99
  2. Write `## Outcome` summary in the intent file (1-2 sentences)
100
100
  3. Move intent from `## Active` to `## Completed` in INDEX.md (with today's date)
101
101
  4. Update cluster entries to show `_(completed)_`
@@ -5,7 +5,7 @@ description: Use when initializing Plastic globally (~/.plastic/) or locally in
5
5
 
6
6
  # Install Plastic
7
7
 
8
- > **Recommended path:** for a first install, run `npx @zalom/plastic@latest --claude`
8
+ > **Recommended path:** for a first install, run `npx @zalom/plastic@latest install --claude`
9
9
  > in your shell (or `bunx @zalom/plastic@latest --claude` if you use Bun). This skill
10
10
  > exists to **re-install or repair** an existing setup from inside the agent, and to
11
11
  > drive interactive global configuration. Whenever this skill performs an install or
@@ -18,7 +18,7 @@ firing, leftover legacy plugin), re-run the installer — it is idempotent, prun
18
18
  files that no longer ship, and removes any legacy plugin/marketplace layout:
19
19
 
20
20
  ```bash
21
- npx @zalom/plastic@latest --claude # or @beta / @alpha to match your channel
21
+ npx @zalom/plastic@latest install --reinstall --claude # or @beta / @alpha to match your channel
22
22
  ```
23
23
 
24
24
  Then **run `/plastic-doctor`** and report what it found.
@@ -36,13 +36,13 @@ runs the appropriate npx command:
36
36
 
37
37
  ```bash
38
38
  # Stable (default)
39
- npx @zalom/plastic --claude
39
+ npx @zalom/plastic install --claude
40
40
 
41
41
  # Beta
42
- npx @zalom/plastic@beta --claude
42
+ npx @zalom/plastic@beta install --claude
43
43
 
44
44
  # Alpha
45
- npx @zalom/plastic@alpha --claude
45
+ npx @zalom/plastic@alpha install --claude
46
46
  ```
47
47
 
48
48
  The installed version and channel are recorded in `~/.plastic/VERSION`.
@@ -14,7 +14,7 @@ underlying uninstaller and adds reporting + verification.
14
14
  ### Step 1: Run the uninstaller
15
15
 
16
16
  ```bash
17
- npx @zalom/plastic@latest --uninstall --claude
17
+ npx @zalom/plastic@latest uninstall --claude
18
18
  ```
19
19
 
20
20
  (Use `--codex` / `--hermes` / `--all` to target other agents. `bunx` works too.)
@@ -55,5 +55,5 @@ Delete it too?
55
55
  b) Delete everything now — removes ~/.plastic/ entirely (irreversible)
56
56
  ```
57
57
 
58
- - **Keep:** "Your data is at ~/.plastic/. Re-install anytime with `npx @zalom/plastic@latest --claude`."
58
+ - **Keep:** "Your data is at ~/.plastic/. Re-install anytime with `npx @zalom/plastic@latest install --claude`."
59
59
  - **Delete:** run `rm -rf ~/.plastic/` and confirm.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: plastic-update
3
- description: Use when updating Plastic. Queries npm for available versions across all channels, presents options interactively, or accepts --alpha/--beta/--latest flags for direct update.
3
+ description: Use when updating Plastic. Runs the `update` verb, which reads the installed VERSION, derives its channel, queries npm dist-tags, and advances to the next version on that channel (or switches channel with a flag).
4
4
  ---
5
5
 
6
6
  # Update Plastic
@@ -8,123 +8,67 @@ description: Use when updating Plastic. Queries npm for available versions acros
8
8
  ## When to Use
9
9
  - User says "update plastic", "sync plastic", or "upgrade plastic"
10
10
  - Statusline shows "Plastic update available"
11
- - After a version bump notification
11
+ - After a version-bump notification
12
+
13
+ ## What it does
14
+
15
+ `update` is a single deterministic command. It reads `~/.plastic/VERSION`, derives the
16
+ channel from the version string (`-alpha`/`-beta`/none → stable), queries `npm` dist-tags,
17
+ and advances to the **next version on the current channel**. "Already up to date" is a
18
+ clean no-op. You do not compute the target yourself — the script does.
12
19
 
13
20
  ## Flags
14
21
 
15
- | Flag | Behavior |
16
- |------|----------|
17
- | `--alpha` | Update to latest alpha, skip interactive prompt |
18
- | `--beta` | Update to latest beta, skip interactive prompt |
19
- | `--latest` | Update to latest stable, skip interactive prompt |
22
+ | Flag | Behaviour |
23
+ |------|-----------|
24
+ | (none) | Advance to the next version on the **current** channel |
25
+ | `--latest` | Switch to / advance the **stable** channel (toward stability — frictionless) |
26
+ | `--beta` | Switch to / advance the **beta** channel |
27
+ | `--alpha` | Switch to / advance the **alpha** channel (bleeding edge — confirmed if moving down in stability) |
20
28
 
21
- No flag = interactive mode (show all available versions).
29
+ Switching toward a more stable channel is frictionless; switching toward bleeding edge is
30
+ confirmed. To roll **back** to a previously-installed version, use `plastic-versions`.
22
31
 
23
32
  ## Prerequisites
24
33
 
25
- Global install must exist (`~/.plastic/INDEX.md` present). If not, tell the
26
- user to run `npx @zalom/plastic@alpha --claude` first.
34
+ Plastic must be installed (`~/.plastic/VERSION` present). If not, run
35
+ `npx @zalom/plastic install --claude` first.
27
36
 
28
37
  ## Procedure
29
38
 
30
- ### Step 1: Read current version
31
-
32
- ```bash
33
- cat ~/.plastic/VERSION
34
- ```
35
-
36
- Parse the version string to determine the current channel:
37
- - Contains `-alpha` → alpha channel
38
- - Contains `-beta` → beta channel
39
- - No pre-release suffix → stable/latest channel
40
-
41
- ### Step 2: Query npm for available versions
42
-
43
- ```bash
44
- npm view @zalom/plastic dist-tags --json
45
- ```
46
-
47
- This returns a JSON object like:
48
- ```json
49
- {
50
- "latest": "0.0.1",
51
- "alpha": "1.0.0-alpha.14",
52
- "beta": "1.0.0-beta.2"
53
- }
54
- ```
55
-
56
- A missing dist-tag means no release exists on that channel.
57
-
58
- ### Step 3: Present options or act on flag
59
-
60
- **If a channel flag was provided** (`--alpha`, `--beta`, `--latest`):
61
-
62
- Skip the interactive prompt. Install the flagged channel directly. Go to Step 4.
63
-
64
- **If no flag (interactive mode):**
65
-
66
- Present the available updates to the user:
67
-
68
- ```
69
- Currently installed: 1.0.0-alpha.11 (alpha channel)
70
-
71
- Available updates:
72
- alpha: 1.0.0-alpha.14 ← your channel
73
- beta: 1.0.0-beta.2
74
- stable: (no stable release yet)
75
-
76
- Which channel do you want to install?
77
- ```
78
-
79
- Use AskUserQuestion with the available channels as options. Mark the user's
80
- current channel with "← your channel". If a dist-tag points to the same
81
- version as currently installed, show "(up to date)" instead of the version.
82
- If a dist-tag doesn't exist, show "(no release yet)".
83
-
84
- Wait for user selection.
85
-
86
- ### Step 4: Run the installer
39
+ ### Step 1: Run the update
87
40
 
88
41
  ```bash
89
- npx @zalom/plastic@{selected-tag} --claude
42
+ npx @zalom/plastic update # next version on the current channel
43
+ # or: npx @zalom/plastic update --beta / --latest / --alpha
90
44
  ```
91
45
 
92
- Replace `{selected-tag}` with `alpha`, `beta`, or `latest` based on the
93
- user's selection or the flag provided. Replace `--claude` with the appropriate
94
- agent flag(s) — detect current agents from `~/.claude/`, `~/.agents/`,
95
- `~/.hermes/` directories.
46
+ Append the agent flag(s) if not just Claude (`--codex`, `--hermes`, `--all`).
47
+ The command prints the transition (`vX → vY`) or "already up to date", and records the
48
+ move in the append-only `~/.plastic/versions.json` ledger.
96
49
 
97
- ### Step 5: Announce key changes
50
+ ### Step 2: Announce key changes
98
51
 
99
- After the installer completes, read `~/.plastic/PLASTIC.md` and announce any
100
- convention changes that affect the current session.
52
+ After it completes, read `~/.plastic/PLASTIC.md` and announce convention changes that
53
+ affect the current session:
101
54
 
102
- Format:
103
55
  ```
104
56
  Plastic updated to vX.Y.Z (channel).
105
57
 
106
- Key changes in this version:
107
- - [list notable convention changes if any]
58
+ Key changes:
59
+ - [notable convention changes, if any]
108
60
 
109
61
  Recommendation: run /clear for a clean session with all new conventions loaded.
110
62
  ```
111
63
 
112
- ### Step 6: Run health check
113
-
114
- Invoke `plastic-doctor` to verify the installation is healthy after the update.
115
-
116
- If all checks pass, show: **"Health check: all clear."**
64
+ ### Step 3: Health check
117
65
 
118
- If issues are found, show the full doctor report and offer to fix.
119
-
120
- ### Step 7: Commit
121
-
122
- ```bash
123
- cd ~/.plastic && git add PLASTIC.md scripts/ AGENTS.md VERSION 2>/dev/null && git commit -m "chore: update Plastic to $(cat ~/.plastic/VERSION)" --allow-empty
124
- ```
66
+ Invoke `plastic-doctor`. If all checks pass: **"Health check: all clear."** Otherwise show
67
+ the report and offer to fix.
125
68
 
126
- ### Step 8: Clear update cache
69
+ ### Step 4: Commit + clear update cache
127
70
 
128
71
  ```bash
72
+ cd ~/.plastic && git add PLASTIC.md scripts/ AGENTS.md VERSION versions.json 2>/dev/null && git commit -m "chore: update Plastic to $(cat ~/.plastic/VERSION)" --allow-empty
129
73
  rm -f ~/.plastic/.cache/update-check.json
130
74
  ```
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: plastic-versions
3
+ description: Use when the user wants to see their Plastic version history or roll back to a previously-installed version after a bad release. Manages the local, append-only versions.json ledger and steps between versions the user has actually run. For moving to a brand-new release, use plastic-update instead.
4
+ ---
5
+
6
+ # Plastic Versions — local version time-machine
7
+
8
+ ## When to Use
9
+ - "show plastic versions", "version history", "what versions have I run"
10
+ - "roll back plastic", "downgrade", "go back to the version that worked", "revert plastic"
11
+ - A new version broke something and the user wants their last known-good build
12
+
13
+ For upgrading to a **new** release, use `plastic-update`. This skill only navigates
14
+ versions you have **already installed** — the ones recorded in the ledger.
15
+
16
+ ## The ledger
17
+
18
+ `~/.plastic/versions.json` is an **append-only JSONL** ledger — one line per version
19
+ change, never modified or deleted:
20
+
21
+ ```json
22
+ {"version":"1.0.0-alpha.17","action":"install","at":"..."}
23
+ {"version":"1.0.0-alpha.18","action":"update","at":"..."}
24
+ ```
25
+
26
+ `action` ∈ `install | reinstall | update | downgrade` (derived from version direction; the
27
+ channel is derived from the version string, never stored). It is a troubleshooting record.
28
+
29
+ ## Procedure
30
+
31
+ ### Show history
32
+
33
+ ```bash
34
+ npx @zalom/plastic versions
35
+ ```
36
+
37
+ Prints the table with the currently-installed version marked. If the most recent action was
38
+ a `downgrade`, it asks whether to keep rolling back.
39
+
40
+ ### Roll back
41
+
42
+ ```bash
43
+ npx @zalom/plastic versions --downgrade # one step back
44
+ npx @zalom/plastic versions --downgrade --version 1.0.0-alpha.15 # to a specific run
45
+ ```
46
+
47
+ Rollback targets are restricted to versions in the ledger (only builds you have actually
48
+ run, so you only ever return to something known-good for you). The chosen version is
49
+ re-fetched from npm and re-synced; your intent store, config, and the ledger are untouched.
50
+
51
+ ### Step forward (after a rollback)
52
+
53
+ ```bash
54
+ npx @zalom/plastic versions --upgrade # one step forward in your history
55
+ ```
56
+
57
+ ### After any change
58
+
59
+ Run `plastic-doctor` to confirm health, and suggest `/clear` so the session picks up the
60
+ swapped conventions.
61
+
62
+ ## Notes
63
+ - The ledger is **never** edited or pruned — it is the audit trail.
64
+ - Downgrades cannot un-migrate a store-format change; if a warning appears, surface it to
65
+ the user rather than forcing the rollback.
@@ -0,0 +1,13 @@
1
+ # Outcome: <intent name>
2
+
3
+ ## Summary
4
+ (what was delivered)
5
+
6
+ ## Delivered
7
+ - ...
8
+
9
+ ## Verification
10
+ - <acceptance criterion> — verified by ... → result
11
+
12
+ ## Follow-ups
13
+ None