@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.
Files changed (74) hide show
  1. package/dist/cli/index.d.ts.map +1 -1
  2. package/dist/cli/index.js +2 -0
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/configs/vitest/base.d.ts +6 -0
  5. package/dist/configs/vitest/base.d.ts.map +1 -1
  6. package/dist/configs/vitest/base.js +11 -0
  7. package/dist/configs/vitest/base.js.map +1 -1
  8. package/dist/configs/vitest/cdk.d.ts +2 -2
  9. package/dist/configs/vitest/cdk.d.ts.map +1 -1
  10. package/dist/configs/vitest/cdk.js +3 -2
  11. package/dist/configs/vitest/cdk.js.map +1 -1
  12. package/dist/configs/vitest/nestjs.d.ts +2 -2
  13. package/dist/configs/vitest/nestjs.d.ts.map +1 -1
  14. package/dist/configs/vitest/nestjs.js +3 -2
  15. package/dist/configs/vitest/nestjs.js.map +1 -1
  16. package/dist/configs/vitest/typescript.d.ts +2 -2
  17. package/dist/configs/vitest/typescript.d.ts.map +1 -1
  18. package/dist/configs/vitest/typescript.js +3 -3
  19. package/dist/configs/vitest/typescript.js.map +1 -1
  20. package/dist/core/config.d.ts +2 -0
  21. package/dist/core/config.d.ts.map +1 -1
  22. package/dist/core/config.js +2 -0
  23. package/dist/core/config.js.map +1 -1
  24. package/dist/core/lisa.d.ts +23 -0
  25. package/dist/core/lisa.d.ts.map +1 -1
  26. package/dist/core/lisa.js +83 -28
  27. package/dist/core/lisa.js.map +1 -1
  28. package/dist/migrations/ensure-expo-postinstall.d.ts +26 -0
  29. package/dist/migrations/ensure-expo-postinstall.d.ts.map +1 -0
  30. package/dist/migrations/ensure-expo-postinstall.js +95 -0
  31. package/dist/migrations/ensure-expo-postinstall.js.map +1 -0
  32. package/dist/migrations/ensure-tsconfig-local-includes.d.ts +26 -0
  33. package/dist/migrations/ensure-tsconfig-local-includes.d.ts.map +1 -0
  34. package/dist/migrations/ensure-tsconfig-local-includes.js +125 -0
  35. package/dist/migrations/ensure-tsconfig-local-includes.js.map +1 -0
  36. package/dist/migrations/index.d.ts +32 -0
  37. package/dist/migrations/index.d.ts.map +1 -0
  38. package/dist/migrations/index.js +53 -0
  39. package/dist/migrations/index.js.map +1 -0
  40. package/dist/migrations/migration.interface.d.ts +48 -0
  41. package/dist/migrations/migration.interface.d.ts.map +1 -0
  42. package/dist/migrations/migration.interface.js +2 -0
  43. package/dist/migrations/migration.interface.js.map +1 -0
  44. package/package.json +1 -1
  45. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa/agents/jira-agent.md +17 -8
  47. package/plugins/lisa/agents/spec-conformance-specialist.md +49 -0
  48. package/plugins/lisa/agents/verification-specialist.md +1 -0
  49. package/plugins/lisa/commands/jira/read-ticket.md +7 -0
  50. package/plugins/lisa/commands/jira/write-ticket.md +7 -0
  51. package/plugins/lisa/commands/spec-conformance.md +7 -0
  52. package/plugins/lisa/skills/jira-create/SKILL.md +7 -1
  53. package/plugins/lisa/skills/jira-read-ticket/SKILL.md +180 -0
  54. package/plugins/lisa/skills/jira-write-ticket/SKILL.md +178 -0
  55. package/plugins/lisa/skills/spec-conformance/SKILL.md +161 -0
  56. package/plugins/lisa/skills/ticket-triage/SKILL.md +14 -2
  57. package/plugins/lisa/skills/verification-lifecycle/SKILL.md +21 -5
  58. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  63. package/plugins/src/base/agents/jira-agent.md +17 -8
  64. package/plugins/src/base/agents/spec-conformance-specialist.md +49 -0
  65. package/plugins/src/base/agents/verification-specialist.md +1 -0
  66. package/plugins/src/base/commands/jira/read-ticket.md +7 -0
  67. package/plugins/src/base/commands/jira/write-ticket.md +7 -0
  68. package/plugins/src/base/commands/spec-conformance.md +7 -0
  69. package/plugins/src/base/skills/jira-create/SKILL.md +7 -1
  70. package/plugins/src/base/skills/jira-read-ticket/SKILL.md +180 -0
  71. package/plugins/src/base/skills/jira-write-ticket/SKILL.md +178 -0
  72. package/plugins/src/base/skills/spec-conformance/SKILL.md +161 -0
  73. package/plugins/src/base/skills/ticket-triage/SKILL.md +14 -2
  74. 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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=migration.interface.js.map
@@ -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.82.2",
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": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "1.82.2",
3
+ "version": "1.83.1",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -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
- Read the ticket fully using the Atlassian MCP tools or CLI:
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
- If you cannot access the ticket, stop and report what access is needed.
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
- - If the ticket references other tickets, read those too for context
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.
@@ -4,6 +4,7 @@ description: Verification specialist agent. Discovers project tooling and execut
4
4
  skills:
5
5
  - verification-lifecycle
6
6
  - jira-journey
7
+ - spec-conformance
7
8
  ---
8
9
 
9
10
  # Verification Specialist Agent
@@ -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", "mcp__atlassian__createJiraIssue", "mcp__atlassian__getVisibleJiraProjects", "mcp__atlassian__getJiraProjectIssueTypesMetadata", "mcp__atlassian__getAccessibleAtlassianResources"]
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.