@zalom/plastic 1.0.0-beta.10 → 1.0.0-beta.11

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.10",
3
+ "version": "1.0.0-beta.11",
4
4
  "description": "Intent-driven idea development system for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -43,13 +43,18 @@ edited before the plan exists (the gate applies to YOU, the orchestrator):
43
43
 
44
44
  ```bash
45
45
  ruby -r ~/.plastic/scripts/lib/bridge -e \
46
- 'Bridge.arm_auto(ENV["CLAUDE_SESSION_ID"], intent_id: "<ID>", intent_dir: "<STORE>/<dir>", store: "<STORE>", name: "<name>")'
46
+ 'Bridge.arm_auto(ENV["CLAUDE_CODE_SESSION_ID"], intent_id: "<ID>", intent_dir: "<STORE>/<dir>", store: "<STORE>", name: "<name>")'
47
47
  ```
48
48
 
49
49
  Replace `<ID>`, `<STORE>` (e.g. `~/.plastic/projects/<slug>/store` or `~/.plastic/store`),
50
- `<dir>` (the `ID--slug` directory), and `<name>`. If `CLAUDE_SESSION_ID` is unset, `arm_auto`
51
- falls back to a deterministic derived bridge key (a hash of the store and intent id), so the
52
- gate still engages; arming prints a one-line notice to stderr in that case.
50
+ `<dir>` (the `ID--slug` directory), and `<name>`. The first argument is the session id you
51
+ want the bridge keyed by: pass the hook stdin `session_id` when you have it, otherwise
52
+ `ENV["CLAUDE_CODE_SESSION_ID"]`, otherwise `nil`. `arm_auto` calls `resolve_session`, which
53
+ picks the first non-empty of: the explicit id you pass -> `CLAUDE_SESSION_ID` ->
54
+ `CLAUDE_CODE_SESSION_ID` -> a deterministic derived key (a hash of the store and intent id).
55
+ It never returns nil, so the gate engages even when every session env var is empty; the call
56
+ never needs a non-empty `CLAUDE_SESSION_ID` to function. Arming prints a one-line notice to
57
+ stderr when it falls through to the derived key.
53
58
 
54
59
  **Hard rule for the rest of this run:** do NOT edit project code (anything outside the
55
60
  intent directory / `~/.plastic/`) until `plan.md` AND `checklist.md` exist for the intent.
@@ -79,7 +84,7 @@ Completion report (require-then-synthesize): every dispatched specialist MUST en
79
84
 
80
85
  Final-gate review: dispatch an independent reviewer subagent at the final gate only, not as a standing role.
81
86
 
82
- Headless manual gate: when running headless or in the background, enforce gates manually and do not rely on hooks, because `CLAUDE_SESSION_ID` may be unset (this ties to the arm-gate fallback above).
87
+ Headless manual gate: when running headless or in the background, still enforce gates manually rather than relying on hooks alone. The PostToolUse gate hook reads `session_id` from hook stdin, and the savepoint ledger write is decoupled from the bridge (derived from the file path, so it fires even with no session id) - these do NOT no-op. What can degrade is the bridge-keyed stage enforcement: if no session id reaches the bridge and no matching bridge is discovered, the stage-gate enforcement step exits without acting, so verify state yourself. The bridge still resolves arming via `CLAUDE_CODE_SESSION_ID` or the derived-key fallback (see the arm-gate note above).
83
88
 
84
89
  Solo fallback: if the harness has no subagent dispatch, fall back to a single agent walking the full What, Why, How, Exec cycle yourself. This preserves current behavior.
85
90
 
@@ -202,7 +207,7 @@ During initial project creation, all decisions are non-destructive by definition
202
207
  store that holds this intent (the global store or the project store).
203
208
  9. Disarm the lifecycle gate (auto delivery is finished):
204
209
  ```bash
205
- ruby -r ~/.plastic/scripts/lib/bridge -e 'Bridge.disarm_auto(ENV["CLAUDE_SESSION_ID"])'
210
+ ruby -r ~/.plastic/scripts/lib/bridge -e 'Bridge.disarm_auto(ENV["CLAUDE_CODE_SESSION_ID"])'
206
211
  ```
207
212
  Disarming also purges stale bridge files from the temp directory automatically (it keeps the
208
213
  current bridge and any live run), so no manual `/tmp` cleanup is needed.
@@ -90,10 +90,13 @@ permanent sixth role, it exists only for the final review.
90
90
 
91
91
  ### Headless Manual Gate
92
92
 
93
- When running headless or in the background, the enforcer enforces gates manually and
94
- does not rely on hooks, because `CLAUDE_SESSION_ID` may be unset in those runs (the
95
- gate-check and savepoint hooks no-op without it). The enforcer arms via the bridge's
96
- derived-key fallback and verifies state itself.
93
+ When running headless or in the background, the enforcer enforces gates manually rather
94
+ than relying on hooks alone. The savepoint ledger and PostToolUse gate hook still fire
95
+ (the gate hook reads `session_id` from stdin; the savepoint write is path-derived and
96
+ bridge-independent), so they do not blanket no-op. Only the bridge-keyed stage-enforcement
97
+ step degrades when no session id reaches the bridge and no bridge is discovered. The
98
+ enforcer arms via `CLAUDE_CODE_SESSION_ID` or the bridge's derived-key fallback and
99
+ verifies state itself.
97
100
 
98
101
  ### Delegation
99
102