@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,46 +1,73 @@
1
1
  ---
2
2
  name: notion-prd-intake
3
- description: "Scans a Notion PRD database for pages with Status=Ready and runs each one through the dry-run validation pipeline. PRDs that pass every gate get tickets written and Status=Ticketed; PRDs that fail get clarifying-question comments and Status=Blocked. The skill is the runtime for the ReadyIn Review Blocked|Ticketed lifecycle. Composes existing skills (notion-to-tracker, tracker-validate, tracker-source-artifacts, product-walkthrough); does not reimplement their logic."
4
- allowed-tools: ["Skill", "Bash", "mcp__claude_ai_Notion__notion-fetch", "mcp__claude_ai_Notion__notion-search", "mcp__claude_ai_Notion__notion-update-page", "mcp__claude_ai_Notion__notion-create-comment", "mcp__atlassian__getAccessibleAtlassianResources"]
3
+ description: "Scans a Notion PRD database for pages in the configured `ready` status and runs each one through the dry-run validation pipeline. PRDs that pass every gate get tickets written and the status flipped to the configured `ticketed` value; PRDs that fail get clarifying-question comments and the status flipped to the configured `blocked` value. The skill is the runtime for the readyin_reviewblocked|ticketed lifecycle. Composes existing skills (notion-to-tracker, tracker-validate, tracker-source-artifacts, product-walkthrough); does not reimplement their logic."
4
+ allowed-tools: ["Skill", "Bash", "Read", "Write", "Edit", "AskUserQuestion"]
5
5
  ---
6
6
 
7
7
  # Notion PRD Intake: $ARGUMENTS
8
8
 
9
+ > **Notion access policy**: all Notion operations in this skill go through `lisa:notion-access`. Do not call Notion REST APIs (`api.notion.com/...`), Notion MCP tools (`mcp__*notion*`), or the `@notionhq/client` library directly. Invoke `lisa:notion-access` via the Skill tool with an operation name and arguments per its dispatch table.
10
+
9
11
  `$ARGUMENTS` is a Notion database URL (or bare database ID) — for example:
10
12
 
11
13
  ```text
12
14
  https://www.notion.so/geminisports/28fd00244d7d47c5866876f7de48c0fe?v=34eba63a2800815891a3000c643f0ea8
13
15
  ```
14
16
 
15
- Run one intake cycle against that database. Each PRD with `Status = Ready` is claimed, validated, and routed to either `Blocked` (with clarifying comments) or `Ticketed` (with JIRA tickets created).
17
+ Run one intake cycle against that database. Each PRD in the configured `ready` status is claimed, validated, and routed to either `blocked` (with clarifying comments) or `ticketed` (with destination tickets created).
18
+
19
+ ## Workflow resolution
20
+
21
+ Status names are read from `.lisa.config.json` `notion.values.*`, falling back to defaults documented in the `config-resolution` rule. Bash pattern:
22
+
23
+ ```bash
24
+ # Read role with default fallback. Local overrides global per-key.
25
+ read_role() {
26
+ local role="$1" default="$2"
27
+ local local_v global_v
28
+ local_v=$(jq -r ".notion.values.${role} // empty" .lisa.config.local.json 2>/dev/null)
29
+ global_v=$(jq -r ".notion.values.${role} // empty" .lisa.config.json 2>/dev/null)
30
+ echo "${local_v:-${global_v:-$default}}"
31
+ }
32
+
33
+ DRAFT=$(read_role draft "Draft")
34
+ READY=$(read_role ready "Ready")
35
+ IN_REVIEW=$(read_role in_review "In Review")
36
+ BLOCKED=$(read_role blocked "Blocked")
37
+ TICKETED=$(read_role ticketed "Ticketed")
38
+ SHIPPED=$(read_role shipped "Shipped")
39
+ STATUS_PROP=$(jq -r '.notion.statusProperty // "Status"' .lisa.config.json 2>/dev/null)
40
+ ```
41
+
42
+ In prose below, the role names refer to the resolved values: e.g. "the `ready` status" means whatever `notion.values.ready` resolves to (default: `Ready`).
16
43
 
17
44
  ## Confirmation policy
18
45
 
19
- Do NOT ask the caller whether to proceed. Once invoked with a database URL, run the cycle to completion — claim, validate, branch to `Blocked` or `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.
46
+ Do NOT ask the caller whether to proceed. Once invoked with a database URL, run the cycle to completion — claim, validate, branch to `blocked` or `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.
20
47
 
21
48
  Specifically forbidden:
22
49
 
23
50
  - Previewing projected scope (epic count, story count, write count) and asking whether to continue.
24
51
  - Offering A/B/C-style choices like "proceed / skip / dry-run only" — the documented behavior IS the default.
25
- - Pausing because a PRD looks large, has many open questions, or is likely to end in `Blocked`. `Blocked` is a valid terminal state of this lifecycle, not a failure mode — routing a PRD to `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.
52
+ - Pausing because a PRD looks large, has many open questions, or is likely to end in the `blocked` status. The `blocked` status 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.
26
53
  - 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.
27
54
 
28
55
  The only legitimate reasons to stop early:
29
56
 
30
57
  - Missing database URL or required configuration (`atlassian.cloudId`, `jira.project` or destination-tracker equivalents in `.lisa.config.json`, `E2E_BASE_URL`, etc.). Surface the missing value and exit.
31
- - Database misconfigured (Status property missing expected values, data source unreachable). Surface and exit.
32
- - Empty `Ready` set. Exit cleanly with `"No PRDs with Status=Ready. Nothing to do."`
58
+ - Database misconfigured (status property missing expected values, data source unreachable). Surface and exit.
59
+ - Empty ready set. Exit cleanly with `"No PRDs with $STATUS_PROP=$READY. Nothing to do."`
33
60
 
34
61
  ## Lifecycle assumed
35
62
 
36
- The PRD database has a `Status` property whose value drives this skill:
63
+ The PRD database has a status property (configurable via `notion.statusProperty`, default `Status`) whose value drives this skill:
37
64
 
38
65
  ```text
39
- DraftReadyIn Review Blocked | TicketedShipped
66
+ draftreadyin_reviewblocked | ticketedshipped
40
67
  (product) (us) (us) (product)
41
68
  ```
42
69
 
43
- This skill ONLY transitions `ReadyIn Review`, then `In Review Blocked` or `In Review Ticketed`. Never touches `Draft` or `Shipped`.
70
+ This skill ONLY transitions `readyin_review`, then `in_reviewblocked` or `in_reviewticketed`. Never touches `draft` or `shipped`.
44
71
 
45
72
  ## Phases
46
73
 
@@ -49,24 +76,36 @@ This skill ONLY transitions `Ready → In Review`, then `In Review → Blocked`
49
76
  1. Parse `$ARGUMENTS`:
50
77
  - Full URL: extract the database ID from the path segment (the 32-hex-char ID after the last `/`, before `?`). Strip dashes if present. Ignore the `?v=...` view ID — we query the data source directly.
51
78
  - Bare ID: use as-is.
52
- 2. Call `mcp__claude_ai_Notion__notion-fetch` on the database ID. Capture:
53
- - The data source ID from `<data-source url="collection://...">` — needed for queries.
54
- - Confirm the schema includes a `Status` property of type `select` (or `status`) with the expected option names (`Ready`, `In Review`, `Blocked`, `Ticketed` at minimum). If any are missing, stop and report — the database is misconfigured.
55
- 3. Resolve Atlassian cloud ID via `mcp__atlassian__getAccessibleAtlassianResources` (downstream skills need it).
79
+ 2. Invoke `lisa:notion-access` via the Skill tool with operation `read-database` and `id: <database-id>`. Capture:
80
+ - The database schema (returned in the response's `properties` field) — needed to confirm the status property exists.
81
+ - Confirm the schema includes the configured `$STATUS_PROP` property of type `select` (or `status`) with the expected option names (`$READY`, `$IN_REVIEW`, `$BLOCKED`, `$TICKETED` at minimum). If any are missing, stop and report — the database is misconfigured.
82
+ 3. Resolve the destination tracker's workspace/cloud identifier via the tracker-specific config in `.lisa.config.json` (e.g., `atlassian.cloudId` for JIRA). Downstream skills consume this from config directly; this skill does not need to probe an external API for it.
83
+
84
+ ### Phase 2 — Find ready PRDs
56
85
 
57
- ### Phase 2 Find Ready PRDs
86
+ Query the database for pages where `$STATUS_PROP = $READY`. Invoke `lisa:notion-access` via the Skill tool with operation `query-database`, `id: <database-id>`, and a filter scoped to the status property. For a `status`-type property the filter shape is:
58
87
 
59
- Query the data source for pages where `Status = Ready`. Use `mcp__claude_ai_Notion__notion-search` with `data_source_url: collection://<data-source-id>` and a query that scopes to that collection. The search supports semantic queries; for an exact-status filter, scan the returned page list and keep only those whose `Status` property equals `Ready` (re-fetch each page if the search results don't expose properties).
88
+ ```json
89
+ { "property": "<STATUS_PROP>", "status": { "equals": "<READY>" } }
90
+ ```
91
+
92
+ For a `select`-type property substitute `"select"` for `"status"`. The response contains the matching pages with their properties inline — no per-page re-fetch is required for status filtering. If you need additional page content (body blocks, child blocks), invoke `lisa:notion-access` with operation `read-page` per page.
60
93
 
61
- If the result set is empty, stop and report `"No PRDs with Status=Ready. Nothing to do."` Exit cleanly — this is the common idle case for a scheduled run.
94
+ If the result set is empty, stop and report `"No PRDs with $STATUS_PROP=$READY. Nothing to do."` Exit cleanly — this is the common idle case for a scheduled run.
62
95
 
63
- ### Phase 3 — Process each Ready PRD
96
+ ### Phase 3 — Process each ready PRD
64
97
 
65
98
  For each PRD page (process serially to keep status transitions auditable):
66
99
 
67
100
  #### 3a. Claim
68
101
 
69
- Set `Status = In Review` via `mcp__claude_ai_Notion__notion-update-page` with `command: update_properties`, `properties: { "Status": "In Review" }`. This is the idempotency lock if a second cycle starts while this one is mid-flight, the second skip-filter (`Status = Ready`) won't see this PRD.
102
+ Set `$STATUS_PROP = $IN_REVIEW` by invoking `lisa:notion-access` via the Skill tool with operation `write-page` and payload:
103
+
104
+ ```json
105
+ { "id": "<PRD-page-id>", "properties": { "<STATUS_PROP>": { "status": { "name": "<IN_REVIEW>" } } } }
106
+ ```
107
+
108
+ (Use `"select": { "name": ... }` instead of `"status": { "name": ... }` if the property is a `select`.) This is the idempotency lock — if a second cycle starts while this one is mid-flight, the second skip-filter (`$STATUS_PROP = $READY`) won't see this PRD.
70
109
 
71
110
  If the update fails (permission error, race), log it and skip this PRD. Do not proceed to validation on a PRD you didn't successfully claim.
72
111
 
@@ -86,11 +125,11 @@ This call also indirectly invokes `lisa:tracker-source-artifacts` (artifact extr
86
125
 
87
126
  1. Re-invoke `lisa:notion-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).
88
127
  2. Capture the created ticket keys from the skill's output.
89
- 3. Post a Notion comment on the PRD via `mcp__claude_ai_Notion__notion-create-comment` listing the created tickets (epic, stories, sub-tasks) with their JIRA URLs. Lead with: `"Ticketed by Claude. Created N JIRA issues — see below. Move Status to Shipped after the work is delivered."`
90
- 4. Set `Status = Ticketed` via `notion-update-page`.
128
+ 3. Post a Notion comment on the PRD via `lisa:notion-access` operation `create-comment` (see "Commenting on PRDs" below), listing the created tickets (epic, stories, sub-tasks) with their JIRA URLs. Lead with: `"Ticketed by Claude. Created N JIRA issues — see below. Move $STATUS_PROP to $SHIPPED after the work is delivered."`
129
+ 4. Set `$STATUS_PROP = $TICKETED` by invoking `lisa:notion-access` operation `write-page` with payload `{ "id": "<PRD-page-id>", "properties": { "<STATUS_PROP>": { "status": { "name": "<TICKETED>" } } } }`.
91
130
  5. **Run Phase 3e (coverage audit)** before considering this PRD done.
92
131
 
93
- #### 3e. Coverage audit (mandatory after Ticketed)
132
+ #### 3e. Coverage audit (mandatory after ticketed)
94
133
 
95
134
  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.
96
135
 
@@ -99,10 +138,10 @@ Per-ticket gates prove each ticket is well-formed; they do NOT prove the *set* o
99
138
 
100
139
  | Verdict | Action |
101
140
  |---------|--------|
102
- | `COMPLETE` | Done. Leave `Status = Ticketed`. Move to next PRD. |
103
- | `COMPLETE_WITH_SCOPE_CREEP` | Post an advisory Notion comment naming the scope-creep tickets (so product can decide whether to close them as out-of-scope). Leave `Status = Ticketed`. |
104
- | `GAPS_FOUND` | The created ticket set is incomplete. (a) For each gap, post a Notion comment using the same product-facing template as Phase 3c.3 — block-anchored via `selection_with_ellipsis` when `prd_anchor` is non-null, page-level 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 summary comment listing the tickets that *were* successfully created (so product knows what to keep vs. what to extend). (c) Transition `Status` from `Ticketed` back to `Blocked` via `notion-update-page`. |
105
- | `NO_TICKETS_FOUND` | Should not happen if step 2 succeeded. If it does, log it as an Error in the cycle summary and leave `Status = Ticketed` with a comment flagging the audit failure for human review. |
141
+ | `COMPLETE` | Done. Leave `$STATUS_PROP = $TICKETED`. Move to next PRD. |
142
+ | `COMPLETE_WITH_SCOPE_CREEP` | Post an advisory Notion comment naming the scope-creep tickets (so product can decide whether to close them as out-of-scope). Leave `$STATUS_PROP = $TICKETED`. |
143
+ | `GAPS_FOUND` | The created ticket set is incomplete. (a) For each gap, post a Notion comment using the same product-facing template as Phase 3c.3 — block-anchored when `prd_anchor` is non-null, page-level 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 summary comment listing the tickets that *were* successfully created (so product knows what to keep vs. what to extend). (c) Transition `$STATUS_PROP` from `$TICKETED` back to `$BLOCKED` by invoking `lisa:notion-access` operation `write-page` with the blocked-status payload. |
144
+ | `NO_TICKETS_FOUND` | Should not happen if step 2 succeeded. If it does, log it as an Error in the cycle summary and leave `$STATUS_PROP = $TICKETED` with a comment flagging the audit failure for human review. |
106
145
 
107
146
  3. The created tickets remain in the destination tracker regardless of the verdict — they are valid in their own right (they passed `lisa:tracker-validate`). The audit only tells us whether *more* are needed.
108
147
 
@@ -119,12 +158,12 @@ The audience for these comments is the **product team**, not engineers. They are
119
158
 
120
159
  ##### 3c.2 Render each comment
121
160
 
122
- For each anchored group, post via `mcp__claude_ai_Notion__notion-create-comment` with:
161
+ For each anchored group, post via `lisa:notion-access` operation `create-comment` (see "Commenting on PRDs" below) with:
123
162
  - `page_id`: the PRD page ID
124
- - `selection_with_ellipsis`: the `prd_anchor` value (e.g. `"# User taps Fol...esume action"`)
163
+ - `block_anchor`: the `prd_anchor` value (e.g. `"# User taps Fol...esume action"`) — the access skill resolves this to a Notion block reference; pass `null` for page-level comments
125
164
  - `rich_text`: the body, formatted using the template below
126
165
 
127
- For the unanchored group, post a single page-level comment (omit `selection_with_ellipsis`) using the same template, prefixed with `Issues without a specific section anchor:` and one block per failure.
166
+ For the unanchored group, post a single page-level comment (omit `block_anchor` or pass `null`) using the same template, prefixed with `Issues without a specific section anchor:` and one block per failure.
128
167
 
129
168
  ##### 3c.3 Comment template
130
169
 
@@ -137,7 +176,7 @@ Each comment body MUST contain these four parts, in this order, no exceptions:
137
176
 
138
177
  **Recommendation:** <validator's `recommendation` field, verbatim — must contain 1–3 concrete options, never a generic "please clarify">
139
178
 
140
- **Action:** Update this section in the PRD, then set Status back to `Ready` and Claude will re-run intake.
179
+ **Action:** Update this section in the PRD, then set $STATUS_PROP back to `$READY` and Claude will re-run intake.
141
180
  ```
142
181
 
143
182
  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.
@@ -168,15 +207,28 @@ Use these exact badge labels — they are the validator's category values transl
168
207
 
169
208
  ##### 3c.6 Status transition
170
209
 
171
- After all comments are posted (anchored groups + the optional page-level summary), set `Status = Blocked` via `notion-update-page`. Do NOT write any JIRA tickets.
210
+ After all comments are posted (anchored groups + the optional page-level summary), set `$STATUS_PROP = $BLOCKED` by invoking `lisa:notion-access` operation `write-page` with payload `{ "id": "<PRD-page-id>", "properties": { "<STATUS_PROP>": { "status": { "name": "<BLOCKED>" } } } }`. Do NOT write any destination tickets.
211
+
212
+ ## Commenting on PRDs
213
+
214
+ The Notion comments API (`POST /v1/comments`) is the correct endpoint for both page-level and block-anchored comments. Invoke `lisa:notion-access` via the Skill tool with:
215
+
216
+ ```text
217
+ operation: create-comment
218
+ page_id: <PRD-page-id>
219
+ block_anchor: <prd_anchor string from notion-to-tracker, or null for page-level>
220
+ rich_text: <Notion rich_text array — the comment body>
221
+ ```
222
+
223
+ The access skill resolves a `prd_anchor` substring to the matching block ID by paging through the PRD's children and posts the comment with `discussion_id` or `parent: { block_id }` as appropriate. If `block_anchor` is `null`, the access skill posts a page-level comment via `parent: { page_id }`.
172
224
 
173
225
  #### 3d. Continue
174
226
 
175
- Move to the next Ready PRD. One PRD failing does not affect others.
227
+ Move to the next ready PRD. One PRD failing does not affect others.
176
228
 
177
229
  ### Phase 4 — Summary report
178
230
 
179
- After processing every Ready PRD, emit a summary:
231
+ After processing every ready PRD, emit a summary:
180
232
 
181
233
  ```text
182
234
  ## notion-prd-intake summary
@@ -186,25 +238,25 @@ Cycle started: <ISO timestamp>
186
238
  Cycle completed: <ISO timestamp>
187
239
 
188
240
  PRDs processed: <n>
189
- - Ticketed: <n>
241
+ - $TICKETED: <n>
190
242
  - <PRD title> → <epic-key> + <story-count> stories + <subtask-count> sub-tasks (coverage: COMPLETE | COMPLETE_WITH_SCOPE_CREEP)
191
- - Blocked: <n>
243
+ - $BLOCKED: <n>
192
244
  - <PRD title> → <gate-failure-count> gate failures (pre-write) OR <gap-count> coverage gaps (post-write)
193
245
  - Errors (claim failed, etc): <n>
194
246
  - <PRD title> — <reason>
195
247
 
196
- Total JIRA tickets created: <n>
248
+ Total destination tickets created: <n>
197
249
  Coverage audit summary: <n> COMPLETE / <n> COMPLETE_WITH_SCOPE_CREEP / <n> GAPS_FOUND
198
250
  ```
199
251
 
200
- Print to the agent's output. Do not write this summary to Notion or JIRA — it's an operational record for the human.
252
+ Print to the agent's output. Do not write this summary to Notion or the destination tracker — it's an operational record for the human.
201
253
 
202
254
  ## Idempotency & safety
203
255
 
204
- - **Single-cycle scope**: this skill processes the Ready set as it exists at the start of Phase 2. New `Ready` PRDs added mid-cycle are picked up next run.
205
- - **No writes outside the lifecycle**: this skill only ever writes to the destination tracker via `lisa:notion-to-tracker` (which delegates to `lisa:tracker-write`), and only ever changes Notion `Status` to `In Review`, `Blocked`, or `Ticketed`. It never edits PRD content, never touches `Draft` or `Shipped`, never deletes pages.
206
- - **Claim-first ordering**: `Status = In Review` is set BEFORE validation runs, so a re-entrant call won't double-process.
207
- - **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 in `In Review` — the human investigates from there.
256
+ - **Single-cycle scope**: this skill processes the ready set as it exists at the start of Phase 2. New ready PRDs added mid-cycle are picked up next run.
257
+ - **No writes outside the lifecycle**: this skill only ever writes to the destination tracker via `lisa:notion-to-tracker` (which delegates to `lisa:tracker-write`), and only ever changes the Notion status property to `$IN_REVIEW`, `$BLOCKED`, or `$TICKETED`. It never edits PRD content, never touches `$DRAFT` or `$SHIPPED`, never deletes pages.
258
+ - **Claim-first ordering**: the status flip to `$IN_REVIEW` is set BEFORE validation runs, so a re-entrant call won't double-process.
259
+ - **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 in `$IN_REVIEW` — the human investigates from there.
208
260
 
209
261
  ## Configuration
210
262
 
@@ -212,9 +264,16 @@ This skill reads project configuration from `.lisa.config.json` (with `.lisa.con
212
264
 
213
265
  ### From `.lisa.config.json`
214
266
 
215
- | Field | Purpose |
216
- |-------|---------|
217
- | `notion.prdDatabaseId` | Notion database hosting PRDs (when `$ARGUMENTS` is the literal token `notion`) |
267
+ | Field | Default | Purpose |
268
+ |-------|---------|---------|
269
+ | `notion.prdDatabaseId` | — | Notion database hosting PRDs (when `$ARGUMENTS` is the literal token `notion`) |
270
+ | `notion.statusProperty` | `Status` | Database property name driving the lifecycle |
271
+ | `notion.values.draft` | `Draft` | Value meaning "in progress; agent ignores" |
272
+ | `notion.values.ready` | `Ready` | Value meaning "ready for ticketing; agent claims" |
273
+ | `notion.values.in_review` | `In Review` | Value the agent sets on claim |
274
+ | `notion.values.blocked` | `Blocked` | Value the agent sets on validation failure |
275
+ | `notion.values.ticketed` | `Ticketed` | Value the agent sets on success |
276
+ | `notion.values.shipped` | `Shipped` | Value product sets after delivery (agent never writes) |
218
277
 
219
278
  ### From environment variables
220
279
 
@@ -227,9 +286,9 @@ This skill reads project configuration from `.lisa.config.json` (with `.lisa.con
227
286
  ## Rules
228
287
 
229
288
  - Never write to the destination tracker outside of `lisa:notion-to-tracker` → `lisa:tracker-write`. The validator's verdict gates progress; bypassing it produces broken tickets.
230
- - Never set Notion `Status` to a value this skill doesn't own (`In Review`, `Blocked`, `Ticketed`). Product owns `Draft`, `Ready`, `Shipped`.
289
+ - Never set the Notion status to a value this skill doesn't own (`$IN_REVIEW`, `$BLOCKED`, `$TICKETED`). Product owns `$DRAFT`, `$READY`, `$SHIPPED`.
231
290
  - Never edit the PRD's body. Communication with product happens only through Notion comments.
232
291
  - Never post a single page-level dump of all gate failures. One comment per `prd_anchor` group (or one page-level summary for unanchored failures only). The audience is product, not engineers — comments must be block-anchored, categorized, plain-language, and contain a concrete recommendation. See Phase 3c.3 for the required template and Phase 3c.5 for forbidden language.
233
292
  - Never include a gate ID, internal skill name, or engineering shorthand in a Notion comment body. If the validator's `what` or `recommendation` field uses one, paraphrase before posting.
234
293
  - Never run more than one intake cycle concurrently against the same database. This skill assumes serial execution. (Scheduling is a separate concern; the runtime should not start a new cycle if a previous one is still in flight.)
235
- - If `lisa:notion-to-tracker` returns errors (e.g. unreachable artifact, malformed PRD structure), treat them as gate failures: comment + Blocked. Don't silently fail.
294
+ - If `lisa:notion-to-tracker` returns errors (e.g. unreachable artifact, malformed PRD structure), treat them as gate failures: comment + `$BLOCKED`. Don't silently fail.
@@ -14,6 +14,8 @@ description: >
14
14
  Convert a Notion PRD into a structured ticket hierarchy in the configured destination tracker (JIRA, GitHub Issues, or Linear per .lisa.config.json): Epics > Stories > Sub-tasks.
15
15
  Each sub-task is scoped to exactly one repo and includes an empirical verification plan.
16
16
 
17
+ > **Notion access policy**: all Notion operations in this skill go through `lisa:notion-access`. Do not call Notion REST APIs (`api.notion.com/...`), Notion MCP tools (`mcp__*notion*`), or the `@notionhq/client` library directly. Invoke `lisa:notion-access` via the Skill tool with an operation name and arguments per its dispatch table.
18
+
17
19
  ## Modes
18
20
 
19
21
  This skill supports two modes, controlled by a `dry_run` flag in `$ARGUMENTS`:
@@ -54,7 +56,7 @@ Dry-run output format:
54
56
  ### Total failures: <n>
55
57
  ```
56
58
 
57
- `prd_anchor` and `prd_section` exist so downstream callers (notably `lisa:notion-prd-intake`) can post block-anchored Notion comments via `notion-create-comment` with `selection_with_ellipsis`. Build them as you parse the PRD: when you assign a planned ticket to a heading, user-story line, or AC bullet, capture the first ~10 and last ~10 characters of that section's text and emit them in the report. If a planned ticket genuinely doesn't trace to a specific section (cross-cutting infrastructure, derived sub-tasks), set both fields to `null` — the caller will fall back to a page-level comment.
59
+ `prd_anchor` and `prd_section` exist so downstream callers (notably `lisa:notion-prd-intake`) can post block-anchored Notion comments via `lisa:notion-access` operation `create-comment`. Build them as you parse the PRD: when you assign a planned ticket to a heading, user-story line, or AC bullet, capture the first ~10 and last ~10 characters of that section's text and emit them in the report. If a planned ticket genuinely doesn't trace to a specific section (cross-cutting infrastructure, derived sub-tasks), set both fields to `null` — the caller will fall back to a page-level comment.
58
60
 
59
61
  The `failures` array passes the validator's `Failure details` block through verbatim. Do not re-format `what` or `recommendation` here — those fields are already product-readable per the validator's contract, and re-summarizing risks losing concrete recommendations.
60
62
 
@@ -110,10 +112,10 @@ If env vars are not available, ask the user to provide them explicitly before pr
110
112
 
111
113
  ### Phase 1: Fetch & Analyze the PRD
112
114
 
113
- 1. **Fetch the main PRD page** with `include_discussions: true`
114
- 2. **Identify all Epic sub-pages** from the content (look for child page links)
115
- 3. **Fetch all Epic pages** in parallel with `include_discussions: true`
116
- 4. **Fetch full comments** from every page using `notion-get-comments` with `include_all_blocks: true`
115
+ 1. **Fetch the main PRD page** by invoking `lisa:notion-access` via the Skill tool with operation `read-page` and `id: <PRD-page-id>`. The returned payload includes the page's properties and content blocks.
116
+ 2. **Identify all Epic sub-pages** from the content (look for child page references in the returned block tree).
117
+ 3. **Fetch all Epic pages** in parallel for each child page ID, invoke `lisa:notion-access` operation `read-page`.
118
+ 4. **Fetch full comments** from every page by invoking `lisa:notion-access` operation `list-comments` with `block_id: <page-id>` (page comments and block-anchored comments alike). If `list-comments` is not in the access skill's dispatch table yet, surface that to the caller — comments are required for engineering-decision synthesis below.
117
119
  5. **Synthesize decisions and blockers** from the PRD content + all comments:
118
120
  - Decisions already confirmed by the team (look for agreement in comment threads)
119
121
  - Open questions that need product/engineering input
@@ -10,14 +10,13 @@ Decompose the PRD/spec at `$ARGUMENTS` into ordered work items with acceptance c
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`. Reading the PRD, exploring the code, fetching context — 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`. Reading the PRD, exploring the code, fetching context — 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. The team lead created the team; teammates inherit it.
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. The team lead created the team; teammates inherit it.
21
20
 
22
21
  ## Source dispatch
23
22
 
@@ -10,14 +10,13 @@ Produce a PRD for the problem in `$ARGUMENTS`.
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`. Gathering context inline as the lead is the exact bypass path that produces ad-hoc work instead of a real team flow.
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`. Gathering context inline as the lead is the exact bypass path that produces ad-hoc work instead of a real team flow.
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. The team lead created the team; teammates inherit it.
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. The team lead created the team; teammates inherit it.
21
20
 
22
21
  ## Flow
23
22