@zalom/plastic 1.0.0-beta.15 → 1.0.0-beta.16

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zalom/plastic",
3
- "version": "1.0.0-beta.15",
3
+ "version": "1.0.0-beta.16",
4
4
  "description": "Intent-driven idea development system for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -116,6 +116,22 @@ module Bridge
116
116
  end
117
117
  return nil if parsed.empty?
118
118
 
119
+ has_session = !blank?(session)
120
+
121
+ # Strict per-session ownership (intent 90): when the caller HAS a session, a foreign
122
+ # session's bridge is NEVER a valid resolution. Own-session and the derived-key case both
123
+ # reduce to candidate["session"] == session (the derived key IS the session that armed the
124
+ # bridge). A caller that owns no bridge resolves to nil, so its gates fail open instead of
125
+ # inheriting another session's armed intent.
126
+ #
127
+ # When the caller has NO session (truly headless, intent 52), keep the legacy degraded
128
+ # selection below so a single armed derived-key bridge is still discoverable - the hook
129
+ # cannot know the session there, and a lone armed intent must still gate.
130
+ if has_session
131
+ parsed = parsed.select { |c| c[:data]["session"].to_s == session.to_s }
132
+ return nil if parsed.empty?
133
+ end
134
+
119
135
  auto = parsed.select { |c| c[:data].dig("build", "auto") == true }
120
136
  pool = auto.empty? ? parsed : auto
121
137
 
@@ -129,7 +145,10 @@ module Bridge
129
145
  cwd_abs.start_with?("#{store_abs}/") ||
130
146
  store_abs.start_with?("#{cwd_abs}/")
131
147
  end
132
- pool = matching unless matching.empty?
148
+ # Hard cwd filter when the caller has a session (intent 90): a non-matching store
149
+ # excludes the candidate outright. Without a session, keep the best-effort revert
150
+ # (intent 52) so a lone armed bridge is still found when cwd does not overlap its store.
151
+ pool = has_session ? matching : (matching.empty? ? pool : matching)
133
152
  end
134
153
 
135
154
  pool.max_by { |c| c[:mtime] }&.fetch(:data)