@zalom/plastic 1.0.0-beta.24 → 1.0.0-beta.26
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/PLASTIC.md +101 -31
- package/agents/plastic-intent-curator.md +4 -1
- package/hooks/code-gate +10 -1
- package/hooks/hooks.json +3 -3
- package/hooks/lock-gate +10 -1
- package/package.json +1 -1
- package/scripts/doctor.rb +225 -3
- package/scripts/hook-bash-gate +21 -3
- package/scripts/hook-create-gate +43 -7
- package/scripts/hook-gate-check +10 -0
- package/scripts/hook-lock-gate +14 -3
- package/scripts/hook-retrieval-gate +29 -17
- package/scripts/lib/bridge.rb +231 -73
- package/scripts/lib/hook_registry.rb +95 -0
- package/scripts/lib/installer_core.rb +8 -62
- package/scripts/lib/lock.rb +193 -0
- package/scripts/lib/power_tools.rb +11 -12
- package/scripts/lib/worktree.rb +21 -46
- package/scripts/plastic-lock +120 -0
- package/skills/auto/SKILL.md +40 -11
- package/skills/executing-plan/SKILL.md +4 -4
- package/skills/intent-curator/SKILL.md +4 -3
- package/skills/intent-starting/SKILL.md +16 -3
- package/skills/lock/SKILL.md +41 -0
- package/skills/managing-index/SKILL.md +5 -1
- package/templates/outcome.md +3 -0
|
@@ -70,12 +70,12 @@ 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, using the `${CLAUDE_PLUGIN_ROOT}/templates/outcome.md` form
|
|
73
|
+
1. Write `outcome.md` with detailed results in the intent directory, using the `${CLAUDE_PLUGIN_ROOT}/templates/outcome.md` form. Set the frontmatter `disposition: delivered` (the delivered terminal). `outcome.md` is mandatory at every terminal and self-declares its disposition (canonical done-marker in PLASTIC.md).
|
|
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)_`
|
|
77
77
|
5. Auto-commit: `cd <store-root> && git add . && git commit -m "feat: complete intent <ID> — <name>"`
|
|
78
|
-
6.
|
|
78
|
+
6. QMD reindex LAST (canonical End tail). As the final End-tail step, after the terminal move and any disarm, ALWAYS refresh the QMD search index for this store (no-op when QMD is absent), running in the background so it never blocks the turn: `ruby ~/.plastic/scripts/qmd-sync reindex --store <store-root> --async`. Completion is the lifecycle event that keeps the search index fresh, and the reindex runs last so the index never references a bridge or lock that is about to disappear (see PLASTIC.md `## Delivery Isolation and the Single-Owner Lock`).
|
|
79
79
|
|
|
80
80
|
**This is NOT optional.** An intent with all checklist items done but no Outcome is a broken state. Complete the intent immediately — do not leave it for later.
|
|
81
81
|
|
|
@@ -96,12 +96,12 @@ For each task:
|
|
|
96
96
|
### Step 3: Update Intent and Complete
|
|
97
97
|
Capture observations in `## Insights`. When ALL checklist items are checked:
|
|
98
98
|
|
|
99
|
-
1. Write `outcome.md` with detailed results in the intent directory, using the `${CLAUDE_PLUGIN_ROOT}/templates/outcome.md` form
|
|
99
|
+
1. Write `outcome.md` with detailed results in the intent directory, using the `${CLAUDE_PLUGIN_ROOT}/templates/outcome.md` form. Set the frontmatter `disposition: delivered` (the delivered terminal). `outcome.md` is mandatory at every terminal and self-declares its disposition (canonical done-marker in PLASTIC.md).
|
|
100
100
|
2. Write `## Outcome` summary in the intent file (1-2 sentences)
|
|
101
101
|
3. Move intent from `## Active` to `## Completed` in INDEX.md (with today's date)
|
|
102
102
|
4. Update cluster entries to show `_(completed)_`
|
|
103
103
|
5. Auto-commit: `cd <store-root> && git add . && git commit -m "feat: complete intent <ID> — <name>"`
|
|
104
|
-
6.
|
|
104
|
+
6. QMD reindex LAST (canonical End tail). As the final End-tail step, after the terminal move and any disarm, ALWAYS refresh the QMD search index for this store (no-op when QMD is absent), running in the background so it never blocks the turn: `ruby ~/.plastic/scripts/qmd-sync reindex --store <store-root> --async`. Completion is the lifecycle event that keeps the search index fresh, and the reindex runs last so the index never references a bridge or lock that is about to disappear (see PLASTIC.md `## Delivery Isolation and the Single-Owner Lock`).
|
|
105
105
|
|
|
106
106
|
**This is NOT optional.** Complete the intent immediately when work is done.
|
|
107
107
|
|
|
@@ -38,9 +38,10 @@ The agent handles:
|
|
|
38
38
|
- Cluster management (create, merge, rename)
|
|
39
39
|
- Orphan detection
|
|
40
40
|
|
|
41
|
-
When an intent reaches a terminal state — moved to Completed OR Abandoned — do
|
|
41
|
+
When an intent reaches a terminal state — moved to Completed OR Abandoned — do these things as the closing act of the transfer, in the canonical End-tail order (see PLASTIC.md `## Delivery Isolation and the Single-Owner Lock`):
|
|
42
42
|
|
|
43
|
-
1.
|
|
44
|
-
2.
|
|
43
|
+
1. Author a real `outcome.md` in the intent directory from `~/.plastic/templates/outcome.md`, with the frontmatter `disposition: delivered` for a completed intent or `disposition: abandoned` for an abandoned one. `outcome.md` is MANDATORY at every terminal, delivered and abandoned alike: on abandon it records the abandonment reason and replaces the scaffolded placeholder sentinel (never leave `outcome.md` a placeholder at a terminal).
|
|
44
|
+
2. Stamp the terminal savepoint bookend (intent 81), so the ledger's last line records the disposition: `ruby -r ~/.plastic/scripts/lib/bridge -e 'Bridge.append_terminal_savepoint("<intent_dir>", "delivered")'` (use `"abandoned"` for an abandoned intent). Idempotent.
|
|
45
|
+
3. Refresh the QMD index for the affected store LAST, after the terminal move and savepoint (no-op when QMD absent), running in the background so it never blocks: `ruby ~/.plastic/scripts/qmd-sync reindex --store <store-root> --async`.
|
|
45
46
|
|
|
46
47
|
After the agent completes, report what changed.
|
|
@@ -34,7 +34,14 @@ enforces it: without a held lock, mutating writes to this active intent's dir ar
|
|
|
34
34
|
1. **Ensure the intent is in INDEX `## Active`.** If it sits in `## Future`, activate it
|
|
35
35
|
(move it to `## Active`, auto-commit) before arming. Creation precedes activation, so a
|
|
36
36
|
brand-new What intent is activated here, then locked.
|
|
37
|
-
2. **
|
|
37
|
+
2. **Self-heal the lock state first.** Run:
|
|
38
|
+
`ruby ~/.plastic/scripts/plastic-lock fix --intent-dir <STORE>/<dir>`
|
|
39
|
+
This is the one repair function (same one /plastic-lock exposes): it removes
|
|
40
|
+
corrupt or legacy lock state and rebuilds the lock and bridge from disk for
|
|
41
|
+
this session. If it reports `held`, another session owns the intent: STOP
|
|
42
|
+
and tell the user who holds it. If it reports `stale`, ask the user before
|
|
43
|
+
running `plastic-lock reclaim` (takeover is audited).
|
|
44
|
+
3. **Arm the bridge.** Which arm is chosen by the mode answer (below), but the lock itself is
|
|
38
45
|
taken first. Reuse the arm one-liner shape from `plastic-auto`:
|
|
39
46
|
```bash
|
|
40
47
|
# guided (lock only):
|
|
@@ -55,8 +62,14 @@ deterministic derived key (a hash of the store and intent id). It never returns
|
|
|
55
62
|
lock is taken even when every session env var is empty; arming prints a one-line stderr
|
|
56
63
|
notice when it falls through to the derived key.
|
|
57
64
|
|
|
58
|
-
|
|
59
|
-
|
|
65
|
+
**What the lock IS.** Ownership is session-keyed and lease-based: arming writes a durable
|
|
66
|
+
`delivery.lock` file in the intent dir naming this session as owner, and the owner's hooks
|
|
67
|
+
refresh the file mtime on tool activity (the lease heartbeat). The /tmp bridge is only a
|
|
68
|
+
cache of that file; on any disagreement the lock file wins, so a wiped /tmp never strands
|
|
69
|
+
the owner. Idempotent re-arm: arming again with the same owner just refreshes the lock; it
|
|
70
|
+
is not an error to re-board an intent this session already owns. A failed arm raises with
|
|
71
|
+
a message naming the resolving `plastic-lock` verb (`status`, `reclaim`, or `fix`): follow
|
|
72
|
+
that message, never delete a lock file by hand.
|
|
60
73
|
|
|
61
74
|
## Confirm delivery state
|
|
62
75
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lock
|
|
3
|
+
description: Inspect, repair, release, or reclaim an intent's delivery lock. Use when a lock-gate deny names /plastic-lock, when resuming interrupted work after a crash, reboot, or /tmp wipe, when a lock reads held or stale, or when the user says "fix the lock", "who holds the lock", or "reclaim the lock".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Plastic Lock
|
|
7
|
+
|
|
8
|
+
Command-only wrapper around `~/.plastic/scripts/plastic-lock`. The durable
|
|
9
|
+
delivery lock is a `delivery.lock` file in the intent directory: ownership is
|
|
10
|
+
session-keyed, liveness is a lease (the owner's hooks refresh the file mtime;
|
|
11
|
+
stale means the heartbeat is older than the TTL). The /tmp bridge is only a
|
|
12
|
+
cache; the lock file wins every disagreement.
|
|
13
|
+
|
|
14
|
+
## Verbs
|
|
15
|
+
|
|
16
|
+
Run from the project (the intent resolves from this session's bridge), or pass
|
|
17
|
+
`--intent-dir` explicitly:
|
|
18
|
+
|
|
19
|
+
| Verb | What it does | When |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| `status` | Report the lock file, bridge cache, freshness, agreement | Always safe; run first |
|
|
22
|
+
| `fix` | Idempotent repair: rebuild lock + bridge from disk truth for THIS session. Never touches a fresh foreign lock | Interrupted work, corrupted state, /tmp wiped, legacy pid locks |
|
|
23
|
+
| `release` | Owner clears the lock | Ending or abandoning a boarding |
|
|
24
|
+
| `reclaim` | Explicit takeover of a STALE lock; appends an audit line to savepoint.md | The owner is gone and the lease expired |
|
|
25
|
+
| `delegate` | Owner registers a subagent session under the lock (`--delegate <session-id>`) | Auto-mode orchestration |
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
ruby ~/.plastic/scripts/plastic-lock status
|
|
29
|
+
ruby ~/.plastic/scripts/plastic-lock fix --intent-dir <store>/<id>--<slug>
|
|
30
|
+
ruby ~/.plastic/scripts/plastic-lock reclaim --intent-dir <store>/<id>--<slug>
|
|
31
|
+
ruby ~/.plastic/scripts/plastic-lock delegate --delegate <subagent-session-id>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Rules
|
|
35
|
+
|
|
36
|
+
- `fix` exits non-zero when another session holds a FRESH lock: back off, do
|
|
37
|
+
not retry in a loop. `status` shows the owner.
|
|
38
|
+
- `reclaim` refuses a fresh lock. There is no silent reclaim anywhere; every
|
|
39
|
+
takeover is audited in the intent's savepoint.md.
|
|
40
|
+
- Acquiring a lock for new work is NOT this skill's job: board through
|
|
41
|
+
`/plastic-intent-starting`, which calls the same repair internally.
|
|
@@ -41,7 +41,11 @@ Topic-based groupings. Manually curated. Create a new cluster when 3+ intents sh
|
|
|
41
41
|
### Completed
|
|
42
42
|
All completed intents with dates. Links preserved, never deleted.
|
|
43
43
|
|
|
44
|
-
When you move an intent INTO Completed or Abandoned,
|
|
44
|
+
When you move an intent INTO Completed or Abandoned, run the closing acts of the transfer in the canonical End-tail order (see PLASTIC.md `## Delivery Isolation and the Single-Owner Lock`):
|
|
45
|
+
|
|
46
|
+
1. Author a real `outcome.md` in the intent directory from `~/.plastic/templates/outcome.md`, with the frontmatter `disposition: delivered` for a completed intent or `disposition: abandoned` for an abandoned one. `outcome.md` is MANDATORY at every terminal, delivered and abandoned alike: on abandon it records the abandonment reason and replaces the scaffolded placeholder sentinel (never leave `outcome.md` a placeholder at a terminal).
|
|
47
|
+
2. Stamp the terminal savepoint bookend (intent 81), so the ledger's last line records the disposition: `ruby -r ~/.plastic/scripts/lib/bridge -e 'Bridge.append_terminal_savepoint("<intent_dir>", "delivered")'` (use `"abandoned"` for an abandoned intent). Idempotent.
|
|
48
|
+
3. Refresh the QMD index for that store LAST, after the terminal move and savepoint (no-op when QMD is absent), in the background so it never blocks: `ruby ~/.plastic/scripts/qmd-sync reindex --store <store-root> --async`.
|
|
45
49
|
|
|
46
50
|
## Workflow
|
|
47
51
|
|