@codyswann/lisa 2.2.0 → 2.4.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.
- package/dist/utils/postinstall-trampoline.d.ts +3 -1
- package/dist/utils/postinstall-trampoline.d.ts.map +1 -1
- package/dist/utils/postinstall-trampoline.js +9 -2
- package/dist/utils/postinstall-trampoline.js.map +1 -1
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/agents/confluence-prd-intake.md +63 -0
- package/plugins/lisa/commands/intake.md +3 -3
- package/plugins/lisa/skills/confluence-prd-intake/SKILL.md +259 -0
- package/plugins/lisa/skills/confluence-to-jira/SKILL.md +318 -0
- package/plugins/lisa/skills/intake/SKILL.md +16 -4
- package/plugins/lisa/skills/jira-validate-ticket/SKILL.md +53 -4
- package/plugins/lisa/skills/notion-prd-intake/SKILL.md +56 -13
- package/plugins/lisa/skills/notion-to-jira/SKILL.md +18 -1
- package/plugins/lisa/skills/plan/SKILL.md +3 -1
- package/plugins/lisa/skills/prd-ticket-coverage/SKILL.md +31 -11
- 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/confluence-prd-intake.md +63 -0
- package/plugins/src/base/commands/intake.md +3 -3
- package/plugins/src/base/skills/confluence-prd-intake/SKILL.md +259 -0
- package/plugins/src/base/skills/confluence-to-jira/SKILL.md +318 -0
- package/plugins/src/base/skills/intake/SKILL.md +16 -4
- package/plugins/src/base/skills/jira-validate-ticket/SKILL.md +53 -4
- package/plugins/src/base/skills/notion-prd-intake/SKILL.md +56 -13
- package/plugins/src/base/skills/notion-to-jira/SKILL.md +18 -1
- package/plugins/src/base/skills/plan/SKILL.md +3 -1
- package/plugins/src/base/skills/prd-ticket-coverage/SKILL.md +31 -11
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
1
2
|
/**
|
|
2
3
|
* Known package managers whose lockfiles must be regenerated when Lisa's apply
|
|
3
4
|
* mutates package.json (e.g., adds/updates resolutions or overrides entries).
|
|
@@ -114,7 +115,8 @@ export declare function hashFile(filePath: string): string | null;
|
|
|
114
115
|
* @param projectDir - Absolute path to the project directory Lisa will reconcile
|
|
115
116
|
* @param lisaDistDir - Absolute path to Lisa's dist directory (where index.js lives)
|
|
116
117
|
* @param parentPid - PID of the package-manager process to wait on (usually process.ppid)
|
|
118
|
+
* @param spawnFn - Optional spawn implementation; defaults to node:child_process spawn. Tests pass a vi.fn() spy here as a dependency-injection seam, avoiding the unreliable vi.doMock-on-builtins pattern that breaks under v8 coverage in CI runners.
|
|
117
119
|
* @returns Promise that resolves immediately after spawning the detached child
|
|
118
120
|
*/
|
|
119
|
-
export declare function scheduleReconciliationChild(projectDir: string, lisaDistDir: string, parentPid: number): Promise<void>;
|
|
121
|
+
export declare function scheduleReconciliationChild(projectDir: string, lisaDistDir: string, parentPid: number, spawnFn?: typeof spawn): Promise<void>;
|
|
120
122
|
//# sourceMappingURL=postinstall-trampoline.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postinstall-trampoline.d.ts","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"postinstall-trampoline.d.ts","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAmC3C;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AA6DD;;;;;GAKG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAAI,OAAO,CASvC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uCAAuC,CACrD,MAAM,EAAE,OAAO,GACd,OAAO,CAIT;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,GACjB,SAAS,cAAc,EAAE,CAI3B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,cAAc,GAAG,iBAAiB,CAE1E;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOxD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAMjB,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,IAAI,CAAC,CAgCf"}
|
|
@@ -219,9 +219,16 @@ export function hashFile(filePath) {
|
|
|
219
219
|
* @param projectDir - Absolute path to the project directory Lisa will reconcile
|
|
220
220
|
* @param lisaDistDir - Absolute path to Lisa's dist directory (where index.js lives)
|
|
221
221
|
* @param parentPid - PID of the package-manager process to wait on (usually process.ppid)
|
|
222
|
+
* @param spawnFn - Optional spawn implementation; defaults to node:child_process spawn. Tests pass a vi.fn() spy here as a dependency-injection seam, avoiding the unreliable vi.doMock-on-builtins pattern that breaks under v8 coverage in CI runners.
|
|
222
223
|
* @returns Promise that resolves immediately after spawning the detached child
|
|
223
224
|
*/
|
|
224
|
-
export async function scheduleReconciliationChild(projectDir, lisaDistDir, parentPid
|
|
225
|
+
export async function scheduleReconciliationChild(projectDir, lisaDistDir, parentPid,
|
|
226
|
+
// Dependency-injection seam: callers can override the spawn function for
|
|
227
|
+
// testing. Default is the real node:child_process spawn. Production callers
|
|
228
|
+
// pass nothing; tests pass a vi.fn() spy and assert on it directly without
|
|
229
|
+
// relying on vi.doMock for node builtins (which is flaky in CI under v8
|
|
230
|
+
// coverage). The seam is invisible to production callers.
|
|
231
|
+
spawnFn = spawn) {
|
|
225
232
|
const nodeBin = process.execPath;
|
|
226
233
|
const lisaEntry = path.join(lisaDistDir, "index.js");
|
|
227
234
|
const trampolineSource = buildTrampolineSource({
|
|
@@ -235,7 +242,7 @@ export async function scheduleReconciliationChild(projectDir, lisaDistDir, paren
|
|
|
235
242
|
trampolineEnvVar: TRAMPOLINE_ENV_VAR,
|
|
236
243
|
lockfileRegenPlans: LOCKFILE_REGEN_PLANS,
|
|
237
244
|
});
|
|
238
|
-
const child =
|
|
245
|
+
const child = spawnFn(nodeBin, ["-e", trampolineSource], {
|
|
239
246
|
cwd: projectDir,
|
|
240
247
|
detached: true,
|
|
241
248
|
stdio: "ignore",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postinstall-trampoline.js","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"postinstall-trampoline.js","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"lodash": ">=4.18.1"
|
|
79
79
|
},
|
|
80
80
|
"name": "@codyswann/lisa",
|
|
81
|
-
"version": "2.
|
|
81
|
+
"version": "2.4.0",
|
|
82
82
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
83
83
|
"main": "dist/index.js",
|
|
84
84
|
"exports": {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: confluence-prd-intake
|
|
3
|
+
description: PRD intake agent for Confluence-hosted PRDs. Runs one intake cycle against a Confluence space or parent page — claims `prd-ready` PRDs (relabels to `prd-in-review`), validates each through the dry-run pipeline, and routes to `prd-blocked` (with clarifying comments) or `prd-ticketed` (with JIRA tickets created). Confluence counterpart of `notion-prd-intake`. Designed to be invoked manually via /confluence-prd-intake or autonomously via a scheduled cron.
|
|
4
|
+
skills:
|
|
5
|
+
- confluence-prd-intake
|
|
6
|
+
- confluence-to-jira
|
|
7
|
+
- jira-validate-ticket
|
|
8
|
+
- jira-source-artifacts
|
|
9
|
+
- product-walkthrough
|
|
10
|
+
- jira-write-ticket
|
|
11
|
+
- prd-ticket-coverage
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# PRD Intake Agent (Confluence)
|
|
15
|
+
|
|
16
|
+
You are a PRD intake agent. Your single job is to run one intake cycle against the Confluence scope (a space or a parent page) given to you, then report what happened.
|
|
17
|
+
|
|
18
|
+
This agent is the Confluence counterpart of `notion-prd-intake`. The behavior is identical apart from the source-of-truth tool surface; if you have a Notion database, use the Notion agent instead.
|
|
19
|
+
|
|
20
|
+
## Confirmation policy
|
|
21
|
+
|
|
22
|
+
Once you have a space or parent-page URL, RUN. Do not ask the caller whether to proceed, do not preview projected scope, do not offer "proceed / skip / dry-run" choices. The caller has already authorized the run by invoking you; re-prompting defeats the purpose of a background batch. `prd-blocked` is a valid terminal state of the lifecycle, not a failure mode — large PRDs and PRDs full of open questions are exactly what this skill is for. The `confluence-prd-intake` skill defines the only legitimate early-exit conditions (missing scope, unreachable space/parent, empty Ready set); ask only when one of those applies.
|
|
23
|
+
|
|
24
|
+
## Workflow
|
|
25
|
+
|
|
26
|
+
### 1. Receive the scope URL or key
|
|
27
|
+
|
|
28
|
+
The invoking caller (a slash command, a scheduled cron, or a parent agent) hands you a Confluence space URL/key or a parent page URL/ID. You do not pick the scope yourself.
|
|
29
|
+
|
|
30
|
+
If no scope is provided, stop and ask. Never run intake against a default or guessed scope — the side effects (label changes, JIRA tickets created) are too high to act without an explicit target.
|
|
31
|
+
|
|
32
|
+
### 2. Run the intake skill
|
|
33
|
+
|
|
34
|
+
Invoke the `confluence-prd-intake` skill with the scope as `$ARGUMENTS`. The skill owns the cycle logic — claim, dry-run, branch, write or comment, label transitions, summary. Do not duplicate that logic here.
|
|
35
|
+
|
|
36
|
+
Treat the skill's output as the source of truth. If it reports `prd-ticketed: 3 / prd-blocked: 1 / Errors: 0`, that's what you report.
|
|
37
|
+
|
|
38
|
+
### 3. Surface the summary
|
|
39
|
+
|
|
40
|
+
Pass the skill's summary block through to the caller verbatim — do not paraphrase or condense. The caller (often a human running `/confluence-prd-intake` ad-hoc, or a scheduled cron) needs the structured record:
|
|
41
|
+
|
|
42
|
+
- Total processed
|
|
43
|
+
- Per-PRD outcomes (`prd-ticketed` → which tickets created; `prd-blocked` → how many gate failures; Errors → reason)
|
|
44
|
+
- JIRA ticket count
|
|
45
|
+
|
|
46
|
+
If the cycle errored before processing any PRDs (e.g. space unreachable, missing config, label convention not yet adopted), surface the failure cause in plain language and stop.
|
|
47
|
+
|
|
48
|
+
### 4. Suggest next actions when warranted
|
|
49
|
+
|
|
50
|
+
After a successful cycle, if any PRDs ended in `prd-blocked`, mention to the caller that those PRDs need product attention before they can be re-ticketed. Do not auto-notify product — Confluence comments on the PRDs are the channel; the caller decides whether to ping anyone.
|
|
51
|
+
|
|
52
|
+
When reporting `prd-blocked` outcomes, distinguish the cause: **pre-write gate failure** (per-ticket validator caught a problem before any tickets were created) vs **post-write coverage gap** (tickets were created and remain in JIRA, but the PRD has uncovered requirements that the next intake cycle will address). Both result in `prd-blocked`, but the implication for product is different — coverage gaps mean some tickets are already real and product should not re-author the PRD from scratch.
|
|
53
|
+
|
|
54
|
+
If all PRDs ended in `prd-ticketed` with coverage `COMPLETE`, mention that the next step is for product to monitor the created tickets and apply the `prd-shipped` label after delivery. If any are `COMPLETE_WITH_SCOPE_CREEP`, point that out so product can review the flagged tickets.
|
|
55
|
+
|
|
56
|
+
## Rules
|
|
57
|
+
|
|
58
|
+
- **Never run a cycle without an explicit scope.** Side effects are too high to default.
|
|
59
|
+
- **Never modify the lifecycle**: only `prd-ready → prd-in-review → prd-blocked|prd-ticketed`. Never touch `prd-draft` or `prd-shipped`. Never invent new labels.
|
|
60
|
+
- **Never write JIRA tickets directly.** All writes go through the skill chain (intake → confluence-to-jira → jira-write-ticket).
|
|
61
|
+
- **Never edit a PRD's body.** Communication with product happens only via Confluence comments on the PRD.
|
|
62
|
+
- **Never start a second cycle while one is in flight against the same scope.** Serial execution; the scheduling layer is responsible for not double-firing.
|
|
63
|
+
- **Stop and surface failures rather than retry-loop.** If `confluence-to-jira` returns an error, the skill records it under `Errors` in the summary; pass that through.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Vendor-agnostic batch scanner for
|
|
3
|
-
argument-hint: "<Notion-PRD-database-URL | JIRA-project-key | JQL-filter>"
|
|
2
|
+
description: "Vendor-agnostic batch scanner for Ready queues. Notion PRD database URL → finds Status=Ready PRDs and runs lisa:plan per item. Confluence space or parent-page URL → finds prd-ready PRDs and runs lisa:plan per item. JIRA project key or JQL → finds Ready tickets and runs lisa:implement per item. Designed as the cron target for /schedule."
|
|
3
|
+
argument-hint: "<Notion-PRD-database-URL | Confluence-space-URL | Confluence-parent-page-URL | JIRA-project-key | JQL-filter>"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Use the /lisa:intake skill to scan the queue for
|
|
6
|
+
Use the /lisa:intake skill to scan the queue for Ready items and dispatch each one through the appropriate single-item lifecycle skill. $ARGUMENTS
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: confluence-prd-intake
|
|
3
|
+
description: "Scans a Confluence space (or a parent page) for PRD pages labelled `prd-ready` and runs each one through the dry-run validation pipeline. PRDs that pass every gate get tickets written and the label flipped to `prd-ticketed`; PRDs that fail get clarifying-question comments and the label flipped to `prd-blocked`. Confluence counterpart of `lisa:notion-prd-intake` — the workflow is identical; only the source-of-truth tools differ. Composes existing skills (confluence-to-jira, jira-validate-ticket, jira-source-artifacts, product-walkthrough)."
|
|
4
|
+
allowed-tools: ["Skill", "Bash", "mcp__atlassian__getConfluencePage", "mcp__atlassian__getConfluenceSpaces", "mcp__atlassian__getPagesInConfluenceSpace", "mcp__atlassian__getConfluencePageDescendants", "mcp__atlassian__searchConfluenceUsingCql", "mcp__atlassian__updateConfluencePage", "mcp__atlassian__createConfluenceFooterComment", "mcp__atlassian__createConfluenceInlineComment", "mcp__atlassian__getConfluencePageFooterComments", "mcp__atlassian__getConfluencePageInlineComments", "mcp__atlassian__getAccessibleAtlassianResources"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Confluence PRD Intake: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
`$ARGUMENTS` is one of:
|
|
10
|
+
|
|
11
|
+
- A Confluence **space** URL or space key — scans every page in the space whose labels include `prd-ready`. Example: `https://mycompany.atlassian.net/wiki/spaces/PRD` or `PRD`.
|
|
12
|
+
- A Confluence **parent page** URL or page ID — scans every descendant of the parent whose labels include `prd-ready`. Example: `https://mycompany.atlassian.net/wiki/spaces/PRD/pages/123456789/PRDs`.
|
|
13
|
+
|
|
14
|
+
Run one intake cycle against that scope. Each PRD with the `prd-ready` label is claimed, validated, and routed to either `prd-blocked` (with clarifying comments) or `prd-ticketed` (with JIRA tickets created).
|
|
15
|
+
|
|
16
|
+
This skill is the Confluence counterpart of `lisa:notion-prd-intake`. The phases, gates, comment templates, and rules are identical — the only differences are (1) the lifecycle is encoded as **page labels** instead of a Status property, and (2) the fetch / comment / update tools are Confluence MCP instead of Notion MCP. Keep the two skills behaviorally aligned: when changing intake logic, change BOTH skills together.
|
|
17
|
+
|
|
18
|
+
## Confirmation policy
|
|
19
|
+
|
|
20
|
+
Do NOT ask the caller whether to proceed. Once invoked with a space or parent-page URL, run the cycle to completion — claim, validate, branch to `prd-blocked` or `prd-ticketed`, write the summary. The caller (a human or a cron) has already authorized the run by invoking the skill; re-prompting defeats the purpose of a background batch.
|
|
21
|
+
|
|
22
|
+
Specifically forbidden:
|
|
23
|
+
|
|
24
|
+
- Previewing projected scope (epic count, story count, write count) and asking whether to continue.
|
|
25
|
+
- Offering A/B/C-style choices like "proceed / skip / dry-run only" — the documented behavior IS the default.
|
|
26
|
+
- Pausing because a PRD looks large, has many open questions, or is likely to end in `prd-blocked`. `prd-blocked` is a valid terminal state of this lifecycle, not a failure mode — routing a PRD to `prd-blocked` with gate-failure comments is exactly how this skill communicates "the PRD needs more work before it can be ticketed." That outcome is success.
|
|
27
|
+
- Pausing because the dry-run validation looks expensive. The cost of one cycle is bounded; the cost of stalling a scheduled cron waiting on a human is unbounded.
|
|
28
|
+
|
|
29
|
+
The only legitimate reasons to stop early:
|
|
30
|
+
|
|
31
|
+
- Missing space/parent argument or required configuration (`JIRA_PROJECT`, `JIRA_SERVER`, `E2E_BASE_URL`, etc.). Surface the missing value and exit.
|
|
32
|
+
- Space/parent unreachable, or the labelling convention not yet adopted (no PRDs carry any of `prd-ready` / `prd-in-review` / `prd-blocked` / `prd-ticketed`). Surface and exit.
|
|
33
|
+
- Empty `prd-ready` set. Exit cleanly with `"No PRDs labelled prd-ready. Nothing to do."`
|
|
34
|
+
|
|
35
|
+
## Lifecycle assumed
|
|
36
|
+
|
|
37
|
+
The Confluence PRD lifecycle is encoded as **page labels** (Confluence has no native status field). Exactly one of these labels is expected on a PRD page at any time:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
prd-draft → prd-ready → prd-in-review → prd-blocked | prd-ticketed → prd-shipped
|
|
41
|
+
(product) (us) (us) (product)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This skill ONLY transitions:
|
|
45
|
+
|
|
46
|
+
- `prd-ready` → `prd-in-review` (claim)
|
|
47
|
+
- `prd-in-review` → `prd-blocked` (gate failures or coverage gaps)
|
|
48
|
+
- `prd-in-review` → `prd-ticketed` (success)
|
|
49
|
+
|
|
50
|
+
It never adds, removes, or touches `prd-draft` or `prd-shipped`. Those labels are owned by product.
|
|
51
|
+
|
|
52
|
+
A "transition" means: remove the old lifecycle label and add the new one in a single `updateConfluencePage` call. The skill MUST verify that exactly one lifecycle label exists on the page after the update — having two simultaneously breaks idempotency.
|
|
53
|
+
|
|
54
|
+
If the project does not yet use `prd-*` labels, this skill cannot run. Adopting the convention is a one-time setup the project owner does (see "Adoption" at the bottom of this file).
|
|
55
|
+
|
|
56
|
+
## Phases
|
|
57
|
+
|
|
58
|
+
### Phase 1 — Resolve the scope
|
|
59
|
+
|
|
60
|
+
1. Parse `$ARGUMENTS`:
|
|
61
|
+
- Space URL → extract space key from `/wiki/spaces/<KEY>`.
|
|
62
|
+
- Bare space key → use as-is.
|
|
63
|
+
- Parent page URL → extract numeric page ID from `/pages/<ID>/...`.
|
|
64
|
+
- Bare page ID → use as-is.
|
|
65
|
+
2. Resolve Atlassian cloud ID via `mcp__atlassian__getAccessibleAtlassianResources` (downstream tools need it).
|
|
66
|
+
3. Verify the scope is reachable:
|
|
67
|
+
- For a space: call `mcp__atlassian__getConfluenceSpaces` and confirm the key resolves.
|
|
68
|
+
- For a parent page: call `mcp__atlassian__getConfluencePage` on the ID and confirm it loads.
|
|
69
|
+
|
|
70
|
+
### Phase 2 — Find Ready PRDs
|
|
71
|
+
|
|
72
|
+
Build a CQL query and call `mcp__atlassian__searchConfluenceUsingCql`:
|
|
73
|
+
|
|
74
|
+
- For a space: `space = "<KEY>" AND label = "prd-ready" AND type = page`
|
|
75
|
+
- For a parent: `ancestor = <PARENT-ID> AND label = "prd-ready" AND type = page`
|
|
76
|
+
|
|
77
|
+
The query returns the list of candidate pages with IDs and titles. For each candidate, confirm the label set on the page (CQL hits should be authoritative, but a follow-up `getConfluencePage` with labels included guards against eventual-consistency lag) and ensure exactly one lifecycle label is present.
|
|
78
|
+
|
|
79
|
+
If the result set is empty, run a secondary CQL to distinguish between a genuinely empty queue and a project that has not yet adopted the label convention:
|
|
80
|
+
|
|
81
|
+
- Secondary query (space scope): `space = "<KEY>" AND (label = "prd-ready" OR label = "prd-in-review" OR label = "prd-blocked" OR label = "prd-ticketed") AND type = page`
|
|
82
|
+
- Secondary query (parent scope): `ancestor = <PARENT-ID> AND (label = "prd-ready" OR label = "prd-in-review" OR label = "prd-blocked" OR label = "prd-ticketed") AND type = page`
|
|
83
|
+
|
|
84
|
+
If the secondary query also returns nothing → the `prd-*` label convention has not been adopted. Surface a misconfiguration message: `"No pages in this scope carry prd-* labels. If this is a new project, apply the prd-ready label to PRDs that are ready for ticketing (see Adoption section)."` Exit with an error — this is a setup issue, not a normal idle cycle.
|
|
85
|
+
|
|
86
|
+
If the secondary query returns results → the queue is genuinely empty (all PRDs are already in-review, blocked, ticketed, or shipped). Exit cleanly with `"No PRDs labelled prd-ready. Nothing to do."`
|
|
87
|
+
|
|
88
|
+
### Phase 3 — Process each Ready PRD
|
|
89
|
+
|
|
90
|
+
For each PRD page (process serially to keep label transitions auditable):
|
|
91
|
+
|
|
92
|
+
#### 3a. Claim
|
|
93
|
+
|
|
94
|
+
Transition labels via `mcp__atlassian__updateConfluencePage`: remove `prd-ready`, add `prd-in-review`. This is the idempotency lock — a re-entrant cycle running concurrently won't see this PRD because its CQL query filters on `label = "prd-ready"`.
|
|
95
|
+
|
|
96
|
+
If the update fails (permission error, version conflict / 409 race), log it and skip this PRD. Do not proceed to validation on a PRD you didn't successfully claim.
|
|
97
|
+
|
|
98
|
+
The `updateConfluencePage` call must preserve the page body; only the labels change. (If the MCP tool requires a full body in the update payload, fetch the current body via `getConfluencePage` immediately before the update and pass it back unchanged — preserving body content is non-negotiable, this skill never edits PRD content.)
|
|
99
|
+
|
|
100
|
+
#### 3b. Dry-run validation
|
|
101
|
+
|
|
102
|
+
Invoke the `lisa:confluence-to-jira` skill with `dry_run: true` and the PRD's URL. The skill returns a structured report containing:
|
|
103
|
+
- The planned ticket hierarchy
|
|
104
|
+
- Per-ticket validation verdicts and remediation
|
|
105
|
+
- An overall PASS / FAIL verdict
|
|
106
|
+
- A failure count
|
|
107
|
+
|
|
108
|
+
This call also indirectly invokes `lisa:jira-source-artifacts` (artifact extraction + classification) and `lisa:product-walkthrough` (when the PRD touches existing user-facing surfaces). All gate logic lives in `lisa:jira-validate-ticket`, which `lisa:confluence-to-jira` calls per ticket.
|
|
109
|
+
|
|
110
|
+
#### 3c. Branch on the verdict
|
|
111
|
+
|
|
112
|
+
**If `PASS`** (every planned ticket passed every applicable gate):
|
|
113
|
+
|
|
114
|
+
1. Re-invoke `lisa:confluence-to-jira` with `dry_run: false` to actually write the tickets. This re-runs Phases 1-5 and runs the preservation gate (Phase 5.5).
|
|
115
|
+
2. Capture the created ticket keys from the skill's output.
|
|
116
|
+
3. Post a Confluence **footer comment** on the PRD via `mcp__atlassian__createConfluenceFooterComment` listing the created tickets (epic, stories, sub-tasks) with their JIRA URLs. Lead with: `"Ticketed by Claude. Created N JIRA issues — see below. Add the prd-shipped label after the work is delivered."`
|
|
117
|
+
4. Transition labels: remove `prd-in-review`, add `prd-ticketed` via `updateConfluencePage`.
|
|
118
|
+
5. **Run Phase 3e (coverage audit)** before considering this PRD done.
|
|
119
|
+
|
|
120
|
+
**If `FAIL`** (one or more planned tickets failed one or more gates):
|
|
121
|
+
|
|
122
|
+
The audience for these comments is the **product team**, not engineers. They are not familiar with JIRA gate IDs, validator vocabulary, or skill internals. Follow the rules below strictly — the goal is for a non-engineer product owner to read a comment, understand what is unclear, and know what to do next.
|
|
123
|
+
|
|
124
|
+
##### 3c.1 Partition failures
|
|
125
|
+
|
|
126
|
+
1. Drop every failure where `product_relevant = false`. Those are internal data-quality problems — the agent should fix its own spec rather than ask product to clarify a missing core field. Record the dropped failures under `Errors` in the cycle summary so engineers can see them; never surface them on the PRD.
|
|
127
|
+
2. Group the remaining product-relevant failures by `prd_anchor` (the inline-comment anchor from `confluence-to-jira`'s dry-run report). Failures that share an anchor become one comment thread on that block. Failures with `prd_anchor: null` are batched into one footer comment, since they have no source section to attach to.
|
|
128
|
+
|
|
129
|
+
##### 3c.2 Render each comment
|
|
130
|
+
|
|
131
|
+
For each anchored group, post via `mcp__atlassian__createConfluenceInlineComment` with:
|
|
132
|
+
- `page_id`: the PRD page ID
|
|
133
|
+
- `inline_text` (or whatever the MCP tool calls the selection-anchor parameter): the `prd_anchor` value
|
|
134
|
+
- `body`: the comment body, formatted using the template below
|
|
135
|
+
|
|
136
|
+
For the unanchored group, post a single footer comment via `mcp__atlassian__createConfluenceFooterComment` using the same template, prefixed with `Issues without a specific section anchor:` and one block per failure.
|
|
137
|
+
|
|
138
|
+
If `createConfluenceInlineComment` returns "anchor not found" (the page text changed between fetch and post), fall back to a footer comment for that group. Do not silently drop the failure.
|
|
139
|
+
|
|
140
|
+
##### 3c.3 Comment template
|
|
141
|
+
|
|
142
|
+
Each comment body MUST contain these four parts, in this order, no exceptions:
|
|
143
|
+
|
|
144
|
+
```text
|
|
145
|
+
[<Category badge>] <prd_section heading text>
|
|
146
|
+
|
|
147
|
+
**What's unclear:** <validator's `what` field, verbatim — already product-readable>
|
|
148
|
+
|
|
149
|
+
**Recommendation:** <validator's `recommendation` field, verbatim — must contain 1–3 concrete options, never a generic "please clarify">
|
|
150
|
+
|
|
151
|
+
**Action:** Update this section in the PRD, then replace the `prd-blocked` label with `prd-ready` and Claude will re-run intake.
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
If multiple failures share an anchor, render each as its own `**What's unclear:** ... **Recommendation:** ...` block within the same comment, separated by horizontal lines (`---`). Keep the single `[Category badge]` heading at the top using the most-severe / most-blocking category from the group.
|
|
155
|
+
|
|
156
|
+
##### 3c.4 Category badges
|
|
157
|
+
|
|
158
|
+
Use these exact badge labels — they are the validator's category values translated for product readers:
|
|
159
|
+
|
|
160
|
+
| Validator category | Badge label |
|
|
161
|
+
|---------------------|-------------|
|
|
162
|
+
| `product-clarity` | `[Product clarity]` |
|
|
163
|
+
| `acceptance-criteria` | `[Acceptance criteria]` |
|
|
164
|
+
| `design-ux` | `[Design / UX]` |
|
|
165
|
+
| `scope` | `[Scope]` |
|
|
166
|
+
| `dependency` | `[Dependency]` |
|
|
167
|
+
| `data` | `[Data]` |
|
|
168
|
+
| `technical` | `[Technical]` |
|
|
169
|
+
|
|
170
|
+
`structural` failures must never reach this step (filtered in 3c.1). If you see one here, treat it as an Error and surface internally.
|
|
171
|
+
|
|
172
|
+
##### 3c.5 Forbidden in product comments
|
|
173
|
+
|
|
174
|
+
- Gate IDs (`S4`, `F2`, etc.). Never appear in a comment body.
|
|
175
|
+
- JIRA terminology that has no product meaning (e.g. "Gherkin", "epic parent", "issue link", "validation journey", "sub-task hierarchy"). Paraphrase before posting.
|
|
176
|
+
- Internal skill names (`lisa:jira-validate-ticket`, `confluence-to-jira`).
|
|
177
|
+
- Engineering shorthand (`AC`, `OOS`, `repo`, `env var`).
|
|
178
|
+
- "Clarify this" / "Please specify" without candidate resolutions. The validator is required to provide candidates; if `recommendation` is empty or vague, treat the failure as an Error and surface internally rather than posting a useless comment.
|
|
179
|
+
|
|
180
|
+
##### 3c.6 Label transition
|
|
181
|
+
|
|
182
|
+
After all comments are posted (anchored groups + the optional footer summary), transition labels: remove `prd-in-review`, add `prd-blocked` via `updateConfluencePage`. Do NOT write any JIRA tickets.
|
|
183
|
+
|
|
184
|
+
#### 3d. Continue
|
|
185
|
+
|
|
186
|
+
Move to the next Ready PRD. One PRD failing does not affect others.
|
|
187
|
+
|
|
188
|
+
#### 3e. Coverage audit (mandatory after prd-ticketed)
|
|
189
|
+
|
|
190
|
+
Per-ticket gates prove each ticket is well-formed; they do NOT prove the *set* of created tickets covers the *whole* PRD. Silent drops happen — invoke the `lisa:prd-ticket-coverage` skill to catch them.
|
|
191
|
+
|
|
192
|
+
1. Invoke `lisa:prd-ticket-coverage` with `<PRD URL> tickets=[<created ticket keys from 3c step 2>]`. The coverage skill auto-detects the PRD vendor from the URL.
|
|
193
|
+
2. Read the verdict:
|
|
194
|
+
|
|
195
|
+
| Verdict | Action |
|
|
196
|
+
|---------|--------|
|
|
197
|
+
| `COMPLETE` | Done. Leave label as `prd-ticketed`. Move to next PRD. |
|
|
198
|
+
| `COMPLETE_WITH_SCOPE_CREEP` | Post an advisory footer comment naming the scope-creep tickets (so product can decide whether to close them as out-of-scope). Leave label as `prd-ticketed`. |
|
|
199
|
+
| `GAPS_FOUND` | The created ticket set is incomplete. (a) For each gap, post a comment using the same product-facing template as Phase 3c.3 — inline-anchored when `prd_anchor` is non-null, footer otherwise; category badge from the gap's `category` field; `What's unclear` and `Recommendation` from the audit report's `what` and `recommendation` fields. Apply the same forbidden-language rules from Phase 3c.5. (b) Post one footer summary comment listing the tickets that *were* successfully created (so product knows what to keep vs. what to extend). (c) Transition labels from `prd-ticketed` back to `prd-blocked` via `updateConfluencePage`. |
|
|
200
|
+
| `NO_TICKETS_FOUND` | Should not happen if step 2 succeeded. If it does, log it as an Error in the cycle summary and leave label as `prd-ticketed` with a comment flagging the audit failure for human review. |
|
|
201
|
+
|
|
202
|
+
3. The created tickets remain in JIRA regardless of the verdict — they are valid in their own right. The audit only tells us whether *more* are needed.
|
|
203
|
+
|
|
204
|
+
### Phase 4 — Summary report
|
|
205
|
+
|
|
206
|
+
After processing every Ready PRD, emit a summary:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
## confluence-prd-intake summary
|
|
210
|
+
|
|
211
|
+
Scope: <space-key | parent-page-title> (<URL>)
|
|
212
|
+
Cycle started: <ISO timestamp>
|
|
213
|
+
Cycle completed: <ISO timestamp>
|
|
214
|
+
|
|
215
|
+
PRDs processed: <n>
|
|
216
|
+
- prd-ticketed: <n>
|
|
217
|
+
- <PRD title> → <epic-key> + <story-count> stories + <subtask-count> sub-tasks (coverage: COMPLETE | COMPLETE_WITH_SCOPE_CREEP)
|
|
218
|
+
- prd-blocked: <n>
|
|
219
|
+
- <PRD title> → <gate-failure-count> gate failures (pre-write) OR <gap-count> coverage gaps (post-write)
|
|
220
|
+
- Errors (claim failed, etc): <n>
|
|
221
|
+
- <PRD title> — <reason>
|
|
222
|
+
|
|
223
|
+
Total JIRA tickets created: <n>
|
|
224
|
+
Coverage audit summary: <n> COMPLETE / <n> COMPLETE_WITH_SCOPE_CREEP / <n> GAPS_FOUND
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Print to the agent's output. Do not write this summary to Confluence or JIRA — it's an operational record for the human.
|
|
228
|
+
|
|
229
|
+
## Idempotency & safety
|
|
230
|
+
|
|
231
|
+
- **Single-cycle scope**: this skill processes the `prd-ready` set as it exists at the start of Phase 2. New `prd-ready` PRDs added mid-cycle are picked up next run.
|
|
232
|
+
- **No writes outside the lifecycle**: this skill only ever writes to JIRA via `lisa:confluence-to-jira` (which delegates to `lisa:jira-write-ticket`), and only ever changes Confluence labels among `prd-in-review`, `prd-blocked`, `prd-ticketed`. It never edits PRD body content, never touches `prd-draft` or `prd-shipped`, never deletes pages.
|
|
233
|
+
- **Claim-first ordering**: the label flip to `prd-in-review` happens BEFORE validation runs, so a re-entrant call won't double-process.
|
|
234
|
+
- **Failure isolation**: an exception processing one PRD must not stop the cycle. Catch, record under "Errors" in the summary, continue to the next PRD. The PRD that errored is left labelled `prd-in-review` — the human investigates from there.
|
|
235
|
+
- **Single-label invariant**: after every transition, verify exactly one lifecycle label is present on the page. If two are present (rare race), surface as an Error and skip — do NOT auto-resolve, the human decides.
|
|
236
|
+
|
|
237
|
+
## Configuration
|
|
238
|
+
|
|
239
|
+
Same env vars as `lisa:confluence-to-jira` — `JIRA_PROJECT`, `JIRA_SERVER`, `CONFLUENCE_HOST`, `E2E_BASE_URL`, `E2E_TEST_PHONE`, `E2E_TEST_OTP`, `E2E_TEST_ORG`, `E2E_GRAPHQL_URL`. If any required value is missing, surface the missing key(s) and exit this cycle — never invent values.
|
|
240
|
+
|
|
241
|
+
## Rules
|
|
242
|
+
|
|
243
|
+
- Never write to JIRA outside of `lisa:confluence-to-jira` → `lisa:jira-write-ticket`. The validator's verdict gates progress; bypassing it produces broken tickets.
|
|
244
|
+
- Never add or remove a label this skill doesn't own (`prd-in-review`, `prd-blocked`, `prd-ticketed`). Product owns `prd-draft`, `prd-ready`, `prd-shipped`.
|
|
245
|
+
- Never edit the PRD's body. Communication with product happens only through Confluence comments. If `updateConfluencePage` requires a body in the payload, refetch and pass it back unchanged.
|
|
246
|
+
- Never post a single page-level dump of all gate failures. One inline comment per `prd_anchor` group (or one footer summary for unanchored failures only). Comments must be inline-anchored where possible, categorized, plain-language, and contain a concrete recommendation.
|
|
247
|
+
- Never include a gate ID, internal skill name, or engineering shorthand in a comment body.
|
|
248
|
+
- Never run more than one intake cycle concurrently against the same scope. This skill assumes serial execution.
|
|
249
|
+
- If `lisa:confluence-to-jira` returns errors, treat them as gate failures: comment + `prd-blocked`. Don't silently fail.
|
|
250
|
+
|
|
251
|
+
## Adoption (one-time per project)
|
|
252
|
+
|
|
253
|
+
Before this skill can run against a project, the project must adopt the `prd-*` label convention:
|
|
254
|
+
|
|
255
|
+
1. Apply `prd-ready` to PRDs that are ready for ticketing (replaces the Notion `Status = Ready` flip).
|
|
256
|
+
2. Reserve `prd-in-review`, `prd-blocked`, `prd-ticketed` for this skill — humans should not set them manually except to recover from an error.
|
|
257
|
+
3. (Optional but recommended) Add `prd-draft` for in-progress PRDs and `prd-shipped` for delivered work, so the full lifecycle is visible at a glance.
|
|
258
|
+
|
|
259
|
+
If the project hasn't adopted these labels, the first run exits with a label-convention error (not the idle empty-set message) — this distinguishes a setup issue from a genuinely empty queue so operators know to apply the convention rather than assuming the queue is drained. See Phase 2 for how the skill detects this case.
|