@zalom/plastic 1.0.0-alpha.36 → 1.0.0-alpha.37
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/package.json +1 -1
- package/scripts/lib/bridge.rb +44 -0
- package/skills/auto/SKILL.md +2 -0
package/package.json
CHANGED
package/scripts/lib/bridge.rb
CHANGED
|
@@ -10,6 +10,14 @@ require "digest"
|
|
|
10
10
|
module Bridge
|
|
11
11
|
STAGES = %w[what why how exec done].freeze
|
|
12
12
|
|
|
13
|
+
# Stale-bridge purge window (intent 67). The bridge file is ephemeral
|
|
14
|
+
# live-session gate state, NOT a continuation source: an intent is resumed from
|
|
15
|
+
# its savepoint.md ledger, never from a /tmp bridge. So any bridge older than
|
|
16
|
+
# this window is dead weight and safe to purge, regardless of arm state. No
|
|
17
|
+
# real session stays live for two days, so a 48h cutoff never removes a bridge
|
|
18
|
+
# an active run depends on.
|
|
19
|
+
PURGE_AGE_SECONDS = 48 * 3600 # 48 hours
|
|
20
|
+
|
|
13
21
|
def self.intent_file(intent_dir)
|
|
14
22
|
dir_name = File.basename(intent_dir)
|
|
15
23
|
"#{intent_dir}/#{dir_name}.md"
|
|
@@ -106,6 +114,40 @@ module Bridge
|
|
|
106
114
|
pool.max_by { |c| c[:mtime] }&.fetch(:data)
|
|
107
115
|
end
|
|
108
116
|
|
|
117
|
+
# --- Stale-bridge purge (intent 67) ---------------------------------------
|
|
118
|
+
#
|
|
119
|
+
# Remove stale tmp/plastic-*.json bridge files so discover_bridge's per-fire
|
|
120
|
+
# scan stays bounded. Best-effort and non-raising: returns the array of removed
|
|
121
|
+
# paths. Continuation does not depend on these files (an intent resumes from its
|
|
122
|
+
# savepoint.md ledger), so the only safety rule is age: a bridge older than
|
|
123
|
+
# max_age_seconds is purged regardless of arm state, while anything newer is kept
|
|
124
|
+
# (it may be a live run). The current session's own bridge is never purged
|
|
125
|
+
# (preserves the disarm_auto contract that it stays readable). Wired into
|
|
126
|
+
# arm_auto and disarm_auto so both manual and auto delivery keep the temp dir
|
|
127
|
+
# clean.
|
|
128
|
+
def self.purge_stale_bridges(session:, now: Time.now, max_age_seconds: PURGE_AGE_SECONDS,
|
|
129
|
+
tmp: tmp_dir)
|
|
130
|
+
current = path(session, tmp: tmp)
|
|
131
|
+
removed = []
|
|
132
|
+
Dir.glob(File.join(tmp, "plastic-*.json")).each do |f|
|
|
133
|
+
next if f == current
|
|
134
|
+
begin
|
|
135
|
+
next if (now - File.mtime(f)) < max_age_seconds
|
|
136
|
+
File.delete(f)
|
|
137
|
+
removed << f
|
|
138
|
+
rescue Errno::ENOENT
|
|
139
|
+
# Raced with another job that already removed it; count as purged.
|
|
140
|
+
removed << f
|
|
141
|
+
rescue => e
|
|
142
|
+
$stderr.puts "plastic: purge skipped #{f}: #{e.message}"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
removed
|
|
146
|
+
rescue => e
|
|
147
|
+
$stderr.puts "plastic: purge_stale_bridges failed: #{e.message}"
|
|
148
|
+
removed || []
|
|
149
|
+
end
|
|
150
|
+
|
|
109
151
|
def self.read(session, tmp: tmp_dir)
|
|
110
152
|
p = path(session, tmp: tmp)
|
|
111
153
|
return nil unless File.exist?(p)
|
|
@@ -323,6 +365,7 @@ module Bridge
|
|
|
323
365
|
data = derive(key, intent_id: intent_id, intent_dir: intent_dir, store: store, name: name)
|
|
324
366
|
data["build"]["auto"] = true
|
|
325
367
|
write(key, data)
|
|
368
|
+
purge_stale_bridges(session: key)
|
|
326
369
|
data
|
|
327
370
|
end
|
|
328
371
|
|
|
@@ -333,6 +376,7 @@ module Bridge
|
|
|
333
376
|
data["build"] ||= {}
|
|
334
377
|
data["build"]["auto"] = false
|
|
335
378
|
write(session, data)
|
|
379
|
+
purge_stale_bridges(session: session)
|
|
336
380
|
data
|
|
337
381
|
end
|
|
338
382
|
|
package/skills/auto/SKILL.md
CHANGED
|
@@ -194,6 +194,8 @@ During initial project creation, all decisions are non-destructive by definition
|
|
|
194
194
|
```bash
|
|
195
195
|
ruby -r ~/.plastic/scripts/lib/bridge -e 'Bridge.disarm_auto(ENV["CLAUDE_SESSION_ID"])'
|
|
196
196
|
```
|
|
197
|
+
Disarming also purges stale bridge files from the temp directory automatically (it keeps the
|
|
198
|
+
current bridge and any live run), so no manual `/tmp` cleanup is needed.
|
|
197
199
|
10. Notify user: "Intent [ID] — [name] delivered. [1-2 sentence summary]. See outcome.md for details."
|
|
198
200
|
|
|
199
201
|
## Error Handling
|