@pavp/storywright 1.13.1 → 1.13.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/.claude-plugin/plugin.json +1 -1
- package/commands/story-from-figma.md +2 -2
- package/commands/story-split.md +2 -2
- package/package.json +2 -1
- package/scripts/install-skills.mjs +4 -2
- package/scripts/sync-plugin-version.mjs +51 -0
- package/skills/story-generate/SKILL.md +1 -1
- package/skills/story-refine/SKILL.md +1 -1
|
@@ -13,7 +13,7 @@ Follow the skill's procedure:
|
|
|
13
13
|
2. Phase 0.5 — detect companion text / screenshots. Use text as canonical for `User Story / Scope / Business Goal`; Figma as canonical for `Components / States / Flows`. Surface conflicts as BLOCKING clarifications. Never silently pick a winner.
|
|
14
14
|
3. Phase 1 — inventory pages and frames; group by prototype links into flows.
|
|
15
15
|
4. Phase 2 — per flow: identify goal, entry point, states, components. Score per-inference confidence (HIGH/MEDIUM/LOW). Mark MEDIUM/LOW with `> ⚠️ Assumed:` blockquotes.
|
|
16
|
-
5. Phase 3 — for any flow that fails INVEST (Small),
|
|
17
|
-
6. Phase 4 — invoke `story-generate` per flow. Emit
|
|
16
|
+
5. Phase 3 — for any flow that fails INVEST (Small) OR whose deterministic pre-split count ≥2, STOP that flow's draft, route to `/story-split`, and mark it `SPLIT RECOMMENDED` in `flow-summary.md`. Continue with the other flows.
|
|
17
|
+
6. Phase 4 — invoke `story-generate` per drafted flow. Emit the full 3-file trio per story (`story-<N>.standard.md` + `story-<N>.jira-wiki.md` + `story-<N>.dev.md`) + `flow-summary.md` mapping stories → frames for traceability.
|
|
18
18
|
|
|
19
19
|
Output in the input language (text language wins if mixed inputs).
|
package/commands/story-split.md
CHANGED
|
@@ -20,6 +20,6 @@ Follow the skill's procedure:
|
|
|
20
20
|
4. Draft a split plan as a Markdown table with rationale, pattern, and proposed children.
|
|
21
21
|
5. Run the strategic evaluation: does the split reveal low-value work? Are children equal-sized?
|
|
22
22
|
6. STOP and ask the user to approve / adjust / cancel. Never auto-split.
|
|
23
|
-
7. After approval: write `epic.md` +
|
|
23
|
+
7. After approval: write `epic.md` (single file — epic metadata, holds the decision trail; NO `split-plan.md`) + the full 3-file trio per child (`story-<N>.standard.md` + `story-<N>.jira-wiki.md` + `story-<N>.dev.md`).
|
|
24
24
|
8. Coherence check + recursive re-split for children still >1 sprint.
|
|
25
|
-
9. Save artifacts under
|
|
25
|
+
9. Save artifacts under the canonical output folder `docs/storywright/YYYY-MM-DD-HHmm-<epic-slug>/`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pavp/storywright",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.3",
|
|
4
4
|
"description": "PM Skills pack for Claude Code — turn ambiguous inputs (prompts, screenshots, Figma links) into Jira-ready user stories.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"@commitlint/cli": "^19.5.0",
|
|
54
54
|
"@commitlint/config-conventional": "^19.5.0",
|
|
55
55
|
"@semantic-release/changelog": "^6.0.3",
|
|
56
|
+
"@semantic-release/exec": "^7.1.0",
|
|
56
57
|
"@semantic-release/git": "^10.0.1",
|
|
57
58
|
"@semantic-release/github": "^11.0.0",
|
|
58
59
|
"@semantic-release/npm": "^12.0.1",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { cp, mkdir, readdir, readFile, rm, unlink, writeFile } from "node:fs/promises";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
-
import { execSync } from "node:child_process";
|
|
5
|
+
import { execSync, execFileSync } from "node:child_process";
|
|
6
6
|
import { REPO_ROOT, SKILLS_DIR, pathExists } from "./lib/skills.mjs";
|
|
7
7
|
|
|
8
8
|
const skillsTarget = join(homedir(), ".claude", "skills", "storywright");
|
|
@@ -51,7 +51,9 @@ async function ensureGlobalGitignore() {
|
|
|
51
51
|
globalIgnorePath = execSync("git config --global core.excludesFile", { encoding: "utf8" }).trim();
|
|
52
52
|
} catch {
|
|
53
53
|
globalIgnorePath = join(homedir(), ".gitignore_global");
|
|
54
|
-
|
|
54
|
+
// Array form (no shell) so a homedir with spaces or shell metacharacters
|
|
55
|
+
// can't break or inject into the command.
|
|
56
|
+
execFileSync("git", ["config", "--global", "core.excludesFile", globalIgnorePath]);
|
|
55
57
|
}
|
|
56
58
|
if (globalIgnorePath === "~") {
|
|
57
59
|
globalIgnorePath = homedir();
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Write a version into the Claude marketplace manifest (.claude-plugin/plugin.json).
|
|
3
|
+
//
|
|
4
|
+
// semantic-release owns the version number in package.json (@semantic-release/npm
|
|
5
|
+
// bumps it in-place). plugin.json is a separate file no release plugin touches, so
|
|
6
|
+
// without this step the manifest drifts behind every release. Wired as the
|
|
7
|
+
// @semantic-release/exec prepareCmd, it runs after the version is computed and
|
|
8
|
+
// before @semantic-release/git commits the bump, keeping both files in lockstep.
|
|
9
|
+
//
|
|
10
|
+
// Usage: node scripts/sync-plugin-version.mjs <version>
|
|
11
|
+
// <version> defaults to package.json's version when omitted, so the script is
|
|
12
|
+
// also usable manually to repair drift outside a release.
|
|
13
|
+
|
|
14
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
import { dirname, join } from "node:path";
|
|
17
|
+
|
|
18
|
+
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
19
|
+
const manifestPath = join(root, ".claude-plugin", "plugin.json");
|
|
20
|
+
|
|
21
|
+
async function readJson(path) {
|
|
22
|
+
return JSON.parse(await readFile(path, "utf8"));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const version = process.argv[2] ?? (await readJson(join(root, "package.json"))).version;
|
|
26
|
+
|
|
27
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(version)) {
|
|
28
|
+
console.error(`✗ Refusing to write an invalid semver into plugin.json: "${version}"`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const raw = await readFile(manifestPath, "utf8");
|
|
33
|
+
|
|
34
|
+
const versionLine = /("version"\s*:\s*")([^"]*)(")/;
|
|
35
|
+
const match = raw.match(versionLine);
|
|
36
|
+
if (!match) {
|
|
37
|
+
console.error(`✗ Could not find a "version" field in ${manifestPath}`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const previous = match[2];
|
|
42
|
+
if (previous === version) {
|
|
43
|
+
console.log(`✓ plugin.json already at ${version} — no change`);
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Surgical replace of only the version value — preserves the file's existing
|
|
48
|
+
// formatting (indentation, array style) so releases don't churn unrelated lines.
|
|
49
|
+
const updated = raw.replace(versionLine, `$1${version}$3`);
|
|
50
|
+
await writeFile(manifestPath, updated);
|
|
51
|
+
console.log(`✓ plugin.json version ${previous} → ${version}`);
|
|
@@ -56,7 +56,7 @@ If the base **deterministic pre-split test** returns count ≥2:
|
|
|
56
56
|
- Show candidate children + dep notes + V audit.
|
|
57
57
|
- Ask via `AskUserQuestion`: "This story has [N] independent flows. Run split now?" with options:
|
|
58
58
|
- "Yes, split" → execute `[[story-split]]` inline (epic + children + .storywright-context.json).
|
|
59
|
-
- "Continue without split" → proceed with single-story path (fill canonical block → INVEST → render
|
|
59
|
+
- "Continue without split" → proceed with single-story path (fill canonical block → INVEST → render the 3-file trio).
|
|
60
60
|
- "No, keep as-is" → stop. No output written.
|
|
61
61
|
- Do NOT silently auto-split without the AskUserQuestion confirmation.
|
|
62
62
|
|
|
@@ -48,7 +48,7 @@ If the base **deterministic pre-split test** returns count ≥2:
|
|
|
48
48
|
- Show candidate children + per-pair dep notes (base rule 10) + V audit (base rule 11).
|
|
49
49
|
- Ask via `AskUserQuestion`: "This story has [N] independent flows. Run split now?" with options:
|
|
50
50
|
- "Yes, split" → execute `[[story-split]]` inline (epic + children + .storywright-context.json).
|
|
51
|
-
- "Continue without split" → proceed with single-story path (fill canonical block → INVEST → render
|
|
51
|
+
- "Continue without split" → proceed with single-story path (fill canonical block → INVEST → render the 3-file trio).
|
|
52
52
|
- "No, keep as-is" → stop. No output written.
|
|
53
53
|
- Do NOT silently auto-split without the AskUserQuestion confirmation.
|
|
54
54
|
|