@zalom/plastic 1.0.0-beta.9 → 1.0.1
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 +398 -82
- package/README.md +98 -82
- package/agents/plastic-brainstorming.md +12 -9
- package/agents/plastic-enforcer.md +52 -12
- package/agents/plastic-executor.md +10 -10
- package/agents/plastic-future-intent-researcher.md +4 -8
- package/agents/plastic-intent-curator.md +12 -14
- package/agents/plastic-intent-discovery.md +35 -0
- package/agents/plastic-planner.md +15 -10
- package/agents/plastic-spec-specialist.md +15 -10
- package/bin/plastic.js +7 -3
- package/hooks/code-gate +17 -2
- package/hooks/hooks.json +28 -3
- package/hooks/lock-gate +21 -0
- package/hooks/retrieval-gate +10 -0
- package/hooks/savepoint-pre +10 -0
- package/hooks/statusline +48 -6
- package/package.json +2 -1
- package/scripts/agent-report +21 -0
- package/scripts/dashboard.rb +98 -23
- package/scripts/doctor.rb +232 -5
- package/scripts/hook-auto-arm +1 -1
- package/scripts/hook-bash-gate +22 -4
- package/scripts/hook-code-gate +30 -7
- package/scripts/hook-continue +17 -0
- package/scripts/hook-create-gate +45 -9
- package/scripts/hook-gate-check +24 -23
- package/scripts/hook-lock-gate +83 -0
- package/scripts/hook-retrieval-gate +148 -0
- package/scripts/hook-savepoint-pre +32 -0
- package/scripts/hook-session-start +1 -1
- package/scripts/insight-append +51 -0
- package/scripts/install.rb +44 -7
- package/scripts/lib/agent_models.rb +43 -0
- package/scripts/lib/bridge.rb +924 -84
- package/scripts/lib/dashboard_banner.rb +42 -0
- package/scripts/lib/hook_registry.rb +95 -0
- package/scripts/lib/insights.rb +86 -0
- package/scripts/lib/installer_core.rb +101 -60
- package/scripts/lib/link_suggestions.rb +319 -0
- package/scripts/lib/lock.rb +375 -0
- package/scripts/lib/power_tools.rb +22 -21
- package/scripts/lib/preflight.rb +79 -0
- package/scripts/lib/qmd_sync.rb +48 -6
- package/scripts/lib/retrieval_gate.rb +211 -0
- package/scripts/lib/worktree.rb +384 -0
- package/scripts/link-suggest +213 -0
- package/scripts/new-intent +58 -17
- package/scripts/plastic-lock +164 -0
- package/scripts/read-config +4 -0
- package/scripts/spawn-preamble +36 -4
- package/scripts/update.rb +16 -7
- package/skills/auto/SKILL.md +127 -20
- package/skills/auto/references/agent-architecture.md +7 -4
- package/skills/auto/references/agent-report-contract.md +36 -1
- package/skills/auto/references/end-tail.md +56 -0
- package/skills/auto/references/human-report-contract.md +55 -0
- package/skills/auto/references/tiers.md +77 -0
- package/skills/brainstorming/SKILL.md +7 -34
- package/skills/brainstorming/references/design-principles.md +49 -0
- package/skills/continuing/SKILL.md +26 -7
- package/skills/creating-intent/SKILL.md +13 -28
- package/skills/creating-project/SKILL.md +11 -74
- package/skills/creating-project/references/project-scaffolding.md +97 -0
- package/skills/creating-skills/SKILL.md +65 -0
- package/skills/creating-skills/evals/evals.json +108 -0
- package/skills/creating-skills/references/agents.md +168 -0
- package/skills/creating-skills/references/evals.md +41 -0
- package/skills/creating-skills/references/hooks.md +248 -0
- package/skills/creating-skills/references/progressive-disclosure.md +176 -0
- package/skills/creating-skills/references/scripts.md +166 -0
- package/skills/creating-skills/references/skills.md +165 -0
- package/skills/creating-skills/scripts/scaffold.rb +313 -0
- package/skills/dashboard/SKILL.md +13 -11
- package/skills/dashboard/references/classification.md +22 -0
- package/skills/doctor/SKILL.md +10 -7
- package/skills/executing-plan/SKILL.md +4 -4
- package/skills/humanizer/SKILL.md +39 -0
- package/skills/humanizer/evals/evals.json +70 -0
- package/skills/humanizer/references/always-on-snippet.md +9 -0
- package/skills/humanizer/references/examples.md +48 -0
- package/skills/install/SKILL.md +75 -84
- package/skills/intent-curator/SKILL.md +5 -1
- package/skills/intent-discovery/SKILL.md +47 -0
- package/skills/intent-starting/SKILL.md +130 -0
- package/skills/intent-starting/evals/evals.json +117 -0
- package/skills/intent-starting/references/boarding-matrix.md +35 -0
- package/skills/linking-intents/SKILL.md +48 -12
- package/skills/lock/SKILL.md +41 -0
- package/skills/managing-index/SKILL.md +6 -0
- package/skills/releasing/SKILL.md +44 -29
- package/skills/releasing/references/promotion-and-tagging.md +60 -0
- package/skills/roadmap/SKILL.md +51 -0
- package/skills/roadmap/references/file-format.md +91 -0
- package/skills/roadmap/references/operations.md +88 -0
- package/skills/uninstall/SKILL.md +29 -11
- package/skills/update/SKILL.md +34 -23
- package/skills/versions/SKILL.md +27 -12
- package/skills/writing-plans/SKILL.md +10 -88
- package/skills/writing-plans/references/plan-format.md +102 -0
- package/templates/config.yml +8 -0
- package/templates/outcome.md +3 -0
- package/templates/revisions.md +58 -0
- package/templates/roadmap.md +30 -0
- package/skills/writing-instructions/SKILL.md +0 -159
- package/skills/writing-instructions/references/agentskills-spec.md +0 -135
package/PLASTIC.md
CHANGED
|
@@ -1,32 +1,43 @@
|
|
|
1
|
-
# Plastic
|
|
1
|
+
# Plastic: Conventions
|
|
2
2
|
|
|
3
3
|
> **This file is maintained by Plastic.** It will be overwritten when the
|
|
4
|
-
> plugin is updated. Do not modify
|
|
4
|
+
> plugin is updated. Do not modify it: your changes will be lost.
|
|
5
5
|
> For project-specific rules, use `AGENTS.md` instead.
|
|
6
6
|
|
|
7
|
+
See `PLASTIC-reference.md` for reference material: read it on demand, it is not injected at session start.
|
|
8
|
+
|
|
7
9
|
## What is an Intent
|
|
8
10
|
|
|
9
11
|
A directory in the store containing `{ID}--{slug}.md` and optional supporting files.
|
|
10
|
-
It represents a desire
|
|
12
|
+
It represents a desire: something a human or agent wants to accomplish, explore, or understand.
|
|
11
13
|
|
|
12
14
|
```
|
|
13
15
|
store/
|
|
14
16
|
ID--three-to-five-words/
|
|
15
|
-
{ID}--{slug}.md # required
|
|
16
|
-
spec.md # optional
|
|
17
|
-
plan.md # optional
|
|
18
|
-
checklist.md # optional
|
|
19
|
-
outcome.md # optional
|
|
20
|
-
actions/ # optional
|
|
21
|
-
resources/ # optional
|
|
22
|
-
savepoint.md # optional
|
|
17
|
+
{ID}--{slug}.md # required - the intent itself
|
|
18
|
+
spec.md # optional - specification (Why deliverable)
|
|
19
|
+
plan.md # optional - implementation plan (How deliverable)
|
|
20
|
+
checklist.md # optional - execution registry (How deliverable)
|
|
21
|
+
outcome.md # optional - detailed result (Exec deliverable)
|
|
22
|
+
actions/ # optional - individual work items
|
|
23
|
+
resources/ # optional - research, references, screenshots, diagrams
|
|
24
|
+
savepoint.md # optional - deterministic cycle-step ledger (auto-written)
|
|
25
|
+
revisions.md # optional - append-only structural-maintenance audit trail
|
|
23
26
|
```
|
|
24
27
|
|
|
25
28
|
Lifecycle files (`spec.md`, `plan.md`, `checklist.md`, `outcome.md`) have defined
|
|
26
|
-
roles. Supporting artifacts that aren't lifecycle deliverables
|
|
27
|
-
reference docs, external API snapshots, screenshots, diagrams
|
|
29
|
+
roles. Supporting artifacts that aren't lifecycle deliverables (research reports,
|
|
30
|
+
reference docs, external API snapshots, screenshots, diagrams) go in `resources/`.
|
|
28
31
|
Name files inside as `{type}--{description}.md` (e.g., `deep-research--gsd-core.md`).
|
|
29
32
|
|
|
33
|
+
`revisions.md` is an optional, append-only structural-maintenance audit trail. It is not a
|
|
34
|
+
lifecycle deliverable and is never scaffolded at intent birth. Its mere existence signals that
|
|
35
|
+
the intent underwent structural (not conceptual) change. Structural maintenance is move-and-record:
|
|
36
|
+
it removes a misplaced section, file, or ref from its artifact and preserves that content in full
|
|
37
|
+
inside `revisions.md` (newest entry at the bottom, one entry per relocated item), so no record is
|
|
38
|
+
lost and the delivered meaning is never altered. Changing what an intent delivered is a new intent,
|
|
39
|
+
not a revision.
|
|
40
|
+
|
|
30
41
|
## Frontmatter
|
|
31
42
|
|
|
32
43
|
Identity and knowledge graph only. Nothing operational.
|
|
@@ -57,19 +68,27 @@ tags: [plastic, architecture]
|
|
|
57
68
|
Ordering is mandatory: all `sources` first (top), then all `chain`, frontmatter order
|
|
58
69
|
preserved within each group. Sources never appear at the end. No source/chain tags, no
|
|
59
70
|
sub-grouping. An intent with empty `sources` and `chain` carries the empty-state comment.
|
|
71
|
+
- `## Links` is a DERIVED view, not a place to author links (Convention over Configuration).
|
|
72
|
+
It equals the projection of `sources` (first) then `chain`. Never hand-write or hand-edit a
|
|
73
|
+
`## Links` line, and never auto-delete one. The edge lives in the frontmatter graph; the
|
|
74
|
+
section is regenerated from it (doctor `graph_links_projection` enforces this identity). To
|
|
75
|
+
add a link, add the frontmatter edge, then reproject.
|
|
76
|
+
- Links are decided by CONTEXT INFLUENCE, not by shared files, shared symbols, or a topic
|
|
77
|
+
similarity score. The question is whether one intent's context actually informed another.
|
|
78
|
+
Three tiers:
|
|
79
|
+
- **sources:** the foundational context that shaped this intent's creation (a split, an idea
|
|
80
|
+
born during development, a merge). Earns an edge.
|
|
81
|
+
- **chain:** the context that materially helps DELIVER this intent. This is a HIGH bar: only
|
|
82
|
+
the genuinely delivery-moving intents, not everything in the same area. Earns an edge,
|
|
83
|
+
reflected in `## Links`.
|
|
84
|
+
- **tags:** a loose theme grouping for search. NOT a link. A shared tag is a door INTO the
|
|
85
|
+
store (filtered discovery), not a pathway BETWEEN two notes.
|
|
86
|
+
Judging influence is an agent's call, made by reading the candidate's Intent and Context. A
|
|
87
|
+
script cannot grade it, so `scripts/link-suggest` only gathers candidates with that evidence,
|
|
88
|
+
records a confirmed edge with a rating and reason, and flags drift.
|
|
60
89
|
- IDs use Luhmann's alternating convention: `1` → `1a` → `1a1` → `1a1a`
|
|
61
90
|
- Multiple branches increment: `1a`, `1b`, `1c`
|
|
62
91
|
|
|
63
|
-
## Two Processes
|
|
64
|
-
|
|
65
|
-
| Process | Scope | Type | Actor |
|
|
66
|
-
|---|---|---|---|
|
|
67
|
-
| **Build → Observe → Repeat** | The system | Continuous loop | Coordinator |
|
|
68
|
-
| **What → Why → How → Exec** | One intent | Finite lifecycle | Agent |
|
|
69
|
-
|
|
70
|
-
B→O→R is the Coordinator's heartbeat. W→W→H→E is what happens inside each intent.
|
|
71
|
-
The connection: an intent's `## Insights` feeds the Coordinator's Observe phase.
|
|
72
|
-
|
|
73
92
|
## Lifecycle Stages
|
|
74
93
|
|
|
75
94
|
| Stage | Section | Deliverable | Detail |
|
|
@@ -79,25 +98,165 @@ The connection: an intent's `## Insights` feeds the Coordinator's Observe phase.
|
|
|
79
98
|
| **How** | Planning | `plan.md` + `actions/` + `checklist.md` | `plastic-writing-plans` |
|
|
80
99
|
| **Exec** | Execution | `outcome.md` | `plastic-executing-plan` |
|
|
81
100
|
|
|
82
|
-
`## Insights`
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
101
|
+
`## Insights` is the append-only log of durable discoveries captured throughout ALL stages.
|
|
102
|
+
An insight is a discovery worth keeping for later reads: novel, or old but newly relevant,
|
|
103
|
+
surfaced at any stage (What, Why, How, Exec). It is the most interesting residue of an
|
|
104
|
+
intent, the part a future reader most wants. **Append-only means newest entry at the bottom;
|
|
105
|
+
never prepend.** This ordering is a hard convention: Insights are the semantic trace of an
|
|
106
|
+
intent, and a consistent newest-last order keeps that trace readable across every intent.
|
|
107
|
+
|
|
108
|
+
Every entry leads with a fixed, machine-parseable prefix `{utc-iso8601} · {stage} · {author}`,
|
|
109
|
+
for example `2026-06-24T08:13:05Z · Why · plastic-brainstorming (autonomous)`. The UTC ISO8601
|
|
110
|
+
timestamp (to the second, trailing `Z`) is the same convention the savepoint ledger uses, so
|
|
111
|
+
the store has one timestamp convention. This per-entry prefix is not prepending the entry:
|
|
112
|
+
entries stay append-only, newest at the bottom; the prefix only stamps each line with when,
|
|
113
|
+
which stage, and who.
|
|
114
|
+
|
|
115
|
+
The blessed write path is the `insight-append` helper
|
|
116
|
+
(`scripts/insight-append <intent_dir> <text> --stage S --author A`), which formats the prefix,
|
|
117
|
+
validates it, and appends at the bottom. Hand-editing `## Insights` is an escape hatch; the
|
|
118
|
+
helper is the default so the format cannot drift.
|
|
119
|
+
|
|
120
|
+
Background sessions and dispatched sub-agents do not write the insight themselves. They carry
|
|
121
|
+
each nugget home in the completion report's `insights:` field, and the orchestrator (or any
|
|
122
|
+
agent that can write the file) persists it via the helper. A session that cannot write the
|
|
123
|
+
intent file still returns its report, so the insight survives.
|
|
86
124
|
For full lifecycle detail, the skills in the Detail column have references/.
|
|
87
125
|
|
|
88
|
-
|
|
126
|
+
## Tiers (proportional auto sizing)
|
|
127
|
+
|
|
128
|
+
Auto mode sizes every intent S/M/L at Why: S = single mechanism or file cluster (hours);
|
|
129
|
+
M = one subsystem (about a day); L = cross-cutting or novel design.
|
|
130
|
+
|
|
131
|
+
Speed comes from two levers only: artifact content depth and agent topology. The
|
|
132
|
+
same-structure invariant holds: same file set, stage order, gates, and savepoint ledger at
|
|
133
|
+
every tier and in both modes.
|
|
134
|
+
|
|
135
|
+
S/M collapse the topology (one thinker agent writes spec.md then plan.md plus
|
|
136
|
+
checklist.md in one context; actions/ only for L; a sonnet executor implements). L keeps
|
|
137
|
+
the full team.
|
|
138
|
+
|
|
139
|
+
Never cut at any tier: the independent reviewer, outcome.md as truth of delivery, the
|
|
140
|
+
delivery lock, worktree isolation, intent creation via skill, INDEX as status truth, the
|
|
141
|
+
QMD reindex at End.
|
|
142
|
+
|
|
143
|
+
Tier is recorded as a `Tier: S|M|L` line at the top of spec.md. It is convention-only,
|
|
144
|
+
read by the orchestrator, not enforced by any gate or by doctor.
|
|
145
|
+
|
|
146
|
+
Guided mode is unchanged: full-depth artifacts, the human at every gate.
|
|
147
|
+
|
|
148
|
+
## Agent Models and Dispatch (intent 116)
|
|
149
|
+
|
|
150
|
+
Every lifecycle stage has exactly one dispatchable background agent, plus the enforcer that
|
|
151
|
+
orchestrates them:
|
|
152
|
+
|
|
153
|
+
| Stage | Agent |
|
|
154
|
+
|---|---|
|
|
155
|
+
| What | `plastic-intent-discovery` |
|
|
156
|
+
| Why | `plastic-brainstorming` + `plastic-spec-specialist` |
|
|
157
|
+
| How | `plastic-planner` |
|
|
158
|
+
| Exec | `plastic-executor` |
|
|
159
|
+
| Done | `plastic-intent-curator` |
|
|
160
|
+
|
|
161
|
+
Final-gate code review stays an ad-hoc subagent the enforcer dispatches at the final gate, not
|
|
162
|
+
a standing role.
|
|
163
|
+
|
|
164
|
+
**Auto-mode entry.** `plastic-auto` is the entry skill for autonomous delivery: it takes over How
|
|
165
|
+
and Exec, spins up the team above, and works the dashboard's dispatchable queue. The dashboard's
|
|
166
|
+
`--data` output splits intents into a `dispatchable_queue` (work an agent can pick up) and
|
|
167
|
+
`human_only` (intents that need a person); auto mode consumes the former.
|
|
168
|
+
|
|
169
|
+
**Model contract.** Every agent in `agents/*.md` pins an explicit Claude Code model alias in
|
|
170
|
+
its own frontmatter: `opus`, `sonnet`, or `haiku`. Never `inherit`, never Fable. Aliases track
|
|
171
|
+
"latest per tier" so no Plastic release is required to advance a tier. The tier by role:
|
|
172
|
+
`plastic-enforcer`, `plastic-brainstorming`, `plastic-planner` are `opus`;
|
|
173
|
+
`plastic-spec-specialist`, `plastic-executor`, `plastic-intent-curator`,
|
|
174
|
+
`plastic-future-intent-researcher`, `plastic-intent-discovery` are `sonnet`.
|
|
175
|
+
|
|
176
|
+
**Config and installer mechanism.** `agents.models.<basename>` in a project's
|
|
177
|
+
`<dir>/.plastic_store/config.yml` or the global `~/.plastic/config.yml` overrides one agent's
|
|
178
|
+
tier. Precedence is project, then global, then the shipped default, matching every other
|
|
179
|
+
`read-config` key. The installer applies the resolved override to each agent file's `model:`
|
|
180
|
+
line at copy time (install, update, and repair, across every harness target). With no override
|
|
181
|
+
configured, the shipped frontmatter passes through unchanged.
|
|
182
|
+
|
|
183
|
+
**Dispatch-time contract.** Frontmatter is primary, and Claude Code reads it at dispatch, but
|
|
184
|
+
because that read is a harness implementation detail rather than a contract Plastic controls,
|
|
185
|
+
every dispatch site also resolves the target agent's model through the config chain
|
|
186
|
+
(`read-config agents.models.<basename> --project <repo>`) and passes it explicitly at dispatch,
|
|
187
|
+
belt-and-braces on top of the frontmatter pin.
|
|
188
|
+
|
|
189
|
+
**Cross-harness portability.** The dispatch and model-tier contract above is harness-facing. The
|
|
190
|
+
adapter layer that maps Plastic's hooks and model aliases onto each supported agent runtime
|
|
191
|
+
(Claude, Codex, Hermes) is the cross-harness portability layer; see
|
|
192
|
+
docs/reference/harness-adapters.md for the adapter contract.
|
|
193
|
+
|
|
194
|
+
**Orchestrator advisory.** At auto-mode start, the orchestrator recommends once that the user
|
|
195
|
+
run the main session on the best available thinking model (Fable, Opus, or whatever supersedes
|
|
196
|
+
them). This is advisory only: it changes no behavior and blocks nothing if ignored, and it
|
|
197
|
+
concerns the human's main session, never a dispatched subagent.
|
|
198
|
+
|
|
199
|
+
**`plastic-intent-discovery`.** The What-stage agent. It fires at intent activation, after the
|
|
200
|
+
delivery lock is armed and before Why begins, running under that lock as the owner session (it
|
|
201
|
+
does not acquire the lock itself and is not blocked by it): it reads the intent's
|
|
202
|
+
`chain`/`sources` frontmatter, runs QMD-first discovery over completed predecessor work and
|
|
203
|
+
related parked or future intents, and deposits findings to `resources/discovery--<slug>.md` in
|
|
204
|
+
the intent directory ONLY. It never writes the intent file, `spec.md`, or any other lifecycle
|
|
205
|
+
deliverable; the Why-stage `plastic-brainstorming` agent reads its deposit and enriches
|
|
206
|
+
`## Context`.
|
|
207
|
+
|
|
208
|
+
`savepoint.md`: a deterministic, append-only ledger of cycle-step milestones (one line per
|
|
89
209
|
lifecycle boundary, newest at the bottom), written automatically by the gate hook. It is
|
|
90
210
|
sugar on top of the conventions, not a source of truth: state is always derivable from
|
|
91
211
|
files-on-disk, and the ledger is rebuildable. It exists so a resuming agent reads the cycle's
|
|
92
212
|
succession at a glance (last line = where we are).
|
|
93
213
|
|
|
214
|
+
## Auto-Mode Human Reporting (intent 92)
|
|
215
|
+
|
|
216
|
+
In auto mode the orchestrator briefs the human at every lifecycle stage boundary in a fixed,
|
|
217
|
+
impact-first shape (the EM-to-CTO report contract): State, then Risk, then Call. It leads with
|
|
218
|
+
what changed and why it matters, names one risk, and leaves the decision to the human. Separately,
|
|
219
|
+
the `plastic-humanizer` skill cleans authored prose (specs, outcomes, READMEs, release notes) of
|
|
220
|
+
AI tells and slop; it is for documents, not for every reply.
|
|
221
|
+
|
|
222
|
+
## Operational Skills
|
|
223
|
+
|
|
224
|
+
Beyond the lifecycle agents, Plastic ships thin skills for day-to-day operation:
|
|
225
|
+
|
|
226
|
+
- **`plastic-dashboard`** renders a deterministic Value x Effort work cockpit across the global
|
|
227
|
+
store and every project, and emits a machine-readable queue (`scripts/dashboard.rb --data
|
|
228
|
+
[continue|project <slug>]`) that auto mode consumes.
|
|
229
|
+
- **`plastic-doctor`** checks installation health. See the Skills Reference in PLASTIC-reference.md
|
|
230
|
+
for its three scopes (`--core` for the boot integrity check, `--store` per store on dashboard
|
|
231
|
+
load, and the full no-flag walk after an update).
|
|
232
|
+
- **Lifecycle skills** (`plastic-install`, `plastic-update`, `plastic-uninstall`,
|
|
233
|
+
`plastic-versions`, intent 55) are thin wrappers over a single pinned
|
|
234
|
+
`npx -y @zalom/plastic@<channel> <verb>` call: initialize or repair an install, advance a
|
|
235
|
+
channel, remove Plastic, and step the local versions ledger.
|
|
236
|
+
|
|
237
|
+
## Releases and Versioning
|
|
238
|
+
|
|
239
|
+
Plastic ships as versioned releases. A release is a collection of intents: a cut bundles whichever
|
|
240
|
+
intents landed since the previous cut and completes them, so the intent schema itself stays
|
|
241
|
+
release-agnostic and carries no version number. Cutting a release bumps the three version files
|
|
242
|
+
(`package.json`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`), tags
|
|
243
|
+
`v{version}`, runs `gh release create --latest`, and publishes to npm. The npm dist-tag follows
|
|
244
|
+
the version string: a `-alpha` suffix routes to the `alpha` tag, `-beta` to `beta`, and a plain
|
|
245
|
+
version with no suffix routes to `latest`. Release history lives in `CHANGELOG.md` at the repo
|
|
246
|
+
root, one line per cut. The `plastic-releasing` skill runs the whole flow.
|
|
247
|
+
|
|
248
|
+
Deprecations are declared in `deprecations.yml` and shown at SessionStart. While Plastic is
|
|
249
|
+
pre-1.0, a satisfied deprecation may be removed immediately; from `1.0.0` on the steady-state
|
|
250
|
+
grace rule applies (removal at least two minors ahead). See PLASTIC-reference.md for the
|
|
251
|
+
Deprecation Process.
|
|
252
|
+
|
|
94
253
|
## Gotchas
|
|
95
254
|
|
|
96
255
|
- **Artifacts go in the intent directory.** Never create `docs/plans/`,
|
|
97
256
|
`docs/specs/`, `researches/`, or similar. All meta-artifacts go in
|
|
98
257
|
`~/.plastic/store/ID--slug/` or the project store equivalent.
|
|
99
258
|
- **Code goes in the project. Everything else goes in the intent.**
|
|
100
|
-
Plans, specs, checklists, savepoints
|
|
259
|
+
Plans, specs, checklists, savepoints: all in the intent directory.
|
|
101
260
|
- **The global store is never pushed.** `~/.plastic/` is git-tracked locally
|
|
102
261
|
but contains sensitive data. Never push to a remote.
|
|
103
262
|
- **Agent-created repos are private by default.** Use `gh repo create --private`.
|
|
@@ -110,26 +269,6 @@ succession at a glance (last line = where we are).
|
|
|
110
269
|
brainstorming, writing-plans, etc., Plastic's directory rules override
|
|
111
270
|
their default output paths.
|
|
112
271
|
|
|
113
|
-
## Defaults-First
|
|
114
|
-
|
|
115
|
-
Plastic stands on its own. Skills and agents use Plastic's own defaults; an
|
|
116
|
-
external skill (for example `superpowers:*`) is opt-in, never load-bearing.
|
|
117
|
-
|
|
118
|
-
- **Default to Plastic, delegate by exception.** Name the Plastic-native path as
|
|
119
|
-
the default. Delegate to an external skill only when (a) it is available in the
|
|
120
|
-
harness, or (b) the user explicitly asks for it. A user without that plugin must
|
|
121
|
-
still get the core behavior.
|
|
122
|
-
- **Phrase external skills as enhancements.** Write "use Plastic's native X by
|
|
123
|
-
default; if `superpowers:<skill>` is available, or the user prefers it, delegate
|
|
124
|
-
to it" never "delegate to `superpowers:<skill>`" as the only path.
|
|
125
|
-
- **Optional dependencies detect then degrade.** `qmd` is the reference shape:
|
|
126
|
-
`scripts/lib/qmd_sync.rb` detects the binary first and every verb no-ops cleanly
|
|
127
|
-
when it is absent (see `scripts/qmd-sync`). Optional CLIs and MCP servers follow
|
|
128
|
-
the same detect-then-skip pattern, so a missing tool never crashes a session.
|
|
129
|
-
- **Legitimate hard dependencies are exempt.** Ruby, Node, git, and POSIX tools are
|
|
130
|
-
the cost of running Plastic, not silent coupling. The principle targets accidental
|
|
131
|
-
dependence on external skills doing work Plastic should do itself.
|
|
132
|
-
|
|
133
272
|
## State System
|
|
134
273
|
|
|
135
274
|
```
|
|
@@ -163,10 +302,10 @@ Format: `ID--three-to-five-words` (all stores).
|
|
|
163
302
|
- Intent file matches directory: `1a1--slug/1a1--slug.md`
|
|
164
303
|
- Next ID: `"${CLAUDE_PLUGIN_ROOT}/scripts/folgezettel-id" <parent_id> <store_path>`
|
|
165
304
|
|
|
166
|
-
**Branch vs root
|
|
305
|
+
**Branch vs root: the semantic decision.** The numbering is mechanics; choosing
|
|
167
306
|
*whether* to branch is meaning:
|
|
168
307
|
|
|
169
|
-
- **Branch (`14a`, `14b`)
|
|
308
|
+
- **Branch (`14a`, `14b`):** a sub-task, refinement, or direct continuation of the
|
|
170
309
|
parent. It cannot stand on its own; it only makes sense as part of the parent's work.
|
|
171
310
|
- **Root (`15`, `16`)**: an independent thought, even if inspired by another intent.
|
|
172
311
|
Reserve `sources` for true created-from provenance (intents this was built out of). An
|
|
@@ -183,6 +322,18 @@ Sections: `## Active`, `## Future`, `## Clusters`, `## Abandoned`, `## Completed
|
|
|
183
322
|
|
|
184
323
|
For index maintenance, use `plastic-managing-index`.
|
|
185
324
|
|
|
325
|
+
One-line entry convention. Each index entry is ONE line: `- [<id> <terse title>](<dir>) <tags>`.
|
|
326
|
+
The title is the title, not a summary: aim for about 80 characters, no multi-sentence
|
|
327
|
+
descriptions. This is a self-check, not a gate.
|
|
328
|
+
|
|
329
|
+
## Roadmaps
|
|
330
|
+
|
|
331
|
+
A roadmap is a named, ordered, delivery-side collection of intents (waves of parallel-safe
|
|
332
|
+
entries plus an append-only log), the delivery-side counterpart to a release and a sibling of
|
|
333
|
+
`INDEX.md` (never inside `store/`). Create, order, close, and consume one with `plastic-roadmap`.
|
|
334
|
+
`INDEX.md` stays the single writer of intent status; a roadmap entry mirrors it and yields on any
|
|
335
|
+
conflict. See PLASTIC-reference.md for the full Roadmaps format.
|
|
336
|
+
|
|
186
337
|
## Rules for Skills
|
|
187
338
|
|
|
188
339
|
ALL work flows through intents.
|
|
@@ -194,42 +345,207 @@ ALL work flows through intents.
|
|
|
194
345
|
5. Researches are intents. No separate folder.
|
|
195
346
|
6. Intents are created only via `plastic-creating-intent`. Never hand-author an intent file. The skill self-verifies the written intent with `scripts/validate-intent` before announcing or committing, so every intent is born complete.
|
|
196
347
|
|
|
348
|
+
## House Style (self-check)
|
|
349
|
+
|
|
350
|
+
The agent is the heaviest contributor to the transcript, so terseness pays every turn. These
|
|
351
|
+
are pre-send self-checks the agent applies to its own output. They are not gated.
|
|
352
|
+
|
|
353
|
+
- Answer or decision first. Lead with the result, then support it.
|
|
354
|
+
- Bullets over paragraphs.
|
|
355
|
+
- No preamble, no end-recap. Do not restate the question or summarize what you just said.
|
|
356
|
+
- One question-cluster at a time when asking the human.
|
|
357
|
+
- Reasoning goes in the thinking channel, not duplicated into the visible reply. This keeps
|
|
358
|
+
the human's visibility into your reasoning without paying for it twice in the transcript.
|
|
359
|
+
|
|
360
|
+
Active-intent cache rule. For the intent under active development you already hold its
|
|
361
|
+
delivered artifacts in your own context: prefer revisiting that in-context memory (hit the
|
|
362
|
+
cache) over re-reading them from disk, which only widens context. QMD is for OTHER or indexed
|
|
363
|
+
intents, not for re-reading what you just wrote. Pairs with `/clear` plus savepoint-resume
|
|
364
|
+
hygiene after each intent. Advisory self-check, not hard-verifiable.
|
|
365
|
+
|
|
366
|
+
## Retrieval Gate
|
|
367
|
+
|
|
368
|
+
Advisory. Hard gates guard writes, locks, and structure, never reads or searches. Read,
|
|
369
|
+
Grep, Glob, and bash search are always allowed, including over the stores. When QMD is
|
|
370
|
+
present and fresh, a content search over store markdown receives an advisory hint pointing
|
|
371
|
+
at `qmd search` alongside its result; when QMD is present but stale, a background reindex
|
|
372
|
+
fires so the next turn's hint runs against a fresh index (never synchronous). QMD and
|
|
373
|
+
Serena are recommendations, not obligations: the UserPromptSubmit power-tools hook appends
|
|
374
|
+
one recommendation line per present tool. The legacy trailing `# qmd-ok` token is still
|
|
375
|
+
accepted on Bash commands and simply silences the hint. Scope stays the agent's own tool
|
|
376
|
+
calls; Ruby `File.read` inside a script is invisible to the hook by design.
|
|
377
|
+
|
|
378
|
+
The deterministic entry point is the `scripts/qmd-sync` CLI (verbs: detect, register, reindex,
|
|
379
|
+
status, search), a clean no-op when QMD is absent. Each store indexes into its own
|
|
380
|
+
`plastic-<slug>` collection (`plastic-global` for the global store, `plastic-<slug>` per project).
|
|
381
|
+
Index mutation is lifecycle-only, and the reindex runs LAST in the End tail, after the bridge
|
|
382
|
+
purge. See `docs/internals.md` for depth.
|
|
383
|
+
|
|
197
384
|
## Transition Gates
|
|
198
385
|
|
|
199
386
|
| Transition | Trigger | Gate |
|
|
200
387
|
|---|---|---|
|
|
201
|
-
| What → Why | `spec.md` written |
|
|
388
|
+
| What → Why | `spec.md` written | (none) |
|
|
202
389
|
| Why → How | `plan.md` + `actions/` + `checklist.md` | `spec.md` must exist |
|
|
203
390
|
| How → Exec | Checklist has items | Plan triplet must exist |
|
|
204
391
|
| Exec → Done | `outcome.md` written | All checklist items checked |
|
|
205
392
|
|
|
206
|
-
Hard blocking
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
393
|
+
Hard blocking: hooks exit code 2 on gate failure.
|
|
394
|
+
|
|
395
|
+
### The gates by name
|
|
396
|
+
|
|
397
|
+
Each gate guards one thing. All are hard except the retrieval gate:
|
|
398
|
+
|
|
399
|
+
- **create-gate** validates the proposed intent file at What write-time (Write, Edit, and MCP
|
|
400
|
+
edits), so a malformed or incomplete intent never lands.
|
|
401
|
+
- **gate-check** enforces lifecycle stage order (spec.md before plan.md, the plan triplet before
|
|
402
|
+
the checklist, all checklist items before outcome.md).
|
|
403
|
+
- **lock-gate** arbitrates ownership and claims: it admits only the intent's lock owner or a
|
|
404
|
+
registered delegate to write into an active intent directory, and every deny names the
|
|
405
|
+
resolving `plastic-lock` command.
|
|
406
|
+
- **bash-gate** intercepts a write attempted through a bash or interpreter one-liner (a heredoc, a
|
|
407
|
+
`>` redirect, a `ruby -e` or `python -c` write), so the same rules apply whether an edit goes
|
|
408
|
+
through the Write tool or a shell. A trailing `# plastic-ok` comment is an auditable escape that
|
|
409
|
+
lets a deliberate command through, and every use is logged to
|
|
410
|
+
`~/.plastic/.cache/gate-escapes.log`.
|
|
411
|
+
- **retrieval-gate** is advisory only (see the Retrieval Gate section): it hints at QMD and never
|
|
412
|
+
blocks a read or search.
|
|
413
|
+
|
|
414
|
+
## Delivery Isolation and the Single-Owner Lock
|
|
415
|
+
|
|
416
|
+
Exactly one session or agent develops an intent's delivery at a time. Ownership is
|
|
417
|
+
session-keyed and durable: arming acquires `delivery.lock` inside the intent directory
|
|
418
|
+
(atomically, O_EXCL), recording the owner session, the host, the acquired-at time, a
|
|
419
|
+
delegates list, and the lock type. Liveness is a lease: the owner's hooks refresh the lock
|
|
420
|
+
file's mtime on tool activity, and the lock counts as stale only when that heartbeat is
|
|
421
|
+
older than the TTL. No process id is consulted anywhere. The /tmp session bridge is a cache
|
|
422
|
+
of this state; on any disagreement, or when the bridge is missing, the lock file wins.
|
|
423
|
+
Another session that finds a fresh lock backs off; a stale lock is reclaimed only by
|
|
424
|
+
explicit takeover, which replaces the lock and appends an audit line to the intent's
|
|
425
|
+
savepoint.md. Subagents spawned by the owner write under the owner's lock once registered
|
|
426
|
+
as delegates. Disarm clears the lock; the End tail is ordered: verify, merge and remove
|
|
427
|
+
worktrees, clear the lock, and only then is the bridge purge-eligible. Repair is one
|
|
428
|
+
idempotent function with two entry points: the `plastic-lock` command (status, fix,
|
|
429
|
+
release, reclaim, delegate) and `/plastic-intent-starting`, so boarding self-heals. This is
|
|
430
|
+
mandatory, not a convention.
|
|
431
|
+
|
|
432
|
+
Solo-mode gate defaults (intent 128): on a confirmed positive solo determination
|
|
433
|
+
(`Bridge.solo_delivery?`, a single owner working alone with no sign of parallel or team
|
|
434
|
+
delivery), the lock and worktree arbitration gates relax from enforced to advisory. The moment
|
|
435
|
+
any parallel or team activity appears they return to strictly enforced. This is a real behavior
|
|
436
|
+
difference, not just a message change: a solo session is not hard-blocked by these gates, a
|
|
437
|
+
shared one still is.
|
|
438
|
+
|
|
439
|
+
The bridge resolves the current session in a fixed precedence: the stdin `session_id` first, then
|
|
440
|
+
the `CLAUDE_CODE_SESSION_ID` environment variable, then a derived key when neither is present. A
|
|
441
|
+
bridge is purge-eligible by terminal state, not by age: it is removed only once its intent is no
|
|
442
|
+
longer active, never on a timer. See `docs/internals.md` for depth.
|
|
443
|
+
|
|
444
|
+
The delivery lock arbitrates at the whole-intent grain: it decides who may work
|
|
445
|
+
an intent at all. Underneath it, a per-artifact claim token (intent 111)
|
|
446
|
+
arbitrates at the file grain: it decides who, among those already holding the
|
|
447
|
+
delivery lock, is the one writer for one lifecycle file right now. A write to
|
|
448
|
+
`spec.md`, `plan.md`, `checklist.md`, or the intent file must hold both the
|
|
449
|
+
delivery lock and that file's claim. Claims live in `.claims/<artifact>.claim`
|
|
450
|
+
inside the intent directory, one small JSON file per artifact, scoped strictly
|
|
451
|
+
per-intent-per-artifact, never session-global. The claim gate is dormant
|
|
452
|
+
(allows) when no claim file exists for an artifact, so ordinary single-owner
|
|
453
|
+
work is unaffected; it engages, and denies, only when a second writer tries to
|
|
454
|
+
take a fresh claim someone else already holds. A stale or corrupt claim fails
|
|
455
|
+
open (the write proceeds, the claim yields) and the condition is surfaced in
|
|
456
|
+
`plastic-lock status`, which lists any live claims alongside the delivery
|
|
457
|
+
lock. See `plastic-lock claim`/`release-claim` and `docs/internals.md` for the
|
|
458
|
+
full mechanism.
|
|
459
|
+
|
|
460
|
+
Two locks share this schema (the two-lock doctrine): `delivery.lock` (exclusive, one owner
|
|
461
|
+
plus delegates) and the future `maintenance.lock` (short TTL, structural move-and-record
|
|
462
|
+
only). They are mutually exclusive in either direction; maintenance is allowed at any
|
|
463
|
+
lifecycle stage provided no delivery lock is held. Intent 108 ships the delivery lock and
|
|
464
|
+
the mutual-exclusion seam; the maintenance lock implementation follows intent 93 in a
|
|
465
|
+
chained intent.
|
|
466
|
+
|
|
467
|
+
Every code-touching intent gets its own git worktree named `{id}--{slug}`, and all code edits
|
|
468
|
+
for that intent happen only inside it. Plastic provisions the worktree deterministically: it
|
|
469
|
+
resolves the project repo from `projects.yml` and runs `git -C <repo> worktree add`, so
|
|
470
|
+
isolation never depends on the current working directory. There are two worktrees per project
|
|
471
|
+
intent: a code worktree at `<repo>/.claude/worktrees/{id}--{slug}` (branch `plastic/{id}--{slug}`)
|
|
472
|
+
and a store worktree at `<plastic_home>/.worktrees/{id}--{slug}` (branch
|
|
473
|
+
`plastic-store/{id}--{slug}`), so lifecycle-doc commits and code commits move as one unit.
|
|
474
|
+
|
|
475
|
+
Provisioning fails open for intents that touch no project code (pure research or decision
|
|
476
|
+
intents in the global store, or a non-git repo): those get the lock only, and the worktree
|
|
477
|
+
block stays unprovisioned. The fail-open path is always logged, never silent.
|
|
478
|
+
|
|
479
|
+
Cleanup is part of Done: the End tail merges the branch, then removes both worktrees. Never leave
|
|
480
|
+
an orphaned worktree behind, and clear a stale worktree reference with `git worktree prune`.
|
|
481
|
+
|
|
482
|
+
### Intent delivery, station by station
|
|
483
|
+
|
|
484
|
+
How one intent travels from boarding to Done, and what the lock, bridge, and gates do at
|
|
485
|
+
each station.
|
|
486
|
+
|
|
487
|
+
| Station | Delivered artifact | Lock and bridge steps | Pre-stage gate | Post-stage record |
|
|
488
|
+
|---|---|---|---|---|
|
|
489
|
+
| Start (board) | none (a procedure, not a stage) | `plastic-lock fix` self-heals stale, corrupt, or legacy state; arm acquires `delivery.lock` (O_EXCL, session-keyed), provisions the code worktree, writes the bridge cache | lock-gate denies any write into an active intent dir without this intent's lock; every deny names the resolving command | savepoint confirms the boarding station |
|
|
490
|
+
| What (create) | `<id>--<slug>.md`, born complete | no lock yet; no bridge | create-gate validates the proposed intent content (Write, Edit, and MCP edits) | savepoint `What` line; intent listed in INDEX `## Active` |
|
|
491
|
+
| Why | `spec.md` | owner writes refresh the lease (lock file mtime heartbeat) | gate-check requires the intent file with `## Intent` before spec.md; lock-gate admits only the owner or a delegate | savepoint `Why started`, `Why spec.md created` |
|
|
492
|
+
| How | `plan.md`, `actions/`, `checklist.md` | heartbeat on writes; the code gate stays closed until plan.md plus checklist.md exist | gate-check requires spec.md before plan.md, and plan.md plus actions/ before checklist.md | savepoint `How started`, `How plan.md created`, `How checklist.md created`, `Exec started` |
|
|
493
|
+
| Exec | code on the intent branch, checklist checked off | heartbeat; code edits confined to the provisioned worktree; delegates write under the owner's lock; bash, interpreter, and MCP writes gated the same way | code-gate, worktree-gate, bash-gate, lock-gate | checklist boxes; savepoint milestones |
|
|
494
|
+
| End (done) | mandatory `outcome.md` (`disposition: delivered\|abandoned`), INDEX moves to Completed or Abandoned | ordered End tail: verify, merge and remove worktrees, disarm clears `delivery.lock`, then the bridge is purge-eligible, and the QMD reindex runs LAST (after purge) | gate-check blocks outcome.md while checklist items are unchecked | savepoint `Done delivered` (or `abandoned`); takeover audits, if any, remain in savepoint.md |
|
|
495
|
+
| Maintenance (any stage) | `revisions.md` move-and-record entries | future `maintenance.lock` (short TTL), mutually exclusive with `delivery.lock` in either direction; 108 ships the schema seam only, the implementation follows intent 93 in a chained intent | acquisition refuses while the other lock type is fresh; a terminal intent with no lock held is read-only | dated, rule-tagged `revisions.md` entry; savepoint untouched |
|
|
496
|
+
|
|
497
|
+
### What "intent done" means (intent 93)
|
|
498
|
+
|
|
499
|
+
Done is one law with three signals, and they must agree. INDEX `## Completed` /
|
|
500
|
+
`## Abandoned` is the single canonical terminal marker: it is the store-wide ledger a fresh
|
|
501
|
+
session reads first, so it wins on any conflict. `outcome.md` is the "deliverable exists"
|
|
502
|
+
signal, and the savepoint `Done delivered|abandoned` line is the audit echo. All three must
|
|
503
|
+
agree; when they disagree, INDEX is authoritative and `doctor` flags the mismatch (the
|
|
504
|
+
`done_signals` check: `outcome.md` real but still under `## Active`, or terminal without a
|
|
505
|
+
real `outcome.md`, or a terminal intent whose savepoint carries no `Done` line).
|
|
506
|
+
|
|
507
|
+
`outcome.md` is mandatory at every terminal transition, delivered and abandoned alike. It
|
|
508
|
+
self-declares its disposition through a `disposition: delivered|abandoned` frontmatter
|
|
509
|
+
header. The delivered path authors it with the result; the abandoned path authors it with
|
|
510
|
+
the abandonment reason and no longer leaves the scaffolded placeholder sentinel in place.
|
|
511
|
+
|
|
512
|
+
The canonical End tail runs in this order, and the QMD reindex is always LAST, after the
|
|
513
|
+
purge: `outcome.md -> INDEX terminal -> savepoint Done -> commit -> disarm (Worktree.release
|
|
514
|
+
-> Lock.release -> purge) -> QMD reindex`. Running the reindex last keeps the index from
|
|
515
|
+
ever referencing a bridge or lock that disarm is about to remove.
|
|
516
|
+
|
|
517
|
+
The post-done access window is lock-bounded: `[INDEX terminal -> Lock.release]`. Through it
|
|
518
|
+
the completing session keeps full read and write access to the terminal directory and no
|
|
519
|
+
purge can fire (108's lock-held keep-guard keeps the bridge while `delivery.lock` exists).
|
|
520
|
+
Once the lock is released the window closes: the bridge becomes purge-eligible and the
|
|
521
|
+
directory is frozen. A crash mid-tail is recovered by stale-lock reclaim plus finishing the
|
|
522
|
+
tail; `doctor` surfaces this as a "stalled completion" (terminal in INDEX but the lock is
|
|
523
|
+
still present or stale). Finishing the tail is FINISHING a completion, never a reactivation:
|
|
524
|
+
a done intent is never moved back to `## Active`.
|
|
525
|
+
|
|
526
|
+
Terminal immutability (the contract intent 112 enforces): a terminal directory is writable
|
|
527
|
+
ONLY while a lock is held. The delivery lock covers the completing session's End tail up to
|
|
528
|
+
`Lock.release`; the maintenance lock covers sanctioned structural move-and-record edits
|
|
529
|
+
after. Terminal with no lock held is frozen. There are only two locks in the system,
|
|
530
|
+
delivery and maintenance (108 D11). This governs WRITES only: reads of a terminal intent are
|
|
531
|
+
always allowed and unbounded (curator reindex, dashboards, and future intents that reference
|
|
532
|
+
its id or chain), so a done intent stays fully readable forever. Intent 93 states this rule;
|
|
533
|
+
intent 112 builds the gate that enforces it.
|
|
534
|
+
|
|
535
|
+
Fail-safe lock doctrine (the contract intent 111 implements): the lock system never traps a
|
|
536
|
+
session or burns credits. When a gate cannot verify lock integrity it fails open, degrading
|
|
537
|
+
to advisory (warn) rather than hard-blocking. Repair is orchestrator-driven: on a lock-issue
|
|
538
|
+
signal the orchestrator inspects and repairs the lock automatically, and the human
|
|
539
|
+
`plastic-lock` command is a fallback path, not the trigger. Intent 93 states this doctrine;
|
|
540
|
+
intent 111 builds the fail-open behavior, the lock-liveness surface, the lock-issue message,
|
|
541
|
+
and the auto-repair.
|
|
542
|
+
|
|
543
|
+
Scope split. Intent 93 ships doctrine plus the low-risk reconciliation that needs no new
|
|
544
|
+
lock: the canonical done-marker and three-signal reconciliation, the mandatory `outcome.md`
|
|
545
|
+
plus `disposition` header at both terminals, the End tail with the reindex moved last, the
|
|
546
|
+
`done_signals` doctor check (three-signal agreement plus stalled-completion detection), and
|
|
547
|
+
the lock-bounded post-done window with its keep-guard test. Intent 111 owns the lock
|
|
548
|
+
liveness surface, the lock-issue message, orchestrator auto-repair, and the fail-open
|
|
549
|
+
behavior itself. Intent 112 owns the maintenance lock and the immutability gate (it inherits
|
|
550
|
+
fail-open from 111). Intent 4a1b1 owns deep agent stuck-detection and is not superseded.
|
|
551
|
+
|