@juicesharp/rpiv-pi 1.13.0 → 1.14.0

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 (41) hide show
  1. package/README.md +0 -9
  2. package/extensions/rpiv-core/artifact-collector.ts +111 -0
  3. package/extensions/rpiv-core/built-in-workflows.test.ts +601 -0
  4. package/extensions/rpiv-core/built-in-workflows.ts +232 -0
  5. package/extensions/rpiv-core/index.ts +9 -1
  6. package/extensions/rpiv-core/paths.test.ts +58 -0
  7. package/extensions/rpiv-core/paths.ts +52 -0
  8. package/extensions/rpiv-core/session-hooks.test.ts +70 -1
  9. package/extensions/rpiv-core/session-hooks.ts +43 -19
  10. package/extensions/rpiv-core/siblings.test.ts +6 -2
  11. package/extensions/rpiv-core/siblings.ts +5 -0
  12. package/package.json +7 -2
  13. package/skills/architecture-review/SKILL.md +314 -0
  14. package/skills/architecture-review/templates/architecture-review.md +231 -0
  15. package/skills/blueprint/SKILL.md +13 -13
  16. package/skills/code-review/SKILL.md +2 -4
  17. package/skills/code-review/templates/review.md +0 -1
  18. package/skills/commit/SKILL.md +0 -2
  19. package/skills/create-handoff/SKILL.md +0 -3
  20. package/skills/design/SKILL.md +2 -4
  21. package/skills/discover/SKILL.md +2 -4
  22. package/skills/explore/SKILL.md +2 -4
  23. package/skills/implement/SKILL.md +12 -3
  24. package/skills/plan/SKILL.md +2 -4
  25. package/skills/research/SKILL.md +3 -5
  26. package/skills/revise/SKILL.md +16 -7
  27. package/skills/validate/SKILL.md +30 -43
  28. package/skills/validate/templates/validation.md +71 -0
  29. package/agents/test-case-locator.md +0 -121
  30. package/skills/outline-test-cases/SKILL.md +0 -377
  31. package/skills/outline-test-cases/templates/feature-meta.md +0 -50
  32. package/skills/outline-test-cases/templates/outline-readme.md +0 -36
  33. package/skills/write-test-cases/SKILL.md +0 -339
  34. package/skills/write-test-cases/examples/customer-auth-flow.md +0 -50
  35. package/skills/write-test-cases/examples/order-management-suite.md +0 -57
  36. package/skills/write-test-cases/examples/order-placement-flow.md +0 -54
  37. package/skills/write-test-cases/examples/team-management-flow.md +0 -56
  38. package/skills/write-test-cases/examples/team-management-suite.md +0 -54
  39. package/skills/write-test-cases/templates/coverage-map.md +0 -64
  40. package/skills/write-test-cases/templates/regression-suite.md +0 -63
  41. package/skills/write-test-cases/templates/test-case.md +0 -65
package/README.md CHANGED
@@ -121,7 +121,6 @@ Skills compose. Pick the entry point that matches your intent:
121
121
  - **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`.
122
122
  - **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`).
123
123
  - **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.
124
- - **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>/`.
125
124
  - **Hand off across sessions** - `/skill:create-handoff` → (new session) `/skill:resume-handoff <doc>`. Preserves context when stopping mid-task.
126
125
  - **Onboard a fresh repo** - `/skill:annotate-guidance` once, then use the rest of the pipeline normally. Use `annotate-inline` instead if the project follows the `CLAUDE.md` convention.
127
126
 
@@ -148,13 +147,6 @@ Invoke via `/skill:<name>` from inside a Pi Agent session.
148
147
  | `revise` | Plan artifact | Updated plan | Revise plans based on feedback |
149
148
  | `validate` | Plan artifact | Validation report | Verify plan execution |
150
149
 
151
- #### Testing
152
-
153
- | Skill | Input | Output | Description |
154
- |---|---|---|---|
155
- | `outline-test-cases` | - | `.rpiv/test-cases/` | Discover testable features with per-feature metadata |
156
- | `write-test-cases` | Outline metadata | Test case specs | Generate manual test specifications |
157
-
158
150
  #### Annotation
159
151
 
160
152
  | Skill | Input | Output | Description |
@@ -198,7 +190,6 @@ Agents are dispatched automatically by skills via the `Agent` tool - you don't i
198
190
  | `integration-scanner` | Maps inbound references, outbound dependencies, config registrations, and event subscriptions for a component |
199
191
  | `peer-comparator` | Compares a new file against a peer sibling and tags each invariant Mirrored / Missing / Diverged / Intentionally-absent |
200
192
  | `precedent-locator` | Finds similar past changes in git history - commits, blast radius, and follow-up fixes |
201
- | `test-case-locator` | Catalogs existing manual test cases under `.rpiv/test-cases/` and reports coverage stats |
202
193
  | `artifacts-analyzer` | Performs deep-dive analysis on a research topic in `.rpiv/artifacts/` |
203
194
  | `artifacts-locator` | Discovers relevant documents in the `.rpiv/artifacts/` directory |
204
195
  | `web-search-researcher` | Researches modern web-only information via deep search and fetch |
@@ -0,0 +1,111 @@
1
+ /**
2
+ * rpiv-flavoured artifact collection — the `.rpiv/artifacts/<bucket>/<file>.md`
3
+ * convention all rpiv-pi skills emit into. This module owns the
4
+ * convention; the framework (`@juicesharp/rpiv-workflow`) ships only
5
+ * the primitives (`ArtifactCollector`, `ArtifactParser`, handle
6
+ * constructors, `defineCollector`, etc.) and stays layout-agnostic.
7
+ *
8
+ * Two collectors:
9
+ * - `rpivArtifactCollector` — accepts any `.rpiv/artifacts/<bucket>/...md`
10
+ * path the agent announces in text (bucket-agnostic). Use when a
11
+ * stage may emit to several sibling subfolders.
12
+ * - `rpivBucketCollector(bucket)` — accepts only that one bucket's
13
+ * paths. Use when the stage MUST land in a specific subfolder
14
+ * (`research`, `plans`, etc.) — the collector halts the chain if the
15
+ * agent strayed.
16
+ *
17
+ * One parser: `frontmatterParser` parses YAML frontmatter from the
18
+ * primary fs artifact into `Record<string, unknown>` — what
19
+ * `outputSchema` validates against for typed downstream narrowing.
20
+ *
21
+ * Pre-bundled outcome: `rpivArtifactMdOutcome` =
22
+ * `{ collector: rpivArtifactCollector, parser: frontmatterParser }` —
23
+ * the default rpiv-pi's built-in workflows wire into every
24
+ * `produces()` stage.
25
+ */
26
+
27
+ import { existsSync, readFileSync } from "node:fs";
28
+ import { isAbsolute, join } from "node:path";
29
+ import { parseFrontmatter } from "@earendil-works/pi-coding-agent";
30
+ import {
31
+ type ArtifactCollector,
32
+ type ArtifactParser,
33
+ defineParser,
34
+ type OutputSpec,
35
+ type ParseCtx,
36
+ transcriptPathCollector,
37
+ } from "@juicesharp/rpiv-workflow";
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Collectors — text-scan over assistant transcript
41
+ // ---------------------------------------------------------------------------
42
+
43
+ const RPIV_ARTIFACT_PATTERN = /\.rpiv\/artifacts\/[\w.-]+\/[\w.-]+\.md/g;
44
+
45
+ /** Bucket-agnostic — accepts any `.rpiv/artifacts/<bucket>/...md`. */
46
+ export const rpivArtifactCollector: ArtifactCollector = transcriptPathCollector({ pattern: RPIV_ARTIFACT_PATTERN });
47
+
48
+ /** Bucket-narrowed — accepts only `.rpiv/artifacts/<bucket>/...md`. */
49
+ export function rpivBucketCollector(bucket: string): ArtifactCollector {
50
+ const escaped = bucket.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
51
+ const pattern = new RegExp(`\\.rpiv/artifacts/${escaped}/[\\w.-]+\\.md`, "g");
52
+ return transcriptPathCollector({ pattern });
53
+ }
54
+
55
+ // ---------------------------------------------------------------------------
56
+ // Parser — markdown frontmatter
57
+ // ---------------------------------------------------------------------------
58
+
59
+ /**
60
+ * Reads YAML frontmatter from the primary fs artifact. Files without
61
+ * frontmatter produce `data: {}`. Fatals when the announced path
62
+ * doesn't exist on disk (the agent claimed to write but didn't).
63
+ */
64
+ export const frontmatterParser: ArtifactParser<undefined, "artifact-md", Record<string, unknown>> = defineParser({
65
+ parse(ctx: ParseCtx<undefined>) {
66
+ const primary = ctx.artifacts[0];
67
+ if (primary?.handle.kind !== "fs") {
68
+ return {
69
+ kind: "fatal",
70
+ message: `${ctx.skill}: frontmatterParser requires an fs artifact (got ${primary?.handle.kind ?? "none"})`,
71
+ };
72
+ }
73
+ const abs = isAbsolute(primary.handle.path) ? primary.handle.path : join(ctx.cwd, primary.handle.path);
74
+ if (!existsSync(abs)) {
75
+ return {
76
+ kind: "fatal",
77
+ message: `agent announced ${primary.handle.path} but file does not exist on disk`,
78
+ };
79
+ }
80
+ const content = readFileSync(abs, "utf-8");
81
+ const { frontmatter } = parseFrontmatter(content);
82
+ return {
83
+ kind: "ok",
84
+ payload: {
85
+ kind: "artifact-md",
86
+ data: frontmatter && typeof frontmatter === "object" ? (frontmatter as Record<string, unknown>) : {},
87
+ },
88
+ };
89
+ },
90
+ });
91
+
92
+ // ---------------------------------------------------------------------------
93
+ // OutputSpec — pre-bundled wiring rpiv-pi workflows plug in
94
+ // ---------------------------------------------------------------------------
95
+
96
+ /** Default rpiv-pi produces outcome — bucket-agnostic text scan + frontmatter parse. */
97
+ export const rpivArtifactMdOutcome: OutputSpec<unknown, "artifact-md", Record<string, unknown>> = {
98
+ collector: rpivArtifactCollector,
99
+ parser: frontmatterParser,
100
+ };
101
+
102
+ /**
103
+ * Per-bucket variant — narrows accepted paths to the supplied subfolder
104
+ * AND publishes the resulting `Output` under `state.named[bucket]` so
105
+ * downstream stages can reference it via `reads: [bucket, ...]` without
106
+ * restating the bucket on each producing stage. Multiple stages wiring
107
+ * the same bucket converge to one named slot (latest entry wins on read).
108
+ */
109
+ export function rpivBucketOutcome(bucket: string): OutputSpec<unknown, "artifact-md", Record<string, unknown>> {
110
+ return { name: bucket, collector: rpivBucketCollector(bucket), parser: frontmatterParser };
111
+ }