@zalom/plastic 1.0.0-alpha.3 → 1.0.0-alpha.5

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.
package/hooks/hooks.json CHANGED
@@ -62,17 +62,6 @@
62
62
  }
63
63
  ]
64
64
  }
65
- ],
66
- "statusLine": [
67
- {
68
- "matcher": "",
69
- "hooks": [
70
- {
71
- "type": "command",
72
- "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/statusline\""
73
- }
74
- ]
75
- }
76
65
  ]
77
66
  }
78
67
  }
package/hooks/statusline CHANGED
@@ -1,16 +1,56 @@
1
1
  #!/bin/bash
2
- # plastic-hook-version: 1.0.0
3
- # StatusLine hook — shows update available warning
2
+ # plastic-hook-version: 2.0.0
3
+ # StatusLine hook — chains user's original statusline, adds Plastic info
4
4
 
5
- CACHE_FILE="$HOME/.plastic/.cache/update-check.json"
5
+ INPUT=$(cat)
6
+
7
+ # --- Chain original statusline ---
8
+ ORIGINAL_CONFIG="$HOME/.plastic/.cache/original-statusline.json"
9
+ ORIGINAL_OUTPUT=""
10
+ if [ -f "$ORIGINAL_CONFIG" ]; then
11
+ ORIGINAL_CMD=$(grep -o '"command":"[^"]*"' "$ORIGINAL_CONFIG" 2>/dev/null | head -1 | cut -d'"' -f4)
12
+ if [ -z "$ORIGINAL_CMD" ]; then
13
+ ORIGINAL_CMD=$(grep -o '"command": "[^"]*"' "$ORIGINAL_CONFIG" 2>/dev/null | head -1 | sed 's/.*"command": "//;s/".*//')
14
+ fi
15
+ if [ -n "$ORIGINAL_CMD" ] && [ -x "$ORIGINAL_CMD" ]; then
16
+ ORIGINAL_OUTPUT=$(echo "$INPUT" | "$ORIGINAL_CMD" 2>/dev/null)
17
+ fi
18
+ fi
19
+
20
+ # --- Plastic status ---
21
+ PLASTIC_PARTS=""
6
22
 
7
- if [ ! -f "$CACHE_FILE" ]; then
8
- exit 0
23
+ # Active intent from INDEX.md
24
+ INDEX="$HOME/.plastic/INDEX.md"
25
+ if [ -f "$INDEX" ]; then
26
+ ACTIVE=$(sed -n '/^## Active$/,/^## /{/^- \[/p;}' "$INDEX" | head -1)
27
+ if [ -n "$ACTIVE" ]; then
28
+ INTENT=$(echo "$ACTIVE" | sed 's/^- \[\([^]]*\)\].*/\1/')
29
+ PLASTIC_PARTS="plastic: ${INTENT}"
30
+ fi
31
+ fi
32
+
33
+ # Update notification
34
+ CACHE_FILE="$HOME/.plastic/.cache/update-check.json"
35
+ if [ -f "$CACHE_FILE" ]; then
36
+ UPDATE_AVAILABLE=$(grep -o '"updateAvailable":true' "$CACHE_FILE" 2>/dev/null)
37
+ if [ -n "$UPDATE_AVAILABLE" ]; then
38
+ LATEST=$(grep -o '"latest":"[^"]*"' "$CACHE_FILE" 2>/dev/null | head -1 | cut -d'"' -f4)
39
+ CURRENT=$(grep -o '"current":"[^"]*"' "$CACHE_FILE" 2>/dev/null | head -1 | cut -d'"' -f4)
40
+ UPDATE_MSG="plastic update: $CURRENT -> $LATEST"
41
+ if [ -n "$PLASTIC_PARTS" ]; then
42
+ PLASTIC_PARTS="$PLASTIC_PARTS | $UPDATE_MSG"
43
+ else
44
+ PLASTIC_PARTS="$UPDATE_MSG"
45
+ fi
46
+ fi
9
47
  fi
10
48
 
11
- UPDATE_AVAILABLE=$(grep -o '"updateAvailable":true' "$CACHE_FILE" 2>/dev/null)
12
- if [ -n "$UPDATE_AVAILABLE" ]; then
13
- LATEST=$(grep -o '"latest":"[^"]*"' "$CACHE_FILE" | cut -d'"' -f4)
14
- CURRENT=$(grep -o '"current":"[^"]*"' "$CACHE_FILE" | cut -d'"' -f4)
15
- echo "Plastic update: $CURRENT → $LATEST — run /plastic:update"
49
+ # --- Combine output ---
50
+ if [ -n "$ORIGINAL_OUTPUT" ] && [ -n "$PLASTIC_PARTS" ]; then
51
+ echo "$ORIGINAL_OUTPUT | $PLASTIC_PARTS"
52
+ elif [ -n "$ORIGINAL_OUTPUT" ]; then
53
+ echo "$ORIGINAL_OUTPUT"
54
+ elif [ -n "$PLASTIC_PARTS" ]; then
55
+ echo "$PLASTIC_PARTS"
16
56
  fi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zalom/plastic",
3
- "version": "1.0.0-alpha.3",
3
+ "version": "1.0.0-alpha.5",
4
4
  "description": "Intent-driven idea development system for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -150,11 +150,22 @@ active_deprecations = deprecations.select do |dep|
150
150
  !dismissed.include?(dep["id"])
151
151
  end
152
152
 
153
+ # --- Check for available updates (from previous session's check) ---
154
+
155
+ update_notice = nil
156
+ cache_file = "#{store_root}/.cache/update-check.json"
157
+ if File.exist?(cache_file)
158
+ cache = JSON.parse(File.read(cache_file)) rescue {}
159
+ if cache["updateAvailable"]
160
+ update_notice = "Plastic update available: #{cache["current"]} -> #{cache["latest"]} — run /plastic:update"
161
+ end
162
+ end
163
+
153
164
  # --- Early exit if nothing to show ---
154
165
 
155
166
  all_active = active + project_active
156
167
  all_future = future + project_future
157
- exit 0 if all_active.empty? && stale.empty? && all_future.empty? && active_deprecations.empty?
168
+ exit 0 if all_active.empty? && stale.empty? && all_future.empty? && active_deprecations.empty? && update_notice.nil?
158
169
 
159
170
  # --- Build context ---
160
171
 
@@ -215,6 +226,10 @@ if active_deprecations.any?
215
226
  end
216
227
  end
217
228
 
229
+ if update_notice
230
+ parts.unshift("! #{update_notice}\n")
231
+ end
232
+
218
233
  payload = {
219
234
  "hookSpecificOutput" => {
220
235
  "hookEventName" => "SessionStart",
@@ -359,23 +359,32 @@ def merge_claude_hooks(settings_path)
359
359
  end
360
360
  end
361
361
 
362
+ existing_status = settings["statusLine"]
363
+ if existing_status && !existing_status.dig("command").to_s.include?("plastic-")
364
+ cache_dir = File.join(PLASTIC_HOME, ".cache")
365
+ FileUtils.mkdir_p(cache_dir)
366
+ File.write(File.join(cache_dir, "original-statusline.json"), JSON.pretty_generate(existing_status))
367
+ end
368
+
362
369
  settings["statusLine"] = { "type" => "command", "command" => "#{hook_dir}/plastic-statusline" }
363
370
 
364
371
  write_json_atomic(settings_path, settings)
365
372
  end
366
373
 
367
374
  def purge_stale_plastic_hooks(hooks)
368
- stale = ->(cmd) { cmd.to_s.match?(/ruby\s+.*plastic-/) || cmd.to_s.match?(/plastic-[a-z-]+\.rb/) }
375
+ plastic_cmd = ->(cmd) { cmd.to_s.include?("plastic-") }
376
+
377
+ hooks.delete("statusLine")
369
378
 
370
379
  hooks.each do |event, groups|
371
380
  next unless groups.is_a?(Array)
372
381
 
373
382
  hooks[event] = groups.map do |group|
374
383
  if group.is_a?(Hash) && group["hooks"].is_a?(Array)
375
- group["hooks"].reject! { |h| stale.call(h["command"]) }
384
+ group["hooks"].reject! { |h| plastic_cmd.call(h["command"]) }
376
385
  group unless group["hooks"].empty?
377
386
  elsif group.is_a?(Hash) && group["command"]
378
- stale.call(group["command"]) ? nil : group
387
+ plastic_cmd.call(group["command"]) ? nil : group
379
388
  else
380
389
  group
381
390
  end
@@ -463,7 +472,14 @@ def remove_claude_hooks(settings_path)
463
472
 
464
473
  settings["hooks"].delete_if { |_, v| v.is_a?(Array) && v.empty? }
465
474
  settings.delete("hooks") if settings["hooks"]&.empty?
466
- settings.delete("statusLine") if settings.dig("statusLine", "command").to_s.include?("plastic-")
475
+ if settings.dig("statusLine", "command").to_s.include?("plastic-")
476
+ settings.delete("statusLine")
477
+ original_path = File.join(PLASTIC_HOME, ".cache", "original-statusline.json")
478
+ if File.exist?(original_path)
479
+ original = JSON.parse(File.read(original_path)) rescue nil
480
+ settings["statusLine"] = original if original
481
+ end
482
+ end
467
483
 
468
484
  write_json_atomic(settings_path, settings)
469
485
  end