@zalom/plastic 1.0.0-alpha.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/LICENSE +21 -0
- package/PLASTIC.md +534 -0
- package/README.md +88 -0
- package/agents/future-intent-researcher.md +38 -0
- package/agents/intent-curator.md +40 -0
- package/bin/install.js +29 -0
- package/deprecations.yml +23 -0
- package/hooks/check-update +42 -0
- package/hooks/continue +31 -0
- package/hooks/future-intent-check +25 -0
- package/hooks/gate-check +10 -0
- package/hooks/hooks.json +78 -0
- package/hooks/run-hook +7 -0
- package/hooks/savepoint +6 -0
- package/hooks/session-start +9 -0
- package/hooks/statusline +16 -0
- package/package.json +43 -0
- package/scripts/folgezettel-id +40 -0
- package/scripts/hash-intent +29 -0
- package/scripts/hook-continue +130 -0
- package/scripts/hook-future-intent-check +90 -0
- package/scripts/hook-gate-check +136 -0
- package/scripts/hook-session-start +224 -0
- package/scripts/install.rb +474 -0
- package/scripts/lib/bridge.rb +139 -0
- package/scripts/migrate-folgezettel +535 -0
- package/scripts/migrate-to-global +96 -0
- package/scripts/read-config +129 -0
- package/skills/auto/SKILL.md +127 -0
- package/skills/brainstorming-grill-me/SKILL.md +105 -0
- package/skills/continuing/SKILL.md +104 -0
- package/skills/creating-intent/SKILL.md +122 -0
- package/skills/creating-project/SKILL.md +166 -0
- package/skills/executing-plan/SKILL.md +120 -0
- package/skills/executing-plan/code-quality-reviewer-prompt.md +32 -0
- package/skills/executing-plan/implementer-prompt.md +42 -0
- package/skills/executing-plan/spec-reviewer-prompt.md +27 -0
- package/skills/install/SKILL.md +134 -0
- package/skills/intent-curator/SKILL.md +41 -0
- package/skills/linking-intents/SKILL.md +72 -0
- package/skills/managing-index/SKILL.md +66 -0
- package/skills/managing-index/references/zettelkasten-linking.md +27 -0
- package/skills/releasing/SKILL.md +124 -0
- package/skills/savepoint/SKILL.md +57 -0
- package/skills/uninstall/SKILL.md +48 -0
- package/skills/update/SKILL.md +69 -0
- package/templates/agents.md +46 -0
- package/templates/checklist.md +11 -0
- package/templates/config.yml +13 -0
- package/templates/index.md +13 -0
- package/templates/intent.md +24 -0
- package/templates/plan.md +11 -0
- package/templates/projects.yml +3 -0
- package/templates/savepoint.md +13 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# Usage: read-config <key> [--default VALUE] [--project PATH]
|
|
3
|
+
# Resolves a config value: project -> global -> built-in defaults.
|
|
4
|
+
# Nested keys use dot notation: agent.type, architect.style
|
|
5
|
+
# Returns scalar values as strings, hash/array values as JSON.
|
|
6
|
+
#
|
|
7
|
+
# Environment:
|
|
8
|
+
# PLASTIC_GLOBAL_ROOT -- override ~/.plastic (for testing)
|
|
9
|
+
|
|
10
|
+
require "yaml"
|
|
11
|
+
require "json"
|
|
12
|
+
|
|
13
|
+
DEFAULTS = {
|
|
14
|
+
"version" => 3,
|
|
15
|
+
"stale_threshold_days" => 3,
|
|
16
|
+
"execution_mode" => "subagent-driven",
|
|
17
|
+
"hash_length" => 6,
|
|
18
|
+
"hash_algorithm" => "sha256-base36",
|
|
19
|
+
"max_slug_words" => 5,
|
|
20
|
+
"project_roots" => ["~/.plastic/projects"],
|
|
21
|
+
"deprecations_dismissed" => [],
|
|
22
|
+
"agent" => {
|
|
23
|
+
"type" => "claude-code",
|
|
24
|
+
"parallel_mode" => "linear"
|
|
25
|
+
},
|
|
26
|
+
"architect" => {
|
|
27
|
+
"style" => nil
|
|
28
|
+
}
|
|
29
|
+
}.freeze
|
|
30
|
+
|
|
31
|
+
def parse_args(argv)
|
|
32
|
+
key = nil
|
|
33
|
+
default_val = nil
|
|
34
|
+
project_dir = nil
|
|
35
|
+
|
|
36
|
+
i = 0
|
|
37
|
+
while i < argv.length
|
|
38
|
+
case argv[i]
|
|
39
|
+
when "--default"
|
|
40
|
+
abort "Error: --default requires a value" unless argv[i + 1]
|
|
41
|
+
default_val = argv[i + 1]
|
|
42
|
+
i += 2
|
|
43
|
+
when "--project"
|
|
44
|
+
abort "Error: --project requires a value" unless argv[i + 1]
|
|
45
|
+
project_dir = argv[i + 1]
|
|
46
|
+
i += 2
|
|
47
|
+
else
|
|
48
|
+
key = argv[i]
|
|
49
|
+
i += 1
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
[key, default_val, project_dir]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def load_yaml(path)
|
|
57
|
+
return {} unless File.exist?(path)
|
|
58
|
+
YAML.safe_load(File.read(path)) || {}
|
|
59
|
+
rescue => e
|
|
60
|
+
$stderr.puts "Warning: failed to parse #{path}: #{e.message}"
|
|
61
|
+
{}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def dig_key(hash, dotted_key)
|
|
65
|
+
keys = dotted_key.split(".")
|
|
66
|
+
value = hash
|
|
67
|
+
keys.each do |k|
|
|
68
|
+
return nil unless value.is_a?(Hash) && value.key?(k)
|
|
69
|
+
value = value[k]
|
|
70
|
+
end
|
|
71
|
+
value
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def format_value(value)
|
|
75
|
+
case value
|
|
76
|
+
when Hash, Array
|
|
77
|
+
JSON.generate(value)
|
|
78
|
+
when nil
|
|
79
|
+
""
|
|
80
|
+
else
|
|
81
|
+
value.to_s
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Handle --migrate mode
|
|
86
|
+
if ARGV.include?("--migrate")
|
|
87
|
+
global_root = ENV.fetch("PLASTIC_GLOBAL_ROOT", File.expand_path("~/.plastic"))
|
|
88
|
+
config_path = File.join(global_root, "config.yml")
|
|
89
|
+
config = load_yaml(config_path)
|
|
90
|
+
|
|
91
|
+
if config["version"].to_i >= 3
|
|
92
|
+
puts "Config already at version #{config["version"]}."
|
|
93
|
+
exit 0
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
config["version"] = 3
|
|
97
|
+
config["agent"] ||= {}
|
|
98
|
+
config["agent"]["type"] ||= "claude-code"
|
|
99
|
+
config["agent"]["parallel_mode"] ||= "linear"
|
|
100
|
+
config["architect"] ||= {}
|
|
101
|
+
config["architect"]["style"] ||= nil
|
|
102
|
+
|
|
103
|
+
File.write(config_path, YAML.dump(config))
|
|
104
|
+
puts "Migrated config.yml to version 3."
|
|
105
|
+
exit 0
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
key, explicit_default, project_dir = parse_args(ARGV)
|
|
109
|
+
|
|
110
|
+
if key.nil? || key.empty?
|
|
111
|
+
$stderr.puts "Usage: read-config <key> [--default VALUE] [--project PATH]"
|
|
112
|
+
exit 1
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
global_root = ENV.fetch("PLASTIC_GLOBAL_ROOT", File.expand_path("~/.plastic"))
|
|
116
|
+
global_config = load_yaml(File.join(global_root, "config.yml"))
|
|
117
|
+
|
|
118
|
+
project_config = {}
|
|
119
|
+
if project_dir
|
|
120
|
+
project_config_path = File.join(project_dir, ".plastic_store", "config.yml")
|
|
121
|
+
project_config = load_yaml(project_config_path)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
value = dig_key(project_config, key)
|
|
125
|
+
value = dig_key(global_config, key) if value.nil?
|
|
126
|
+
value = explicit_default if value.nil? && explicit_default
|
|
127
|
+
value = dig_key(DEFAULTS, key) if value.nil?
|
|
128
|
+
|
|
129
|
+
puts format_value(value)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plastic:auto
|
|
3
|
+
description: >-
|
|
4
|
+
Autonomous intent delivery — agent takes over How and Exec. Use when user says
|
|
5
|
+
"auto", "take it from here", "deliver this", or when brainstorming-grill-me concludes
|
|
6
|
+
and user confirms autonomous execution. Requires an active intent in INDEX.md.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Auto — Autonomous Intent Delivery
|
|
10
|
+
|
|
11
|
+
Announce: "Taking over intent [ID] — [name] for autonomous delivery."
|
|
12
|
+
|
|
13
|
+
## Precondition
|
|
14
|
+
|
|
15
|
+
An active intent MUST exist in INDEX.md. If none exists, refuse: "No active intent found. Create one first with /plastic:creating-intent."
|
|
16
|
+
|
|
17
|
+
If multiple active intents exist, ask the user which one to deliver (this is the only question auto asks).
|
|
18
|
+
|
|
19
|
+
## Flags
|
|
20
|
+
|
|
21
|
+
- `--skip-permissions` — bypass hard stops on destructive actions on existing projects. Full trust mode. Default: off.
|
|
22
|
+
|
|
23
|
+
## Stage-Aware Entry
|
|
24
|
+
|
|
25
|
+
Read the active intent's directory. Determine current lifecycle stage from filesystem state:
|
|
26
|
+
|
|
27
|
+
| Check (in order) | Stage |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `checklist.md` exists with some items checked | Resume Exec from last unchecked item |
|
|
30
|
+
| `plan.md` + `checklist.md` exist (no items checked) | Enter Exec |
|
|
31
|
+
| `spec.md` exists, no `plan.md` | Enter How |
|
|
32
|
+
| `## Context` has content in intent file, no `spec.md` | Complete Why (fill gaps, write spec.md) |
|
|
33
|
+
| Only `## Intent` exists | Start Why from scratch |
|
|
34
|
+
|
|
35
|
+
Announce which stage you're entering and why.
|
|
36
|
+
|
|
37
|
+
## Why Completion (Autonomous)
|
|
38
|
+
|
|
39
|
+
When entering at Why stage:
|
|
40
|
+
|
|
41
|
+
1. Read existing `## Context` and `### Decisions` from the intent file
|
|
42
|
+
2. Assess gaps — what decisions are missing? What context is incomplete?
|
|
43
|
+
3. Self-directed research — read code, search docs, explore related intents (via wikilinks in `## Links`), web search if needed. NO questions to human.
|
|
44
|
+
4. Adaptive budget — assess complexity and set your own research budget:
|
|
45
|
+
- Simple (config change, small feature): 2-3 research steps
|
|
46
|
+
- Medium (new feature, integration): 5-8 research steps
|
|
47
|
+
- Complex (new project, architecture): 10-15 research steps
|
|
48
|
+
5. Make decisions — pick best option, document in `## Context > ### Decisions` with rationale
|
|
49
|
+
6. Log all autonomous decisions in `## Insights` with `(autonomous)` marker: "Decision: chose X because Y (autonomous)"
|
|
50
|
+
7. Write `spec.md` — consolidated specification
|
|
51
|
+
|
|
52
|
+
Then proceed to How.
|
|
53
|
+
|
|
54
|
+
## How Phase
|
|
55
|
+
|
|
56
|
+
1. If `superpowers:writing-plans` is available as a skill, delegate plan creation to it. Tell it the plan saves to the active intent's directory (not `docs/superpowers/plans/`).
|
|
57
|
+
2. Otherwise, write `plan.md` directly — implementation plan with numbered tasks
|
|
58
|
+
3. Create `actions/` directory with `ACTION_N.md` files (one per task, self-contained)
|
|
59
|
+
4. Write `checklist.md` — execution registry with checkboxes covering all actions
|
|
60
|
+
|
|
61
|
+
Then proceed to Exec.
|
|
62
|
+
|
|
63
|
+
## Project Creation Gate
|
|
64
|
+
|
|
65
|
+
If the plan calls for creating a new project (the intent is an implementation intent that needs a new codebase):
|
|
66
|
+
|
|
67
|
+
1. Determine project path from `~/.plastic/config.yml` `project_roots` or from intent context
|
|
68
|
+
2. **Confirm path with user** — this is the ONE human interaction during auto delivery:
|
|
69
|
+
> "Creating project `<slug>` at `<path>`. Confirm path, or provide alternative."
|
|
70
|
+
3. Invoke `plastic:creating-project` skill
|
|
71
|
+
4. The global intent is now Completed (creating-project handles this)
|
|
72
|
+
5. The tactical mirror in the project store becomes the active intent
|
|
73
|
+
6. Continue execution from the project directory using the tactical intent
|
|
74
|
+
|
|
75
|
+
## Exec Phase
|
|
76
|
+
|
|
77
|
+
1. If `superpowers:subagent-driven-development` or `superpowers:executing-plans` is available, delegate execution to it
|
|
78
|
+
2. Otherwise invoke `plastic:executing-plan`
|
|
79
|
+
3. Execute actions from checklist sequentially
|
|
80
|
+
4. Check off items in `checklist.md` as completed
|
|
81
|
+
5. Append observations to `## Insights` with `(autonomous)` marker
|
|
82
|
+
6. Sub-agents can be spawned for parallel actions (one agent per action)
|
|
83
|
+
|
|
84
|
+
## Permission Model — Safe-by-Default
|
|
85
|
+
|
|
86
|
+
The agent MUST prefer non-destructive routes:
|
|
87
|
+
|
|
88
|
+
| Instead of... | Do this... |
|
|
89
|
+
|---|---|
|
|
90
|
+
| Drop table | Rename to `_deprecated_<table>`, flag for cleanup |
|
|
91
|
+
| Delete files | Move to `.archive/` or backup branch |
|
|
92
|
+
| Alter column | Additive migration — new column + backfill |
|
|
93
|
+
| Remove feature | Feature flag off, code stays until human confirms |
|
|
94
|
+
| Database migration | Backup before migration, keep rollback path |
|
|
95
|
+
|
|
96
|
+
### Hard Stop (without `--skip-permissions`)
|
|
97
|
+
|
|
98
|
+
When a genuinely destructive action on an existing project has NO safe alternative:
|
|
99
|
+
1. Log the proposed action in `## Insights`
|
|
100
|
+
2. Notify user: "Blocked on destructive action: [description]. Approve to continue, or provide alternative direction."
|
|
101
|
+
3. **STOP and wait for human response.** Do not proceed.
|
|
102
|
+
|
|
103
|
+
With `--skip-permissions`, the agent logs the action in Insights but proceeds without stopping.
|
|
104
|
+
|
|
105
|
+
### Greenfield Exception
|
|
106
|
+
|
|
107
|
+
During initial project creation, all decisions are non-destructive by definition (there's nothing to destroy). The agent has full autonomy for greenfield choices — DB engine, framework, gems, architecture.
|
|
108
|
+
|
|
109
|
+
## Completion
|
|
110
|
+
|
|
111
|
+
1. Verify all checklist items are checked
|
|
112
|
+
2. Write `outcome.md` with detailed results
|
|
113
|
+
3. Write `## Outcome` summary in the intent file (1-2 sentences)
|
|
114
|
+
4. Review `## Insights` for observations that should spawn future intents. If any:
|
|
115
|
+
- Create them (using `plastic:creating-intent` conventions)
|
|
116
|
+
- Update `chain` in the current intent's frontmatter
|
|
117
|
+
5. Move intent from `## Active` to `## Completed` in INDEX.md (with today's date)
|
|
118
|
+
6. Auto-commit: `cd <store-root> && git add . && git commit -m "feat: deliver intent <ID> — <name>"`
|
|
119
|
+
7. Notify user: "Intent [ID] — [name] delivered. [1-2 sentence summary]. See outcome.md for details."
|
|
120
|
+
|
|
121
|
+
## Error Handling
|
|
122
|
+
|
|
123
|
+
If the agent gets stuck (can't resolve a gap, dependency is missing, tests fail persistently):
|
|
124
|
+
1. Log the blocker in `## Insights`
|
|
125
|
+
2. Write `savepoint.md` with current state
|
|
126
|
+
3. Notify user: "Blocked on intent [ID] — [name]: [description]. Savepoint written."
|
|
127
|
+
4. **STOP.** Do not attempt workarounds that could leave the project in a broken state.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plastic:brainstorming-grill-me
|
|
3
|
+
description: >-
|
|
4
|
+
Deep brainstorming that interviews the user relentlessly about a plan or design until reaching shared understanding.
|
|
5
|
+
Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
|
|
6
|
+
Complements superpowers:brainstorming — use brainstorming for quick ideation, grill-me for thorough interrogation.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Grill Me — Deep Brainstorming
|
|
10
|
+
|
|
11
|
+
You are about to interview the user relentlessly. This is NOT a quick brainstorm — it is a thorough interrogation of every assumption, dependency, and design decision until you reach shared understanding.
|
|
12
|
+
|
|
13
|
+
## Detect Mode
|
|
14
|
+
|
|
15
|
+
**Coding mode** — the user is designing something that involves code (feature, architecture, refactor, system design):
|
|
16
|
+
- You CAN and SHOULD explore the codebase to answer your own questions
|
|
17
|
+
- Before asking "how does X work?", check if you can find out yourself
|
|
18
|
+
- Ground your questions in what actually exists, not what you imagine
|
|
19
|
+
|
|
20
|
+
**Non-coding mode** — the user is designing something conceptual (process, workflow, strategy, product):
|
|
21
|
+
- No codebase to explore
|
|
22
|
+
- Focus purely on the design tree
|
|
23
|
+
|
|
24
|
+
## Workflow
|
|
25
|
+
|
|
26
|
+
### 1. Identify the Root
|
|
27
|
+
|
|
28
|
+
Ask: "What are we designing?" Get the one-sentence version. Restate it back to confirm.
|
|
29
|
+
|
|
30
|
+
### 2. Walk the Decision Tree
|
|
31
|
+
|
|
32
|
+
For each branch of the design:
|
|
33
|
+
|
|
34
|
+
1. **State the branch** — "Let's talk about [aspect]."
|
|
35
|
+
2. **Ask your question** — Be specific. "How will X handle Y when Z happens?"
|
|
36
|
+
3. **Provide your recommended answer** — Always lead with what YOU think the answer should be, based on what you know. Let the user confirm, correct, or redirect.
|
|
37
|
+
4. **Resolve before moving on** — Do not leave ambiguity. If the user says "I'm not sure", help them decide. Push.
|
|
38
|
+
5. **Track dependencies** — If decision A affects decision B, say so. Resolve A first.
|
|
39
|
+
|
|
40
|
+
### 3. Be Relentless
|
|
41
|
+
|
|
42
|
+
- Do NOT accept vague answers. "It depends" requires "on what?"
|
|
43
|
+
- Do NOT skip edge cases. "What happens when the list is empty?"
|
|
44
|
+
- Do NOT assume. If you think you know, verify.
|
|
45
|
+
- Do NOT be polite at the expense of thoroughness. Friendly but unrelenting.
|
|
46
|
+
- DO challenge the user's assumptions. "Why not [alternative]?"
|
|
47
|
+
- DO synthesize as you go. After every 3-4 questions, summarize what's been decided.
|
|
48
|
+
|
|
49
|
+
### 4. Time Awareness
|
|
50
|
+
|
|
51
|
+
This process is thorough. It typically takes 20-45 minutes for a complex design. At natural checkpoints (~every 10 questions), offer:
|
|
52
|
+
|
|
53
|
+
> "We've covered [areas]. Still to explore: [areas]. Continue, or pause and capture what we have?"
|
|
54
|
+
|
|
55
|
+
If the user wants to pause, capture all decisions made so far into the active intent's spec.md.
|
|
56
|
+
|
|
57
|
+
### 5. Close Out
|
|
58
|
+
|
|
59
|
+
When all branches are resolved:
|
|
60
|
+
|
|
61
|
+
1. Write the complete spec to the active intent directory (`spec.md`)
|
|
62
|
+
2. List all decisions made
|
|
63
|
+
3. List any deferred items (things the user explicitly chose to decide later)
|
|
64
|
+
4. Proceed to Autonomous Handoff Offer (step 6)
|
|
65
|
+
|
|
66
|
+
### 6. Autonomous Handoff Offer
|
|
67
|
+
|
|
68
|
+
After closing out (spec written, decisions listed), assess whether the agent has enough context to deliver the intent autonomously.
|
|
69
|
+
|
|
70
|
+
**Self-assessment checklist:**
|
|
71
|
+
- All key decisions resolved (no open "it depends" or "TBD")
|
|
72
|
+
- Scope is clear and bounded
|
|
73
|
+
- Dependencies are identified
|
|
74
|
+
- Success criteria are defined
|
|
75
|
+
|
|
76
|
+
If ALL items pass, offer autonomous delivery:
|
|
77
|
+
|
|
78
|
+
> "I have enough context to take this from here. Here's my understanding:
|
|
79
|
+
>
|
|
80
|
+
> **Decisions:** [list key decisions]
|
|
81
|
+
> **Scope:** [one-line scope summary]
|
|
82
|
+
> **Approach:** [high-level approach]
|
|
83
|
+
>
|
|
84
|
+
> Want to grill more, or should I go autonomous?"
|
|
85
|
+
|
|
86
|
+
- If human says go → invoke `plastic:auto`
|
|
87
|
+
- If human says grill more → continue grilling (reset to step 2)
|
|
88
|
+
- If human says neither (wants to drive manually) → proceed as before (offer planning)
|
|
89
|
+
|
|
90
|
+
This offer replaces the final question in Close Out ("Ready to plan implementation, or do you want another pass?"). The new options are:
|
|
91
|
+
1. Go autonomous (`plastic:auto`)
|
|
92
|
+
2. Grill more (continue interrogation)
|
|
93
|
+
3. Plan manually (invoke `superpowers:writing-plans` or proceed with human-driven planning)
|
|
94
|
+
|
|
95
|
+
## Relationship to superpowers:brainstorming
|
|
96
|
+
|
|
97
|
+
| | superpowers:brainstorming | plastic:brainstorming-grill-me |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| Speed | Quick (5-10 min) | Thorough (20-45 min) |
|
|
100
|
+
| Depth | Surface-level exploration | Exhaustive decision tree |
|
|
101
|
+
| When | Starting ideation, exploring options | Stress-testing a design, resolving ambiguity |
|
|
102
|
+
| Output | Initial spec | Battle-tested spec with all branches resolved |
|
|
103
|
+
| Style | Collaborative, exploratory | Interrogative, relentless |
|
|
104
|
+
|
|
105
|
+
Use `superpowers:brainstorming` to generate ideas. Use `plastic:brainstorming-grill-me` to pressure-test them.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plastic:continuing
|
|
3
|
+
description: Use when the user says "continue" after a /clear, or when resuming work in a new session. Reads intent state from global store (~/.plastic/) or local store, offers active intents first, then future intents, and surfaces stale intents for triage.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Continuing
|
|
7
|
+
|
|
8
|
+
## When to Use
|
|
9
|
+
- UserPromptSubmit hook detects "continue" (automatic)
|
|
10
|
+
- User says "continue", "resume", or "pick up where we left off"
|
|
11
|
+
- Starting a new session with existing active intents
|
|
12
|
+
|
|
13
|
+
## Determine Store
|
|
14
|
+
|
|
15
|
+
1. Check `~/.plastic/INDEX.md` → global mode
|
|
16
|
+
2.
|
|
17
|
+
3. If neither exists → announce "No Plastic store found. Run /plastic:install."
|
|
18
|
+
|
|
19
|
+
## Workflow
|
|
20
|
+
|
|
21
|
+
### 1. Read INDEX.md
|
|
22
|
+
Read the INDEX.md from the active store. Extract intents under `## Active` and `## Future`.
|
|
23
|
+
|
|
24
|
+
### 2. Detect Current Project (global mode only)
|
|
25
|
+
Read `~/.plastic/projects.yml`, match CWD against registered project paths. If in a project:
|
|
26
|
+
- Load the governing intent (from `parent` in projects.yml)
|
|
27
|
+
- Load tactical intents from `~/.plastic/projects/{slug}/store/`
|
|
28
|
+
|
|
29
|
+
### 3. If Active Intents Exist → Resume
|
|
30
|
+
|
|
31
|
+
For each active intent in the store:
|
|
32
|
+
|
|
33
|
+
**a. Read `{ID}--{slug}.md`:**
|
|
34
|
+
- What we're doing (`## Intent`)
|
|
35
|
+
- Why (`## Context`)
|
|
36
|
+
- What insights have emerged (`## Insights`)
|
|
37
|
+
|
|
38
|
+
**b. Read savepoint.md** (if exists):
|
|
39
|
+
- What was in progress, what's next, blockers
|
|
40
|
+
|
|
41
|
+
**c. Read checklist.md** (if exists):
|
|
42
|
+
- What's completed, what's next
|
|
43
|
+
|
|
44
|
+
**d. Announce:**
|
|
45
|
+
```
|
|
46
|
+
Resuming intent [ID] — [name]
|
|
47
|
+
Store: [global | project:<slug> | local]
|
|
48
|
+
Status: active
|
|
49
|
+
Last session: [date from savepoint]
|
|
50
|
+
In progress: [from savepoint]
|
|
51
|
+
Next step: [from checklist or savepoint]
|
|
52
|
+
Blockers: [from savepoint, or "none"]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**e. Resume** — proceed with the next step.
|
|
56
|
+
|
|
57
|
+
### 3b. Detect Autonomous Resume
|
|
58
|
+
|
|
59
|
+
When resuming an active intent, check `## Insights` for entries containing `(autonomous)`.
|
|
60
|
+
|
|
61
|
+
If found — this intent was being delivered autonomously:
|
|
62
|
+
|
|
63
|
+
**Announce:**
|
|
64
|
+
```
|
|
65
|
+
Resuming autonomous delivery of intent [ID] — [name]
|
|
66
|
+
Store: [global | project:<slug> | local]
|
|
67
|
+
Last autonomous action: [last (autonomous) insight entry]
|
|
68
|
+
Next step: [from checklist or savepoint]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Then:** Continue autonomous execution by invoking `plastic:auto`. The auto skill will pick up from the current lifecycle stage (it reads filesystem state to determine where to resume).
|
|
72
|
+
|
|
73
|
+
If NOT found — resume normally as described in step 3.
|
|
74
|
+
|
|
75
|
+
### 4. If No Active Intents → Offer Future Intents
|
|
76
|
+
|
|
77
|
+
Present future intents as options. When user picks one, move to Active in INDEX.md. Auto-commit.
|
|
78
|
+
|
|
79
|
+
### 5. Surface Stale Future Intents
|
|
80
|
+
|
|
81
|
+
If any future intent has `created` date older than the configured `stale_threshold_days` (default 3):
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
Stale future intents (no action taken):
|
|
85
|
+
|
|
86
|
+
- [ID — name] (X days old)
|
|
87
|
+
Options:
|
|
88
|
+
a) Activate — start working on it now
|
|
89
|
+
b) Abandon — mark as abandoned
|
|
90
|
+
c) Defer to agent:
|
|
91
|
+
- implement: agent builds it
|
|
92
|
+
- research: agent investigates feasibility
|
|
93
|
+
- ideate: agent explores the problem space
|
|
94
|
+
d) Auto — go fully autonomous (invokes plastic:auto — agent delivers the intent end-to-end)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Auto-commit all triage changes.
|
|
98
|
+
|
|
99
|
+
### 6. Priority Order
|
|
100
|
+
|
|
101
|
+
1. **Active intents first** — resume work in progress
|
|
102
|
+
2. **Project context** — if in a registered project, show governing intent + tactical intents
|
|
103
|
+
3. **Stale future intents** — surface for triage
|
|
104
|
+
4. **Fresh future intents** — offer as next work
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plastic:creating-intent
|
|
3
|
+
description: Use when new work begins, the user expresses a new goal, says "new intent", or no active intent exists for the current task. Creates intents in the global store (~/.plastic/store/) or in a project's store (~/.plastic/projects/{slug}/store/) depending on context.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Creating an Intent
|
|
7
|
+
|
|
8
|
+
## When to Use
|
|
9
|
+
- User starts new work ("build X", "fix Y", "research Z")
|
|
10
|
+
- No active intent matches the current task
|
|
11
|
+
- User explicitly says "new intent" or "create intent"
|
|
12
|
+
- An agent discovers work needed during implementation
|
|
13
|
+
|
|
14
|
+
## Determine Tier
|
|
15
|
+
|
|
16
|
+
**Global intent** (strategic): created when working outside a registered project, or when the user expresses a high-level goal. Stored in `~/.plastic/store/`.
|
|
17
|
+
|
|
18
|
+
**Project intent** (tactical): created when working inside a registered project directory. Stored in `~/.plastic/projects/{slug}/store/`. Automatically linked to the project's governing intent.
|
|
19
|
+
|
|
20
|
+
### Detection logic:
|
|
21
|
+
1. Read `~/.plastic/projects.yml`
|
|
22
|
+
2. **CWD match:** Match CWD against registered project paths
|
|
23
|
+
- If CWD is inside a registered project → **project intent (tactical)**
|
|
24
|
+
3. **Explicit mention:** User mentions an existing project by name ("add this to reddit-kb", "new intent for plastic")
|
|
25
|
+
- Look up project in `projects.yml` by slug
|
|
26
|
+
- If found → **project intent (tactical)** in that project's store at `~/.plastic/projects/{slug}/store/`
|
|
27
|
+
- Agent changes working directory to the project path for execution
|
|
28
|
+
4. **No match:** CWD is not in a project AND no project mentioned
|
|
29
|
+
- → **global intent (strategic)** in `~/.plastic/store/`
|
|
30
|
+
|
|
31
|
+
When creating a tactical intent in a project store:
|
|
32
|
+
- Read the project's `AGENTS.md` for project context and decisions
|
|
33
|
+
- Link back to the project's governing intent (from `projects.yml` `parent` field) via `sources`
|
|
34
|
+
- Add `[[global:<parent_ID>]]` backlink in `## Links`
|
|
35
|
+
- The intent's Folgezettel ID is scoped to the project store (run `folgezettel-id` against the project's store at `~/.plastic/projects/{slug}/store/`)
|
|
36
|
+
|
|
37
|
+
## Workflow
|
|
38
|
+
|
|
39
|
+
### 1. Determine Store Location
|
|
40
|
+
|
|
41
|
+
- **Global:** `~/.plastic/store/`
|
|
42
|
+
- **Project:** `~/.plastic/projects/{slug}/store/`
|
|
43
|
+
|
|
44
|
+
### 2. Determine Folgezettel ID
|
|
45
|
+
|
|
46
|
+
IDs are scoped to the store they live in. Use the correct store path:
|
|
47
|
+
|
|
48
|
+
**Global store:**
|
|
49
|
+
```bash
|
|
50
|
+
"${CLAUDE_PLUGIN_ROOT}/scripts/folgezettel-id" "~/.plastic/store"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Project store:**
|
|
54
|
+
```bash
|
|
55
|
+
"${CLAUDE_PLUGIN_ROOT}/scripts/folgezettel-id" "~/.plastic/projects/{slug}/store"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Branch intent (has parent, either store):**
|
|
59
|
+
```bash
|
|
60
|
+
"${CLAUDE_PLUGIN_ROOT}/scripts/folgezettel-id" "<STORE>" "<parent_id>"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3. Determine Intent Properties
|
|
64
|
+
|
|
65
|
+
Ask or infer from context:
|
|
66
|
+
- **intent**: one-line description
|
|
67
|
+
- **author**: `human` | `claude-code` | other agent name
|
|
68
|
+
- **sources**: array of Folgezettel IDs that influenced this intent (e.g., `["4a1"]`)
|
|
69
|
+
- **chain**: starts empty `[]`, populated when this intent spawns others
|
|
70
|
+
- **tags**: freeform list (use `project-<name>` for project membership)
|
|
71
|
+
|
|
72
|
+
Place in `## Active` or `## Future` in INDEX.md (status is convention-derived, not a frontmatter field).
|
|
73
|
+
|
|
74
|
+
### 4. Create Directory and Files
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
mkdir -p <STORE>/ID--slug
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Write `{ID}--{slug}.md` using the intent template. For project intents, add the governing intent's ID to `sources` and add `[[global:ID]]` backlink in `## Links`.
|
|
81
|
+
|
|
82
|
+
### 5. If Implementation Intent Spawns a Project
|
|
83
|
+
|
|
84
|
+
When the user says "start building" or the plan calls for a new project:
|
|
85
|
+
|
|
86
|
+
1. Determine project slug from intent name
|
|
87
|
+
2. Create project directory in first `project_roots` path (from `~/.plastic/config.yml`):
|
|
88
|
+
```bash
|
|
89
|
+
mkdir -p <project_root>/<slug>
|
|
90
|
+
cd <project_root>/<slug>
|
|
91
|
+
git init
|
|
92
|
+
mkdir -p ~/.plastic/projects/{slug}/store
|
|
93
|
+
touch ~/.plastic/projects/{slug}/store/.gitkeep
|
|
94
|
+
```
|
|
95
|
+
3. Copy `AGENTS.md` template from `${CLAUDE_PLUGIN_ROOT}/templates/agents.md`
|
|
96
|
+
4. Register in `~/.plastic/projects.yml`:
|
|
97
|
+
```yaml
|
|
98
|
+
<slug>:
|
|
99
|
+
path: <full-path>
|
|
100
|
+
parent: "ID"
|
|
101
|
+
registered: <today>
|
|
102
|
+
status: active
|
|
103
|
+
```
|
|
104
|
+
5. Add `project-<slug>` to the intent's `tags` array
|
|
105
|
+
6. Auto-commit in both `~/.plastic/` and the new project
|
|
106
|
+
|
|
107
|
+
### 6. Update INDEX.md
|
|
108
|
+
|
|
109
|
+
- **Global intents:** update `~/.plastic/INDEX.md`
|
|
110
|
+
- **Project intents:** no global INDEX.md change (tactical intents are project-scoped)
|
|
111
|
+
|
|
112
|
+
Add to `## Active` (or `## Future`) and appropriate cluster.
|
|
113
|
+
|
|
114
|
+
### 7. Auto-commit
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
cd <store-root> && git add . && git commit -m "feat: create intent ID — [name]"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 8. Announce
|
|
121
|
+
|
|
122
|
+
"Created intent ID — [name]. Placed in: [Active|Future]. Store: [global|project:<slug>|local]."
|