@juicesharp/rpiv-pi 1.8.1 → 1.8.3

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/README.md CHANGED
@@ -19,9 +19,9 @@ Skill-based development workflow for [Pi Agent](https://github.com/badlogic/pi-m
19
19
 
20
20
  ## What you get
21
21
 
22
- - **A pipeline of chained AI skills** - discover → research → design → plan → implement → validate, each producing a reviewable artifact under `thoughts/shared/`.
22
+ - **A pipeline of chained AI skills** - discover → research → design → plan → implement → validate, each producing a reviewable artifact under `.rpiv/artifacts/`.
23
23
  - **Named subagents for parallel analysis** - `codebase-analyzer`, `codebase-locator`, `codebase-pattern-finder`, `claim-verifier`, and 8 more, dispatched automatically by skills.
24
- - **Session lifecycle hooks** - agent profiles, guidance files, and pipeline directories scaffold themselves on first launch.
24
+ - **Session lifecycle hooks** - agent profiles and guidance files install themselves on first launch.
25
25
 
26
26
  ## Prerequisites
27
27
 
@@ -93,7 +93,7 @@ pi install npm:@juicesharp/rpiv-pi
93
93
  On first Pi Agent session start, rpiv-pi automatically:
94
94
  - Copies agent profiles to `~/.pi/agent/agents/` (user-global, shared across all projects)
95
95
  - Detects outdated or removed agents on subsequent starts
96
- - Scaffolds `thoughts/shared/` directories for pipeline artifacts
96
+ - Migrates legacy pipeline-artifact content into `.rpiv/artifacts/` (one-way) when an old `thoughts/shared/` tree is found; otherwise `.rpiv/artifacts/` is created lazily by the first skill that writes an artifact
97
97
  - Shows a warning if any sibling plugins are missing
98
98
 
99
99
  ## Usage
@@ -102,10 +102,10 @@ On first Pi Agent session start, rpiv-pi automatically:
102
102
 
103
103
  ```
104
104
  /skill:discover "add a /skill:fast that runs research+design+plan in one shot"
105
- /skill:research thoughts/shared/discover/<latest>.md
106
- /skill:design thoughts/shared/research/<latest>.md
107
- /skill:plan thoughts/shared/designs/<latest>.md
108
- /skill:implement thoughts/shared/plans/<latest>.md Phase <N>
105
+ /skill:research .rpiv/artifacts/discover/<latest>.md
106
+ /skill:design .rpiv/artifacts/research/<latest>.md
107
+ /skill:plan .rpiv/artifacts/designs/<latest>.md
108
+ /skill:implement .rpiv/artifacts/plans/<latest>.md Phase <N>
109
109
  ```
110
110
 
111
111
  Each skill produces an artifact consumed by the next. Run them in order, or jump in at any stage if you already have the input artifact.
@@ -114,14 +114,14 @@ Each skill produces an artifact consumed by the next. Run them in order, or jump
114
114
 
115
115
  Skills compose. Pick the entry point that matches your intent:
116
116
 
117
- - **Capture intent before research** - `/skill:discover "[feature description]"`. Walks you through a one-question-at-a-time interview to settle Goals/Non-Goals, Functional/Non-Functional Requirements, Acceptance Criteria, and a Decisions log into a Feature Requirements Document under `thoughts/shared/discover/`. Use as the canonical entry point of the pipeline before research, or to stress-test a feature idea before any codebase work. The FRD's Decisions are inherited by `design` through `research`'s Developer Context.
118
- - **Form context before a task** - `/skill:research "[topic]"` (or `/skill:research thoughts/shared/discover/<latest>.md` if you ran discover first). Produces a high-signal subspace of the codebase relevant to your topic, ready to feed directly into the next prompt. The `scope-tracer` subagent runs in-band to formulate trace-quality questions before analysis dispatch; when chained from discover, FRD Decisions translate into Developer Context Q/A entries verbatim.
117
+ - **Capture intent before research** - `/skill:discover "[feature description]"`. Walks you through a one-question-at-a-time interview to settle Goals/Non-Goals, Functional/Non-Functional Requirements, Acceptance Criteria, and a Decisions log into a Feature Requirements Document under `.rpiv/artifacts/discover/`. Use as the canonical entry point of the pipeline before research, or to stress-test a feature idea before any codebase work. The FRD's Decisions are inherited by `design` through `research`'s Developer Context.
118
+ - **Form context before a task** - `/skill:research "[topic]"` (or `/skill:research .rpiv/artifacts/discover/<latest>.md` if you ran discover first). Produces a high-signal subspace of the codebase relevant to your topic, ready to feed directly into the next prompt. The `scope-tracer` subagent runs in-band to formulate trace-quality questions before analysis dispatch; when chained from discover, FRD Decisions translate into Developer Context Q/A entries verbatim.
119
119
  - **Compare approaches before designing** - `/skill:explore "[problem]"` → `/skill:design <solutions artifact>`. Use when multiple valid solutions exist; the solutions artifact is a first-class input to `design` alongside a `research` artifact.
120
120
  - **One-shot plan from research** - `/skill:research <questions>` → `/skill:blueprint <research artifact>` → `/skill:implement`. Fuses `design` + `plan` into a single pass with the same slice-by-slice rigor, but spawns only `codebase-pattern-finder` upfront (vs `design`'s 4-agent fan-out) by trusting the research artifact's integration/precedent sections. Use for solo work or when no one else needs to review the design before implementation; pick `design` → `plan` when the design is itself a deliverable or when research is thin and you want the fuller verification sweep.
121
121
  - **Full feature build** - `/skill:discover` → `research` → `design` → `plan` → `implement` → `validate` → (`code-review` ↔ `commit`). The default pipeline; jump in at any stage if you already have the input artifact.
122
- - **Investigate a bug** - `/skill:discover "why does X fail"` → `/skill:research thoughts/shared/discover/<latest>.md`. The discover interview surfaces what you actually want to know before research grounds it; fix from research output without writing a plan when the change is small.
122
+ - **Investigate a bug** - `/skill:discover "why does X fail"` → `/skill:research .rpiv/artifacts/discover/<latest>.md`. The discover interview surfaces what you actually want to know before research grounds it; fix from research output without writing a plan when the change is small.
123
123
  - **Adjust mid-implementation** - `/skill:revise <plan artifact>` → resume `/skill:implement`. Use when new constraints land after the plan is drafted.
124
- - **Review before shipping** - `/skill:code-review` ↔ `/skill:commit`. Order is your call: review `staged`/`working` before committing to catch issues at the smallest blast radius, or commit first and review the resulting branch (empty scope defaults to feature-branch-vs-default-branch, first-parent). Produces a Quality/Security/Dependencies artifact under `thoughts/shared/reviews/` with claim-verifier-grounded findings and `status: approved | needs_changes`.
124
+ - **Review before shipping** - `/skill:code-review` ↔ `/skill:commit`. Order is your call: review `staged`/`working` before committing to catch issues at the smallest blast radius, or commit first and review the resulting branch (empty scope defaults to feature-branch-vs-default-branch, first-parent). Produces a Quality/Security/Dependencies artifact under `.rpiv/artifacts/reviews/` with claim-verifier-grounded findings and `status: approved | needs_changes`.
125
125
  - **Audit a specific scope** - `/skill:code-review <commit|staged|working|hash|A..B|branch>`. Targeted lenses over a commit, range, staged/working tree, or PR branch; advisor adjudication applies when configured (`/advisor`).
126
126
  - **Review-driven plan revision** - `/skill:code-review` → `/skill:revise <plan artifact>` → resume `/skill:implement`. When a mid-stream review surfaces structural findings that the existing plan can't absorb as spot fixes.
127
127
  - **Scaffold manual UI test specs** - `/skill:outline-test-cases` → `/skill:write-test-cases <feature>`. Outline first via Frontend-First Discovery to map project scope and avoid duplicate coverage, then generate flow-based manual test cases (with a regression suite) under `.rpiv/test-cases/<feature>/`.
@@ -136,17 +136,17 @@ Invoke via `/skill:<name>` from inside a Pi Agent session.
136
136
 
137
137
  | Skill | Input | Output | Description |
138
138
  |---|---|---|---|
139
- | `discover` | Free-text feature description or existing artifact path | `thoughts/shared/discover/` | Interview-driven Feature Requirements Document producer; one question at a time with a recommended answer at every step. FRD Decisions inherited by `design` via `research`'s Developer Context |
140
- | `research` | Free-text prompt or `discover` artifact path | `thoughts/shared/research/` | Frame scope via the `scope-tracer` subagent, then answer via parallel analysis agents |
141
- | `explore` | - | `thoughts/shared/solutions/` | Compare solution approaches with pros/cons |
142
- | `design` | Research or solutions artifact | `thoughts/shared/designs/` | Design features via vertical-slice decomposition |
139
+ | `discover` | Free-text feature description or existing artifact path | `.rpiv/artifacts/discover/` | Interview-driven Feature Requirements Document producer; one question at a time with a recommended answer at every step. FRD Decisions inherited by `design` via `research`'s Developer Context |
140
+ | `research` | Free-text prompt or `discover` artifact path | `.rpiv/artifacts/research/` | Frame scope via the `scope-tracer` subagent, then answer via parallel analysis agents |
141
+ | `explore` | - | `.rpiv/artifacts/solutions/` | Compare solution approaches with pros/cons |
142
+ | `design` | Research or solutions artifact | `.rpiv/artifacts/designs/` | Design features via vertical-slice decomposition |
143
143
 
144
144
  #### Implementation
145
145
 
146
146
  | Skill | Input | Output | Description |
147
147
  |---|---|---|---|
148
- | `plan` | Design artifact | `thoughts/shared/plans/` | Create phased implementation plans |
149
- | `blueprint` | Research or solutions artifact | `thoughts/shared/plans/` | Fused `design` + `plan`: vertical-slice decomposition with micro-checkpoints, emits implement-ready phased plan in one pass. Lighter on subagent fan-out than `design` - trusts the research artifact's integration/precedent sections instead of re-dispatching. Use when a separate design artifact isn't needed for review or handoff |
148
+ | `plan` | Design artifact | `.rpiv/artifacts/plans/` | Create phased implementation plans |
149
+ | `blueprint` | Research or solutions artifact | `.rpiv/artifacts/plans/` | Fused `design` + `plan`: vertical-slice decomposition with micro-checkpoints, emits implement-ready phased plan in one pass. Lighter on subagent fan-out than `design` - trusts the research artifact's integration/precedent sections instead of re-dispatching. Use when a separate design artifact isn't needed for review or handoff |
150
150
  | `implement` | Plan artifact | Code changes | Execute plans phase by phase |
151
151
  | `revise` | Plan artifact | Updated plan | Revise plans based on feedback |
152
152
  | `validate` | Plan artifact | Validation report | Verify plan execution |
@@ -202,8 +202,8 @@ Agents are dispatched automatically by skills via the `Agent` tool - you don't i
202
202
  | `peer-comparator` | Compares a new file against a peer sibling and tags each invariant Mirrored / Missing / Diverged / Intentionally-absent |
203
203
  | `precedent-locator` | Finds similar past changes in git history - commits, blast radius, and follow-up fixes |
204
204
  | `test-case-locator` | Catalogs existing manual test cases under `.rpiv/test-cases/` and reports coverage stats |
205
- | `thoughts-analyzer` | Performs deep-dive analysis on a research topic in `thoughts/` |
206
- | `thoughts-locator` | Discovers relevant documents in the `thoughts/` directory |
205
+ | `artifacts-analyzer` | Performs deep-dive analysis on a research topic in `.rpiv/artifacts/` |
206
+ | `artifacts-locator` | Discovers relevant documents in the `.rpiv/artifacts/` directory |
207
207
  | `web-search-researcher` | Researches modern web-only information via deep search and fetch |
208
208
 
209
209
  ## Architecture
@@ -213,7 +213,7 @@ rpiv-pi/
213
213
  ├── extensions/rpiv-core/ - runtime extension: hooks, commands, guidance injection
214
214
  ├── skills/ - AI workflow skills (research → design → plan → implement)
215
215
  ├── agents/ - named subagent profiles dispatched by skills
216
- └── thoughts/shared/ - pipeline artifact store
216
+ └── .rpiv/artifacts/ - pipeline artifact store
217
217
  ```
218
218
 
219
219
  Pi Agent discovers extensions via `"extensions": ["./extensions"]` and skills via `"skills": ["./skills"]` in `package.json`.
@@ -1,11 +1,11 @@
1
1
  ---
2
- name: thoughts-analyzer
2
+ name: artifacts-analyzer
3
3
  description: The research equivalent of codebase-analyzer. Use this subagent_type when wanting to deep dive on a research topic. Not commonly needed otherwise.
4
4
  tools: read, grep, find, ls
5
5
  isolated: true
6
6
  ---
7
7
 
8
- You are a specialist at extracting HIGH-VALUE insights from thoughts documents. Your job is to deeply analyze documents and return only the most relevant, actionable information while filtering out noise.
8
+ You are a specialist at extracting HIGH-VALUE insights from .rpiv/artifacts/ documents. Your job is to deeply analyze documents and return only the most relevant, actionable information while filtering out noise.
9
9
 
10
10
  ## Core Responsibilities
11
11
 
@@ -113,28 +113,6 @@ Structure your analysis like this:
113
113
  - It's too vague to action
114
114
  - It's redundant with better sources
115
115
 
116
- ## Example Transformation
117
-
118
- ### From Document:
119
- "I've been thinking about rate limiting and there are so many options. We could use Redis, or maybe in-memory, or perhaps a distributed solution. Redis seems nice because it's battle-tested, but adds a dependency. In-memory is simple but doesn't work for multiple instances. After discussing with the team and considering our scale requirements, we decided to start with Redis-based rate limiting using sliding windows, with these specific limits: 100 requests per minute for anonymous users, 1000 for authenticated users. We'll revisit if we need more granular controls. Oh, and we should probably think about websockets too at some point."
120
-
121
- ### To Analysis:
122
- ```
123
- ### Key Decisions
124
- 1. **Rate Limiting Implementation**: Redis-based with sliding windows
125
- - Rationale: Battle-tested, works across multiple instances
126
- - Trade-off: Chose external dependency over in-memory simplicity
127
-
128
- ### Technical Specifications
129
- - Anonymous users: 100 requests/minute
130
- - Authenticated users: 1000 requests/minute
131
- - Algorithm: Sliding window
132
-
133
- ### Still Open/Unclear
134
- - Websocket rate limiting approach
135
- - Granular per-endpoint controls
136
- ```
137
-
138
116
  ## Important Guidelines
139
117
 
140
118
  - **Be skeptical** - Not everything written is valuable
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: artifacts-locator
3
+ description: Finds relevant documents in .rpiv/artifacts/. The research equivalent of codebase-locator. Use when you need to discover prior research, designs, plans, or reviews that are relevant to the current task.
4
+ tools: grep, find, ls
5
+ isolated: true
6
+ ---
7
+
8
+ You are a specialist at finding documents in the .rpiv/artifacts/ directory. Your job is to locate relevant artifact documents and categorize them, NOT to analyze their contents in depth.
9
+
10
+ ## Core Responsibilities
11
+
12
+ 1. **Search .rpiv/artifacts/ directory structure**
13
+ - Check .rpiv/artifacts/ for pipeline artifacts
14
+
15
+ 2. **Categorize findings by type**
16
+ - Research documents (in research/) — codebase analysis, patterns, dependencies
17
+ - Solution analyses (in solutions/) — multi-approach comparisons with recommendations
18
+ - Design artifacts (in designs/) — architectural designs with implementation signatures
19
+ - Implementation plans (in plans/) — phased plans with success criteria
20
+ - Code reviews (in reviews/) — code quality and compliance reviews
21
+ - Handoff documents (in handoffs/) — session context snapshots for resumption
22
+ - FRD documents (in discover/) — feature requirements from discover skill
23
+ - General notes and discussions
24
+
25
+ 3. **Return organized results**
26
+ - Group by document type
27
+ - Include brief one-line description from title/header
28
+ - Note document dates if visible in filename
29
+
30
+ ## Search Strategy
31
+
32
+ First, think deeply about the search approach - consider which directories to prioritize based on the query, what search patterns and synonyms to use, and how to best categorize the findings for the user.
33
+
34
+ ### Directory Structure
35
+ ```
36
+ .rpiv/artifacts/
37
+ ├── discover/ # Feature requirements documents (FRDs)
38
+ ├── research/ # Codebase analysis, patterns, dependencies
39
+ ├── solutions/ # Multi-approach comparisons with recommendations
40
+ ├── designs/ # Architectural designs with implementation signatures
41
+ ├── plans/ # Phased implementation plans, success criteria
42
+ ├── handoffs/ # Session context snapshots for resumption
43
+ ├── reviews/ # Code quality and compliance reviews
44
+ └── tickets/ # Ticket documentation
45
+ ```
46
+
47
+ ### Search Patterns
48
+ - Use grep for content searching
49
+ - Use glob for filename patterns
50
+ - Check standard subdirectories
51
+
52
+ ## Output Format
53
+
54
+ Structure your findings like this:
55
+
56
+ ```
57
+ ## Artifact Documents about {Topic}
58
+
59
+ ### FRD Documents
60
+ - `.rpiv/artifacts/discover/2026-05-17_13-29-24_rate-limiting.md` - Rate limit configuration FRD
61
+
62
+ ### Research Documents
63
+ - `.rpiv/artifacts/research/2026-01-15_10-45-00_rate-limiting-approaches.md` - Research on rate limiting strategies
64
+ - tags: [research, codebase, rate-limiting, api]
65
+
66
+ ### Solution Analyses
67
+ - `.rpiv/artifacts/solutions/2026-01-16_14-30-00_rate-limiting-strategies.md` - Comparison of Redis vs in-memory vs distributed approaches
68
+
69
+ ### Design Artifacts
70
+ - `.rpiv/artifacts/designs/2026-01-17_09-00-00_rate-limiter-design.md` - Architectural design for sliding window rate limiter
71
+ - parent: `.rpiv/artifacts/research/2026-01-15_10-45-00_rate-limiting-approaches.md`
72
+
73
+ ### Implementation Plans
74
+ - `.rpiv/artifacts/plans/2026-01-18_11-20-00_rate-limiter-implementation.md` - Phased plan for rate limits
75
+ - parent: `.rpiv/artifacts/designs/2026-01-17_09-00-00_rate-limiter-design.md`
76
+
77
+ ### Code Reviews
78
+ - `.rpiv/artifacts/reviews/2026-01-25_16-00-00_rate-limiter-review.md` - Review of rate limiting implementation
79
+
80
+ ### Handoff Documents
81
+ - `.rpiv/artifacts/handoffs/2026-01-20_17-30-00_rate-limiter-handoff.md` - Session snapshot: rate limiter phase 1 complete
82
+
83
+ Total: 7 relevant documents found
84
+ Artifact chain: research → design → plan (3 linked documents)
85
+ ```
86
+
87
+ ## Search Tips
88
+
89
+ 1. **Use multiple search terms**:
90
+ - Technical terms: "rate limit", "throttle", "quota"
91
+ - Component names: "RateLimiter", "throttling"
92
+ - Related concepts: "429", "too many requests"
93
+
94
+ 2. **Check all artifact subdirectories**:
95
+ - Each subdirectory corresponds to a pipeline stage
96
+ - Don't skip directories — relevant artifacts can appear at any stage
97
+
98
+ 3. **Look for patterns**:
99
+ - Skill-generated files use `YYYY-MM-DD_HH-MM-SS_topic.md` naming
100
+ - Documents have YAML frontmatter with searchable `topic:`, `tags:`, `status:`, `parent:` fields
101
+
102
+ 4. **Follow artifact chains**:
103
+ - Research → Solutions → Designs → Plans → Reviews → Handoffs
104
+ - Check `parent:` in frontmatter to find related documents
105
+ - When you find one artifact, look for upstream/downstream artifacts on the same topic
106
+
107
+ ## Important Guidelines
108
+
109
+ - **Don't read full file contents** - Just scan for relevance
110
+ - **Preserve directory structure** - Show where documents live
111
+ - **Be thorough** - Check all relevant subdirectories
112
+ - **Group logically** - Make categories meaningful
113
+ - **Note patterns** - Help user understand naming conventions
114
+
115
+ ## What NOT to Do
116
+
117
+ - Don't analyze document contents deeply
118
+ - Don't make judgments about document quality
119
+ - Don't skip subdirectories
120
+ - Don't ignore old documents
121
+
122
+ Remember: You're a document finder for the .rpiv/artifacts/ directory. Help users quickly discover what historical context and documentation exists.
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: precedent-locator
3
- description: "Finds similar past changes in git history: commits, blast radius, follow-up fixes, and lessons from related thoughts/ docs. Use when planning a change and you need to know what went wrong last time something similar was done."
3
+ description: "Finds similar past changes in git history: commits, blast radius, follow-up fixes, and lessons from related .rpiv/artifacts/ docs. Use when planning a change and you need to know what went wrong last time something similar was done."
4
4
  tools: bash, grep, find, read, ls
5
5
  isolated: true
6
6
  ---
7
7
 
8
- You are a specialist at finding PRECEDENTS for planned changes. Your job is to mine git history and thoughts/ documents to find the most similar past changes, extract what happened, and surface lessons that help a planner avoid repeating mistakes.
8
+ You are a specialist at finding PRECEDENTS for planned changes. Your job is to mine git history and .rpiv/artifacts/ documents to find the most similar past changes, extract what happened, and surface lessons that help a planner avoid repeating mistakes.
9
9
 
10
10
  ## Pre-flight: Git Availability Check
11
11
 
@@ -16,7 +16,7 @@ git rev-parse --is-inside-work-tree 2>/dev/null
16
16
 
17
17
  **If this fails (not a git repo):**
18
18
  - Skip all git-based searches (Steps 2 and 3 of Search Strategy)
19
- - Still search thoughts/ for lessons (Step 4 — Grep/Glob-based, works without git)
19
+ - Still search .rpiv/artifacts/ for lessons (Step 4 — Grep/Glob-based, works without git)
20
20
  - Return this format:
21
21
 
22
22
  ```
@@ -25,7 +25,7 @@ git rev-parse --is-inside-work-tree 2>/dev/null
25
25
  **No git history available** — not a git repository.
26
26
 
27
27
  ### Lessons from Documentation
28
- {Findings from thoughts/, or "No relevant documents found"}
28
+ {Findings from .rpiv/artifacts/, or "No relevant documents found"}
29
29
 
30
30
  ### Composite Lessons
31
31
  - No git-based lessons available
@@ -48,7 +48,7 @@ git rev-parse --is-inside-work-tree 2>/dev/null
48
48
  - Identify what broke and how quickly it was discovered
49
49
 
50
50
  4. **Extract lessons from docs**
51
- - Search thoughts/ for plans, research, or bug analyses related to each precedent
51
+ - Search .rpiv/artifacts/ for plans, research, or bug analyses related to each precedent
52
52
  - Read relevant documents to extract key lessons and warnings
53
53
 
54
54
  5. **Distill composite lessons**
@@ -73,7 +73,7 @@ git rev-parse --is-inside-work-tree 2>/dev/null
73
73
  - Look for fix/bug/hotfix keywords in follow-up commit messages
74
74
 
75
75
  ### Step 4: Correlate with Thoughts
76
- - `grep -r "keyword" thoughts/` to find related plans, research, bug analyses
76
+ - `grep -r "keyword" .rpiv/artifacts/` to find related plans, research, bug analyses
77
77
  - Read the most relevant documents to extract lessons
78
78
  - Check if plans documented risks that materialized as bugs
79
79
 
@@ -98,7 +98,7 @@ CRITICAL: Use EXACTLY this format. Be concise — commit hashes and dates are th
98
98
  - `hash` — "message" (date) — what went wrong
99
99
 
100
100
  **Lessons from docs**:
101
- - thoughts/path/to/doc.md — key lesson extracted
101
+ - .rpiv/artifacts/path/to/doc.md — key lesson extracted
102
102
 
103
103
  **Takeaway**: {one sentence — what to watch out for}
104
104
 
@@ -85,7 +85,7 @@ Using combined knowledge from Steps 1-4, write 5-10 dense paragraphs:
85
85
  - **Trace-quality** — names a complete path, not a generic theme
86
86
  - **>=3 code artifacts** per paragraph (file references, function names, type names)
87
87
 
88
- thoughts/ docs are NOT questions — surface them in the Discovery Summary, not as numbered items.
88
+ .rpiv/artifacts/ docs are NOT questions — surface them in the Discovery Summary, not as numbered items.
89
89
 
90
90
  Coverage check: every key file read in Step 4 appears in at least one question. Files read but absent from all questions indicate either an unnecessary read or a missing question.
91
91
 
@@ -101,7 +101,7 @@ CRITICAL: Use EXACTLY this format. The `research` skill parses this block — fr
101
101
  # Research Questions: how does the plugin system load and initialize extensions
102
102
 
103
103
  ## Discovery Summary
104
- Swept the plugin loader and lifecycle anchors across `src/plugins/`. Key files for depth: `src/plugins/types.ts:8-30` (definition — PluginManifest interface), `src/plugins/registry.ts:23` (entry — scan + manifest validation), `src/plugins/loader.ts:45` (factory — instantiation), `src/plugins/lifecycle.ts:12-44` (contract — hook ordering), `tests/plugins/registry.test.ts` (coverage). Two thoughts/ docs surfaced: `thoughts/shared/research/2026-03-12_plugin-architecture.md` (prior architectural decisions) and `thoughts/shared/plans/2026-04-01_plugin-lifecycle-extension.md` (recent lifecycle hook addition). The shape is a synchronous scan + lazy instantiate + lifecycle-hook chain pattern; no async loaders or hot-reload paths found.
104
+ Swept the plugin loader and lifecycle anchors across `src/plugins/`. Key files for depth: `src/plugins/types.ts:8-30` (definition — PluginManifest interface), `src/plugins/registry.ts:23` (entry — scan + manifest validation), `src/plugins/loader.ts:45` (factory — instantiation), `src/plugins/lifecycle.ts:12-44` (contract — hook ordering), `tests/plugins/registry.test.ts` (coverage). Two .rpiv/artifacts/ docs surfaced: `.rpiv/artifacts/research/2026-03-12_plugin-architecture.md` (prior architectural decisions) and `.rpiv/artifacts/plans/2026-04-01_plugin-lifecycle-extension.md` (recent lifecycle hook addition). The shape is a synchronous scan + lazy instantiate + lifecycle-hook chain pattern; no async loaders or hot-reload paths found.
105
105
 
106
106
  ## Questions
107
107
 
@@ -118,7 +118,7 @@ Swept the plugin loader and lifecycle anchors across `src/plugins/`. Key files f
118
118
  - **Don't make recommendations** — no "we should…", no architectural advice; that's `design` / `blueprint` territory
119
119
  - **Don't read more than 10 files in Step 4** — context budget is real; rank ruthlessly
120
120
  - **Don't synthesize generic titles** — every question must cite >=3 specific files / functions / types; vague themes are too thin
121
- - **Don't include thoughts/ docs as numbered questions** — surface them in the Discovery Summary; numbered questions are about live code paths
121
+ - **Don't include .rpiv/artifacts/ docs as numbered questions** — surface them in the Discovery Summary; numbered questions are about live code paths
122
122
  - **Don't write any file** — the artifact body lives in your final assistant message; the calling skill parses it in-memory
123
123
  - **Don't dispatch other agents** — `Agent` is not in the allowlist by design; the anchor sweep is sequential within this agent's own toolkit
124
124
 
@@ -32,6 +32,7 @@ const AGENTS_MD = "AGENTS.md";
32
32
  const CLAUDE_MD = "CLAUDE.md";
33
33
  const RPIV_DIR = ".rpiv";
34
34
  const GUIDANCE_SUBDIR = "guidance";
35
+ export const ARTIFACTS_SUBDIR = "artifacts";
35
36
  const ARCHITECTURE_MD = "architecture.md";
36
37
  /** Forward-slash dedup key for root guidance — must NOT use join() for cross-platform compat. */
37
38
  const ROOT_GUIDANCE_KEY = `${RPIV_DIR}/${GUIDANCE_SUBDIR}/${ARCHITECTURE_MD}`;
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdtempSync, rmSync } from "node:fs";
1
+ import { chmodSync, existsSync, mkdirSync, mkdtempSync, rmSync, statSync, writeFileSync } from "node:fs";
2
2
  import { homedir, tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { createMockCtx, createMockPi, stubGitExec } from "@juicesharp/rpiv-test-utils";
@@ -65,22 +65,128 @@ describe("registerSessionHooks — event wiring", () => {
65
65
  });
66
66
  });
67
67
 
68
- describe("session_start hook", () => {
69
- it("scaffolds thoughts dirs under ctx.cwd", async () => {
68
+ describe("session_start hook — migration", () => {
69
+ it("does NOT create .rpiv/artifacts/ on fresh project (no migration source) — issue #31", async () => {
70
70
  const { pi, captured } = createMockPi({ exec: stubGitExec({}) as never });
71
71
  registerSessionHooks(pi);
72
72
  const handler = captured.events.get("session_start")?.[0];
73
73
  const ctx = createMockCtx({ cwd: projectDir, hasUI: true });
74
74
  await handler?.({ reason: "startup" } as never, ctx as never);
75
- for (const d of [
76
- "thoughts/shared/discover",
77
- "thoughts/shared/research",
78
- "thoughts/shared/designs",
79
- "thoughts/shared/plans",
80
- "thoughts/shared/handoffs",
81
- "thoughts/shared/reviews",
82
- ]) {
83
- expect(existsSync(join(projectDir, d))).toBe(true);
75
+ expect(existsSync(join(projectDir, ".rpiv", "artifacts"))).toBe(false);
76
+ });
77
+
78
+ it("migrates thoughts/shared/ to .rpiv/artifacts/ with content preservation", async () => {
79
+ const oldResearch = join(projectDir, "thoughts", "shared", "research");
80
+ mkdirSync(oldResearch, { recursive: true });
81
+ writeFileSync(join(oldResearch, "test.md"), "# Test Research");
82
+
83
+ const { pi, captured } = createMockPi({ exec: stubGitExec({}) as never });
84
+ registerSessionHooks(pi);
85
+ const handler = captured.events.get("session_start")?.[0];
86
+ const ctx = createMockCtx({ cwd: projectDir, hasUI: true });
87
+ await handler?.({ reason: "startup" } as never, ctx as never);
88
+
89
+ // Content preserved
90
+ expect(existsSync(join(projectDir, ".rpiv", "artifacts", "research", "test.md"))).toBe(true);
91
+ // Old dir removed
92
+ expect(existsSync(join(projectDir, "thoughts", "shared"))).toBe(false);
93
+ // thoughts/ root removed (was empty after shared/ deleted)
94
+ expect(existsSync(join(projectDir, "thoughts"))).toBe(false);
95
+ });
96
+
97
+ it("preserves thoughts/ root when non-shared content exists", async () => {
98
+ const oldResearch = join(projectDir, "thoughts", "shared", "research");
99
+ mkdirSync(oldResearch, { recursive: true });
100
+ writeFileSync(join(oldResearch, "test.md"), "content");
101
+ const meDir = join(projectDir, "thoughts", "me");
102
+ mkdirSync(meDir, { recursive: true });
103
+ writeFileSync(join(meDir, "notes.md"), "personal");
104
+
105
+ const { pi, captured } = createMockPi({ exec: stubGitExec({}) as never });
106
+ registerSessionHooks(pi);
107
+ const handler = captured.events.get("session_start")?.[0];
108
+ const ctx = createMockCtx({ cwd: projectDir, hasUI: true });
109
+ await handler?.({ reason: "startup" } as never, ctx as never);
110
+
111
+ expect(existsSync(join(projectDir, ".rpiv", "artifacts", "research", "test.md"))).toBe(true);
112
+ expect(existsSync(join(projectDir, "thoughts", "shared"))).toBe(false);
113
+ expect(existsSync(join(projectDir, "thoughts", "me", "notes.md"))).toBe(true);
114
+ expect(existsSync(join(projectDir, "thoughts"))).toBe(true);
115
+ });
116
+
117
+ it("does NOT create .rpiv/artifacts/ when thoughts/shared/ exists but is empty", async () => {
118
+ // Edge case: thoughts/shared/ pre-exists (created by tool, partial migration, etc.) but holds no entries.
119
+ // Migration must not leak an empty .rpiv/artifacts/ tree, and must not delete the empty source.
120
+ mkdirSync(join(projectDir, "thoughts", "shared"), { recursive: true });
121
+
122
+ const { pi, captured } = createMockPi({ exec: stubGitExec({}) as never });
123
+ registerSessionHooks(pi);
124
+ const handler = captured.events.get("session_start")?.[0];
125
+ const ctx = createMockCtx({ cwd: projectDir, hasUI: true });
126
+ await handler?.({ reason: "startup" } as never, ctx as never);
127
+
128
+ expect(existsSync(join(projectDir, ".rpiv", "artifacts"))).toBe(false);
129
+ expect(existsSync(join(projectDir, "thoughts", "shared"))).toBe(true);
130
+ });
131
+
132
+ it("preserves loose files at thoughts/shared/ root (copies them, not just subdirectories)", async () => {
133
+ // Regression: prior implementation filtered to directories only, dropping loose .md files
134
+ // at the shared/ root on rmSync. Now cpSync copies both files and directories.
135
+ const oldShared = join(projectDir, "thoughts", "shared");
136
+ mkdirSync(oldShared, { recursive: true });
137
+ writeFileSync(join(oldShared, "loose.md"), "loose content");
138
+ const oldResearch = join(oldShared, "research");
139
+ mkdirSync(oldResearch, { recursive: true });
140
+ writeFileSync(join(oldResearch, "nested.md"), "nested content");
141
+
142
+ const { pi, captured } = createMockPi({ exec: stubGitExec({}) as never });
143
+ registerSessionHooks(pi);
144
+ const handler = captured.events.get("session_start")?.[0];
145
+ const ctx = createMockCtx({ cwd: projectDir, hasUI: true });
146
+ await handler?.({ reason: "startup" } as never, ctx as never);
147
+
148
+ expect(existsSync(join(projectDir, ".rpiv", "artifacts", "loose.md"))).toBe(true);
149
+ expect(existsSync(join(projectDir, ".rpiv", "artifacts", "research", "nested.md"))).toBe(true);
150
+ expect(existsSync(join(projectDir, "thoughts"))).toBe(false);
151
+ });
152
+
153
+ it("no-ops when thoughts/shared/ does not exist (fresh project)", async () => {
154
+ const { pi, captured } = createMockPi({ exec: stubGitExec({}) as never });
155
+ registerSessionHooks(pi);
156
+ const handler = captured.events.get("session_start")?.[0];
157
+ const ctx = createMockCtx({ cwd: projectDir, hasUI: true });
158
+ await handler?.({ reason: "startup" } as never, ctx as never);
159
+
160
+ // No migration source → no .rpiv/artifacts/ tree, no thoughts/ tree
161
+ expect(existsSync(join(projectDir, ".rpiv", "artifacts"))).toBe(false);
162
+ expect(existsSync(join(projectDir, "thoughts"))).toBe(false);
163
+ });
164
+
165
+ it.skipIf(process.platform === "win32")("never crashes session_start even when migration step fails", async () => {
166
+ // ESM module namespaces are not configurable under this Vitest config
167
+ // (see agents.test.ts Q7), so induce the failure at the filesystem layer:
168
+ // chmod 0o000 on thoughts/shared makes the inner readdirSync throw EACCES,
169
+ // hitting the migration's catch block.
170
+ const sharedDir = join(projectDir, "thoughts", "shared");
171
+ const oldResearch = join(sharedDir, "research");
172
+ mkdirSync(oldResearch, { recursive: true });
173
+ writeFileSync(join(oldResearch, "test.md"), "content");
174
+
175
+ const originalMode = statSync(sharedDir).mode & 0o777;
176
+ chmodSync(sharedDir, 0o000);
177
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
178
+
179
+ try {
180
+ const { pi, captured } = createMockPi({ exec: stubGitExec({}) as never });
181
+ registerSessionHooks(pi);
182
+ const handler = captured.events.get("session_start")?.[0];
183
+ const ctx = createMockCtx({ cwd: projectDir, hasUI: true });
184
+ // Must not throw — migration is best-effort
185
+ await expect(handler?.({ reason: "startup" } as never, ctx as never)).resolves.toBeUndefined();
186
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("migration"));
187
+ } finally {
188
+ chmodSync(sharedDir, originalMode);
189
+ warnSpy.mockRestore();
84
190
  }
85
191
  });
86
192
  });
@@ -5,7 +5,7 @@
5
5
  * Ordering and invariants preserved verbatim from the pre-refactor index.ts.
6
6
  */
7
7
 
8
- import { mkdirSync } from "node:fs";
8
+ import { cpSync, existsSync, mkdirSync, readdirSync, rmSync } from "node:fs";
9
9
  import { join } from "node:path";
10
10
  import {
11
11
  type ExtensionAPI,
@@ -27,18 +27,9 @@ import {
27
27
  resetInjectedMarker,
28
28
  takeGitContextIfChanged,
29
29
  } from "./git-context.js";
30
- import { clearInjectionState, handleToolCallGuidance, injectRootGuidance } from "./guidance.js";
30
+ import { ARTIFACTS_SUBDIR, clearInjectionState, handleToolCallGuidance, injectRootGuidance } from "./guidance.js";
31
31
  import { findMissingSiblings } from "./package-checks.js";
32
32
 
33
- const THOUGHTS_DIRS = [
34
- "thoughts/shared/discover",
35
- "thoughts/shared/research",
36
- "thoughts/shared/designs",
37
- "thoughts/shared/plans",
38
- "thoughts/shared/handoffs",
39
- "thoughts/shared/reviews",
40
- ] as const;
41
-
42
33
  const msgAgentsAdded = (n: number) => `Copied ${n} rpiv-pi agent(s) to ~/.pi/agent/agents/`;
43
34
  const msgAgentsHealed = (parts: string[]) => `Synced bundled agent(s): ${parts.join(", ")}.`;
44
35
  const msgAgentsDrift = (parts: string[]) => `${parts.join(", ")} agent(s). Run /rpiv-update-agents to sync.`;
@@ -83,7 +74,7 @@ async function onSessionStart(
83
74
  ): Promise<void> {
84
75
  resetInjectionState();
85
76
  injectRootGuidance(ctx.cwd, pi);
86
- scaffoldThoughtsDirs(ctx.cwd);
77
+ migrateThoughtsToArtifacts(ctx.cwd);
87
78
  await injectGitContext(pi, (msg) => sendGitContextMessage(pi, msg));
88
79
  const cleanup = cleanupPerCwdAgents(ctx.cwd);
89
80
  const agents = syncBundledAgents(false);
@@ -131,9 +122,42 @@ function resetInjectionState(): void {
131
122
  clearInjectionState();
132
123
  }
133
124
 
134
- function scaffoldThoughtsDirs(cwd: string): void {
135
- for (const dir of THOUGHTS_DIRS) {
136
- mkdirSync(join(cwd, dir), { recursive: true });
125
+ function migrateThoughtsToArtifacts(cwd: string): void {
126
+ const oldShared = join(cwd, "thoughts", "shared");
127
+ if (!existsSync(oldShared)) return;
128
+
129
+ try {
130
+ const entries = readdirSync(oldShared, { withFileTypes: true });
131
+ if (entries.length === 0) return; // empty source — nothing to copy, leave on disk
132
+
133
+ const newArtifacts = join(cwd, ".rpiv", ARTIFACTS_SUBDIR);
134
+ mkdirSync(newArtifacts, { recursive: true });
135
+
136
+ for (const entry of entries) {
137
+ const src = join(oldShared, entry.name);
138
+ const dest = join(newArtifacts, entry.name);
139
+ cpSync(src, dest, { recursive: true, errorOnExist: false, force: true });
140
+ if (!existsSync(dest)) {
141
+ console.warn(`[rpiv-pi] migration: failed to copy ${src} → ${dest}`);
142
+ return; // abort — don't delete source if copy failed
143
+ }
144
+ }
145
+
146
+ // All copies verified — safe to remove source
147
+ rmSync(oldShared, { recursive: true, force: true });
148
+
149
+ // Remove thoughts/ root only if empty (preserves thoughts/me/ etc.)
150
+ const thoughtsRoot = join(cwd, "thoughts");
151
+ try {
152
+ if (readdirSync(thoughtsRoot).length === 0) {
153
+ rmSync(thoughtsRoot, { recursive: true, force: true });
154
+ }
155
+ } catch {
156
+ // thoughts/ already gone or unreadable — not an error
157
+ }
158
+ } catch (e) {
159
+ console.warn(`[rpiv-pi] migration: ${e instanceof Error ? e.message : String(e)}`);
160
+ // Never crash session_start — migration is best-effort
137
161
  }
138
162
  }
139
163
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juicesharp/rpiv-pi",
3
- "version": "1.8.1",
3
+ "version": "1.8.3",
4
4
  "description": "A skill-based development workflow for Pi Agent. Five skills (research, design, plan, implement, validate) and the shared subagents that compose its ship-loop.",
5
5
  "keywords": [
6
6
  "pi-package",