@codyswann/lisa 2.21.1 → 2.23.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 (152) hide show
  1. package/package.json +3 -2
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  4. package/plugins/lisa/agents/confluence-prd-intake.md +11 -9
  5. package/plugins/lisa/agents/github-agent.md +18 -10
  6. package/plugins/lisa/agents/github-build-intake.md +10 -8
  7. package/plugins/lisa/agents/github-prd-intake.md +11 -9
  8. package/plugins/lisa/agents/jira-agent.md +12 -8
  9. package/plugins/lisa/agents/jira-build-intake.md +9 -7
  10. package/plugins/lisa/agents/learnings-synthesizer.md +1 -1
  11. package/plugins/lisa/agents/linear-agent.md +15 -9
  12. package/plugins/lisa/agents/linear-build-intake.md +13 -11
  13. package/plugins/lisa/agents/linear-prd-intake.md +11 -9
  14. package/plugins/lisa/agents/notion-prd-intake.md +11 -9
  15. package/plugins/lisa/agents/pr-mining-specialist.md +1 -1
  16. package/plugins/lisa/agents/tracker-mining-specialist.md +1 -1
  17. package/plugins/lisa/commands/setup/atlassian.md +7 -0
  18. package/plugins/lisa/commands/setup/confluence.md +7 -0
  19. package/plugins/lisa/commands/setup/jira.md +7 -0
  20. package/plugins/lisa/commands/setup/notion.md +7 -0
  21. package/plugins/lisa/hooks/enforce-team-first.sh +14 -6
  22. package/plugins/lisa/rules/base-rules.md +3 -3
  23. package/plugins/lisa/rules/config-resolution.md +242 -24
  24. package/plugins/lisa/rules/intent-routing.md +4 -4
  25. package/plugins/lisa/rules/repo-scope-split.md +41 -0
  26. package/plugins/lisa/rules/verification.md +13 -0
  27. package/plugins/lisa/skills/atlassian-access/SKILL.md +260 -0
  28. package/plugins/lisa/skills/confluence-prd-intake/SKILL.md +167 -82
  29. package/plugins/lisa/skills/confluence-to-tracker/SKILL.md +39 -26
  30. package/plugins/lisa/skills/debrief/SKILL.md +4 -5
  31. package/plugins/lisa/skills/github-add-journey/SKILL.md +1 -0
  32. package/plugins/lisa/skills/github-build-intake/SKILL.md +104 -40
  33. package/plugins/lisa/skills/github-evidence/SKILL.md +22 -5
  34. package/plugins/lisa/skills/github-prd-intake/SKILL.md +87 -51
  35. package/plugins/lisa/skills/github-to-tracker/SKILL.md +2 -2
  36. package/plugins/lisa/skills/github-validate-issue/SKILL.md +11 -1
  37. package/plugins/lisa/skills/implement/SKILL.md +5 -6
  38. package/plugins/lisa/skills/intake/SKILL.md +5 -6
  39. package/plugins/lisa/skills/jira-add-journey/SKILL.md +1 -0
  40. package/plugins/lisa/skills/jira-build-intake/SKILL.md +110 -45
  41. package/plugins/lisa/skills/jira-create/SKILL.md +5 -3
  42. package/plugins/lisa/skills/jira-evidence/SKILL.md +19 -2
  43. package/plugins/lisa/skills/jira-journey/SKILL.md +3 -1
  44. package/plugins/lisa/skills/jira-read-ticket/SKILL.md +10 -8
  45. package/plugins/lisa/skills/jira-sync/SKILL.md +11 -5
  46. package/plugins/lisa/skills/jira-validate-ticket/SKILL.md +22 -10
  47. package/plugins/lisa/skills/jira-verify/SKILL.md +5 -3
  48. package/plugins/lisa/skills/jira-write-ticket/SKILL.md +16 -14
  49. package/plugins/lisa/skills/linear-add-journey/SKILL.md +1 -0
  50. package/plugins/lisa/skills/linear-build-intake/SKILL.md +90 -32
  51. package/plugins/lisa/skills/linear-evidence/SKILL.md +22 -5
  52. package/plugins/lisa/skills/linear-prd-intake/SKILL.md +92 -57
  53. package/plugins/lisa/skills/linear-validate-issue/SKILL.md +10 -0
  54. package/plugins/lisa/skills/monitor/SKILL.md +4 -5
  55. package/plugins/lisa/skills/notion-access/SKILL.md +193 -0
  56. package/plugins/lisa/skills/notion-prd-intake/SKILL.md +105 -46
  57. package/plugins/lisa/skills/notion-to-tracker/SKILL.md +7 -5
  58. package/plugins/lisa/skills/plan/SKILL.md +4 -5
  59. package/plugins/lisa/skills/research/SKILL.md +4 -5
  60. package/plugins/lisa/skills/setup-atlassian/SKILL.md +316 -0
  61. package/plugins/lisa/skills/setup-confluence/SKILL.md +245 -0
  62. package/plugins/lisa/skills/setup-jira/SKILL.md +198 -0
  63. package/plugins/lisa/skills/setup-notion/SKILL.md +283 -0
  64. package/plugins/lisa/skills/task-decomposition/SKILL.md +2 -0
  65. package/plugins/lisa/skills/ticket-triage/SKILL.md +4 -1
  66. package/plugins/lisa/skills/tracker-evidence/SKILL.md +1 -0
  67. package/plugins/lisa/skills/verification-lifecycle/SKILL.md +2 -0
  68. package/plugins/lisa/skills/verify/SKILL.md +4 -5
  69. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  71. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  73. package/plugins/lisa-expo/skills/ops-browser-uat/SKILL.md +1 -1
  74. package/plugins/lisa-expo/skills/ops-check-logs/SKILL.md +1 -1
  75. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  77. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  79. package/plugins/lisa-nestjs/skills/nestjs-graphql/references/project-patterns.md +48 -0
  80. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  82. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  84. package/plugins/src/base/agents/confluence-prd-intake.md +11 -9
  85. package/plugins/src/base/agents/github-agent.md +18 -10
  86. package/plugins/src/base/agents/github-build-intake.md +10 -8
  87. package/plugins/src/base/agents/github-prd-intake.md +11 -9
  88. package/plugins/src/base/agents/jira-agent.md +12 -8
  89. package/plugins/src/base/agents/jira-build-intake.md +9 -7
  90. package/plugins/src/base/agents/learnings-synthesizer.md +1 -1
  91. package/plugins/src/base/agents/linear-agent.md +15 -9
  92. package/plugins/src/base/agents/linear-build-intake.md +13 -11
  93. package/plugins/src/base/agents/linear-prd-intake.md +11 -9
  94. package/plugins/src/base/agents/notion-prd-intake.md +11 -9
  95. package/plugins/src/base/agents/pr-mining-specialist.md +1 -1
  96. package/plugins/src/base/agents/tracker-mining-specialist.md +1 -1
  97. package/plugins/src/base/commands/setup/atlassian.md +7 -0
  98. package/plugins/src/base/commands/setup/confluence.md +7 -0
  99. package/plugins/src/base/commands/setup/jira.md +7 -0
  100. package/plugins/src/base/commands/setup/notion.md +7 -0
  101. package/plugins/src/base/hooks/enforce-team-first.sh +14 -6
  102. package/plugins/src/base/rules/base-rules.md +3 -3
  103. package/plugins/src/base/rules/config-resolution.md +242 -24
  104. package/plugins/src/base/rules/intent-routing.md +4 -4
  105. package/plugins/src/base/rules/repo-scope-split.md +41 -0
  106. package/plugins/src/base/rules/verification.md +13 -0
  107. package/plugins/src/base/skills/atlassian-access/SKILL.md +260 -0
  108. package/plugins/src/base/skills/confluence-prd-intake/SKILL.md +167 -82
  109. package/plugins/src/base/skills/confluence-to-tracker/SKILL.md +39 -26
  110. package/plugins/src/base/skills/debrief/SKILL.md +4 -5
  111. package/plugins/src/base/skills/github-add-journey/SKILL.md +1 -0
  112. package/plugins/src/base/skills/github-build-intake/SKILL.md +104 -40
  113. package/plugins/src/base/skills/github-evidence/SKILL.md +22 -5
  114. package/plugins/src/base/skills/github-prd-intake/SKILL.md +87 -51
  115. package/plugins/src/base/skills/github-to-tracker/SKILL.md +2 -2
  116. package/plugins/src/base/skills/github-validate-issue/SKILL.md +11 -1
  117. package/plugins/src/base/skills/implement/SKILL.md +5 -6
  118. package/plugins/src/base/skills/intake/SKILL.md +5 -6
  119. package/plugins/src/base/skills/jira-add-journey/SKILL.md +1 -0
  120. package/plugins/src/base/skills/jira-build-intake/SKILL.md +110 -45
  121. package/plugins/src/base/skills/jira-create/SKILL.md +5 -3
  122. package/plugins/src/base/skills/jira-evidence/SKILL.md +19 -2
  123. package/plugins/src/base/skills/jira-journey/SKILL.md +3 -1
  124. package/plugins/src/base/skills/jira-read-ticket/SKILL.md +10 -8
  125. package/plugins/src/base/skills/jira-sync/SKILL.md +11 -5
  126. package/plugins/src/base/skills/jira-validate-ticket/SKILL.md +22 -10
  127. package/plugins/src/base/skills/jira-verify/SKILL.md +5 -3
  128. package/plugins/src/base/skills/jira-write-ticket/SKILL.md +16 -14
  129. package/plugins/src/base/skills/linear-add-journey/SKILL.md +1 -0
  130. package/plugins/src/base/skills/linear-build-intake/SKILL.md +90 -32
  131. package/plugins/src/base/skills/linear-evidence/SKILL.md +22 -5
  132. package/plugins/src/base/skills/linear-prd-intake/SKILL.md +92 -57
  133. package/plugins/src/base/skills/linear-validate-issue/SKILL.md +10 -0
  134. package/plugins/src/base/skills/monitor/SKILL.md +4 -5
  135. package/plugins/src/base/skills/notion-access/SKILL.md +193 -0
  136. package/plugins/src/base/skills/notion-prd-intake/SKILL.md +105 -46
  137. package/plugins/src/base/skills/notion-to-tracker/SKILL.md +7 -5
  138. package/plugins/src/base/skills/plan/SKILL.md +4 -5
  139. package/plugins/src/base/skills/research/SKILL.md +4 -5
  140. package/plugins/src/base/skills/setup-atlassian/SKILL.md +316 -0
  141. package/plugins/src/base/skills/setup-confluence/SKILL.md +245 -0
  142. package/plugins/src/base/skills/setup-jira/SKILL.md +198 -0
  143. package/plugins/src/base/skills/setup-notion/SKILL.md +283 -0
  144. package/plugins/src/base/skills/task-decomposition/SKILL.md +2 -0
  145. package/plugins/src/base/skills/ticket-triage/SKILL.md +4 -1
  146. package/plugins/src/base/skills/tracker-evidence/SKILL.md +1 -0
  147. package/plugins/src/base/skills/verification-lifecycle/SKILL.md +2 -0
  148. package/plugins/src/base/skills/verify/SKILL.md +4 -5
  149. package/plugins/src/expo/skills/ops-browser-uat/SKILL.md +1 -1
  150. package/plugins/src/expo/skills/ops-check-logs/SKILL.md +1 -1
  151. package/plugins/src/nestjs/skills/nestjs-graphql/references/project-patterns.md +48 -0
  152. package/scripts/check-plugins-sync.sh +45 -0
@@ -1,101 +1,176 @@
1
1
  ---
2
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-tracker, tracker-validate, tracker-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"]
3
+ description: "Scans a Confluence space (or a parent page) for PRD pages currently parented under the configured `ready` lifecycle page and runs each one through the dry-run validation pipeline. PRDs that pass every gate get tickets written and are re-parented under the `ticketed` lifecycle page; PRDs that fail get clarifying-question comments and are re-parented under the `blocked` lifecycle page. Confluence counterpart of `lisa:notion-prd-intake` — the workflow is identical; only the source-of-truth tools and the state encoding differ (parent-page re-parenting instead of a status property). Composes existing skills (confluence-to-tracker, tracker-validate, tracker-source-artifacts, product-walkthrough)."
4
+ allowed-tools: ["Skill", "Bash"]
5
5
  ---
6
6
 
7
7
  # Confluence PRD Intake: $ARGUMENTS
8
8
 
9
+ All Atlassian operations in this skill go through `lisa:atlassian-access`. Do not call MCP tools or `acli` directly.
10
+
9
11
  `$ARGUMENTS` is one of:
10
12
 
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
+ - A Confluence **space** URL or space key — used as the surrounding scope sanity check. Example: `https://mycompany.atlassian.net/wiki/spaces/PRD` or `PRD`.
14
+ - A Confluence **parent page** URL or page ID — overrides the configured `confluence.parents.ready` page for this run (useful when an operator wants to drain an alternative lifecycle parent). Example: `https://mycompany.atlassian.net/wiki/spaces/PRD/pages/123456789/PRDs`.
15
+ - Empty — use `confluence.parents.ready` from `.lisa.config.json` as the scope.
16
+
17
+ Run one intake cycle against the resolved `ready` lifecycle parent. Each direct child of that parent is treated as a PRD currently in the `ready` state. Each PRD is claimed (re-parented to `in_review`), validated, and routed to either the `blocked` parent (with clarifying comments) or the `ticketed` parent (with destination tickets created).
18
+
19
+ ## Why parent pages, not labels
20
+
21
+ GitHub and Linear PRD lifecycles use labels (`prd-ready` / `prd-in-review` / etc.). Confluence does NOT — it uses parent pages instead. Scoped Atlassian API tokens (the only secure form Atlassian offers) cannot write Confluence labels via the v1 endpoint, and the v2 Label API group has no POST endpoint at all. Parent-id transitions, by contrast, are first-class in v2 and work with `write:page:confluence` scope. See `config-resolution` rule, section "Confluence PRD lifecycle uses parent pages, not labels," for the full rationale.
22
+
23
+ ## Workflow resolution
24
+
25
+ Lifecycle parent-page IDs are read from `.lisa.config.json` `confluence.parents.*`. Local overrides global per-key. Bash pattern:
26
+
27
+ ```bash
28
+ # Read a lifecycle parent-page id by role. Local overrides global per-key.
29
+ read_parent_id() {
30
+ local role="$1"
31
+ local local_v global_v
32
+ local_v=$(jq -r ".confluence.parents.${role} // empty" .lisa.config.local.json 2>/dev/null)
33
+ global_v=$(jq -r ".confluence.parents.${role} // empty" .lisa.config.json 2>/dev/null)
34
+ echo "${local_v:-$global_v}"
35
+ }
36
+
37
+ READY_PARENT=$(read_parent_id ready)
38
+ IN_REVIEW_PARENT=$(read_parent_id in_review)
39
+ BLOCKED_PARENT=$(read_parent_id blocked)
40
+ TICKETED_PARENT=$(read_parent_id ticketed)
41
+ SHIPPED_PARENT=$(read_parent_id shipped)
42
+ DRAFT_PARENT=$(read_parent_id draft)
43
+
44
+ # Fail fast if any required role is unmapped — the lifecycle scaffolding hasn't been provisioned.
45
+ for role in ready in_review blocked ticketed; do
46
+ if [ -z "$(read_parent_id "$role")" ]; then
47
+ echo "Error: confluence.parents.${role} is not set in .lisa.config.json. Run /lisa:setup:confluence to provision the lifecycle parent pages." >&2
48
+ exit 1
49
+ fi
50
+ done
51
+
52
+ # Reverse-lookup: given a page's parentId, return which lifecycle role it currently occupies.
53
+ current_role_for_prd() {
54
+ local parent_id="$1"
55
+ for role in draft ready in_review blocked ticketed shipped; do
56
+ if [ "$(read_parent_id "$role")" = "$parent_id" ]; then
57
+ echo "$role"; return
58
+ fi
59
+ done
60
+ echo "unknown"
61
+ }
62
+ ```
13
63
 
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).
64
+ In prose below, the role names refer to the resolved parent-page IDs: e.g. "the `ready` parent" means whatever `confluence.parents.ready` resolves to.
15
65
 
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.
66
+ 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 **parent-page placement** instead of a status property, and (2) the fetch / comment / update tools route through `lisa:atlassian-access`. Keep the two skills behaviorally aligned: when changing intake logic, change BOTH skills together.
17
67
 
18
68
  ## Confirmation policy
19
69
 
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.
70
+ Do NOT ask the caller whether to proceed. Once invoked, run the cycle to completion — claim, validate, branch to the `blocked` or `ticketed` parent, 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
71
 
22
72
  Specifically forbidden:
23
73
 
24
74
  - Previewing projected scope (epic count, story count, write count) and asking whether to continue.
25
75
  - 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.
76
+ - Pausing because a PRD looks large, has many open questions, or is likely to end under the `blocked` parent. The `blocked` parent is a valid terminal state of this lifecycle, not a failure mode — routing a PRD there 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
77
  - 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
78
 
29
79
  The only legitimate reasons to stop early:
30
80
 
31
- - Missing space/parent argument or required configuration (`atlassian.cloudId` in `.lisa.config.json`, `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."`
81
+ - Missing required configuration (`atlassian.cloudId`, `confluence.parents.{ready,in_review,blocked,ticketed}` in `.lisa.config.json`, `E2E_BASE_URL`, etc.). Surface the missing value and exit.
82
+ - Lifecycle parent unreachable. Surface and exit.
83
+ - Empty ready set. Exit cleanly with `"No PRDs currently parented under the 'ready' lifecycle page. Nothing to do."`
34
84
 
35
85
  ## Lifecycle assumed
36
86
 
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:
87
+ The Confluence PRD lifecycle is encoded as **parent-page placement** Confluence has no native status field, and scoped API tokens cannot write labels. Each lifecycle role corresponds to a dedicated parent page in the project's Confluence space:
38
88
 
39
89
  ```text
40
- prd-draft → prd-ready → prd-in-reviewprd-blocked | prd-ticketed → prd-shipped
41
- (product) (us) (us) (product)
90
+ draft → ready → in_review → blocked | ticketed → shipped
91
+ (product) (us) (us) (product)
42
92
  ```
43
93
 
94
+ A PRD's current state is determined entirely by which lifecycle parent it sits under. Re-parenting is the transition.
95
+
44
96
  This skill ONLY transitions:
45
97
 
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)
98
+ - `ready` → `in_review` (claim)
99
+ - `in_review` → `blocked` (gate failures or coverage gaps)
100
+ - `in_review` → `ticketed` (success)
49
101
 
50
- It never adds, removes, or touches `prd-draft` or `prd-shipped`. Those labels are owned by product.
102
+ It never re-parents PRDs into or out of the `draft` or `shipped` parents. Those parents are owned by product.
51
103
 
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 updatehaving two simultaneously breaks idempotency.
104
+ A "transition" means: update the PRD's `parentId` to the new role's parent-page id via `lisa:atlassian-access` `operation: write-page payload: { id, parentId, title, version: { number: <next> } }`. The v2 PUT endpoint requires the next version number and the page title in the payload; the body content is not strictly required for a re-parent-only edit, but some Atlassian deployments reject PUTs without a body. The skill MUST therefore GET the page first via `read-page`, capture title + current version + current body, then PUT with `parentId` swapped and `version.number` bumped preserving body content is non-negotiable, this skill never edits PRD content. See `transition_prd` helper in Phase 3a for the canonical implementation.
53
105
 
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).
106
+ If the project does not yet have the lifecycle parent pages provisioned, this skill cannot run. Provisioning is a one-time setup the project owner does (see "Adoption" at the bottom of this file).
55
107
 
56
108
  ## Phases
57
109
 
58
110
  ### Phase 1 — Resolve the scope
59
111
 
60
112
  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`:
113
+ - Space URL → extract space key from `/wiki/spaces/<KEY>`. (Used only as a sanity check that the operator's scope matches the configured space.)
114
+ - Bare space key → same.
115
+ - Parent page URL → extract numeric page ID from `/pages/<ID>/...`; use as the override for `READY_PARENT` for this run.
116
+ - Bare page ID → same.
117
+ - Empty use `confluence.parents.ready` from config as `READY_PARENT`.
118
+ 2. Confirm the configured Atlassian site by invoking `lisa:atlassian-access` `operation: list-sites` (it enforces connection match against `.lisa.config.json`).
119
+ 3. Verify `READY_PARENT` is reachable: invoke `lisa:atlassian-access` `operation: read-page id: $READY_PARENT` and confirm it loads. If 404, surface a provisioning error and exit.
73
120
 
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`
121
+ ### Phase 2 Find ready PRDs
76
122
 
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.
123
+ Invoke `lisa:atlassian-access` `operation: read-page-descendants id: $READY_PARENT` and take the **direct children** (depth 1) of the ready lifecycle parent. Those are the PRDs currently in the `ready` state. Capture each child's id and title.
78
124
 
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:
125
+ For each candidate, follow up with `lisa:atlassian-access` `operation: read-page id: <PAGE-ID>` and read its `parentId` to confirm it is still parented under `$READY_PARENT` (guards against eventual-consistency lag and concurrent re-parenting by another operator).
80
126
 
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`
127
+ If the result set is empty, run a sanity probe across the other lifecycle parents to distinguish between a genuinely empty queue and a project where the lifecycle scaffolding is misconfigured:
83
128
 
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.
129
+ - For each of `IN_REVIEW_PARENT`, `BLOCKED_PARENT`, `TICKETED_PARENT`: invoke `read-page-descendants id: <parent>` and count direct children.
130
+ - If every lifecycle parent has zero direct children → the lifecycle scaffolding is provisioned but unused, OR PRDs are still parented under the legacy structure. Surface: `"No PRDs found under any of the configured lifecycle parent pages (ready, in_review, blocked, ticketed). If this is a new project, move PRDs that are ready for ticketing under the configured 'ready' parent page (see Adoption section)."` Exit with an error — this is a setup / migration issue, not a normal idle cycle.
131
+ - If any non-ready parent has children → the queue is genuinely empty (PRDs exist but are in `in_review`, `blocked`, `ticketed`, or `shipped`). Exit cleanly with `"No PRDs currently parented under the 'ready' lifecycle page. Nothing to do."`
85
132
 
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."`
133
+ ### Phase 3 Process each ready PRD
87
134
 
88
- ### Phase 3 Process each Ready PRD
89
-
90
- For each PRD page (process serially to keep label transitions auditable):
135
+ For each PRD page (process serially to keep transitions auditable):
91
136
 
92
137
  #### 3a. Claim
93
138
 
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"`.
139
+ Transition the PRD from `ready` to `in_review` by re-parenting it:
140
+
141
+ ```bash
142
+ # Pseudo-code; the actual call is a Skill tool invocation of lisa:atlassian-access.
143
+ #
144
+ # NOTE: the v2 PUT endpoint that backs write-page requires:
145
+ # - id
146
+ # - title (unchanged)
147
+ # - version.number (current + 1)
148
+ # - parentId (the new lifecycle parent)
149
+ # - body (some deployments reject PUTs without a body; preserving the body
150
+ # also matches this skill's invariant of never editing PRD content)
151
+ # We therefore GET-then-PUT: fetch via read-page to capture title, version,
152
+ # and body, then write-page with parentId swapped.
153
+ transition_prd() {
154
+ local prd_id="$1" target_role="$2"
155
+ local new_parent
156
+ new_parent=$(read_parent_id "$target_role")
157
+ # 1. read-page id: $prd_id -> capture title, version.number (=N), body.storage.value
158
+ # 2. write-page payload: {
159
+ # "id": "$prd_id",
160
+ # "title": "<unchanged>",
161
+ # "parentId": "$new_parent",
162
+ # "version": { "number": N+1 },
163
+ # "body": { "storage": { "value": "<unchanged>", "representation": "storage" } }
164
+ # }
165
+ }
166
+
167
+ # Claim:
168
+ transition_prd "$PRD_ID" in_review
169
+ ```
95
170
 
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.
171
+ This re-parent is the idempotency lock a re-entrant cycle running concurrently won't see this PRD because `read-page-descendants id: $READY_PARENT` no longer includes it once parentId has moved.
97
172
 
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.)
173
+ 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.
99
174
 
100
175
  #### 3b. Dry-run validation
101
176
 
@@ -113,8 +188,8 @@ This call also indirectly invokes `lisa:tracker-source-artifacts` (artifact extr
113
188
 
114
189
  1. Re-invoke `lisa:confluence-to-tracker` with `dry_run: false` to actually write the tickets. This re-runs Phases 1-5 and runs the preservation gate (Phase 5.5).
115
190
  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`.
191
+ 3. Post a Confluence **footer comment** on the PRD via `lisa:atlassian-access` `operation: comment-page id: <PAGE-ID> kind: footer body: "..."` listing the created tickets (epic, stories, sub-tasks) with their JIRA URLs. Lead with: `"Ticketed by Claude. Created N JIRA issues — see below. Move this page under the 'shipped' lifecycle parent after the work is delivered."`
192
+ 4. Re-parent to `ticketed`: `transition_prd "$PRD_ID" ticketed`.
118
193
  5. **Run Phase 3e (coverage audit)** before considering this PRD done.
119
194
 
120
195
  **If `FAIL`** (one or more planned tickets failed one or more gates):
@@ -128,14 +203,14 @@ The audience for these comments is the **product team**, not engineers. They are
128
203
 
129
204
  ##### 3c.2 Render each comment
130
205
 
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
206
+ For each anchored group, invoke `lisa:atlassian-access` `operation: comment-page kind: inline` with:
207
+ - `id`: the PRD page ID
208
+ - `anchor`: the `prd_anchor` value (the substring the inline comment will be attached to)
134
209
  - `body`: the comment body, formatted using the template below
135
210
 
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.
211
+ For the unanchored group, post a single footer comment via `lisa:atlassian-access` `operation: comment-page kind: footer body: "..."` using the same template, prefixed with `Issues without a specific section anchor:` and one block per failure.
137
212
 
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.
213
+ If the inline comment call returns "anchor not found" (the page text changed between fetch and post), fall back to a footer comment for that group via the same access skill operation. Do not silently drop the failure.
139
214
 
140
215
  ##### 3c.3 Comment template
141
216
 
@@ -148,7 +223,7 @@ Each comment body MUST contain these four parts, in this order, no exceptions:
148
223
 
149
224
  **Recommendation:** <validator's `recommendation` field, verbatim — must contain 1–3 concrete options, never a generic "please clarify">
150
225
 
151
- **Action:** Update this section in the PRD, then replace the `prd-blocked` label with `prd-ready` and Claude will re-run intake.
226
+ **Action:** Update this section in the PRD, then move the page back under the 'ready' lifecycle parent and Claude will re-run intake.
152
227
  ```
153
228
 
154
229
  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.
@@ -177,15 +252,15 @@ Use these exact badge labels — they are the validator's category values transl
177
252
  - Engineering shorthand (`AC`, `OOS`, `repo`, `env var`).
178
253
  - "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
254
 
180
- ##### 3c.6 Label transition
255
+ ##### 3c.6 Lifecycle transition
181
256
 
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.
257
+ After all comments are posted (anchored groups + the optional footer summary), re-parent the PRD to the `blocked` lifecycle parent: `transition_prd "$PRD_ID" blocked`. Do NOT write any destination tickets.
183
258
 
184
259
  #### 3d. Continue
185
260
 
186
- Move to the next Ready PRD. One PRD failing does not affect others.
261
+ Move to the next ready PRD. One PRD failing does not affect others.
187
262
 
188
- #### 3e. Coverage audit (mandatory after prd-ticketed)
263
+ #### 3e. Coverage audit (mandatory after re-parenting to `ticketed`)
189
264
 
190
265
  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
266
 
@@ -194,71 +269,81 @@ Per-ticket gates prove each ticket is well-formed; they do NOT prove the *set* o
194
269
 
195
270
  | Verdict | Action |
196
271
  |---------|--------|
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. |
272
+ | `COMPLETE` | Done. Leave PRD under `ticketed` parent. Move to next PRD. |
273
+ | `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 PRD under `ticketed` parent. |
274
+ | `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) Re-parent the PRD from `ticketed` back to `blocked`: `transition_prd "$PRD_ID" blocked`. |
275
+ | `NO_TICKETS_FOUND` | Should not happen if step 2 succeeded. If it does, log it as an Error in the cycle summary and leave the PRD under `ticketed` with a comment flagging the audit failure for human review. |
201
276
 
202
277
  3. The created tickets remain in the destination tracker regardless of the verdict — they are valid in their own right. The audit only tells us whether *more* are needed.
203
278
 
204
279
  ### Phase 4 — Summary report
205
280
 
206
- After processing every Ready PRD, emit a summary:
281
+ After processing every ready PRD, emit a summary:
207
282
 
208
283
  ```text
209
284
  ## confluence-prd-intake summary
210
285
 
211
- Scope: <space-key | parent-page-title> (<URL>)
286
+ Scope: ready parent = <READY_PARENT> (<URL>)
212
287
  Cycle started: <ISO timestamp>
213
288
  Cycle completed: <ISO timestamp>
214
289
 
215
290
  PRDs processed: <n>
216
- - prd-ticketed: <n>
291
+ - Ticketed: <n>
217
292
  - <PRD title> → <epic-key> + <story-count> stories + <subtask-count> sub-tasks (coverage: COMPLETE | COMPLETE_WITH_SCOPE_CREEP)
218
- - prd-blocked: <n>
293
+ - Blocked: <n>
219
294
  - <PRD title> → <gate-failure-count> gate failures (pre-write) OR <gap-count> coverage gaps (post-write)
220
295
  - Errors (claim failed, etc): <n>
221
296
  - <PRD title> — <reason>
222
297
 
223
- Total JIRA tickets created: <n>
298
+ Total destination tickets created: <n>
224
299
  Coverage audit summary: <n> COMPLETE / <n> COMPLETE_WITH_SCOPE_CREEP / <n> GAPS_FOUND
225
300
  ```
226
301
 
227
- Print to the agent's output. Do not write this summary to Confluence or JIRA — it's an operational record for the human.
302
+ Print to the agent's output. Do not write this summary to Confluence or the destination tracker — it's an operational record for the human.
228
303
 
229
304
  ## Idempotency & safety
230
305
 
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 the destination tracker via `lisa:confluence-to-tracker` (which delegates to `lisa:tracker-write`), 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.
306
+ - **Single-cycle scope**: this skill processes the ready set as it exists at the start of Phase 2. New PRDs moved under the `ready` parent mid-cycle are picked up next run.
307
+ - **No writes outside the lifecycle**: this skill only ever writes to the destination tracker via `lisa:confluence-to-tracker` (which delegates to `lisa:tracker-write`), and only ever re-parents PRDs among `in_review`, `blocked`, and `ticketed` via `lisa:atlassian-access` `operation: write-page`. It never edits PRD body content, never re-parents into or out of `draft` / `shipped`, never deletes pages.
308
+ - **Claim-first ordering**: the re-parent to `in_review` happens BEFORE validation runs, so a re-entrant call won't double-process.
309
+ - **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 under whatever parent it currently occupies (usually `in_review` if claim succeeded) — the human investigates from there.
310
+ - **Single-parent invariant**: a page has exactly one parent by construction in Confluence the multi-state ambiguity that label-based systems can hit (two `prd-*` labels simultaneously) cannot occur here. After every transition, re-read the page and confirm `parentId` matches the expected role; if not, surface as an Error and skip.
236
311
 
237
312
  ## Configuration
238
313
 
239
314
  Same configuration as `lisa:confluence-to-tracker`. See that skill for the full table. Key items:
240
315
 
241
- - **From `.lisa.config.json`**: `atlassian.cloudId` (required for Confluence MCP), `confluence.spaceKey` and/or `confluence.parentPageId` (when `$ARGUMENTS` doesn't pin a specific page).
316
+ - **From `.lisa.config.json`**: `atlassian.cloudId` (required), `confluence.spaceKey` and/or `confluence.parentPageId` (for breadth-of-scope sanity checks), and `confluence.parents.{draft,ready,in_review,blocked,ticketed,shipped}` for the lifecycle parent-page IDs.
242
317
  - **From environment variables**: `E2E_BASE_URL`, `E2E_TEST_PHONE`, `E2E_TEST_OTP`, `E2E_TEST_ORG`, `E2E_GRAPHQL_URL` (operational E2E test config).
243
318
 
244
319
  Destination tracker config (jira / github / linear) is consumed by `lisa:tracker-write` internally — this skill does NOT read it. If any required value is missing, surface the missing key(s) and exit this cycle — never invent values.
245
320
 
321
+ | Field | Required | Purpose |
322
+ |-------|----------|---------|
323
+ | `.lisa.config.json` `confluence.parents.ready` | yes | Parent page id for "ready for ticketing" |
324
+ | `.lisa.config.json` `confluence.parents.in_review` | yes | Parent page id for "claimed by the agent" |
325
+ | `.lisa.config.json` `confluence.parents.blocked` | yes | Parent page id for "validation failure" |
326
+ | `.lisa.config.json` `confluence.parents.ticketed` | yes | Parent page id for "successfully ticketed" |
327
+ | `.lisa.config.json` `confluence.parents.draft` | recommended | Parent page id for PRDs still being drafted by product |
328
+ | `.lisa.config.json` `confluence.parents.shipped` | recommended | Parent page id for delivered PRDs |
329
+
246
330
  ## Rules
247
331
 
248
332
  - Never write to the destination tracker outside of `lisa:confluence-to-tracker` → `lisa:tracker-write`. The validator's verdict gates progress; bypassing it produces broken tickets.
249
- - 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`.
250
- - 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.
333
+ - Never re-parent a PRD into a lifecycle parent this skill doesn't own (`in_review`, `blocked`, `ticketed`). Product owns `draft`, `ready` (as the entry signal), and `shipped`.
334
+ - Never edit the PRD's body. Communication with product happens only through Confluence comments. The `write-page` call preserves the body verbatim fetch then PUT with body unchanged.
251
335
  - 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.
252
336
  - Never include a gate ID, internal skill name, or engineering shorthand in a comment body.
253
337
  - Never run more than one intake cycle concurrently against the same scope. This skill assumes serial execution.
254
- - If `lisa:confluence-to-tracker` returns errors, treat them as gate failures: comment + `prd-blocked`. Don't silently fail.
338
+ - If `lisa:confluence-to-tracker` returns errors, treat them as gate failures: comment + re-parent to `blocked`. Don't silently fail.
255
339
 
256
340
  ## Adoption (one-time per project)
257
341
 
258
- Before this skill can run against a project, the project must adopt the `prd-*` label convention:
342
+ Before this skill can run against a project, the project must adopt the lifecycle parent-page convention:
259
343
 
260
- 1. Apply `prd-ready` to PRDs that are ready for ticketing (replaces the Notion `Status = Ready` flip).
261
- 2. Reserve `prd-in-review`, `prd-blocked`, `prd-ticketed` for this skill humans should not set them manually except to recover from an error.
262
- 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.
344
+ 1. Create six pages in the project's Confluence space, one per lifecycle role: `Draft`, `Ready`, `In Review`, `Blocked`, `Ticketed`, `Shipped`. (Page titles are not significant they exist to be re-parenting targets.)
345
+ 2. Record each page's numeric id in `.lisa.config.json` under `confluence.parents.<role>`. `/lisa:setup:confluence` automates this.
346
+ 3. Move each existing PRD page under the appropriate lifecycle parent based on its current state. Product moves PRDs from `draft` `ready` when they are ready for ticketing (replaces the Notion `Status = Ready` flip).
347
+ 4. Reserve the `in_review`, `blocked`, and `ticketed` parents for this skill — humans should not re-parent PRDs into them manually except to recover from an error.
263
348
 
264
- 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.
349
+ If the project hasn't adopted these parent pages, the first run exits with a provisioning error (not the idle empty-set message) — this distinguishes a setup issue from a genuinely empty queue so operators know to run `/lisa:setup:confluence` rather than assuming the queue is drained. See Phase 2 for how the skill detects this case.
@@ -7,11 +7,13 @@ description: >
7
7
  or similar. This skill mirrors `lisa:notion-to-tracker` for projects whose PRDs live in Confluence —
8
8
  the workflow, gates, dry-run mode, and validation rules are identical; only the source-of-truth tool
9
9
  surface differs (Confluence MCP instead of Notion MCP).
10
- allowed-tools: ["Skill", "Bash", "mcp__atlassian__getConfluencePage", "mcp__atlassian__getConfluencePageDescendants", "mcp__atlassian__getConfluencePageFooterComments", "mcp__atlassian__getConfluencePageInlineComments", "mcp__atlassian__getConfluenceCommentChildren", "mcp__atlassian__searchConfluenceUsingCql", "mcp__atlassian__getAccessibleAtlassianResources"]
10
+ allowed-tools: ["Skill", "Bash"]
11
11
  ---
12
12
 
13
13
  # Confluence PRD to Tracker Breakdown
14
14
 
15
+ All Atlassian operations in this skill go through `lisa:atlassian-access`. Do not call MCP tools or `acli` directly.
16
+
15
17
  Convert a Confluence PRD into a structured ticket hierarchy in the configured destination tracker (JIRA, GitHub Issues, or Linear per .lisa.config.json): Epics > Stories > Sub-tasks.
16
18
  Each sub-task is scoped to exactly one repo and includes an empirical verification plan.
17
19
 
@@ -29,8 +31,9 @@ This skill supports two modes, controlled by a `dry_run` flag in `$ARGUMENTS`:
29
31
 
30
32
  Dry-run output format is identical to `lisa:notion-to-tracker`'s. Reuse the same fields, including
31
33
  `prd_anchor` and `prd_section`. The only difference: `prd_anchor` is the inline-comment anchor text
32
- that `createConfluenceInlineComment` accepts (typically the full selected substring; truncate if it
33
- exceeds the tool's max anchor length and emit `null` if no resolvable anchor exists).
34
+ that `lisa:atlassian-access` `operation: comment-page kind: inline` accepts (typically the full
35
+ selected substring; truncate if it exceeds the substrate's max anchor length and emit `null` if no
36
+ resolvable anchor exists).
34
37
 
35
38
  ```text
36
39
  ## confluence-to-tracker dry-run: <PRD title>
@@ -63,13 +66,21 @@ exceeds the tool's max anchor length and emit `null` if no resolvable anchor exi
63
66
  ### Total failures: <n>
64
67
  ```
65
68
 
66
- The dry-run mode never writes to JIRA and never calls `mcp__atlassian__createJiraIssue`. It also never
67
- modifies the source Confluence page, never adds/removes labels, and never posts comments — that is the
69
+ The dry-run mode never writes to the destination tracker. It also never modifies the source Confluence
70
+ page, never re-parents the PRD between lifecycle parents, and never posts comments — that is the
68
71
  orchestrating skill's responsibility (`lisa:confluence-prd-intake`).
69
72
 
73
+ ## PRD lifecycle is parent-page-based on Confluence
74
+
75
+ Unlike GitHub and Linear (which use labels for PRD lifecycle state), Confluence encodes PRD lifecycle as **parent-page placement**: each lifecycle role (`draft`, `ready`, `in_review`, `blocked`, `ticketed`, `shipped`) corresponds to a dedicated parent page in the project's Confluence space, listed in `.lisa.config.json` under `confluence.parents.<role>`. A PRD's current state is determined by which of those parents it sits under; a "transition" is a `PUT /wiki/api/v2/pages/{id}` that swaps `parentId`.
76
+
77
+ This skill itself does NOT transition the PRD between lifecycle parents — that is the orchestrating skill's job (`lisa:confluence-prd-intake`). This skill consumes the PRD content and produces tickets; lifecycle state changes (`ready` → `in_review`, `in_review` → `ticketed` / `blocked`) happen in the orchestrator, before and after this skill runs.
78
+
79
+ Why parent-page-based, not label-based: scoped Atlassian API tokens cannot write Confluence labels via the v1 endpoint, and the v2 Label API group has no POST endpoint at all. Parent-id transitions, by contrast, are first-class in v2 and work with `write:page:confluence` scope. See `config-resolution` rule, section "Confluence PRD lifecycle uses parent pages, not labels," for the full rationale.
80
+
70
81
  ## Hard Rule: All Writes Go Through `lisa:tracker-write`
71
82
 
72
- **Every JIRA ticket created by this skill — every epic, story, and sub-task — MUST be created by invoking the `lisa:tracker-write` skill. Never call `mcp__atlassian__createJiraIssue`, `mcp__atlassian__editJiraIssue`, `mcp__atlassian__createIssueLink`, or any other Atlassian write tool directly from this skill or from any sub-agent it spawns.**
83
+ **Every ticket created by this skill — every epic, story, and sub-task — MUST be created by invoking the `lisa:tracker-write` skill. Never invoke `lisa:atlassian-access` write operations (`write-ticket`, `link`, `comment`, `transition`) directly from this skill or from any sub-agent it spawns.**
73
84
 
74
85
  `lisa:tracker-write` enforces gates this skill does not:
75
86
  - 3-audience description (Context / Technical Approach / Acceptance Criteria)
@@ -80,7 +91,7 @@ orchestrating skill's responsibility (`lisa:confluence-prd-intake`).
80
91
  - Sign-in account and target environment recorded in description
81
92
  - Post-create verification
82
93
 
83
- Bypassing `lisa:tracker-write` produces thin tickets that the rest of the lifecycle (triage, ticket-verify, journey, evidence) treats as broken. The Atlassian read tools (`getJiraIssue`, `searchJiraIssuesUsingJql`, `getJiraIssueRemoteIssueLinks`, `getAccessibleAtlassianResources`, `getJiraProjectIssueTypesMetadata`, `getVisibleJiraProjects`, and the Confluence read endpoints listed in `allowed-tools` above) ARE allowed for context gathering and the Phase 5.5 preservation gate.
94
+ Bypassing `lisa:tracker-write` produces thin tickets that the rest of the lifecycle (triage, ticket-verify, journey, evidence) treats as broken. Read operations on Atlassian (ticket reads, JQL search, Confluence page reads, comment fetches) are still performed in this skill — but ONLY via `lisa:atlassian-access` (`operation: read-ticket | search-issues | read-page | search-pages | list-sites`), never via direct MCP tool calls or `acli`.
84
95
 
85
96
  ## Input
86
97
 
@@ -130,14 +141,15 @@ If env vars are not available, ask the user to provide them explicitly before pr
130
141
 
131
142
  ### Phase 1: Fetch & Analyze the PRD
132
143
 
133
- 1. **Resolve the Atlassian cloud ID** via `mcp__atlassian__getAccessibleAtlassianResources`. Confluence MCP calls require it.
134
- 2. **Fetch the main PRD page** via `mcp__atlassian__getConfluencePage` with the page ID. Capture body, labels, and child page references.
135
- 3. **Identify all Epic child pages** via `mcp__atlassian__getConfluencePageDescendants` (one level deep first; recurse if the PRD nests epics under a "Specs" parent).
136
- 4. **Fetch all Epic pages** in parallel via `getConfluencePage`.
137
- 5. **Fetch full comments** for the main page and every epic page in parallel:
138
- - `mcp__atlassian__getConfluencePageFooterComments` — page-level threaded comments (equivalent to Notion's page-level discussions)
139
- - `mcp__atlassian__getConfluencePageInlineComments` — block-anchored comments tied to specific text spans
140
- - For any comment with replies, walk the tree via `mcp__atlassian__getConfluenceCommentChildren` until exhausted
144
+ 1. **Confirm the configured Atlassian site** by invoking `lisa:atlassian-access` `operation: list-sites` (it enforces connection match against `.lisa.config.json`).
145
+ 2. **Fetch the main PRD page** by invoking `lisa:atlassian-access` `operation: read-page id: <PAGE-ID>`. Capture body, parent page id (used by `lisa:confluence-prd-intake` to determine the PRD's lifecycle state — see "PRD lifecycle is parent-page-based" below), and child page references.
146
+ 3. **Identify all Epic child pages** by invoking `lisa:atlassian-access` `operation: read-page-descendants id: <PAGE-ID>` (one level deep first; recurse if the PRD nests epics under a "Specs" parent). If `atlassian-access` does not yet expose `read-page-descendants`, request its addition (see report at bottom).
147
+ 4. **Fetch all Epic pages** in parallel via `lisa:atlassian-access` `operation: read-page id: <EPIC-PAGE-ID>`.
148
+ 5. **Fetch full comments** for the main page and every epic page in parallel via `lisa:atlassian-access`:
149
+ - `operation: read-page-comments id: <PAGE-ID> kind: footer` — page-level threaded comments (equivalent to Notion's page-level discussions)
150
+ - `operation: read-page-comments id: <PAGE-ID> kind: inline` — block-anchored comments tied to specific text spans
151
+ - For any comment with replies, walk the tree via `operation: read-comment-children id: <COMMENT-ID>` until exhausted
152
+ (If any of these read-comment operations is not yet in `atlassian-access`'s dispatch table, request their addition — they are intentionally listed here so the access skill can be extended.)
141
153
  6. **Synthesize decisions and blockers** from the PRD content + all comments:
142
154
  - Decisions already confirmed by the team (look for agreement in comment threads)
143
155
  - Open questions that need product/engineering input
@@ -180,13 +192,13 @@ Identical to `lisa:notion-to-tracker` Phase 2. Two complementary inputs ground P
180
192
 
181
193
  Skip 2b only when the work is purely backend with no user-visible surface, or affects a screen that does not yet exist in dev/prod.
182
194
 
183
- Walkthrough findings are attached to the originating Confluence PRD as a **footer comment** (Confluence has no general "page-level discussion attached to a heading" — footer comments are the page-level equivalent), via `mcp__atlassian__createConfluenceFooterComment`. Title the comment "Current product walkthrough — `<route>`". Inherited onto the resulting epic / stories under a `## Current Product` subsection.
195
+ Walkthrough findings are attached to the originating Confluence PRD as a **footer comment** (Confluence has no general "page-level discussion attached to a heading" — footer comments are the page-level equivalent), via `lisa:atlassian-access` `operation: comment-page id: <PAGE-ID> kind: footer body: "..."`. Title the comment "Current product walkthrough — `<route>`". Inherited onto the resulting epic / stories under a `## Current Product` subsection.
184
196
 
185
197
  ### Phase 3: Create Epics
186
198
 
187
199
  > **Mode guard**: In `dry_run: true` mode, do not invoke `lisa:tracker-write` in this phase. Instead, draft the epic spec (summary, description_body, artifacts) and validate it with `lisa:tracker-validate --spec-only`. Record the drafted spec (including a placeholder epic key like `DRY-RUN-EPIC-1`) for Phase 4 to use as parent references. In `dry_run: false` mode (default), proceed as described below.
188
200
 
189
- For each PRD epic, **invoke the `lisa:tracker-write` skill** (do not call `createJiraIssue` directly). Pass it everything it needs to enforce its quality gates:
201
+ For each PRD epic, **invoke the `lisa:tracker-write` skill** (do not invoke `lisa:atlassian-access` write operations directly). Pass it everything it needs to enforce its quality gates:
190
202
 
191
203
  - `project_key`: resolved by `lisa:tracker-write` from `.lisa.config.json`
192
204
  - `issue_type`: `Epic`
@@ -236,7 +248,7 @@ Capture each returned story key — Phase 5 needs it as the parent for sub-tasks
236
248
 
237
249
  **Auto-split cross-repo work before delegation.** For each candidate sub-task, apply `lisa:task-decomposition` step 1.5: if the work touches more than one repo, split it into one sub-task per repo under the same parent Story (e.g., `[backend-api] Add field` + `[mobile-app] Display field`), and encode the producer-before-consumer ordering via dependencies. Work units that may span repos (Epic, Story, Spike) stay as planned; work units that must be single-repo (Bug, Task, Sub-task, Improvement) are split now. Splitting is this skill's responsibility — the validator's S10 gate is `product_relevant: false` because cross-repo failures are decomposition errors caught here, not product questions sent back to the PRD.
238
250
 
239
- Delegate sub-task creation to **parallel agents** (one per epic or batch of stories) for efficiency. **Every spawned agent must invoke `lisa:tracker-write` for each sub-task — no agent may call `createJiraIssue` directly.**
251
+ Delegate sub-task creation to **parallel agents** (one per epic or batch of stories) for efficiency. **Every spawned agent must invoke `lisa:tracker-write` for each sub-task — no agent may invoke `lisa:atlassian-access` write operations directly.**
240
252
 
241
253
  Each sub-task MUST:
242
254
  1. **Be scoped to exactly ONE repo** — indicated in brackets in the summary: `[repo-name]`
@@ -293,16 +305,17 @@ When you encounter something the PRD + comments + codebase can't resolve:
293
305
 
294
306
  ## Agent Prompt Template for Sub-task Creation
295
307
 
296
- When delegating to agents, provide this context. **The "MUST invoke jira-write-ticket" instruction is load-bearing — do not edit it out when adapting this template.**
308
+ When delegating to agents, provide this context. **The "MUST invoke lisa:tracker-write" instruction is load-bearing — do not edit it out when adapting this template.**
297
309
 
298
310
  ```text
299
- Create JIRA sub-tasks in the [PROJECT] project at [CLOUD_ID].
311
+ Create sub-tasks in the [PROJECT] project.
300
312
 
301
313
  CRITICAL: For each sub-task, invoke the `lisa:tracker-write` skill via the Skill tool.
302
- Do NOT call `mcp__atlassian__createJiraIssue` directly. The `lisa:tracker-write` skill
303
- enforces required quality gates (Gherkin acceptance criteria, 3-audience description,
304
- single-repo scope, sign-in/environment fields, post-create verification). Bypassing it
305
- produces broken tickets that downstream skills (triage, journey, evidence) cannot use.
314
+ Do NOT invoke `lisa:atlassian-access` write operations (write-ticket / link / comment /
315
+ transition) directly. The `lisa:tracker-write` skill enforces required quality gates
316
+ (Gherkin acceptance criteria, 3-audience description, single-repo scope,
317
+ sign-in/environment fields, post-create verification). Bypassing it produces broken
318
+ tickets that downstream skills (triage, journey, evidence) cannot use.
306
319
 
307
320
  For each sub-task, invoke `lisa:tracker-write` with:
308
321
  - issue_type: "Sub-task"
@@ -320,10 +333,10 @@ For each sub-task, invoke `lisa:tracker-write` with:
320
333
  Each sub-task must:
321
334
  1. Be scoped to ONE repo only — repo named in brackets in the summary
322
335
  2. Include the Empirical Verification Plan in the description
323
- 3. Be created via `lisa:tracker-write`, not via direct MCP calls
336
+ 3. Be created via `lisa:tracker-write`, not via direct `lisa:atlassian-access` write operations
324
337
 
325
338
  If `lisa:tracker-write` rejects a sub-task, fix the input and re-invoke. Do NOT fall back
326
- to a direct `createJiraIssue` call to bypass the gate.
339
+ to a direct `lisa:atlassian-access` `operation: write-ticket` call to bypass the gate.
327
340
 
328
341
  Test user info: [credentials from config]
329
342
 
@@ -10,14 +10,13 @@ Walk the original Plan for `$ARGUMENTS`, mine the completed work items and their
10
10
 
11
11
  ## Orchestration: agent team
12
12
 
13
- If you are NOT already operating inside an agent team (no prior `TeamCreate` in this session, not spawned via `Agent` with `team_name`), the very first thing you do is create the team. Two tool calls only, in this exact order:
13
+ If you are NOT already operating inside an agent team (no prior successful team-creation tool call in this session, not spawned into a team context), the very first thing you do is establish team orchestration.
14
14
 
15
- 1. `ToolSearch` with `query: "select:TeamCreate"` `TeamCreate` is a deferred tool whose schema must be loaded before it can be invoked. A cold call returns `InputValidationError` and tempts a fallback to direct `Agent` calls, which bypasses the team.
16
- 2. `TeamCreate` — actually create the team.
15
+ Use `TeamCreate` if available. In Claude, if `TeamCreate` has not been loaded yet, first use `ToolSearch` with `query: "select:TeamCreate"` to load its schema. If `TeamCreate` is not available, use the current runtime's tool-discovery mechanism (for Codex, `tool_search`) to discover available multi-agent/team tools, then call the appropriate team creation tool. If no team creation tool is available, explicitly state that team orchestration is unavailable in this runtime, continue as the lead agent, and preserve the workflow's review, verification, and task-tracking obligations locally.
17
16
 
18
- Until `TeamCreate` returns successfully, do NOT call any of: `Agent`, `TaskCreate`, `Skill`, MCP tools (Atlassian / Linear / GitHub / Notion), `Read`, `Write`, `Edit`, `Bash`, `Grep`, `Glob`. Resolving the work-item set, fetching tickets, walking PRs — all of those are tasks for the team you are about to create, not for the lead session before the team exists.
17
+ Until the team is established or the no-team fallback has been declared, do NOT call any of: `Agent`, `TaskCreate`, `Skill`, MCP tools (Atlassian / Linear / GitHub / Notion), `Read`, `Write`, `Edit`, `Bash`, `Grep`, `Glob`. Resolving the work-item set, fetching tickets, walking PRs — all of those are tasks for the team you are about to create, not for the lead session before orchestration exists.
19
18
 
20
- If you ARE already inside an agent team (e.g., a teammate invoked this skill via the Skill tool), do NOT call `TeamCreate`the harness rejects double-creates. Continue within the existing team.
19
+ If you ARE already inside an agent team (e.g., a teammate invoked this skill via the Skill tool), do NOT create a second team many harnesses reject double-creates. Continue within the existing team.
21
20
 
22
21
  ## Input
23
22