@zalom/plastic 2.0.0-alpha.27 → 2.0.0-alpha.28

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 (207) hide show
  1. package/PLASTIC.md +13 -139
  2. package/README.md +337 -133
  3. package/agents/plastic-enforcer.md +9 -10
  4. package/agents/plastic-executor.md +1 -1
  5. package/bin/crap +4 -0
  6. package/bin/lib/context_budget.rb +35 -1
  7. package/bin/lib/skill_census.rb +839 -0
  8. package/bin/plastic +6 -0
  9. package/bin/plastic-skill-census +114 -0
  10. package/bin/verify-change +345 -0
  11. package/deprecations.yml +1 -1
  12. package/{skills/agent-advisor/references → docs/help}/advisor-protocol.md +4 -7
  13. package/{skills/auto/references → docs/help}/agent-architecture.md +7 -7
  14. package/{skills/conventions/references → docs/help}/completion-and-done.md +1 -1
  15. package/{skills/auto/references → docs/help}/human-report-contract.md +17 -19
  16. package/{skills/conventions/references → docs/help}/roadmaps.md +2 -2
  17. package/{skills/tutorial/references → docs/help}/track-1-guided.md +8 -8
  18. package/{skills/tutorial/references → docs/help}/track-2-auto.md +5 -5
  19. package/{skills/tutorial/references → docs/help}/track-3-projects-and-roadmaps.md +24 -17
  20. package/package.json +3 -2
  21. package/scripts/append-ledger +2 -1
  22. package/scripts/dashboard.rb +10 -9
  23. package/scripts/day-summary +2 -1
  24. package/scripts/doctor.rb +48 -42
  25. package/scripts/end-intent +2 -8
  26. package/scripts/file-session-intent +2 -1
  27. package/scripts/hook-capture +4 -3
  28. package/scripts/hook-close +2 -1
  29. package/scripts/hook-record +3 -2
  30. package/scripts/hook-savepoint +3 -2
  31. package/scripts/hook-session-start +5 -4
  32. package/scripts/hook-stop +2 -1
  33. package/scripts/insight-append +1 -2
  34. package/scripts/install.rb +3 -1
  35. package/scripts/lib/active_delivery.rb +1 -1
  36. package/scripts/lib/arm.rb +2 -1
  37. package/scripts/lib/backup.rb +63 -0
  38. package/scripts/lib/cli/command.rb +85 -0
  39. package/scripts/lib/cli/commands/auto.rb +18 -0
  40. package/scripts/lib/cli/commands/auto_brief.rb +44 -0
  41. package/scripts/lib/cli/commands/auto_lock.rb +60 -0
  42. package/scripts/lib/cli/commands/auto_report.rb +50 -0
  43. package/scripts/lib/cli/commands/auto_take.rb +25 -0
  44. package/scripts/lib/cli/commands/backup.rb +43 -0
  45. package/scripts/lib/cli/commands/checkout.rb +25 -0
  46. package/scripts/lib/cli/commands/continue.rb +66 -0
  47. package/scripts/lib/cli/commands/doctor.rb +20 -0
  48. package/scripts/lib/cli/commands/feedback.rb +40 -0
  49. package/scripts/lib/cli/commands/help.rb +69 -0
  50. package/scripts/lib/cli/commands/hook.rb +32 -0
  51. package/scripts/lib/cli/commands/index.rb +23 -0
  52. package/scripts/lib/cli/commands/install.rb +21 -0
  53. package/scripts/lib/cli/commands/installer_verb.rb +37 -0
  54. package/scripts/lib/cli/commands/intent.rb +19 -0
  55. package/scripts/lib/cli/commands/intent_answer.rb +37 -0
  56. package/scripts/lib/cli/commands/intent_command.rb +53 -0
  57. package/scripts/lib/cli/commands/intent_end.rb +61 -0
  58. package/scripts/lib/cli/commands/intent_new.rb +62 -0
  59. package/scripts/lib/cli/commands/intent_note.rb +43 -0
  60. package/scripts/lib/cli/commands/intent_rule.rb +36 -0
  61. package/scripts/lib/cli/commands/intent_show.rb +25 -0
  62. package/scripts/lib/cli/commands/intent_spec.rb +44 -0
  63. package/scripts/lib/cli/commands/intent_step.rb +43 -0
  64. package/scripts/lib/cli/commands/intent_verify.rb +26 -0
  65. package/scripts/lib/cli/commands/migrate.rb +16 -0
  66. package/scripts/lib/cli/commands/migrate_stores.rb +31 -0
  67. package/scripts/lib/cli/commands/next.rb +49 -0
  68. package/scripts/lib/cli/commands/project.rb +19 -0
  69. package/scripts/lib/cli/commands/project_links.rb +42 -0
  70. package/scripts/lib/cli/commands/project_list.rb +20 -0
  71. package/scripts/lib/cli/commands/project_new.rb +72 -0
  72. package/scripts/lib/cli/commands/query.rb +31 -0
  73. package/scripts/lib/cli/commands/render.rb +25 -0
  74. package/scripts/lib/cli/commands/roadmap.rb +19 -0
  75. package/scripts/lib/cli/commands/roadmap_check.rb +44 -0
  76. package/scripts/lib/cli/commands/roadmap_log.rb +54 -0
  77. package/scripts/lib/cli/commands/roadmap_next.rb +34 -0
  78. package/scripts/lib/cli/commands/roadmap_show.rb +45 -0
  79. package/scripts/lib/cli/commands/rollback.rb +20 -0
  80. package/scripts/lib/cli/commands/search.rb +60 -0
  81. package/scripts/lib/cli/commands/session.rb +18 -0
  82. package/scripts/lib/cli/commands/session_commit.rb +42 -0
  83. package/scripts/lib/cli/commands/session_handoff.rb +34 -0
  84. package/scripts/lib/cli/commands/session_summary.rb +35 -0
  85. package/scripts/lib/cli/commands/status.rb +68 -0
  86. package/scripts/lib/cli/commands/subcommand_list.rb +36 -0
  87. package/scripts/lib/cli/commands/sync.rb +46 -0
  88. package/scripts/lib/cli/commands/uninstall.rb +20 -0
  89. package/scripts/lib/cli/commands/update.rb +20 -0
  90. package/scripts/lib/cli/commands/version.rb +53 -0
  91. package/scripts/lib/cli/frontier.rb +84 -0
  92. package/scripts/lib/cli/legacy.rb +50 -0
  93. package/scripts/lib/cli/output.rb +102 -0
  94. package/scripts/lib/cli/scope.rb +127 -0
  95. package/scripts/lib/cli/table.rb +64 -0
  96. package/scripts/lib/cli.rb +94 -0
  97. package/scripts/lib/compact_instructions.rb +8 -0
  98. package/scripts/lib/day_summary.rb +4 -3
  99. package/scripts/lib/doctor_core.rb +7 -32
  100. package/scripts/lib/doctor_session_ledger.rb +2 -1
  101. package/scripts/lib/feedback_report.rb +1 -1
  102. package/scripts/lib/graph_measure_models.rb +3 -1
  103. package/scripts/lib/index_entry.rb +9 -0
  104. package/scripts/lib/installer_core.rb +73 -19
  105. package/scripts/lib/intent_screen.rb +3 -3
  106. package/scripts/lib/lock.rb +2 -2
  107. package/scripts/lib/node_input.rb +3 -2
  108. package/scripts/lib/preflight.rb +2 -4
  109. package/scripts/lib/project_config.rb +2 -1
  110. package/scripts/lib/project_validator.rb +3 -2
  111. package/scripts/lib/qmd_sync.rb +8 -7
  112. package/scripts/lib/reference_archive.rb +45 -0
  113. package/scripts/lib/release_guard.rb +2 -0
  114. package/scripts/lib/report_screen.rb +4 -3
  115. package/scripts/lib/rlm/corpus.rb +13 -0
  116. package/scripts/lib/rlm/probe.rb +29 -0
  117. package/scripts/lib/rlm/query.rb +22 -0
  118. package/scripts/lib/roadmap_queue.rb +2 -2
  119. package/scripts/lib/roadmap_savepoint.rb +1 -1
  120. package/scripts/lib/runner_absorb.rb +3 -2
  121. package/scripts/lib/search_index.rb +55 -0
  122. package/scripts/lib/session_git.rb +4 -3
  123. package/scripts/lib/sqlite.rb +22 -0
  124. package/scripts/lib/store_discovery.rb +7 -6
  125. package/scripts/lib/store_layout.rb +54 -0
  126. package/scripts/lib/store_provisioning.rb +2 -1
  127. package/scripts/lib/store_sync.rb +85 -0
  128. package/scripts/lib/stores_move.rb +93 -0
  129. package/scripts/lib/verify_intent.rb +2 -7
  130. package/scripts/lib/version_number.rb +48 -0
  131. package/scripts/lib/work_graph.rb +59 -0
  132. package/scripts/lib/worktree.rb +3 -8
  133. package/scripts/lib/worktree_sweep.rb +3 -2
  134. package/scripts/link-suggest +2 -1
  135. package/scripts/migrate-to-global +1 -1
  136. package/scripts/new-intent +3 -12
  137. package/scripts/plastic-lock +3 -2
  138. package/scripts/promote-session-item +3 -2
  139. package/scripts/release-check +10 -5
  140. package/scripts/report-screen +1 -1
  141. package/scripts/session-commit +2 -1
  142. package/scripts/spawn-preamble +2 -2
  143. package/scripts/update.rb +25 -4
  144. package/scripts/write-handoff +2 -1
  145. package/templates/agents.md +6 -6
  146. package/templates/render.css +10 -0
  147. package/bin/plastic.js +0 -70
  148. package/skills/agent-advisor/SKILL.md +0 -84
  149. package/skills/auto/SKILL.md +0 -297
  150. package/skills/auto/evals/evals.json +0 -255
  151. package/skills/auto/references/end-tail.md +0 -64
  152. package/skills/conventions/SKILL.md +0 -29
  153. package/skills/dashboard/SKILL.md +0 -180
  154. package/skills/dashboard/evals/evals.json +0 -38
  155. package/skills/dashboard/references/classification.md +0 -22
  156. package/skills/dashboard/templates/dashboard-global.md +0 -20
  157. package/skills/dashboard/templates/dashboard-project.md +0 -19
  158. package/skills/direct/SKILL.md +0 -66
  159. package/skills/direct/references/request-signals.md +0 -59
  160. package/skills/doctor/SKILL.md +0 -305
  161. package/skills/doctor/report.md +0 -102
  162. package/skills/feedback/SKILL.md +0 -98
  163. package/skills/feedback/references/transport-and-privacy.md +0 -65
  164. package/skills/feedback/report.md +0 -36
  165. package/skills/install/SKILL.md +0 -215
  166. package/skills/intent-continuing/SKILL.md +0 -156
  167. package/skills/intent-continuing/references/board-fill.md +0 -52
  168. package/skills/intent-continuing/references/boarding-matrix.md +0 -35
  169. package/skills/intent-continuing/references/context-management.md +0 -28
  170. package/skills/intent-continuing/references/liveness-ranking.md +0 -57
  171. package/skills/intent-creating/SKILL.md +0 -89
  172. package/skills/intent-creating/evals/evals.json +0 -72
  173. package/skills/intent-creating/references/lifecycle.md +0 -81
  174. package/skills/intent-creating/references/wikilinks.md +0 -8
  175. package/skills/intent-ending/SKILL.md +0 -182
  176. package/skills/intent-ending/evals/evals.json +0 -74
  177. package/skills/intent-executing/SKILL.md +0 -87
  178. package/skills/intent-executing/evals/evals.json +0 -66
  179. package/skills/intent-executing/implementer-prompt.md +0 -47
  180. package/skills/intent-executing/spec-reviewer-prompt.md +0 -27
  181. package/skills/intent-speccing/SKILL.md +0 -136
  182. package/skills/intent-speccing/evals/evals.json +0 -126
  183. package/skills/intent-speccing/references/design-principles.md +0 -44
  184. package/skills/intent-speccing/references/per-section-fill-rules.md +0 -92
  185. package/skills/intent-speccing/references/self-verify-checklist.md +0 -37
  186. package/skills/project-creating/SKILL.md +0 -162
  187. package/skills/project-creating/references/hubs-projects.md +0 -55
  188. package/skills/project-creating/references/project-scaffolding.md +0 -97
  189. package/skills/releasing/SKILL.md +0 -376
  190. package/skills/releasing/references/deprecations.md +0 -60
  191. package/skills/releasing/references/promotion-and-tagging.md +0 -70
  192. package/skills/releasing/references/release-lines.md +0 -105
  193. package/skills/roadmap/SKILL.md +0 -90
  194. package/skills/roadmap/references/file-format.md +0 -134
  195. package/skills/roadmap/references/operations.md +0 -112
  196. package/skills/rollback/SKILL.md +0 -91
  197. package/skills/tutorial/SKILL.md +0 -66
  198. package/skills/tutorial/evals/evals.json +0 -186
  199. package/skills/uninstall/SKILL.md +0 -75
  200. package/skills/update/SKILL.md +0 -126
  201. /package/{skills/auto/references → docs/help}/agent-report-contract.md +0 -0
  202. /package/{skills/intent-executing → docs/help}/code-quality-reviewer-prompt.md +0 -0
  203. /package/{skills/conventions/references → docs/help}/knowledge-graph.md +0 -0
  204. /package/{skills/conventions/references → docs/help}/lifecycle-and-savepoints.md +0 -0
  205. /package/{skills/conventions/references → docs/help}/locks-and-worktrees.md +0 -0
  206. /package/{skills/conventions/references → docs/help}/maintenance-and-revisions.md +0 -0
  207. /package/{skills/intent-executing → docs/help}/plan-reviewer-prompt.md +0 -0
@@ -9,7 +9,7 @@ end to end: a piece of work moved through What, Why, How, and Exec, with a finis
9
9
 
10
10
  ## Before you start
11
11
 
12
- Run `/plastic-update` first (`$plastic-update` on Codex), so the commands below match what is
12
+ Run `plastic update` first, so the commands below match what is
13
13
  actually installed.
14
14
 
15
15
  Work in a sandbox: this track always creates a global-store intent; the throwaway repo below
@@ -22,7 +22,7 @@ directory instead (see station 6). Either way, nothing in this track touches a r
22
22
 
23
23
  ### 1. Create the intent
24
24
 
25
- Type `/plastic-intent-creating` and describe the work in plain words, for example "add a
25
+ Run `plastic intent new` and describe the work in plain words, for example "add a
26
26
  short Usage section to this project's README."
27
27
 
28
28
  Artifact: a new intent directory, `{id}--slug.md`, plus the sentinel placeholder lifecycle
@@ -35,7 +35,7 @@ tool, never written by hand.
35
35
 
36
36
  ### 2. Board the intent
37
37
 
38
- Type `/plastic-intent-continuing` and name the intent.
38
+ Run `plastic continue` and name the intent.
39
39
 
40
40
  Artifact: a delivery lock (a `delivery.lock` file in the intent directory) naming this
41
41
  session as the one owner, and a line in `savepoint.md` recording the stage. The agent then
@@ -46,13 +46,13 @@ sessions from editing the same intent at the same time.
46
46
 
47
47
  ### 3. Why, rulings one at a time
48
48
 
49
- Type `/plastic-intent-speccing` (say "grill me" for a harder, interview-style pass over
49
+ Run `plastic intent spec` (say "grill me" for a harder, interview-style pass over
50
50
  the same ground). It asks conversational prose questions, one at a
51
51
  time, never a multiple-choice menu, and answers them one at a time in return.
52
52
 
53
53
  Artifact: `## Context` and `### Decisions` in the intent file fill in as each answer lands, and
54
54
  each ruling also lands as its own `## Insights` entry the moment it is made, never batched for
55
- later. This station's product is the enriched Why; it hands off to `/plastic-intent-speccing`
55
+ later. This station's product is the enriched Why; it hands off to `plastic intent spec`
56
56
  next, it does not write `spec.md` itself.
57
57
 
58
58
  Checkpoint: after two or three answers, look at the intent file. Every ruling given out loud
@@ -60,7 +60,7 @@ is already sitting in `### Decisions` and in `## Insights`, in writing.
60
60
 
61
61
  ### 4. How, write the graph
62
62
 
63
- Ask the same conversation (`/plastic-intent-speccing`) to turn the rulings into the graph.
63
+ Ask the same conversation (`plastic intent spec`) to turn the rulings into the graph.
64
64
 
65
65
  Artifact: `graph.md` (nodes, edges, dispatch policy) and one `nodes/N.md` file per node this
66
66
  small delivery needs. A delivery this size is one node; many independent tasks instead get
@@ -70,7 +70,7 @@ Checkpoint: open `graph.md` and point at the one node this worked example needs.
70
70
 
71
71
  ### 5. Exec, drive the runner loop
72
72
 
73
- Type `/plastic-intent-executing`.
73
+ Run `plastic intent step`.
74
74
 
75
75
  Teach the loop: `ruby scripts/runner step <intent_dir>` computes which nodes are ready and
76
76
  prints a spawn block to dispatch, `ruby scripts/runner status <intent_dir>` reads the
@@ -87,7 +87,7 @@ moving to station 6.
87
87
 
88
88
  ### 6. End
89
89
 
90
- Type `/plastic-intent-ending`.
90
+ Run `plastic intent end`.
91
91
 
92
92
  Artifact: a real `outcome.md` (Summary, Delivered, Verification, Follow-ups) generated by
93
93
  `scripts/outcome-report` from `graph.md` and the ledger, the intent moved from `## Active`
@@ -9,7 +9,7 @@ agent end to end, and pausing and resuming that delivery will feel familiar.
9
9
 
10
10
  ## Before you start
11
11
 
12
- Run `/plastic-update` first (`$plastic-update` on Codex), so the commands below match what is
12
+ Run `plastic update` first, so the commands below match what is
13
13
  actually installed.
14
14
 
15
15
  Work in a sandbox: a throwaway git repository, or a global-store intent. Nothing in this
@@ -19,8 +19,8 @@ track touches a real project.
19
19
 
20
20
  ### 1. Board a small intent and choose auto
21
21
 
22
- Start from an active intent (create one first with `/plastic-intent-creating` if none
23
- exists, the same way as track 1 station 1). Type `/plastic-auto`.
22
+ Start from an active intent (create one first with `plastic intent new` if none
23
+ exists, the same way as track 1 station 1). Run `plastic auto take ID`.
24
24
 
25
25
  Artifact: the delivery lock arms, and the agent announces it is taking over the intent for
26
26
  autonomous delivery.
@@ -45,7 +45,7 @@ can review how it checked, not just what it found.
45
45
  The user keeps two things: the rulings made along the way, and the review points, moments
46
46
  auto is built to pause for, such as confirming a project path or stopping before a
47
47
  destructive action with no safe way back. When auto tells you to run a command yourself
48
- ("run /plastic-intent-speccing"), that is an instruction for you to type; it is a different
48
+ ("run plastic intent spec"), that is an instruction for you to type; it is a different
49
49
  thing from the prompts auto hands to its own dispatched subagents, and the two are never
50
50
  mixed up in what it tells you.
51
51
 
@@ -74,7 +74,7 @@ line.
74
74
 
75
75
  ### 5. Continue and where-was-I after time away
76
76
 
77
- Type `/plastic-intent-continuing`.
77
+ Run `plastic continue`.
78
78
 
79
79
  Artifact: the current state, presented and then the session stops. If a specific intent is
80
80
  named, the agent reads its stage and savepoint and resumes exactly there, rather than
@@ -9,7 +9,7 @@ will exist with more than one intent inside it and a roadmap file describing the
9
9
 
10
10
  ## Before you start
11
11
 
12
- Run `/plastic-update` first (`$plastic-update` on Codex), so the commands below match what is
12
+ Run `plastic update` first, so the commands below match what is
13
13
  actually installed.
14
14
 
15
15
  Work in a sandbox: this whole track is a walked example. It creates a real project directory
@@ -20,11 +20,11 @@ one this tutorial keeps or ships.
20
20
 
21
21
  ### 1. Start from a founding implementation intent
22
22
 
23
- Create and board an intent the same way as track 1, stations 1 and 2: `/plastic-intent-creating`,
24
- then `/plastic-intent-continuing`. Describe something meant to grow into a small real project,
23
+ Create and board an intent the same way as track 1, stations 1 and 2: `plastic intent new`,
24
+ then `plastic continue`. Describe something meant to grow into a small real project,
25
25
  for example "build a personal todo app."
26
26
 
27
- Then type `/plastic-intent-speccing` and record a couple of real rulings on this founding
27
+ Then type `plastic intent spec` and record a couple of real rulings on this founding
28
28
  intent, for example the language or how tasks get stored. Keep it short: this intent only
29
29
  needs enough decisions for the new project to inherit, not a full design.
30
30
 
@@ -33,17 +33,21 @@ into a whole new project.
33
33
 
34
34
  ### 2. Grow it into a project
35
35
 
36
- Type `/plastic-project-creating`.
36
+ Make the project directory yourself and write its `AGENTS.md`, carrying forward at least one
37
+ decision from the founding intent. Plastic does not create the directory or fill that file;
38
+ that is ordinary agent work, done once, before the project exists. Once the directory exists,
39
+ run `plastic project new SLUG --path PATH` to register it in `projects.yml` and provision and
40
+ validate its store.
37
41
 
38
- Artifact: a new project directory, an `AGENTS.md` file carrying the founding intent's
39
- decisions, the project's own intent store, and a new entry in `projects.yml` registering it.
42
+ Artifact: a new project directory with its `AGENTS.md`, the project's own intent store, and a
43
+ new entry in `projects.yml` registering it.
40
44
 
41
45
  Checkpoint: open `AGENTS.md` and find at least one line that traces back to a decision
42
46
  recorded in the founding intent back in station 1.
43
47
 
44
48
  ### 3. Add more intents inside the project
45
49
 
46
- Type `/plastic-intent-creating` at least twice, from inside the project, describing two
50
+ Run `plastic intent new` at least twice, from inside the project, describing two
47
51
  pieces of real work, for example "add a task list model" and "add a due date field."
48
52
 
49
53
  Artifact: two or more intent directories inside the project's own store, separate from the
@@ -54,13 +58,16 @@ in the global store.
54
58
 
55
59
  ### 4. Plan a delivery batch
56
60
 
57
- Type `/plastic-roadmap`.
61
+ Copy `templates/roadmap.md` to `roadmaps/<slug>.md`, next to the project's `INDEX.md`, and fill
62
+ it by hand: a title and short meta header, a `## Goal` section in prose describing what "done"
63
+ looks like for the whole batch, a `## Batches` section (an ordered list of groups of intents;
64
+ intents inside one batch are safe to run in parallel, batches themselves run one after another),
65
+ and an append-only, dated `## Log`. `INDEX.md` stays the single source of truth for each
66
+ intent's status; the roadmap only mirrors it. List the two or more intents from station 3
67
+ across one or more batches.
58
68
 
59
- Teach the roadmap file shape exactly: a title and short meta header, a `## Goal` section in
60
- prose describing what "done" looks like for the whole batch, a `## Batches` section (an
61
- ordered list of groups of intents; intents inside one batch are safe to run in parallel,
62
- batches themselves run one after another), and an append-only, dated `## Log`. `INDEX.md`
63
- stays the single source of truth for each intent's status; the roadmap only mirrors it.
69
+ Run `plastic roadmap check <slug>` to confirm the file parses, then `plastic roadmap show
70
+ <slug>` to see it rendered as a report.
64
71
 
65
72
  Artifact: a new `roadmaps/<slug>.md` file, sitting next to the project's `INDEX.md`, listing
66
73
  the two or more intents from station 3 across one or more batches.
@@ -93,8 +100,8 @@ sections you turned into the condition above.
93
100
 
94
101
  No command run here; describe the step instead. Each delivered intent's code merges to main
95
102
  as it lands. When the batch (or a meaningful slice of it) is ready to ship, cutting a release
96
- runs through `/plastic-releasing`, which merges, bumps the version, tags, and completes the
97
- intents it collects.
103
+ is a push to `alpha`, `beta`, or `main`: the version files are bumped in that push, and CI
104
+ tags, publishes, and completes the intents it collects.
98
105
 
99
106
  Releases and any npm publish step are described here, not run: this walkthrough stays in a
100
107
  sandbox and never touches a real package registry.
@@ -108,4 +115,4 @@ This is the same What, Why, How, Exec cycle from tracks 1 and 2, repeated across
108
115
  and gathered by a roadmap. Read
109
116
  [`using-plastic-with-claude-code.md`](https://github.com/zalom/plastic/blob/main/docs/guides/using-plastic-with-claude-code.md) for roadmap-driven delivery in more depth,
110
117
  including a real worked roadmap. For the exact roadmap file format beyond what this
111
- walkthrough covers, the `plastic-roadmap` skill itself is the reference.
118
+ walkthrough covers, [`docs/help/roadmaps.md`](roadmaps.md) is the reference.
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@zalom/plastic",
3
- "version": "2.0.0-alpha.27",
3
+ "version": "2.0.0-alpha.28",
4
4
  "description": "Intent-driven idea development system for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
7
- "plastic": "bin/plastic.js"
7
+ "plastic": "bin/plastic"
8
8
  },
9
9
  "engines": {
10
10
  "node": ">=18.0.0"
@@ -34,6 +34,7 @@
34
34
  "bin/",
35
35
  "scripts/",
36
36
  "skills/",
37
+ "docs/help/",
37
38
  "hooks/",
38
39
  "agents/",
39
40
  "templates/",
@@ -30,6 +30,7 @@
30
30
  # 2 - usage error, or promote/tick found nothing to address (no write happens)
31
31
  # 3 - promote/tick could not take an exclusive lock (filesystem without flock support)
32
32
 
33
+ require_relative "lib/store_layout"
33
34
  require_relative "lib/session_ledger"
34
35
  require_relative "lib/handoff"
35
36
 
@@ -162,7 +163,7 @@ def main(argv)
162
163
  usage_abort("verb must be one of #{VERBS.join(", ")}, got #{opts[:verb].inspect}") unless VERBS.include?(opts[:verb])
163
164
 
164
165
  plastic_home = expand(ENV.fetch("PLASTIC_HOME", "~/.plastic"))
165
- store = opts[:store] ? expand(opts[:store]) : File.join(plastic_home, "store")
166
+ store = opts[:store] ? expand(opts[:store]) : Plastic::StoreLayout.global_store(plastic_home)
166
167
  templates = opts[:templates] ? expand(opts[:templates]) : default_templates_dir
167
168
  usage_abort("templates dir not found: #{templates}") unless Dir.exist?(templates)
168
169
  opts[:templates] = templates
@@ -21,6 +21,7 @@
21
21
  #
22
22
  # Read-only. Never modifies files.
23
23
 
24
+ require_relative "lib/store_layout"
24
25
  require "json"
25
26
  require "yaml"
26
27
  require "date"
@@ -143,13 +144,13 @@ def completion_dates(index_path)
143
144
  end
144
145
 
145
146
  # All stores: global + every registered project. -> [{scope, store, index}]
146
- def stores
147
+ def stores(home = PLASTIC_HOME)
147
148
  list = []
148
- global = File.join(PLASTIC_HOME, "store")
149
- list << { scope: "global", store: global, index: File.join(PLASTIC_HOME, "INDEX.md") } if File.directory?(global)
150
- projects_root = File.join(PLASTIC_HOME, "projects")
149
+ global = Plastic::StoreLayout.global_store(home)
150
+ list << { scope: "global", store: global, index: File.join(Plastic::StoreLayout.global_root(home), "INDEX.md") } if File.directory?(global)
151
+ projects_root = Plastic::StoreLayout.projects_root(home)
151
152
  if File.directory?(projects_root)
152
- Dir.children(projects_root).sort.each do |proj|
153
+ Plastic::StoreLayout.project_slugs(home).each do |proj|
153
154
  store = File.join(projects_root, proj, "store")
154
155
  next unless File.directory?(store)
155
156
  list << { scope: "project:#{proj}", store: store, index: File.join(projects_root, proj, "INDEX.md") }
@@ -592,7 +593,7 @@ def render_continue(records)
592
593
  out.concat(matrix(open, scope_tag: true))
593
594
  out << ""
594
595
  out << LEGEND
595
- out << "ask for the <slug> project board · plastic-auto (works the dispatchable queue)"
596
+ out << "ask for the <slug> project board · plastic auto take ID (works the dispatchable queue)"
596
597
  out.join("\n") + "\n"
597
598
  end
598
599
 
@@ -855,7 +856,7 @@ end
855
856
  def short_description(scope)
856
857
  return "" unless scope.start_with?("project:")
857
858
  slug = scope.sub("project:", "")
858
- agents = File.join(PLASTIC_HOME, "projects", slug, "AGENTS.md")
859
+ agents = File.join(Plastic::StoreLayout.project_root(PLASTIC_HOME, slug), "AGENTS.md")
859
860
  if File.exist?(agents)
860
861
  File.readlines(agents).each do |l|
861
862
  t = l.strip
@@ -1022,7 +1023,7 @@ end
1022
1023
  # directly under PLASTIC_HOME, with no intervening "store" segment.
1023
1024
  def screen_tier_root(plastic_home, scope)
1024
1025
  return plastic_home if scope == "global"
1025
- File.join(plastic_home, "projects", screen_scope_slug(scope))
1026
+ Plastic::StoreLayout.project_root(plastic_home, screen_scope_slug(scope))
1026
1027
  end
1027
1028
 
1028
1029
  # "global" spans every store (the same aggregate render_continue and --json's
@@ -1085,7 +1086,7 @@ end
1085
1086
  # PLASTIC_HOME/store tmp root, and `session: nil` (A6) so the calling
1086
1087
  # session's own live heartbeat counts rather than being excluded as "self".
1087
1088
  def screen_sessions_count(plastic_home, now:)
1088
- store = File.join(plastic_home, "store")
1089
+ store = Plastic::StoreLayout.global_store(plastic_home)
1089
1090
  DaySummary.active_sessions(store, nil, now: now, ttl: DaySummary::HEARTBEAT_TTL).size
1090
1091
  end
1091
1092
 
@@ -14,6 +14,7 @@
14
14
  #
15
15
  # Exit codes: 0 done; 2 usage error.
16
16
 
17
+ require_relative "lib/store_layout"
17
18
  require_relative "lib/session_ledger"
18
19
  require_relative "lib/day_summary"
19
20
 
@@ -43,7 +44,7 @@ end
43
44
 
44
45
  opts = parse_args(ARGV)
45
46
  home = opts[:home] ? expand(opts[:home]) : expand(ENV.fetch("PLASTIC_HOME", "~/.plastic"))
46
- store = opts[:store] ? expand(opts[:store]) : File.join(home, "store")
47
+ store = opts[:store] ? expand(opts[:store]) : Plastic::StoreLayout.global_store(home)
47
48
  day = opts[:day] || SessionLedger.day_id
48
49
  usage_abort("--day must be eight digits parsing as a real date, got #{day.inspect}") unless SessionLedger.valid_day_id?(day)
49
50
  session = SessionLedger.short_session_id(opts[:session], ENV["CLAUDE_CODE_SESSION_ID"])
package/scripts/doctor.rb CHANGED
@@ -9,6 +9,7 @@
9
9
  # Exit codes: 0 (all pass), 1 (warnings only), 2 (failures present)
10
10
  # Read-only — never modifies files.
11
11
 
12
+ require_relative "lib/store_layout"
12
13
  require "date"
13
14
  require "open3"
14
15
  require "timeout"
@@ -40,6 +41,7 @@ require_relative "lib/preflight"
40
41
  require_relative "lib/ruby_probe"
41
42
  require_relative "lib/doctor_session_ledger"
42
43
  require_relative "lib/intent_screen"
44
+ require_relative "lib/store_sync"
43
45
 
44
46
  # Diagnostic engine, instantiable with an injected store/agent map so tests can
45
47
  # run it hermetically (no eval, no global-constant rewriting).
@@ -216,7 +218,7 @@ class Doctor
216
218
  def check_global_store
217
219
  checks = []
218
220
 
219
- index_path = File.join(plastic_home, "INDEX.md")
221
+ index_path = File.join(Plastic::StoreLayout.global_root(plastic_home), "INDEX.md")
220
222
 
221
223
  # index_exists
222
224
  if File.exist?(index_path)
@@ -252,7 +254,7 @@ class Doctor
252
254
  end
253
255
 
254
256
  # orphaned_intents — directories in store/ not referenced in INDEX.md
255
- store_dir = File.join(plastic_home, "store")
257
+ store_dir = Plastic::StoreLayout.global_store(plastic_home)
256
258
  if File.directory?(store_dir)
257
259
  intent_dirs = store_intent_dirs(store_dir)
258
260
  orphans = intent_dirs.reject { |d| content.include?("store/#{d}") }
@@ -278,7 +280,7 @@ class Doctor
278
280
  store_paths = content.scan(%r{store/\S+}).map { |ref| ref.gsub(/[)\]>].*/, "").chomp("/") }.uniq
279
281
 
280
282
  ghosts = store_paths.select do |ref|
281
- full_path = File.join(plastic_home, ref)
283
+ full_path = File.join(Plastic::StoreLayout.global_root(plastic_home), ref)
282
284
  !File.exist?(full_path) && !File.directory?(full_path)
283
285
  end
284
286
 
@@ -330,7 +332,7 @@ class Doctor
330
332
  category: "core_files", name: name, status: "warn",
331
333
  message: "#{config[:name]}'s agent-side VERSION file not found at #{tilde(agent_version_path)}",
332
334
  fixable: true,
333
- fix_hint: "Re-sync the stale harness: npx @zalom/plastic@latest install --reinstall <flag>, or plastic-rollback to a prior version"
335
+ fix_hint: "Re-sync the stale harness: npx @zalom/plastic@latest install --reinstall <flag>, or `plastic rollback` to a prior version"
334
336
  )
335
337
  else
336
338
  agent_version = File.read(agent_version_path).strip
@@ -348,7 +350,7 @@ class Doctor
348
350
  "#{tilde(agent_version_path)}: #{agent_version}",
349
351
  ],
350
352
  fixable: true,
351
- fix_hint: "Re-sync the stale harness: npx @zalom/plastic@latest install --reinstall <flag>, or plastic-rollback to a prior version"
353
+ fix_hint: "Re-sync the stale harness: npx @zalom/plastic@latest install --reinstall <flag>, or `plastic rollback` to a prior version"
352
354
  )
353
355
  end
354
356
  end
@@ -613,7 +615,7 @@ class Doctor
613
615
  fixable: true,
614
616
  fix_hint: "Relocate each unsanctioned section into the " \
615
617
  "intent's revisions.md via move-and-record (a missing required section is restored " \
616
- "or reprojected instead); see plastic-conventions > references/maintenance-and-revisions.md"
618
+ "or reprojected instead); see `plastic help maintenance-and-revisions`"
617
619
  )
618
620
  end
619
621
 
@@ -644,7 +646,7 @@ class Doctor
644
646
  # unpromoted_rules (intent 341, G8, C37): an Insights entry tagged
645
647
  # `rule:` (via `insight-append --rule`) is a promise the rule will make
646
648
  # it into project doctrine. Advisory only.
647
- checks.concat(unpromoted_rules_checks(intent_dirs, home: Dir.home))
649
+ checks.concat(unpromoted_rules_checks(intent_dirs))
648
650
 
649
651
  # cross_store_resolution — RESOLVES (not just shape-checks) every cross-store
650
652
  # `store:id` ref against the FULL store family via the relocation map
@@ -705,14 +707,14 @@ class Doctor
705
707
  if scopes.nil? || scopes.include?("global")
706
708
  stores << {
707
709
  scope: "global",
708
- index: File.join(plastic_home, "INDEX.md"),
709
- store_dir: File.join(plastic_home, "store"),
710
+ index: File.join(Plastic::StoreLayout.global_root(plastic_home), "INDEX.md"),
711
+ store_dir: Plastic::StoreLayout.global_store(plastic_home),
710
712
  }
711
713
  end
712
714
 
713
- projects_root = File.join(plastic_home, "projects")
715
+ projects_root = Plastic::StoreLayout.projects_root(plastic_home)
714
716
  if File.directory?(projects_root)
715
- Dir.children(projects_root).sort.each do |project|
717
+ Plastic::StoreLayout.project_slugs(plastic_home).each do |project|
716
718
  scope = "project:#{project}"
717
719
  next unless scopes.nil? || scopes.include?(scope)
718
720
 
@@ -1228,7 +1230,7 @@ end
1228
1230
  "project-links --intent <id> --apply` over running project-links directly: it detects " \
1229
1231
  "(never acquires) the target's delivery lock, requires a clean store working tree, and " \
1230
1232
  "commits the scoped change plus its revisions.md receipt as one merged operation " \
1231
- "(plastic-conventions > references/maintenance-and-revisions.md)."
1233
+ "(`plastic help maintenance-and-revisions`)."
1232
1234
  )
1233
1235
  end
1234
1236
 
@@ -1692,7 +1694,7 @@ end
1692
1694
  "Every sources/chain id resolves to a real intent (I4)",
1693
1695
  "Record the dangling sources/chain edge as a " \
1694
1696
  "broken-source/broken-chain move-and-record entry in the intent's revisions.md (see " \
1695
- "plastic-conventions > references/maintenance-and-revisions.md), or restore the missing intent"
1697
+ "`plastic help maintenance-and-revisions`), or restore the missing intent"
1696
1698
  )
1697
1699
  checks
1698
1700
  end
@@ -1865,31 +1867,25 @@ end
1865
1867
  #
1866
1868
  # `insight-append --rule` tags an entry "... - rule: <text>". A tag is a
1867
1869
  # promise the rule will make it into project doctrine; until the exact
1868
- # rule text shows up in some skills/conventions/references/*.md chapter,
1869
- # it is only visible to a session that happens to read this one intent
1870
- # file, and the next session repeats the mistake the rule names. Advisory
1871
- # only (warn, never fail): a freshly tagged rule is not yet promoted by
1872
- # design, and nothing here can auto-promote it (that is an editorial call,
1873
- # not a mechanical one).
1870
+ # rule text shows up in some docs/help/*.md chapter, it is only visible to
1871
+ # a session that happens to read this one intent file, and the next
1872
+ # session repeats the mistake the rule names. Advisory only (warn, never
1873
+ # fail): a freshly tagged rule is not yet promoted by design, and nothing
1874
+ # here can auto-promote it (that is an editorial call, not a mechanical
1875
+ # one).
1874
1876
  RULE_ENTRY_RE = /—\s*rule:\s*(.+?)\s*\z/.freeze
1875
1877
 
1876
- def unpromoted_rules_checks(intent_dirs, package_root: PACKAGE_ROOT, home: nil)
1877
- # The installed doctor runs from ~/.plastic/scripts, so PACKAGE_ROOT
1878
- # (~/.plastic) has no skills/ directory: the conventions chapters install
1879
- # to the agent home layout instead. `home` is caller-injected (never an
1880
- # ENV read here) so this stays hermetic in tests; the real call site
1881
- # passes the process's actual home directory.
1882
- chapter_dirs = []
1883
- if home
1884
- chapter_dirs << File.join(home, ".claude", "skills", "plastic-conventions", "references")
1885
- chapter_dirs << File.join(home, ".agents", "skills", "plastic-conventions", "references")
1886
- end
1887
- chapter_dirs << File.join(package_root, "skills", "conventions", "references")
1878
+ def unpromoted_rules_checks(intent_dirs, package_root: PACKAGE_ROOT)
1879
+ # docs/help installs straight under PACKAGE_ROOT for every harness alike
1880
+ # (~/.plastic/docs/help once installed, repo docs/help in a checkout), so
1881
+ # a single path covers both the repo and the installed layout; unlike
1882
+ # the old skills-based chapters, help topics are no longer agent-home
1883
+ # specific, so this needs no `home:` split.
1884
+ chapter_dir = File.join(package_root, "docs", "help")
1888
1885
 
1889
- chapters_text = chapter_dirs.select { |d| Dir.exist?(d) }
1890
- .flat_map { |d| Dir.glob(File.join(d, "*.md")) }
1891
- .map { |f| File.read(f) }
1892
- .join("\n\n")
1886
+ chapters_text = Dir.glob(File.join(chapter_dir, "*.md"))
1887
+ .map { |f| File.read(f) }
1888
+ .join("\n\n")
1893
1889
 
1894
1890
  unpromoted = []
1895
1891
  intent_dirs.each do |d|
@@ -1917,7 +1913,7 @@ end
1917
1913
  category: "conventions", name: "unpromoted_rules", status: "warn",
1918
1914
  message: "#{unpromoted.size} tagged rule(s) not yet carried by any conventions chapter",
1919
1915
  details: unpromoted, fixable: false,
1920
- fix_hint: "Promote the rule into the right skills/conventions/references/*.md chapter, " \
1916
+ fix_hint: "Promote the rule into the right docs/help/*.md chapter, " \
1921
1917
  "or drop the tag if the finding does not belong in doctrine"
1922
1918
  )]
1923
1919
  end
@@ -1934,8 +1930,7 @@ end
1934
1930
  # skill directory under agent_dir/skills that has NO corresponding entry in the
1935
1931
  # current install manifest is a stray (e.g. a leftover old-name copy the
1936
1932
  # install/update prune should have removed, or one it never saw because the
1937
- # manifest predates it). Complements flat_skills_check (which only confirms at
1938
- # least one skill exists). Defers to the manifest check when the manifest itself
1933
+ # manifest predates it). Defers to the manifest check when the manifest itself
1939
1934
  # is missing or malformed, so the two checks never double-report the same gap.
1940
1935
 
1941
1936
  # Auto-mode role agents install as <dir>/agents/plastic-*.md. Pass if at least
@@ -2301,7 +2296,7 @@ end
2301
2296
  # project can be checked in isolation (used by `--store <slug>`).
2302
2297
  def check_project_store(slug, project_info)
2303
2298
  checks = []
2304
- project_dir = File.join(plastic_home, "projects", slug)
2299
+ project_dir = Plastic::StoreLayout.project_root(plastic_home, slug)
2305
2300
 
2306
2301
  # project_dir_exists
2307
2302
  if File.directory?(project_dir)
@@ -2351,7 +2346,7 @@ end
2351
2346
  end
2352
2347
 
2353
2348
  # project_yml_exists
2354
- project_yml_path = File.join(plastic_home, "projects", slug, "project.yml")
2349
+ project_yml_path = File.join(Plastic::StoreLayout.project_root(plastic_home, slug), "project.yml")
2355
2350
  project_yml_data = nil
2356
2351
 
2357
2352
  if File.exist?(project_yml_path)
@@ -2398,7 +2393,7 @@ end
2398
2393
  return checks unless parent_id
2399
2394
 
2400
2395
  # Find the intent directory for the parent ID
2401
- store_dir = File.join(plastic_home, "store")
2396
+ store_dir = Plastic::StoreLayout.global_store(plastic_home)
2402
2397
  parent_dir = nil
2403
2398
  if File.directory?(store_dir)
2404
2399
  parent_dir = Dir.children(store_dir).find { |d| d.start_with?("#{parent_id}--") }
@@ -2555,7 +2550,7 @@ end
2555
2550
  # A config-asks warn in that tier would flip every post-update doctor to
2556
2551
  # "fail" on an otherwise healthy install until the question is answered,
2557
2552
  # re-noising the post-update surface intent 126 deliberately quieted. The
2558
- # recoverable-later path for a pending question is a full `/plastic-doctor`
2553
+ # recoverable-later path for a pending question is a full `plastic doctor`
2559
2554
  # run, the declared maintenance front door; the moment-it-happens path is
2560
2555
  # update.rb#announce_pending_config_asks, which already runs on every hop.
2561
2556
  #
@@ -3019,6 +3014,16 @@ end
3019
3014
  end
3020
3015
  end
3021
3016
 
3017
+ def check_graph_links
3018
+ return [] unless File.exist?(Plastic::WorkGraph.path(plastic_home))
3019
+
3020
+ orphans = Plastic::StoreSync.orphans(plastic_home)
3021
+ return [check(category: "graph_links", name: "graph_links", status: "pass", message: "every stored file belongs to an intent in work_graph.db")] if orphans.empty?
3022
+
3023
+ [check(category: "graph_links", name: "graph_links", status: "warn", details: orphans, fixable: false,
3024
+ message: "#{orphans.size} intent id(s) hold files and have no row in work_graph.db")]
3025
+ end
3026
+
3022
3027
  # --- Run all checks ---
3023
3028
 
3024
3029
  def run_checks(agent_key)
@@ -3037,6 +3042,7 @@ end
3037
3042
  all_checks += check_session_ledger(scopes: ["global"])
3038
3043
  all_checks += check_skill_lint
3039
3044
  all_checks += check_install_integrity
3045
+ all_checks += check_graph_links
3040
3046
  all_checks += check_display_registration(agent_key)
3041
3047
  all_checks += check_display_paints(agent_key)
3042
3048
  all_checks += check_display_not_defeated(agent_key)
@@ -68,6 +68,7 @@
68
68
  # 7 hollow delivered report refused (317a D7) - intent 308's one deliberate
69
69
  # exception to report-and-proceed; --allow-hollow-report overrides.
70
70
 
71
+ require_relative "lib/store_layout"
71
72
  require "fileutils"
72
73
  require "date"
73
74
  require "open3"
@@ -170,14 +171,7 @@ end
170
171
  # "projects" (the StoreDiscovery convention, scripts/lib/store_discovery.rb), never by
171
172
  # hardcoding ".plastic" as a name.
172
173
  def resolve_plastic_home_and_scope(store)
173
- parent = File.dirname(store)
174
- grandparent = File.dirname(parent)
175
- if File.basename(grandparent) == "projects"
176
- slug = File.basename(parent)
177
- [File.dirname(grandparent), "project:#{slug}"]
178
- else
179
- [parent, "global"]
180
- end
174
+ Plastic::StoreLayout.home_and_scope(store)
181
175
  end
182
176
 
183
177
  # --- outcome generation, before the backfill (intent 339, G6, spec D10) -----
@@ -14,6 +14,7 @@
14
14
  # and on any filing error (reported on stderr; the next boot tries again), 2 on
15
15
  # a usage error.
16
16
 
17
+ require_relative "lib/store_layout"
17
18
  require_relative "lib/session_ledger"
18
19
  require_relative "lib/session_backfill"
19
20
 
@@ -48,7 +49,7 @@ if opts[:carry_to] && !SessionLedger.valid_day_id?(opts[:carry_to])
48
49
  usage_abort("--carry-to must be a real calendar date, YYYYMMDD")
49
50
  end
50
51
 
51
- store = opts[:store] || File.join(File.expand_path(ENV.fetch("PLASTIC_HOME", "~/.plastic")), "store")
52
+ store = opts[:store] || Plastic::StoreLayout.global_store(File.expand_path(ENV.fetch("PLASTIC_HOME", "~/.plastic")))
52
53
  templates = opts[:templates] || File.expand_path("../templates", __dir__)
53
54
 
54
55
  begin
@@ -9,6 +9,7 @@
9
9
  # runs in its own rescue and the hook always exits 0 (spec D2). Intent 345
10
10
  # (D7, 323) removed the per-prompt Future-intent hint step entirely.
11
11
 
12
+ require_relative "lib/store_layout"
12
13
  require "json"
13
14
  require "open3"
14
15
  require "time"
@@ -38,7 +39,7 @@ cwd = payload["cwd"].to_s
38
39
  cwd = Dir.pwd if cwd.empty?
39
40
 
40
41
  plastic_home = File.expand_path(ENV["PLASTIC_HOME"] || "~/.plastic")
41
- store = File.join(plastic_home, "store")
42
+ store = Plastic::StoreLayout.global_store(plastic_home)
42
43
  templates = File.expand_path("../templates", __dir__)
43
44
  sid = SessionLedger.short_session_id(nil, session_id)
44
45
  today = SessionLedger.day_id
@@ -108,7 +109,7 @@ begin
108
109
  cockpit, _err, status = Open3.capture3({ "RUBYOPT" => nil }, "ruby", dashboard, "continue")
109
110
  if status.success? && !cockpit.strip.empty?
110
111
  context_parts << (cockpit.rstrip +
111
- "\n\nFollow the plastic-intent-continuing skill workflow to resume: " \
112
+ "\n\nRun `plastic continue` to resume: " \
112
113
  "if active intents exist, read their state and resume; otherwise surface the " \
113
114
  "most-valuable next work and any stale or triage intents from the board above.")
114
115
 
@@ -135,7 +136,7 @@ begin
135
136
  auto_triggers = ["take it from here", "deliver this", "/plastic-auto", "auto mode"].freeze
136
137
  triggered = auto_triggers.any? { |p| message_lower.include?(p) } || message_lower.match?(/\bauto\b/)
137
138
  if triggered
138
- context_parts << "Auto-mode request detected. Invoke the plastic-auto skill to deliver the " \
139
+ context_parts << "Auto-mode request detected. Run `plastic auto take ID` to deliver the " \
139
140
  "active intent autonomously - it takes the intent under a lock and a worktree " \
140
141
  "and points this session at it."
141
142
  end
@@ -8,6 +8,7 @@
8
8
  #
9
9
  # Usage: hook-close <plastic_home> (stdin: the hook JSON)
10
10
 
11
+ require_relative "lib/store_layout"
11
12
  require "json"
12
13
  require_relative "lib/session_ledger"
13
14
  require_relative "lib/session_close"
@@ -23,7 +24,7 @@ payload =
23
24
  {}
24
25
  end
25
26
 
26
- store = File.join(File.expand_path(plastic_home), "store")
27
+ store = Plastic::StoreLayout.global_store(File.expand_path(plastic_home))
27
28
  filer = File.expand_path("file-session-intent", __dir__)
28
29
  templates = File.expand_path("../templates", __dir__)
29
30
  begin