@zalom/plastic 1.0.0-beta.35 → 1.0.0-beta.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/PLASTIC-reference.md +133 -0
- package/PLASTIC.md +21 -145
- package/README.md +88 -65
- package/agents/plastic-brainstorming.md +2 -6
- package/agents/plastic-enforcer.md +11 -6
- package/agents/plastic-executor.md +2 -6
- package/agents/plastic-future-intent-researcher.md +2 -7
- package/agents/plastic-intent-curator.md +2 -10
- package/agents/plastic-intent-discovery.md +2 -7
- package/agents/plastic-planner.md +2 -6
- package/agents/plastic-spec-specialist.md +2 -6
- package/package.json +2 -1
- package/scripts/install.rb +2 -1
- package/scripts/lib/bridge.rb +73 -2
- package/scripts/lib/installer_core.rb +1 -0
- package/scripts/lib/power_tools.rb +18 -16
- package/skills/auto/SKILL.md +40 -38
- package/skills/auto/references/end-tail.md +56 -0
- package/skills/auto/references/human-report-contract.md +55 -0
- package/skills/brainstorming/SKILL.md +7 -34
- package/skills/brainstorming/references/design-principles.md +49 -0
- package/skills/creating-intent/SKILL.md +5 -26
- package/skills/creating-project/SKILL.md +11 -74
- package/skills/creating-project/references/project-scaffolding.md +97 -0
- package/skills/dashboard/SKILL.md +2 -17
- package/skills/dashboard/references/classification.md +22 -0
- package/skills/install/SKILL.md +1 -1
- package/skills/releasing/SKILL.md +14 -46
- package/skills/releasing/references/promotion-and-tagging.md +60 -0
- package/skills/writing-plans/SKILL.md +10 -88
- package/skills/writing-plans/references/plan-format.md +102 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Design Principles: Unit Boundaries and Existing Codebases
|
|
2
|
+
|
|
3
|
+
General good-developer guidance behind two parts of the Process: how to design for
|
|
4
|
+
isolation and clarity, and how to behave in an existing codebase. Also holds the
|
|
5
|
+
Process Flow diagram (the same ordered flow the Checklist already states as numbered
|
|
6
|
+
steps).
|
|
7
|
+
|
|
8
|
+
## Design for isolation and clarity
|
|
9
|
+
|
|
10
|
+
- Break the system into smaller units that each have one clear purpose, communicate through well-defined interfaces, and can be understood and tested independently
|
|
11
|
+
- For each unit, you should be able to answer: what does it do, how do you use it, and what does it depend on?
|
|
12
|
+
- Can someone understand what a unit does without reading its internals? Can you change the internals without breaking consumers? If not, the boundaries need work.
|
|
13
|
+
- Smaller, well-bounded units are also easier for you to work with - you reason better about code you can hold in context at once, and your edits are more reliable when files are focused. When a file grows large, that's often a signal that it's doing too much.
|
|
14
|
+
|
|
15
|
+
## Working in existing codebases
|
|
16
|
+
|
|
17
|
+
- Explore the current structure before proposing changes. Follow existing patterns.
|
|
18
|
+
- Where existing code has problems that affect the work (e.g., a file that's grown too large, unclear boundaries, tangled responsibilities), include targeted improvements as part of the design - the way a good developer improves code they're working in.
|
|
19
|
+
- Don't propose unrelated refactoring. Stay focused on what serves the current goal.
|
|
20
|
+
|
|
21
|
+
## Process Flow (diagram)
|
|
22
|
+
|
|
23
|
+
The Checklist above already states this ordered flow as numbered steps 1-8; this
|
|
24
|
+
diagram is the same flow in a visual form.
|
|
25
|
+
|
|
26
|
+
```dot
|
|
27
|
+
digraph brainstorming {
|
|
28
|
+
"Explore project context" [shape=box];
|
|
29
|
+
"Ask clarifying questions" [shape=box];
|
|
30
|
+
"Propose 2-3 approaches" [shape=box];
|
|
31
|
+
"Present design sections" [shape=box];
|
|
32
|
+
"User approves design?" [shape=diamond];
|
|
33
|
+
"Write spec" [shape=box];
|
|
34
|
+
"Spec self-review\n(fix inline)" [shape=box];
|
|
35
|
+
"User reviews spec?" [shape=diamond];
|
|
36
|
+
"Invoke plastic-writing-plans" [shape=doublecircle];
|
|
37
|
+
|
|
38
|
+
"Explore project context" -> "Ask clarifying questions";
|
|
39
|
+
"Ask clarifying questions" -> "Propose 2-3 approaches";
|
|
40
|
+
"Propose 2-3 approaches" -> "Present design sections";
|
|
41
|
+
"Present design sections" -> "User approves design?";
|
|
42
|
+
"User approves design?" -> "Present design sections" [label="no, revise"];
|
|
43
|
+
"User approves design?" -> "Write spec" [label="yes"];
|
|
44
|
+
"Write spec" -> "Spec self-review\n(fix inline)";
|
|
45
|
+
"Spec self-review\n(fix inline)" -> "User reviews spec?";
|
|
46
|
+
"User reviews spec?" -> "Write spec" [label="changes requested"];
|
|
47
|
+
"User reviews spec?" -> "Invoke plastic-writing-plans" [label="approved"];
|
|
48
|
+
}
|
|
49
|
+
```
|
|
@@ -124,32 +124,11 @@ cleanly, and do not work around the failure by hand-writing the files.
|
|
|
124
124
|
|
|
125
125
|
### 6. If Implementation Intent Spawns a Project
|
|
126
126
|
|
|
127
|
-
When the user says "start building" or the plan calls for a new project
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
mkdir -p <project_root>/<slug>
|
|
133
|
-
cd <project_root>/<slug>
|
|
134
|
-
git init
|
|
135
|
-
```
|
|
136
|
-
3. Copy `AGENTS.md` template from `${CLAUDE_PLUGIN_ROOT}/templates/agents.md`
|
|
137
|
-
4. Register in `~/.plastic/projects.yml`:
|
|
138
|
-
```yaml
|
|
139
|
-
<slug>:
|
|
140
|
-
path: <full-path>
|
|
141
|
-
parent: "ID"
|
|
142
|
-
registered: <today>
|
|
143
|
-
status: active
|
|
144
|
-
```
|
|
145
|
-
5. Provision the project store (the single source of truth for store creation;
|
|
146
|
-
runs after step 4 because the provisioner requires the project to be
|
|
147
|
-
registered):
|
|
148
|
-
```bash
|
|
149
|
-
ruby ~/.plastic/scripts/provision-project-store <slug>
|
|
150
|
-
```
|
|
151
|
-
6. Add `project-<slug>` to the intent's `tags` array
|
|
152
|
-
7. Auto-commit in both `~/.plastic/` and the new project
|
|
127
|
+
When the user says "start building" or the plan calls for a new project, invoke the
|
|
128
|
+
`plastic-creating-project` skill; it owns project directory creation, AGENTS.md
|
|
129
|
+
population, projects.yml registration, store provisioning, and the auto-commit of
|
|
130
|
+
both stores. Add `project-<slug>` to this intent's `tags` array either before
|
|
131
|
+
invoking it or as part of that skill's handoff.
|
|
153
132
|
|
|
154
133
|
### 7. Update INDEX.md
|
|
155
134
|
|
|
@@ -43,89 +43,25 @@ Invoke `plastic-install --local` in the project directory. This creates:
|
|
|
43
43
|
|
|
44
44
|
### 4. Populate AGENTS.md
|
|
45
45
|
|
|
46
|
-
Create `AGENTS.md` in the project root
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
# <Project Name> — Agent Instructions
|
|
50
|
-
|
|
51
|
-
Read `PLASTIC.md` in `~/.plastic/`. It contains all Plastic conventions.
|
|
52
|
-
Follow it exactly.
|
|
53
|
-
|
|
54
|
-
This file is the operating contract for this project. Any agent entering
|
|
55
|
-
this project reads this file first.
|
|
56
|
-
|
|
57
|
-
## Global Store
|
|
58
|
-
|
|
59
|
-
Location: `~/.plastic/`
|
|
60
|
-
Governing intent(s): <list of founding intent IDs with descriptions>
|
|
61
|
-
|
|
62
|
-
## Decisions
|
|
63
|
-
|
|
64
|
-
<Copy ALL decisions from founding intent(s)' `## Context > ### Decisions`>
|
|
65
|
-
|
|
66
|
-
Each decision should include:
|
|
67
|
-
- The decision itself
|
|
68
|
-
- The rationale (why this choice)
|
|
69
|
-
- Date decided
|
|
70
|
-
|
|
71
|
-
## Project-Specific Rules
|
|
72
|
-
|
|
73
|
-
<Any rules derived from the decisions — e.g., "Use Minitest, not RSpec",
|
|
74
|
-
"37signals methodology", "sqlite-vec for vector storage">
|
|
75
|
-
```
|
|
46
|
+
Create `AGENTS.md` in the project root from the skeleton in
|
|
47
|
+
`references/project-scaffolding.md` ("AGENTS.md skeleton"): read it now and fill in
|
|
48
|
+
the project name, governing intent IDs, decisions, and project-specific rules.
|
|
76
49
|
|
|
77
50
|
### 5. Create Tactical Mirror
|
|
78
51
|
|
|
79
|
-
Create the first intent in the project's store at `~/.plastic/projects/{slug}/store
|
|
52
|
+
Create the first intent in the project's store at `~/.plastic/projects/{slug}/store/`
|
|
53
|
+
using the frontmatter, sections, and INDEX.md line in `references/project-scaffolding.md`
|
|
54
|
+
("Tactical mirror intent"), including the Hub multi-intent variant if there is more
|
|
55
|
+
than one founding intent.
|
|
80
56
|
|
|
81
57
|
**Directory:** `~/.plastic/projects/{slug}/store/1--{slug}/`
|
|
82
58
|
**File:** `~/.plastic/projects/{slug}/store/1--{slug}/1--{slug}.md`
|
|
83
59
|
|
|
84
|
-
```yaml
|
|
85
|
-
---
|
|
86
|
-
id: '1'
|
|
87
|
-
intent: "<same description as founding intent>"
|
|
88
|
-
sources: ["global:<founding_intent_ID>"]
|
|
89
|
-
chain: []
|
|
90
|
-
created: <today>
|
|
91
|
-
author: <same as founding intent author>
|
|
92
|
-
tags: [<relevant tags>]
|
|
93
|
-
---
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Sections:
|
|
97
|
-
- `## Intent` — same as founding intent
|
|
98
|
-
- `## Context` — carry forward relevant Context and Decisions
|
|
99
|
-
- `## Outcome` — (pending)
|
|
100
|
-
- `## Insights` — empty
|
|
101
|
-
- `## Links` — `[[global:<founding_intent_ID>|<founding intent name>]]`
|
|
102
|
-
|
|
103
|
-
Update the project's `~/.plastic/projects/{slug}/INDEX.md`:
|
|
104
|
-
```markdown
|
|
105
|
-
# Index
|
|
106
|
-
|
|
107
|
-
## Active
|
|
108
|
-
- [1 — <intent name>](store/1--<slug>/1.md) — implementation, from: global:<ID>
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
**For multi-intent spawning (Hub):**
|
|
112
|
-
- `sources`: `["global:<id1>", "global:<id2>", ...]` — all founding intents
|
|
113
|
-
- All founding intents' decisions merge into AGENTS.md
|
|
114
|
-
- Context carries forward from all founding intents
|
|
115
|
-
|
|
116
60
|
### 6. Register in projects.yml
|
|
117
61
|
|
|
118
|
-
Read `~/.plastic/projects.yml` and add
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
<slug>:
|
|
122
|
-
path: <full-path>
|
|
123
|
-
parent: "<founding_intent_ID>"
|
|
124
|
-
registered: <today>
|
|
125
|
-
status: active
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
For Hub-spawned projects, `parent` references the primary founding intent.
|
|
62
|
+
Read `~/.plastic/projects.yml` and add the entry shown in
|
|
63
|
+
`references/project-scaffolding.md` ("projects.yml registration block"). For
|
|
64
|
+
Hub-spawned projects, `parent` references the primary founding intent.
|
|
129
65
|
|
|
130
66
|
### 7. Provision the Project Store
|
|
131
67
|
|
|
@@ -195,4 +131,5 @@ Announce to user:
|
|
|
195
131
|
|
|
196
132
|
## References
|
|
197
133
|
|
|
134
|
+
- Read `references/project-scaffolding.md` before steps 4-6, for the AGENTS.md skeleton, the tactical mirror intent format, and the projects.yml registration block
|
|
198
135
|
- Read `references/hubs-projects.md` for the full hub/project relationship model, project creation flow, and cross-linking conventions
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Project Scaffolding Templates
|
|
2
|
+
|
|
3
|
+
Full templates for the artifacts created while spawning a project: the AGENTS.md
|
|
4
|
+
skeleton (Workflow step 4), the tactical mirror intent (step 5), and the
|
|
5
|
+
projects.yml registration block (step 6).
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [AGENTS.md skeleton (step 4)](#agentsmd-skeleton-step-4)
|
|
10
|
+
- [Tactical mirror intent (step 5)](#tactical-mirror-intent-step-5)
|
|
11
|
+
- [projects.yml registration block (step 6)](#projectsyml-registration-block-step-6)
|
|
12
|
+
|
|
13
|
+
## AGENTS.md skeleton (step 4)
|
|
14
|
+
|
|
15
|
+
Create `AGENTS.md` in the project root with:
|
|
16
|
+
|
|
17
|
+
```markdown
|
|
18
|
+
# <Project Name> — Agent Instructions
|
|
19
|
+
|
|
20
|
+
Read `PLASTIC.md` in `~/.plastic/`. It contains all Plastic conventions.
|
|
21
|
+
Follow it exactly.
|
|
22
|
+
|
|
23
|
+
This file is the operating contract for this project. Any agent entering
|
|
24
|
+
this project reads this file first.
|
|
25
|
+
|
|
26
|
+
## Global Store
|
|
27
|
+
|
|
28
|
+
Location: `~/.plastic/`
|
|
29
|
+
Governing intent(s): <list of founding intent IDs with descriptions>
|
|
30
|
+
|
|
31
|
+
## Decisions
|
|
32
|
+
|
|
33
|
+
<Copy ALL decisions from founding intent(s)' `## Context > ### Decisions`>
|
|
34
|
+
|
|
35
|
+
Each decision should include:
|
|
36
|
+
- The decision itself
|
|
37
|
+
- The rationale (why this choice)
|
|
38
|
+
- Date decided
|
|
39
|
+
|
|
40
|
+
## Project-Specific Rules
|
|
41
|
+
|
|
42
|
+
<Any rules derived from the decisions — e.g., "Use Minitest, not RSpec",
|
|
43
|
+
"37signals methodology", "sqlite-vec for vector storage">
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Tactical mirror intent (step 5)
|
|
47
|
+
|
|
48
|
+
Create the first intent in the project's store at `~/.plastic/projects/{slug}/store/`:
|
|
49
|
+
|
|
50
|
+
**Directory:** `~/.plastic/projects/{slug}/store/1--{slug}/`
|
|
51
|
+
**File:** `~/.plastic/projects/{slug}/store/1--{slug}/1--{slug}.md`
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
---
|
|
55
|
+
id: '1'
|
|
56
|
+
intent: "<same description as founding intent>"
|
|
57
|
+
sources: ["global:<founding_intent_ID>"]
|
|
58
|
+
chain: []
|
|
59
|
+
created: <today>
|
|
60
|
+
author: <same as founding intent author>
|
|
61
|
+
tags: [<relevant tags>]
|
|
62
|
+
---
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Sections:
|
|
66
|
+
- `## Intent` — same as founding intent
|
|
67
|
+
- `## Context` — carry forward relevant Context and Decisions
|
|
68
|
+
- `## Outcome` — (pending)
|
|
69
|
+
- `## Insights` — empty
|
|
70
|
+
- `## Links` — `[[global:<founding_intent_ID>|<founding intent name>]]`
|
|
71
|
+
|
|
72
|
+
Update the project's `~/.plastic/projects/{slug}/INDEX.md`:
|
|
73
|
+
```markdown
|
|
74
|
+
# Index
|
|
75
|
+
|
|
76
|
+
## Active
|
|
77
|
+
- [1 — <intent name>](store/1--<slug>/1.md) — implementation, from: global:<ID>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**For multi-intent spawning (Hub):**
|
|
81
|
+
- `sources`: `["global:<id1>", "global:<id2>", ...]` — all founding intents
|
|
82
|
+
- All founding intents' decisions merge into AGENTS.md
|
|
83
|
+
- Context carries forward from all founding intents
|
|
84
|
+
|
|
85
|
+
## projects.yml registration block (step 6)
|
|
86
|
+
|
|
87
|
+
Read `~/.plastic/projects.yml` and add:
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
<slug>:
|
|
91
|
+
path: <full-path>
|
|
92
|
+
parent: "<founding_intent_ID>"
|
|
93
|
+
registered: <today>
|
|
94
|
+
status: active
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
For Hub-spawned projects, `parent` references the primary founding intent.
|
|
@@ -110,23 +110,8 @@ a raw terminal. The Markdown board (`--data` + template) is the surface for the
|
|
|
110
110
|
|
|
111
111
|
## How classification works (deterministic)
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
otherwise. A root id (a bare number) is always depth 1, so it is never demoted by this rule.
|
|
116
|
-
- **Value → high** when any of: explicit `value: high`; a human-authored **root** intent; or
|
|
117
|
-
an intent that is a `source` of ≥1 other intent (it has spawned follow-on work). A purely
|
|
118
|
-
relational `chain` entry alone is **not** a value signal (intent 68) — else low.
|
|
119
|
-
- **Flags** — `unblocked` only when a **future** intent has **all** its `sources` done AND at
|
|
120
|
-
least one source's completion date is strictly later than the intent's own `created` date (a
|
|
121
|
-
genuine wait, not a birth-time default); `in-progress` only when the savepoint ledger shows
|
|
122
|
-
real post-birth activity, not just the creation stamp; `stale` only on future intents past
|
|
123
|
-
the staleness threshold. All three kept low-noise by design.
|
|
124
|
-
- **Override** — a `value: high|low` frontmatter field always wins (pre-stamped data, never
|
|
125
|
-
model judgment at render time).
|
|
126
|
-
- **Caps** — quadrant lists and the project board's `active`/`future` lists are capped at 8
|
|
127
|
-
entries plus a trailing "+N more" line; each entry's text is truncated to 120 characters
|
|
128
|
-
with a trailing ellipsis. Applies to the Markdown board only (the ASCII renderer has its own
|
|
129
|
-
separate `CELL_CAP`).
|
|
113
|
+
The script computes Effort/Value/Flags/Override/Caps; the agent never re-derives them.
|
|
114
|
+
To explain or debug a quadrant assignment, read `references/classification.md`.
|
|
130
115
|
|
|
131
116
|
## Eval
|
|
132
117
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# How Classification Works (Deterministic)
|
|
2
|
+
|
|
3
|
+
The script (`dashboard.rb`) computes Effort/Value/Flags/Override/Caps deterministically;
|
|
4
|
+
the agent never re-derives them. Read this to explain or debug a quadrant assignment.
|
|
5
|
+
|
|
6
|
+
- **Effort** — small for `research`/`exploration`/`bugfix`, for already-scoped intents
|
|
7
|
+
(plan/checklist exists), or a **branch id** (folgezettel depth ≥ 2, e.g. `4a`, `12b3`); big
|
|
8
|
+
otherwise. A root id (a bare number) is always depth 1, so it is never demoted by this rule.
|
|
9
|
+
- **Value → high** when any of: explicit `value: high`; a human-authored **root** intent; or
|
|
10
|
+
an intent that is a `source` of ≥1 other intent (it has spawned follow-on work). A purely
|
|
11
|
+
relational `chain` entry alone is **not** a value signal (intent 68) — else low.
|
|
12
|
+
- **Flags** — `unblocked` only when a **future** intent has **all** its `sources` done AND at
|
|
13
|
+
least one source's completion date is strictly later than the intent's own `created` date (a
|
|
14
|
+
genuine wait, not a birth-time default); `in-progress` only when the savepoint ledger shows
|
|
15
|
+
real post-birth activity, not just the creation stamp; `stale` only on future intents past
|
|
16
|
+
the staleness threshold. All three kept low-noise by design.
|
|
17
|
+
- **Override** — a `value: high|low` frontmatter field always wins (pre-stamped data, never
|
|
18
|
+
model judgment at render time).
|
|
19
|
+
- **Caps** — quadrant lists and the project board's `active`/`future` lists are capped at 8
|
|
20
|
+
entries plus a trailing "+N more" line; each entry's text is truncated to 120 characters
|
|
21
|
+
with a trailing ellipsis. Applies to the Markdown board only (the ASCII renderer has its own
|
|
22
|
+
separate `CELL_CAP`).
|
package/skills/install/SKILL.md
CHANGED
|
@@ -158,7 +158,7 @@ Version: none -> <installed>
|
|
|
158
158
|
Doctor: <summary or "all clear">
|
|
159
159
|
```
|
|
160
160
|
|
|
161
|
-
Then: "
|
|
161
|
+
Then: "Read `docs/guides/your-first-intent-in-10-minutes.md` for your first intent, start to finish."
|
|
162
162
|
|
|
163
163
|
### Local Install (testing/legacy)
|
|
164
164
|
|
|
@@ -85,14 +85,11 @@ git merge <branch-name> --no-ff -m "feat: merge intent [ID] - [description]"
|
|
|
85
85
|
|
|
86
86
|
Always `--no-ff` to preserve branch history in the merge commit.
|
|
87
87
|
|
|
88
|
-
**Worktree-isolated intents (intent 73c3).**
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
worktree. If you already merged here by hand, step 9 is a clean no-op merge ("Already up to
|
|
94
|
-
date") and proceeds straight to removal. Do not delete the worktree before its branch is
|
|
95
|
-
merged, or the work is lost.
|
|
88
|
+
**Worktree-isolated intents (intent 73c3).** A worktree-delivered intent's code lives on
|
|
89
|
+
`plastic/{id}--{slug}`, merged together with cleanup in step 9, not on a hand-made feature
|
|
90
|
+
branch. Do not delete the worktree before its branch is merged, or the work is lost. For
|
|
91
|
+
the full rationale and the already-merged-by-hand no-op case, read
|
|
92
|
+
`references/promotion-and-tagging.md`.
|
|
96
93
|
|
|
97
94
|
### 4. Bump Version
|
|
98
95
|
|
|
@@ -231,12 +228,8 @@ A release IS a delivery. The active intent that drove this work must be complete
|
|
|
231
228
|
|
|
232
229
|
### 9. Clean Up the Intent's Worktrees (merge-then-remove)
|
|
233
230
|
|
|
234
|
-
A release is the merge-then-remove path for the intent's worktrees (intent 73c3)
|
|
235
|
-
|
|
236
|
-
(`plastic/{id}--{slug}`) is merged back into the repo's default branch BEFORE the worktree is
|
|
237
|
-
removed, so the integrated work is never lost. (The disarm path in `plastic-auto`, by contrast,
|
|
238
|
-
is a plain remove because no release is merging the branch.)
|
|
239
|
-
|
|
231
|
+
A release is the merge-then-remove path for the intent's worktrees (intent 73c3): the
|
|
232
|
+
intent's code branch is merged back into the default branch BEFORE the worktree is removed.
|
|
240
233
|
Drive it through `Worktree.finish` with `merge: true`, which merges the code branch, then
|
|
241
234
|
removes both worktrees (code + paired store), prunes both repos, and clears the worktree block
|
|
242
235
|
from the bridge:
|
|
@@ -249,10 +242,10 @@ ruby -r ~/.plastic/scripts/lib/worktree -r ~/.plastic/scripts/lib/bridge -e \
|
|
|
249
242
|
(Uses `discover_bridge`, not a bare session-keyed `Bridge.read`, because a session can own more
|
|
250
243
|
than one live bridge now — intent 131 — and `discover_bridge` resolves the right one for this cwd.)
|
|
251
244
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
245
|
+
Honor the worktree-cleanup rule: never leave an orphaned worktree, and run `git worktree
|
|
246
|
+
prune` in the affected repo if you hit a stale reference. For why this is the one place the
|
|
247
|
+
merge-vs-remove policy lands on merge, and the fail-open/idempotent guarantees of `finish`,
|
|
248
|
+
read `references/promotion-and-tagging.md`.
|
|
256
249
|
|
|
257
250
|
## Conventions
|
|
258
251
|
|
|
@@ -266,34 +259,9 @@ prune` in the affected repo if you hit a stale reference.
|
|
|
266
259
|
- **Verify sync** - after pushing, confirm npm dist-tag, GitHub "Latest", and the git tag all show the new version
|
|
267
260
|
- **Branch cleanup** - delete merged feature branches: `git branch -d <branch>`
|
|
268
261
|
|
|
269
|
-
## Promotion
|
|
270
|
-
|
|
271
|
-
To promote a release across channels, use `--promote`:
|
|
272
|
-
|
|
273
|
-
```bash
|
|
274
|
-
plastic-releasing --promote beta # promotes current alpha → beta
|
|
275
|
-
plastic-releasing --promote stable # promotes current beta → stable
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
**Promotion rules:**
|
|
279
|
-
- Linear only: alpha → beta → stable. Cannot skip channels.
|
|
280
|
-
- `--promote beta`: reads version from `package.json`, changes `-alpha.N` suffix
|
|
281
|
-
to `-beta.1`, publishes with `--tag beta`.
|
|
282
|
-
- `--promote stable`: reads version from `package.json`, strips pre-release suffix
|
|
283
|
-
entirely (e.g., `1.0.0-beta.3` → `1.0.0`), publishes to `latest`.
|
|
284
|
-
- Version files are bumped and committed as in a normal release.
|
|
285
|
-
- An annotated tag is created for the promoted version.
|
|
286
|
-
|
|
287
|
-
## Retroactive Tagging
|
|
288
|
-
|
|
289
|
-
For repos without prior tags, tag historical releases:
|
|
290
|
-
|
|
291
|
-
```bash
|
|
292
|
-
git tag -a v0.1.0 <commit-sha> -m "v0.1.0 - [description]"
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
Use `git log --oneline` to find the right commits (look for version bump commits or major feature merges).
|
|
296
|
-
|
|
297
262
|
## References
|
|
298
263
|
|
|
264
|
+
- When promoting a pre-release across channels (`--promote beta`/`--promote stable`) or
|
|
265
|
+
tagging a historical release retroactively, read `references/promotion-and-tagging.md`
|
|
266
|
+
for the exact commands and rules first
|
|
299
267
|
- Read `references/deprecations.md` for the full deprecation process, severity levels, deprecations.yml schema, and dismissal rules when adding or managing deprecations
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Promotion, Retroactive Tagging, and Worktree Merge Rationale
|
|
2
|
+
|
|
3
|
+
Occasional variant paths off the main release workflow: promoting a pre-release
|
|
4
|
+
across channels, tagging historical releases retroactively, and the deep rationale
|
|
5
|
+
for why the intent's worktree is merged before removal.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Worktree merge-then-remove rationale](#worktree-merge-then-remove-rationale)
|
|
10
|
+
- [Promotion](#promotion)
|
|
11
|
+
- [Retroactive Tagging](#retroactive-tagging)
|
|
12
|
+
|
|
13
|
+
## Worktree merge-then-remove rationale
|
|
14
|
+
|
|
15
|
+
**Worktree-isolated intents (intent 73c3).** When the intent was delivered in a Plastic
|
|
16
|
+
worktree (the bridge has a provisioned `worktree` block), its code lives on the branch
|
|
17
|
+
`plastic/{id}--{slug}` inside `<repo>/.claude/worktrees/{id}--{slug}`, not on a hand-made
|
|
18
|
+
feature branch. The merge-then-remove of that worktree is handled together with cleanup in
|
|
19
|
+
Workflow step 9, which merges `plastic/{id}--{slug}` into the default branch BEFORE removing the
|
|
20
|
+
worktree. If you already merged here by hand, step 9 is a clean no-op merge ("Already up to
|
|
21
|
+
date") and proceeds straight to removal. Do not delete the worktree before its branch is
|
|
22
|
+
merged, or the work is lost.
|
|
23
|
+
|
|
24
|
+
A release is the merge-then-remove path for the intent's worktrees. This is the one place
|
|
25
|
+
the merge-vs-remove policy lands on "merge": the intent's code branch (`plastic/{id}--{slug}`)
|
|
26
|
+
is merged back into the repo's default branch BEFORE the worktree is removed, so the
|
|
27
|
+
integrated work is never lost. (The disarm path in `plastic-auto`, by contrast, is a plain
|
|
28
|
+
remove because no release is merging the branch.)
|
|
29
|
+
|
|
30
|
+
`Worktree.finish` is fail-open and idempotent: a conflicting merge is aborted and logged (the
|
|
31
|
+
worktree is still removed rather than stranded), and a second call with the block already
|
|
32
|
+
cleared is a no-op.
|
|
33
|
+
|
|
34
|
+
## Promotion
|
|
35
|
+
|
|
36
|
+
To promote a release across channels, use `--promote`:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
plastic-releasing --promote beta # promotes current alpha → beta
|
|
40
|
+
plastic-releasing --promote stable # promotes current beta → stable
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Promotion rules:**
|
|
44
|
+
- Linear only: alpha → beta → stable. Cannot skip channels.
|
|
45
|
+
- `--promote beta`: reads version from `package.json`, changes `-alpha.N` suffix
|
|
46
|
+
to `-beta.1`, publishes with `--tag beta`.
|
|
47
|
+
- `--promote stable`: reads version from `package.json`, strips pre-release suffix
|
|
48
|
+
entirely (e.g., `1.0.0-beta.3` → `1.0.0`), publishes to `latest`.
|
|
49
|
+
- Version files are bumped and committed as in a normal release.
|
|
50
|
+
- An annotated tag is created for the promoted version.
|
|
51
|
+
|
|
52
|
+
## Retroactive Tagging
|
|
53
|
+
|
|
54
|
+
For repos without prior tags, tag historical releases:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
git tag -a v0.1.0 <commit-sha> -m "v0.1.0 - [description]"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Use `git log --oneline` to find the right commits (look for version bump commits or major feature merges).
|
|
@@ -48,70 +48,13 @@ This structure informs the task decomposition. Each task should produce self-con
|
|
|
48
48
|
- "Run the tests and make sure they pass" - step
|
|
49
49
|
- "Commit" - step
|
|
50
50
|
|
|
51
|
-
## Plan
|
|
51
|
+
## Plan Format
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
> **For agentic workers:** Use `plastic-executing-plan` to implement this plan task-by-task.
|
|
59
|
-
|
|
60
|
-
**Goal:** [One sentence describing what this builds]
|
|
61
|
-
|
|
62
|
-
**Architecture:** [2-3 sentences about approach]
|
|
63
|
-
|
|
64
|
-
**Tech Stack:** [Key technologies/libraries]
|
|
65
|
-
|
|
66
|
-
**Intent:** {id} — {name}
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Task Structure
|
|
72
|
-
|
|
73
|
-
````markdown
|
|
74
|
-
### Task N: [Component Name]
|
|
75
|
-
|
|
76
|
-
**Files:**
|
|
77
|
-
- Create: `exact/path/to/file.rb`
|
|
78
|
-
- Modify: `exact/path/to/existing.rb:123-145`
|
|
79
|
-
- Test: `test/exact/path/to/test.rb`
|
|
80
|
-
|
|
81
|
-
- [ ] **Step 1: Write the failing test**
|
|
82
|
-
|
|
83
|
-
```ruby
|
|
84
|
-
def test_specific_behavior
|
|
85
|
-
result = function(input)
|
|
86
|
-
assert_equal expected, result
|
|
87
|
-
end
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
- [ ] **Step 2: Run test to verify it fails**
|
|
91
|
-
|
|
92
|
-
Run: `ruby -Itest test/path/test.rb --name test_specific_behavior`
|
|
93
|
-
Expected: FAIL with "undefined method"
|
|
94
|
-
|
|
95
|
-
- [ ] **Step 3: Write minimal implementation**
|
|
96
|
-
|
|
97
|
-
```ruby
|
|
98
|
-
def function(input)
|
|
99
|
-
expected
|
|
100
|
-
end
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
- [ ] **Step 4: Run test to verify it passes**
|
|
104
|
-
|
|
105
|
-
Run: `ruby -Itest test/path/test.rb --name test_specific_behavior`
|
|
106
|
-
Expected: PASS
|
|
107
|
-
|
|
108
|
-
- [ ] **Step 5: Commit**
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
git add test/path/test.rb lib/path/file.rb
|
|
112
|
-
git commit -m "feat: add specific feature"
|
|
113
|
-
```
|
|
114
|
-
````
|
|
53
|
+
For the exact plan/task/checklist/action format (the Plan Document Header
|
|
54
|
+
template, the full Task Structure worked example, and the checklist.md /
|
|
55
|
+
actions/ACTION_N.md templates), read `references/plan-format.md` before
|
|
56
|
+
writing plan.md. Every plan starts with the header template and decomposes
|
|
57
|
+
into tasks matching the Task Structure shape.
|
|
115
58
|
|
|
116
59
|
## No Placeholders
|
|
117
60
|
|
|
@@ -144,31 +87,10 @@ If you find issues, fix them inline. No need to re-review — just fix and move
|
|
|
144
87
|
## Plastic Artifacts
|
|
145
88
|
|
|
146
89
|
After writing `plan.md`, create two additional artifacts in the intent directory:
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
```markdown
|
|
153
|
-
# Checklist — Intent {id}: {name}
|
|
154
|
-
|
|
155
|
-
- [ ] Task 1: {task title}
|
|
156
|
-
- [ ] Task 2: {task title}
|
|
157
|
-
- [ ] Task 3: {task title}
|
|
158
|
-
...
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### actions/ACTION_N.md
|
|
162
|
-
|
|
163
|
-
One file per task. Each action is self-contained — a subagent can execute it without reading the plan.
|
|
164
|
-
|
|
165
|
-
```markdown
|
|
166
|
-
# Action {N}: {task title}
|
|
167
|
-
|
|
168
|
-
{Full task text copied from plan.md — all steps, all code, all commands. Nothing omitted.}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
Create the `actions/` directory inside the intent directory: `{intent_dir}/actions/`
|
|
90
|
+
`checklist.md` (execution registry with one checkbox per task) and
|
|
91
|
+
`actions/ACTION_N.md` (one self-contained file per task, in an `actions/`
|
|
92
|
+
directory inside the intent directory). For the exact format of both, read
|
|
93
|
+
`references/plan-format.md`.
|
|
172
94
|
|
|
173
95
|
## Git Commit
|
|
174
96
|
|