@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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/PLASTIC.md +534 -0
  3. package/README.md +88 -0
  4. package/agents/future-intent-researcher.md +38 -0
  5. package/agents/intent-curator.md +40 -0
  6. package/bin/install.js +29 -0
  7. package/deprecations.yml +23 -0
  8. package/hooks/check-update +42 -0
  9. package/hooks/continue +31 -0
  10. package/hooks/future-intent-check +25 -0
  11. package/hooks/gate-check +10 -0
  12. package/hooks/hooks.json +78 -0
  13. package/hooks/run-hook +7 -0
  14. package/hooks/savepoint +6 -0
  15. package/hooks/session-start +9 -0
  16. package/hooks/statusline +16 -0
  17. package/package.json +43 -0
  18. package/scripts/folgezettel-id +40 -0
  19. package/scripts/hash-intent +29 -0
  20. package/scripts/hook-continue +130 -0
  21. package/scripts/hook-future-intent-check +90 -0
  22. package/scripts/hook-gate-check +136 -0
  23. package/scripts/hook-session-start +224 -0
  24. package/scripts/install.rb +474 -0
  25. package/scripts/lib/bridge.rb +139 -0
  26. package/scripts/migrate-folgezettel +535 -0
  27. package/scripts/migrate-to-global +96 -0
  28. package/scripts/read-config +129 -0
  29. package/skills/auto/SKILL.md +127 -0
  30. package/skills/brainstorming-grill-me/SKILL.md +105 -0
  31. package/skills/continuing/SKILL.md +104 -0
  32. package/skills/creating-intent/SKILL.md +122 -0
  33. package/skills/creating-project/SKILL.md +166 -0
  34. package/skills/executing-plan/SKILL.md +120 -0
  35. package/skills/executing-plan/code-quality-reviewer-prompt.md +32 -0
  36. package/skills/executing-plan/implementer-prompt.md +42 -0
  37. package/skills/executing-plan/spec-reviewer-prompt.md +27 -0
  38. package/skills/install/SKILL.md +134 -0
  39. package/skills/intent-curator/SKILL.md +41 -0
  40. package/skills/linking-intents/SKILL.md +72 -0
  41. package/skills/managing-index/SKILL.md +66 -0
  42. package/skills/managing-index/references/zettelkasten-linking.md +27 -0
  43. package/skills/releasing/SKILL.md +124 -0
  44. package/skills/savepoint/SKILL.md +57 -0
  45. package/skills/uninstall/SKILL.md +48 -0
  46. package/skills/update/SKILL.md +69 -0
  47. package/templates/agents.md +46 -0
  48. package/templates/checklist.md +11 -0
  49. package/templates/config.yml +13 -0
  50. package/templates/index.md +13 -0
  51. package/templates/intent.md +24 -0
  52. package/templates/plan.md +11 -0
  53. package/templates/projects.yml +3 -0
  54. 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]."