@codyswann/lisa 1.82.2 → 1.83.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/configs/vitest/base.d.ts +6 -0
- package/dist/configs/vitest/base.d.ts.map +1 -1
- package/dist/configs/vitest/base.js +11 -0
- package/dist/configs/vitest/base.js.map +1 -1
- package/dist/configs/vitest/cdk.d.ts +2 -2
- package/dist/configs/vitest/cdk.d.ts.map +1 -1
- package/dist/configs/vitest/cdk.js +3 -2
- package/dist/configs/vitest/cdk.js.map +1 -1
- package/dist/configs/vitest/nestjs.d.ts +2 -2
- package/dist/configs/vitest/nestjs.d.ts.map +1 -1
- package/dist/configs/vitest/nestjs.js +3 -2
- package/dist/configs/vitest/nestjs.js.map +1 -1
- package/dist/configs/vitest/typescript.d.ts +2 -2
- package/dist/configs/vitest/typescript.d.ts.map +1 -1
- package/dist/configs/vitest/typescript.js +3 -3
- package/dist/configs/vitest/typescript.js.map +1 -1
- package/dist/core/config.d.ts +2 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +2 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/lisa.d.ts +23 -0
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +83 -28
- package/dist/core/lisa.js.map +1 -1
- package/dist/migrations/ensure-expo-postinstall.d.ts +26 -0
- package/dist/migrations/ensure-expo-postinstall.d.ts.map +1 -0
- package/dist/migrations/ensure-expo-postinstall.js +95 -0
- package/dist/migrations/ensure-expo-postinstall.js.map +1 -0
- package/dist/migrations/ensure-tsconfig-local-includes.d.ts +26 -0
- package/dist/migrations/ensure-tsconfig-local-includes.d.ts.map +1 -0
- package/dist/migrations/ensure-tsconfig-local-includes.js +125 -0
- package/dist/migrations/ensure-tsconfig-local-includes.js.map +1 -0
- package/dist/migrations/index.d.ts +32 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +53 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/migration.interface.d.ts +48 -0
- package/dist/migrations/migration.interface.d.ts.map +1 -0
- package/dist/migrations/migration.interface.js +2 -0
- package/dist/migrations/migration.interface.js.map +1 -0
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/agents/jira-agent.md +17 -8
- package/plugins/lisa/agents/spec-conformance-specialist.md +49 -0
- package/plugins/lisa/agents/verification-specialist.md +1 -0
- package/plugins/lisa/commands/jira/read-ticket.md +7 -0
- package/plugins/lisa/commands/jira/write-ticket.md +7 -0
- package/plugins/lisa/commands/spec-conformance.md +7 -0
- package/plugins/lisa/skills/jira-create/SKILL.md +7 -1
- package/plugins/lisa/skills/jira-read-ticket/SKILL.md +180 -0
- package/plugins/lisa/skills/jira-write-ticket/SKILL.md +178 -0
- package/plugins/lisa/skills/spec-conformance/SKILL.md +161 -0
- package/plugins/lisa/skills/ticket-triage/SKILL.md +14 -2
- package/plugins/lisa/skills/verification-lifecycle/SKILL.md +21 -5
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/agents/jira-agent.md +17 -8
- package/plugins/src/base/agents/spec-conformance-specialist.md +49 -0
- package/plugins/src/base/agents/verification-specialist.md +1 -0
- package/plugins/src/base/commands/jira/read-ticket.md +7 -0
- package/plugins/src/base/commands/jira/write-ticket.md +7 -0
- package/plugins/src/base/commands/spec-conformance.md +7 -0
- package/plugins/src/base/skills/jira-create/SKILL.md +7 -1
- package/plugins/src/base/skills/jira-read-ticket/SKILL.md +180 -0
- package/plugins/src/base/skills/jira-write-ticket/SKILL.md +178 -0
- package/plugins/src/base/skills/spec-conformance/SKILL.md +161 -0
- package/plugins/src/base/skills/ticket-triage/SKILL.md +14 -2
- package/plugins/src/base/skills/verification-lifecycle/SKILL.md +21 -5
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Migration, MigrationContext, MigrationResult } from "./migration.interface.js";
|
|
2
|
+
/**
|
|
3
|
+
* Migration: ensure Expo projects chain Lisa into their postinstall script.
|
|
4
|
+
*
|
|
5
|
+
* Some Expo projects (e.g. gsai frontend-v2, propswap/frontend) have a custom postinstall
|
|
6
|
+
* (`patch-package && ...`) that never invokes Lisa. Without the Lisa invocation, template
|
|
7
|
+
* application never runs on `bun install` after a Lisa bump. This migration prepends the
|
|
8
|
+
* standard Lisa invocation so template updates apply automatically on install.
|
|
9
|
+
*/
|
|
10
|
+
export declare class EnsureExpoPostinstallMigration implements Migration {
|
|
11
|
+
readonly name = "ensure-expo-postinstall";
|
|
12
|
+
readonly description = "Ensure Expo projects run Lisa in their postinstall script";
|
|
13
|
+
/**
|
|
14
|
+
* Check whether this migration should run on the project
|
|
15
|
+
* @param ctx - Migration context
|
|
16
|
+
* @returns True when an Expo project is missing the Lisa invocation in postinstall
|
|
17
|
+
*/
|
|
18
|
+
applies(ctx: MigrationContext): Promise<boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* Apply the migration, prepending the Lisa invocation to the project's postinstall
|
|
21
|
+
* @param ctx - Migration context
|
|
22
|
+
* @returns Result describing the action taken
|
|
23
|
+
*/
|
|
24
|
+
apply(ctx: MigrationContext): Promise<MigrationResult>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=ensure-expo-postinstall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensure-expo-postinstall.d.ts","sourceRoot":"","sources":["../../src/migrations/ensure-expo-postinstall.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAuClC;;;;;;;GAOG;AACH,qBAAa,8BAA+B,YAAW,SAAS;IAC9D,QAAQ,CAAC,IAAI,6BAA6B;IAC1C,QAAQ,CAAC,WAAW,+DAC0C;IAE9D;;;;OAIG;IACG,OAAO,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAetD;;;;OAIG;IACG,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;CAqC7D"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { readJsonOrNull, writeJson } from "../utils/json-utils.js";
|
|
3
|
+
const PACKAGE_JSON = "package.json";
|
|
4
|
+
const LISA_INVOCATION = "node node_modules/@codyswann/lisa/dist/index.js --yes --skip-git-check . 2>/dev/null || true";
|
|
5
|
+
const LISA_MARKER = "node_modules/@codyswann/lisa/dist/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Read package.json, returning null if missing
|
|
8
|
+
* @param projectDir - Project directory containing package.json
|
|
9
|
+
* @returns Parsed package.json or null when absent/invalid
|
|
10
|
+
*/
|
|
11
|
+
async function readPackageJson(projectDir) {
|
|
12
|
+
return readJsonOrNull(path.join(projectDir, PACKAGE_JSON));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Compose the new postinstall, prepending the Lisa invocation to any existing command
|
|
16
|
+
* @param existing - Existing postinstall script (may be undefined)
|
|
17
|
+
* @returns The composed postinstall script
|
|
18
|
+
*/
|
|
19
|
+
function composePostinstall(existing) {
|
|
20
|
+
const trimmed = existing?.trim();
|
|
21
|
+
if (!trimmed) {
|
|
22
|
+
return LISA_INVOCATION;
|
|
23
|
+
}
|
|
24
|
+
return `${LISA_INVOCATION} && ${trimmed}`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Migration: ensure Expo projects chain Lisa into their postinstall script.
|
|
28
|
+
*
|
|
29
|
+
* Some Expo projects (e.g. gsai frontend-v2, propswap/frontend) have a custom postinstall
|
|
30
|
+
* (`patch-package && ...`) that never invokes Lisa. Without the Lisa invocation, template
|
|
31
|
+
* application never runs on `bun install` after a Lisa bump. This migration prepends the
|
|
32
|
+
* standard Lisa invocation so template updates apply automatically on install.
|
|
33
|
+
*/
|
|
34
|
+
export class EnsureExpoPostinstallMigration {
|
|
35
|
+
name = "ensure-expo-postinstall";
|
|
36
|
+
description = "Ensure Expo projects run Lisa in their postinstall script";
|
|
37
|
+
/**
|
|
38
|
+
* Check whether this migration should run on the project
|
|
39
|
+
* @param ctx - Migration context
|
|
40
|
+
* @returns True when an Expo project is missing the Lisa invocation in postinstall
|
|
41
|
+
*/
|
|
42
|
+
async applies(ctx) {
|
|
43
|
+
if (!ctx.detectedTypes.includes("expo")) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const pkg = await readPackageJson(ctx.projectDir);
|
|
47
|
+
if (!pkg) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const postinstall = pkg.scripts?.postinstall;
|
|
51
|
+
if (postinstall && postinstall.includes(LISA_MARKER)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Apply the migration, prepending the Lisa invocation to the project's postinstall
|
|
58
|
+
* @param ctx - Migration context
|
|
59
|
+
* @returns Result describing the action taken
|
|
60
|
+
*/
|
|
61
|
+
async apply(ctx) {
|
|
62
|
+
const pkgPath = path.join(ctx.projectDir, PACKAGE_JSON);
|
|
63
|
+
const pkg = await readPackageJson(ctx.projectDir);
|
|
64
|
+
if (!pkg) {
|
|
65
|
+
return { name: this.name, action: "noop" };
|
|
66
|
+
}
|
|
67
|
+
const currentScripts = pkg.scripts ?? {};
|
|
68
|
+
const newPostinstall = composePostinstall(currentScripts.postinstall);
|
|
69
|
+
const nextPkg = {
|
|
70
|
+
...pkg,
|
|
71
|
+
scripts: { ...currentScripts, postinstall: newPostinstall },
|
|
72
|
+
};
|
|
73
|
+
const message = currentScripts.postinstall
|
|
74
|
+
? `Chained Lisa into existing postinstall: ${newPostinstall}`
|
|
75
|
+
: `Set postinstall to Lisa invocation: ${newPostinstall}`;
|
|
76
|
+
if (ctx.dryRun) {
|
|
77
|
+
ctx.logger.dry(`Would update package.json scripts.postinstall`);
|
|
78
|
+
return {
|
|
79
|
+
name: this.name,
|
|
80
|
+
action: "applied",
|
|
81
|
+
changedFiles: [PACKAGE_JSON],
|
|
82
|
+
message,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
await writeJson(pkgPath, nextPkg);
|
|
86
|
+
ctx.logger.success(message);
|
|
87
|
+
return {
|
|
88
|
+
name: this.name,
|
|
89
|
+
action: "applied",
|
|
90
|
+
changedFiles: [PACKAGE_JSON],
|
|
91
|
+
message,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=ensure-expo-postinstall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensure-expo-postinstall.js","sourceRoot":"","sources":["../../src/migrations/ensure-expo-postinstall.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Migration, MigrationContext, MigrationResult } from "./migration.interface.js";
|
|
2
|
+
/**
|
|
3
|
+
* Migration: backfill missing include/exclude in existing tsconfig.local.json files.
|
|
4
|
+
*
|
|
5
|
+
* Before PR #373, include/exclude lived in tsconfig.json. After they moved to
|
|
6
|
+
* tsconfig.local.json (create-only), existing projects kept their include-less local
|
|
7
|
+
* tsconfig and typecheck began compiling tests, worktrees, etc. This migration injects
|
|
8
|
+
* the canonical defaults for any key that is missing without touching existing values.
|
|
9
|
+
*/
|
|
10
|
+
export declare class EnsureTsconfigLocalIncludesMigration implements Migration {
|
|
11
|
+
readonly name = "ensure-tsconfig-local-includes";
|
|
12
|
+
readonly description = "Backfill include/exclude in tsconfig.local.json for projects upgraded past PR #373";
|
|
13
|
+
/**
|
|
14
|
+
* Check whether this migration should run on the project
|
|
15
|
+
* @param ctx - Migration context
|
|
16
|
+
* @returns True when tsconfig.local.json exists but is missing include or exclude
|
|
17
|
+
*/
|
|
18
|
+
applies(ctx: MigrationContext): Promise<boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* Apply the migration, injecting any missing include/exclude keys
|
|
21
|
+
* @param ctx - Migration context
|
|
22
|
+
* @returns Result describing the action taken
|
|
23
|
+
*/
|
|
24
|
+
apply(ctx: MigrationContext): Promise<MigrationResult>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=ensure-tsconfig-local-includes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensure-tsconfig-local-includes.d.ts","sourceRoot":"","sources":["../../src/migrations/ensure-tsconfig-local-includes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AA8ElC;;;;;;;GAOG;AACH,qBAAa,oCAAqC,YAAW,SAAS;IACpE,QAAQ,CAAC,IAAI,oCAAoC;IACjD,QAAQ,CAAC,WAAW,wFACmE;IAEvF;;;;OAIG;IACG,OAAO,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAStD;;;;OAIG;IACG,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;CAgD7D"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import * as fse from "fs-extra";
|
|
3
|
+
import { readJsonOrNull, writeJson } from "../utils/json-utils.js";
|
|
4
|
+
const TSCONFIG_LOCAL = "tsconfig.local.json";
|
|
5
|
+
/**
|
|
6
|
+
* Preferred order of project types for sourcing include/exclude defaults.
|
|
7
|
+
* The first type in detectedTypes matching this list is used.
|
|
8
|
+
*/
|
|
9
|
+
const TEMPLATE_PRIORITY = [
|
|
10
|
+
"expo",
|
|
11
|
+
"cdk",
|
|
12
|
+
"nestjs",
|
|
13
|
+
"npm-package",
|
|
14
|
+
"typescript",
|
|
15
|
+
];
|
|
16
|
+
/**
|
|
17
|
+
* Fallback defaults when the template file cannot be read (matches typescript/create-only)
|
|
18
|
+
*/
|
|
19
|
+
const FALLBACK_DEFAULTS = {
|
|
20
|
+
include: ["src/**/*"],
|
|
21
|
+
exclude: ["node_modules", ".build", "dist", "**/*.test.ts", "**/*.spec.ts"],
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Return the template project type to read defaults from, or null if none applies
|
|
25
|
+
* @param detectedTypes - Detected project types for the destination project
|
|
26
|
+
* @returns The highest-priority matching project type, or null when none match
|
|
27
|
+
*/
|
|
28
|
+
function pickTemplateType(detectedTypes) {
|
|
29
|
+
for (const type of TEMPLATE_PRIORITY) {
|
|
30
|
+
if (detectedTypes.includes(type)) {
|
|
31
|
+
return type;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Load include/exclude defaults from a Lisa template tsconfig.local.json
|
|
38
|
+
* @param lisaDir - Lisa installation directory
|
|
39
|
+
* @param type - Project type whose template to read
|
|
40
|
+
* @returns The template's include/exclude, or the fallback defaults when absent
|
|
41
|
+
*/
|
|
42
|
+
async function loadTemplateDefaults(lisaDir, type) {
|
|
43
|
+
const templatePath = path.join(lisaDir, type, "create-only", TSCONFIG_LOCAL);
|
|
44
|
+
const template = await readJsonOrNull(templatePath);
|
|
45
|
+
if (!template) {
|
|
46
|
+
return FALLBACK_DEFAULTS;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
include: template.include ?? FALLBACK_DEFAULTS.include,
|
|
50
|
+
exclude: template.exclude ?? FALLBACK_DEFAULTS.exclude,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Migration: backfill missing include/exclude in existing tsconfig.local.json files.
|
|
55
|
+
*
|
|
56
|
+
* Before PR #373, include/exclude lived in tsconfig.json. After they moved to
|
|
57
|
+
* tsconfig.local.json (create-only), existing projects kept their include-less local
|
|
58
|
+
* tsconfig and typecheck began compiling tests, worktrees, etc. This migration injects
|
|
59
|
+
* the canonical defaults for any key that is missing without touching existing values.
|
|
60
|
+
*/
|
|
61
|
+
export class EnsureTsconfigLocalIncludesMigration {
|
|
62
|
+
name = "ensure-tsconfig-local-includes";
|
|
63
|
+
description = "Backfill include/exclude in tsconfig.local.json for projects upgraded past PR #373";
|
|
64
|
+
/**
|
|
65
|
+
* Check whether this migration should run on the project
|
|
66
|
+
* @param ctx - Migration context
|
|
67
|
+
* @returns True when tsconfig.local.json exists but is missing include or exclude
|
|
68
|
+
*/
|
|
69
|
+
async applies(ctx) {
|
|
70
|
+
const tsconfigLocalPath = path.join(ctx.projectDir, TSCONFIG_LOCAL);
|
|
71
|
+
const existing = await readJsonOrNull(tsconfigLocalPath);
|
|
72
|
+
if (!existing) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
return existing.include === undefined || existing.exclude === undefined;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Apply the migration, injecting any missing include/exclude keys
|
|
79
|
+
* @param ctx - Migration context
|
|
80
|
+
* @returns Result describing the action taken
|
|
81
|
+
*/
|
|
82
|
+
async apply(ctx) {
|
|
83
|
+
const tsconfigLocalPath = path.join(ctx.projectDir, TSCONFIG_LOCAL);
|
|
84
|
+
const existing = await readJsonOrNull(tsconfigLocalPath);
|
|
85
|
+
if (!existing) {
|
|
86
|
+
return { name: this.name, action: "noop" };
|
|
87
|
+
}
|
|
88
|
+
const templateType = pickTemplateType(ctx.detectedTypes);
|
|
89
|
+
const defaults = templateType
|
|
90
|
+
? await loadTemplateDefaults(ctx.lisaDir, templateType)
|
|
91
|
+
: FALLBACK_DEFAULTS;
|
|
92
|
+
const patched = {
|
|
93
|
+
...existing,
|
|
94
|
+
...(existing.include === undefined ? { include: defaults.include } : {}),
|
|
95
|
+
...(existing.exclude === undefined ? { exclude: defaults.exclude } : {}),
|
|
96
|
+
};
|
|
97
|
+
const missing = [
|
|
98
|
+
...(existing.include === undefined ? ["include"] : []),
|
|
99
|
+
...(existing.exclude === undefined ? ["exclude"] : []),
|
|
100
|
+
];
|
|
101
|
+
if (missing.length === 0) {
|
|
102
|
+
return { name: this.name, action: "noop" };
|
|
103
|
+
}
|
|
104
|
+
const message = `Injected ${missing.join(", ")} into tsconfig.local.json`;
|
|
105
|
+
if (ctx.dryRun) {
|
|
106
|
+
ctx.logger.dry(`Would update tsconfig.local.json: ${missing.join(", ")}`);
|
|
107
|
+
return {
|
|
108
|
+
name: this.name,
|
|
109
|
+
action: "applied",
|
|
110
|
+
changedFiles: [TSCONFIG_LOCAL],
|
|
111
|
+
message,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
await fse.ensureDir(path.dirname(tsconfigLocalPath));
|
|
115
|
+
await writeJson(tsconfigLocalPath, patched);
|
|
116
|
+
ctx.logger.success(message);
|
|
117
|
+
return {
|
|
118
|
+
name: this.name,
|
|
119
|
+
action: "applied",
|
|
120
|
+
changedFiles: [TSCONFIG_LOCAL],
|
|
121
|
+
message,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=ensure-tsconfig-local-includes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensure-tsconfig-local-includes.js","sourceRoot":"","sources":["../../src/migrations/ensure-tsconfig-local-includes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Migration, MigrationContext, MigrationResult } from "./migration.interface.js";
|
|
2
|
+
export type { Migration, MigrationAction, MigrationContext, MigrationResult, } from "./migration.interface.js";
|
|
3
|
+
export { EnsureExpoPostinstallMigration } from "./ensure-expo-postinstall.js";
|
|
4
|
+
export { EnsureTsconfigLocalIncludesMigration } from "./ensure-tsconfig-local-includes.js";
|
|
5
|
+
/**
|
|
6
|
+
* Registry that runs applicable migrations against a destination project
|
|
7
|
+
*/
|
|
8
|
+
export declare class MigrationRegistry {
|
|
9
|
+
private readonly migrations;
|
|
10
|
+
/**
|
|
11
|
+
* Initialize registry with provided or default migrations
|
|
12
|
+
* @param migrations - Optional array of migrations (uses defaults if omitted)
|
|
13
|
+
*/
|
|
14
|
+
constructor(migrations?: readonly Migration[]);
|
|
15
|
+
/**
|
|
16
|
+
* Get all registered migrations
|
|
17
|
+
* @returns All migrations in registration order
|
|
18
|
+
*/
|
|
19
|
+
getAll(): readonly Migration[];
|
|
20
|
+
/**
|
|
21
|
+
* Run every migration whose `applies` returns true
|
|
22
|
+
* @param ctx - Migration context
|
|
23
|
+
* @returns Aggregated results from every registered migration
|
|
24
|
+
*/
|
|
25
|
+
runAll(ctx: MigrationContext): Promise<readonly MigrationResult[]>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create the default migration registry
|
|
29
|
+
* @returns New MigrationRegistry with all default migrations registered
|
|
30
|
+
*/
|
|
31
|
+
export declare function createMigrationRegistry(): MigrationRegistry;
|
|
32
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAE3F;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAElD;;;OAGG;gBACS,UAAU,CAAC,EAAE,SAAS,SAAS,EAAE;IAO7C;;;OAGG;IACH,MAAM,IAAI,SAAS,SAAS,EAAE;IAI9B;;;;OAIG;IACG,MAAM,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC;CAazE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,iBAAiB,CAE3D"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { EnsureExpoPostinstallMigration } from "./ensure-expo-postinstall.js";
|
|
2
|
+
import { EnsureTsconfigLocalIncludesMigration } from "./ensure-tsconfig-local-includes.js";
|
|
3
|
+
export { EnsureExpoPostinstallMigration } from "./ensure-expo-postinstall.js";
|
|
4
|
+
export { EnsureTsconfigLocalIncludesMigration } from "./ensure-tsconfig-local-includes.js";
|
|
5
|
+
/**
|
|
6
|
+
* Registry that runs applicable migrations against a destination project
|
|
7
|
+
*/
|
|
8
|
+
export class MigrationRegistry {
|
|
9
|
+
migrations;
|
|
10
|
+
/**
|
|
11
|
+
* Initialize registry with provided or default migrations
|
|
12
|
+
* @param migrations - Optional array of migrations (uses defaults if omitted)
|
|
13
|
+
*/
|
|
14
|
+
constructor(migrations) {
|
|
15
|
+
this.migrations = migrations ?? [
|
|
16
|
+
new EnsureTsconfigLocalIncludesMigration(),
|
|
17
|
+
new EnsureExpoPostinstallMigration(),
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get all registered migrations
|
|
22
|
+
* @returns All migrations in registration order
|
|
23
|
+
*/
|
|
24
|
+
getAll() {
|
|
25
|
+
return this.migrations;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Run every migration whose `applies` returns true
|
|
29
|
+
* @param ctx - Migration context
|
|
30
|
+
* @returns Aggregated results from every registered migration
|
|
31
|
+
*/
|
|
32
|
+
async runAll(ctx) {
|
|
33
|
+
const results = [];
|
|
34
|
+
for (const migration of this.migrations) {
|
|
35
|
+
const shouldRun = await migration.applies(ctx);
|
|
36
|
+
if (!shouldRun) {
|
|
37
|
+
results.push({ name: migration.name, action: "skipped" });
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const result = await migration.apply(ctx);
|
|
41
|
+
results.push(result);
|
|
42
|
+
}
|
|
43
|
+
return results;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Create the default migration registry
|
|
48
|
+
* @returns New MigrationRegistry with all default migrations registered
|
|
49
|
+
*/
|
|
50
|
+
export function createMigrationRegistry() {
|
|
51
|
+
return new MigrationRegistry();
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAa3F,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAE3F;;GAEG;AACH,MAAM,OAAO,iBAAiB;IACX,UAAU,CAAuB;IAElD;;;OAGG;IACH,YAAY,UAAiC;QAC3C,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI;YAC9B,IAAI,oCAAoC,EAAE;YAC1C,IAAI,8BAA8B,EAAE;SACrC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,MAAM;QACJ,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,GAAqB;QAChC,MAAM,OAAO,GAAsB,EAAE,CAAC;QACtC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC/C,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;gBAC1D,SAAS;YACX,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,IAAI,iBAAiB,EAAE,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ProjectType } from "../core/config.js";
|
|
2
|
+
import type { ILogger } from "../logging/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Action performed by a migration run
|
|
5
|
+
*/
|
|
6
|
+
export type MigrationAction = "applied" | "skipped" | "noop";
|
|
7
|
+
/**
|
|
8
|
+
* Context passed to migrations at runtime
|
|
9
|
+
*/
|
|
10
|
+
export interface MigrationContext {
|
|
11
|
+
/** Destination project directory */
|
|
12
|
+
readonly projectDir: string;
|
|
13
|
+
/** Lisa installation directory (where templates live) */
|
|
14
|
+
readonly lisaDir: string;
|
|
15
|
+
/** Project types detected for the destination project */
|
|
16
|
+
readonly detectedTypes: readonly ProjectType[];
|
|
17
|
+
/** If true, describe what would change without modifying files */
|
|
18
|
+
readonly dryRun: boolean;
|
|
19
|
+
/** Logger for user-facing output */
|
|
20
|
+
readonly logger: ILogger;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Result of running a migration
|
|
24
|
+
*/
|
|
25
|
+
export interface MigrationResult {
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly action: MigrationAction;
|
|
28
|
+
readonly changedFiles?: readonly string[];
|
|
29
|
+
readonly message?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* One-time idempotent transform applied to an existing project
|
|
33
|
+
*/
|
|
34
|
+
export interface Migration {
|
|
35
|
+
readonly name: string;
|
|
36
|
+
readonly description: string;
|
|
37
|
+
/**
|
|
38
|
+
* Whether this migration should run on this project.
|
|
39
|
+
* @param ctx Migration context
|
|
40
|
+
*/
|
|
41
|
+
applies(ctx: MigrationContext): Promise<boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* Apply the migration. Must be idempotent.
|
|
44
|
+
* @param ctx Migration context
|
|
45
|
+
*/
|
|
46
|
+
apply(ctx: MigrationContext): Promise<MigrationResult>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=migration.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.interface.d.ts","sourceRoot":"","sources":["../../src/migrations/migration.interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,yDAAyD;IACzD,QAAQ,CAAC,aAAa,EAAE,SAAS,WAAW,EAAE,CAAC;IAE/C,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEzB,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEjD;;;OAGG;IACH,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CACxD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.interface.js","sourceRoot":"","sources":["../../src/migrations/migration.interface.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"lodash": ">=4.18.1"
|
|
77
77
|
},
|
|
78
78
|
"name": "@codyswann/lisa",
|
|
79
|
-
"version": "1.
|
|
79
|
+
"version": "1.83.1",
|
|
80
80
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
81
81
|
"main": "dist/index.js",
|
|
82
82
|
"exports": {
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
name: jira-agent
|
|
3
3
|
description: JIRA lifecycle agent. Reads tickets, determines intent (Bug → Implement/Fix, Story/Task → Implement/Build, Epic → Plan, Spike → Implement/Investigate), delegates to the appropriate flow, syncs progress at milestones, and posts evidence at completion.
|
|
4
4
|
skills:
|
|
5
|
+
- jira-read-ticket
|
|
6
|
+
- jira-write-ticket
|
|
5
7
|
- jira-sync
|
|
6
8
|
- jira-evidence
|
|
7
9
|
- jira-verify
|
|
@@ -17,13 +19,20 @@ You are a JIRA lifecycle agent. Your job is to read a JIRA ticket, determine wha
|
|
|
17
19
|
|
|
18
20
|
### 1. Read the Ticket
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
- Description, comments, attachments, linked issues
|
|
22
|
-
- Epic parent, subtasks, story points
|
|
23
|
-
- Current status, assignee, labels
|
|
24
|
-
- Extract any credentials, URLs, or reproduction steps from the ticket body
|
|
22
|
+
Invoke the `jira-read-ticket` skill with the ticket key. This is mandatory — do NOT read the ticket ad-hoc via MCP calls. The skill fetches the primary ticket AND its full graph in one pass:
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
- Full description, acceptance criteria, Validation Journey
|
|
25
|
+
- All comments in chronological order
|
|
26
|
+
- All metadata (status, assignee, labels, components, fix version, priority, story points, sprint)
|
|
27
|
+
- Remote links — PRs (with state and unresolved review comments via `gh`), Confluence pages, dashboards
|
|
28
|
+
- Every linked ticket (`blocks`, `is blocked by`, `relates to`, `duplicates`, `clones`) with their descriptions, statuses, and recent comments
|
|
29
|
+
- Epic parent — full description, comments, and acceptance criteria
|
|
30
|
+
- Epic siblings — so you see in-flight related work before starting
|
|
31
|
+
- Subtasks
|
|
32
|
+
|
|
33
|
+
Pass the resulting context bundle verbatim to every downstream agent. Extract credentials, URLs, and reproduction steps from the bundle. If the skill reports that the ticket is inaccessible, stop and report what access is needed.
|
|
34
|
+
|
|
35
|
+
**Never act on a ticket in isolation.** If the bundle shows open blockers, flag them and stop. If it shows an epic sibling in progress with a different assignee, surface that before proceeding so work isn't duplicated.
|
|
27
36
|
|
|
28
37
|
### 2. Validate Ticket Quality
|
|
29
38
|
|
|
@@ -97,7 +106,7 @@ Based on the milestone, suggest (but don't auto-transition):
|
|
|
97
106
|
## Rules
|
|
98
107
|
|
|
99
108
|
- Never auto-transition ticket status — always suggest and let the human confirm
|
|
100
|
-
- Always read the full ticket before determining intent — don't rely on ticket type alone
|
|
101
|
-
-
|
|
109
|
+
- Always read the full ticket graph via `jira-read-ticket` before determining intent — don't rely on ticket type alone
|
|
110
|
+
- Never create or materially edit a ticket by calling MCP write tools directly — always delegate to `jira-write-ticket` so relationships, Gherkin criteria, and metadata gates are enforced
|
|
102
111
|
- If sign-in credentials are in the ticket, extract and pass them to the flow
|
|
103
112
|
- If the ticket has a Validation Journey section, pass it to the verifier agent
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-conformance-specialist
|
|
3
|
+
description: "Spec conformance specialist agent. Verifies shipped work matches its spec exactly — acceptance criteria, Out of Scope, Technical Approach, Validation Journey assertions, and deliverables. Produces a coverage matrix, flags scope creep separately from misses, and issues a verdict (CONFORMS / PARTIAL / DIVERGES). Runs alongside verification-specialist and product-specialist during the verification phase; they catch different failure modes."
|
|
4
|
+
skills:
|
|
5
|
+
- spec-conformance
|
|
6
|
+
- jira-read-ticket
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Spec Conformance Specialist Agent
|
|
10
|
+
|
|
11
|
+
You are a spec conformance specialist. Your job is to prove that the shipped work matches its spec **exactly** — nothing more, nothing less.
|
|
12
|
+
|
|
13
|
+
## Scope
|
|
14
|
+
|
|
15
|
+
You answer one question: **Does what shipped match what was asked?**
|
|
16
|
+
|
|
17
|
+
That is distinct from two adjacent questions that other agents own:
|
|
18
|
+
|
|
19
|
+
| Question | Owner |
|
|
20
|
+
|----------|-------|
|
|
21
|
+
| Does the system actually run and produce correct observable output? | `verification-specialist` |
|
|
22
|
+
| Is the user experience coherent and are error states humane? | `product-specialist` |
|
|
23
|
+
| Does every line of shipped code trace back to a requirement, and is nothing missing from the spec? | **you** |
|
|
24
|
+
|
|
25
|
+
You depend on `verification-specialist`'s empirical evidence — you do not gather it yourself. If their report is not available, request it before producing a verdict.
|
|
26
|
+
|
|
27
|
+
## Process
|
|
28
|
+
|
|
29
|
+
Follow the `spec-conformance` skill end-to-end:
|
|
30
|
+
|
|
31
|
+
1. Resolve the spec source (plan file, JIRA key, Linear, GitHub issue, PRD).
|
|
32
|
+
2. Extract every requirement into a structured list — acceptance criteria, Out of Scope, technical commitments, Validation Journey assertions, deliverables.
|
|
33
|
+
3. Inspect shipped work (diff, tests, PR body, verification-specialist evidence).
|
|
34
|
+
4. Build the coverage matrix — every requirement gets a row with a status.
|
|
35
|
+
5. Detect scope creep and untraceable changes separately.
|
|
36
|
+
6. Produce the verdict.
|
|
37
|
+
|
|
38
|
+
## Output
|
|
39
|
+
|
|
40
|
+
Return the structured report defined in the skill. Never summarize or drop rows. The matrix is the deliverable — a human or another agent reads it to decide whether to ship.
|
|
41
|
+
|
|
42
|
+
## Rules
|
|
43
|
+
|
|
44
|
+
- **Require empirical evidence.** A requirement is not `MATCH` because code exists. It is `MATCH` only when there is a test AND runtime observation (captured by verification-specialist).
|
|
45
|
+
- **Scope creep is a distinct failure.** Do not fold `SCOPE_CREEP_VIOLATION` into "missing" or "untraceable." Scope creep means Out of Scope was violated — it blocks shipping.
|
|
46
|
+
- **Untraceable changes get surfaced, not judged.** Refactors and test helpers often land here. Surface them so the human can confirm intent; do not automatically fail.
|
|
47
|
+
- **If the spec itself is inadequate** (no acceptance criteria, no Out of Scope, no Validation Journey for runtime changes), the verdict is `DIVERGES` until the spec is tightened. Do not paper over an ambiguous spec with a generous match.
|
|
48
|
+
- **Never gather empirical evidence yourself.** That is verification-specialist's job. You read their report. If it's missing, block and ask.
|
|
49
|
+
- **Never approve your own work.** If you produced the implementation in this session, say so explicitly in the report and recommend the human double-check — self-review of conformance is weakest when the same mind built the thing.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Read a JIRA ticket with full scope — metadata, comments, remote PRs, linked tickets, epic siblings, subtasks"
|
|
3
|
+
allowed-tools: ["Skill"]
|
|
4
|
+
argument-hint: "<TICKET-ID>"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Use the /lisa:jira-read-ticket skill to fetch the full scope of the JIRA ticket and its related graph. $ARGUMENTS
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Create or update a JIRA ticket with enforced relationships, Gherkin criteria, and metadata quality gates"
|
|
3
|
+
allowed-tools: ["Skill"]
|
|
4
|
+
argument-hint: "[TICKET-ID | <create-intent-description>]"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Use the /lisa:jira-write-ticket skill to create or update the JIRA ticket with full relationship discovery and quality enforcement. $ARGUMENTS
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Verify shipped work matches its spec — coverage matrix with scope-creep detection and verdict"
|
|
3
|
+
allowed-tools: ["Skill"]
|
|
4
|
+
argument-hint: "[plan-file | TICKET-KEY | issue-url]"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Use the /lisa:spec-conformance skill to compare shipped work against its spec and produce a coverage matrix with verdict. $ARGUMENTS
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jira-create
|
|
3
3
|
description: This skill should be used when creating JIRA epics, stories, and tasks from code files or descriptions. It analyzes the provided input, determines the appropriate issue hierarchy, and creates issues with comprehensive quality requirements including test-first development and documentation.
|
|
4
|
-
allowed-tools: ["Read", "Glob", "LS", "
|
|
4
|
+
allowed-tools: ["Read", "Glob", "LS", "Skill", "mcp__atlassian__getVisibleJiraProjects", "mcp__atlassian__getJiraProjectIssueTypesMetadata", "mcp__atlassian__getAccessibleAtlassianResources"]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Create JIRA Issues from $ARGUMENTS
|
|
@@ -93,3 +93,9 @@ Default project: from jira-cli config (override via arguments)
|
|
|
93
93
|
Exclude unless requested: migration plans, performance tests
|
|
94
94
|
|
|
95
95
|
Execute the analysis and create the complete JIRA structure with proper parent-child relationships.
|
|
96
|
+
|
|
97
|
+
## Delegation to jira-write-ticket
|
|
98
|
+
|
|
99
|
+
For every individual ticket that will be created, delegate to the `jira-write-ticket` skill rather than calling `mcp__atlassian__createJiraIssue` directly. `jira-write-ticket` enforces description quality (Gherkin acceptance criteria, stakeholder/developer/assistant sections), relationship discovery (`blocks`, `is blocked by`, `relates to`, remote PR/Confluence/dashboard links), epic parent validation, and post-create verification.
|
|
100
|
+
|
|
101
|
+
This skill's role is to analyze the input and decide the hierarchy (which epics, which stories, which tasks, in what parent-child structure). `jira-write-ticket` handles the actual write with full quality gates.
|