@codyswann/lisa 2.21.0 → 2.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/agents/confluence-prd-intake.md +11 -9
- package/plugins/lisa/agents/github-agent.md +18 -10
- package/plugins/lisa/agents/github-build-intake.md +10 -8
- package/plugins/lisa/agents/github-prd-intake.md +11 -9
- package/plugins/lisa/agents/jira-agent.md +12 -8
- package/plugins/lisa/agents/jira-build-intake.md +9 -7
- package/plugins/lisa/agents/linear-agent.md +15 -9
- package/plugins/lisa/agents/linear-build-intake.md +13 -11
- package/plugins/lisa/agents/linear-prd-intake.md +11 -9
- package/plugins/lisa/agents/notion-prd-intake.md +11 -9
- package/plugins/lisa/commands/setup/atlassian.md +7 -0
- package/plugins/lisa/commands/setup/confluence.md +7 -0
- package/plugins/lisa/commands/setup/jira.md +7 -0
- package/plugins/lisa/commands/setup/notion.md +7 -0
- package/plugins/lisa/rules/base-rules.md +2 -2
- package/plugins/lisa/rules/config-resolution.md +242 -24
- package/plugins/lisa/rules/repo-scope-split.md +41 -0
- package/plugins/lisa/rules/verification.md +13 -0
- package/plugins/lisa/skills/atlassian-access/SKILL.md +260 -0
- package/plugins/lisa/skills/confluence-prd-intake/SKILL.md +167 -82
- package/plugins/lisa/skills/confluence-to-tracker/SKILL.md +39 -26
- package/plugins/lisa/skills/git-submit-pr/SKILL.md +1 -1
- package/plugins/lisa/skills/github-add-journey/SKILL.md +1 -0
- package/plugins/lisa/skills/github-build-intake/SKILL.md +104 -40
- package/plugins/lisa/skills/github-evidence/SKILL.md +22 -5
- package/plugins/lisa/skills/github-prd-intake/SKILL.md +87 -51
- package/plugins/lisa/skills/github-to-tracker/SKILL.md +2 -2
- package/plugins/lisa/skills/github-validate-issue/SKILL.md +11 -1
- package/plugins/lisa/skills/jira-add-journey/SKILL.md +1 -0
- package/plugins/lisa/skills/jira-build-intake/SKILL.md +110 -45
- package/plugins/lisa/skills/jira-create/SKILL.md +5 -3
- package/plugins/lisa/skills/jira-evidence/SKILL.md +19 -2
- package/plugins/lisa/skills/jira-journey/SKILL.md +3 -1
- package/plugins/lisa/skills/jira-read-ticket/SKILL.md +10 -8
- package/plugins/lisa/skills/jira-sync/SKILL.md +11 -5
- package/plugins/lisa/skills/jira-validate-ticket/SKILL.md +22 -10
- package/plugins/lisa/skills/jira-verify/SKILL.md +5 -3
- package/plugins/lisa/skills/jira-write-ticket/SKILL.md +16 -14
- package/plugins/lisa/skills/linear-add-journey/SKILL.md +1 -0
- package/plugins/lisa/skills/linear-build-intake/SKILL.md +90 -32
- package/plugins/lisa/skills/linear-evidence/SKILL.md +22 -5
- package/plugins/lisa/skills/linear-prd-intake/SKILL.md +92 -57
- package/plugins/lisa/skills/linear-validate-issue/SKILL.md +10 -0
- package/plugins/lisa/skills/notion-access/SKILL.md +193 -0
- package/plugins/lisa/skills/notion-prd-intake/SKILL.md +105 -46
- package/plugins/lisa/skills/notion-to-tracker/SKILL.md +7 -5
- package/plugins/lisa/skills/setup-atlassian/SKILL.md +316 -0
- package/plugins/lisa/skills/setup-confluence/SKILL.md +245 -0
- package/plugins/lisa/skills/setup-jira/SKILL.md +198 -0
- package/plugins/lisa/skills/setup-notion/SKILL.md +283 -0
- package/plugins/lisa/skills/task-decomposition/SKILL.md +2 -0
- package/plugins/lisa/skills/ticket-triage/SKILL.md +4 -1
- package/plugins/lisa/skills/tracker-evidence/SKILL.md +1 -0
- package/plugins/lisa/skills/verification-lifecycle/SKILL.md +2 -0
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/src/base/agents/confluence-prd-intake.md +11 -9
- package/plugins/src/base/agents/github-agent.md +18 -10
- package/plugins/src/base/agents/github-build-intake.md +10 -8
- package/plugins/src/base/agents/github-prd-intake.md +11 -9
- package/plugins/src/base/agents/jira-agent.md +12 -8
- package/plugins/src/base/agents/jira-build-intake.md +9 -7
- package/plugins/src/base/agents/linear-agent.md +15 -9
- package/plugins/src/base/agents/linear-build-intake.md +13 -11
- package/plugins/src/base/agents/linear-prd-intake.md +11 -9
- package/plugins/src/base/agents/notion-prd-intake.md +11 -9
- package/plugins/src/base/commands/setup/atlassian.md +7 -0
- package/plugins/src/base/commands/setup/confluence.md +7 -0
- package/plugins/src/base/commands/setup/jira.md +7 -0
- package/plugins/src/base/commands/setup/notion.md +7 -0
- package/plugins/src/base/rules/base-rules.md +2 -2
- package/plugins/src/base/rules/config-resolution.md +242 -24
- package/plugins/src/base/rules/repo-scope-split.md +41 -0
- package/plugins/src/base/rules/verification.md +13 -0
- package/plugins/src/base/skills/atlassian-access/SKILL.md +260 -0
- package/plugins/src/base/skills/confluence-prd-intake/SKILL.md +167 -82
- package/plugins/src/base/skills/confluence-to-tracker/SKILL.md +39 -26
- package/plugins/src/base/skills/git-submit-pr/SKILL.md +1 -1
- package/plugins/src/base/skills/github-add-journey/SKILL.md +1 -0
- package/plugins/src/base/skills/github-build-intake/SKILL.md +104 -40
- package/plugins/src/base/skills/github-evidence/SKILL.md +22 -5
- package/plugins/src/base/skills/github-prd-intake/SKILL.md +87 -51
- package/plugins/src/base/skills/github-to-tracker/SKILL.md +2 -2
- package/plugins/src/base/skills/github-validate-issue/SKILL.md +11 -1
- package/plugins/src/base/skills/jira-add-journey/SKILL.md +1 -0
- package/plugins/src/base/skills/jira-build-intake/SKILL.md +110 -45
- package/plugins/src/base/skills/jira-create/SKILL.md +5 -3
- package/plugins/src/base/skills/jira-evidence/SKILL.md +19 -2
- package/plugins/src/base/skills/jira-journey/SKILL.md +3 -1
- package/plugins/src/base/skills/jira-read-ticket/SKILL.md +10 -8
- package/plugins/src/base/skills/jira-sync/SKILL.md +11 -5
- package/plugins/src/base/skills/jira-validate-ticket/SKILL.md +22 -10
- package/plugins/src/base/skills/jira-verify/SKILL.md +5 -3
- package/plugins/src/base/skills/jira-write-ticket/SKILL.md +16 -14
- package/plugins/src/base/skills/linear-add-journey/SKILL.md +1 -0
- package/plugins/src/base/skills/linear-build-intake/SKILL.md +90 -32
- package/plugins/src/base/skills/linear-evidence/SKILL.md +22 -5
- package/plugins/src/base/skills/linear-prd-intake/SKILL.md +92 -57
- package/plugins/src/base/skills/linear-validate-issue/SKILL.md +10 -0
- package/plugins/src/base/skills/notion-access/SKILL.md +193 -0
- package/plugins/src/base/skills/notion-prd-intake/SKILL.md +105 -46
- package/plugins/src/base/skills/notion-to-tracker/SKILL.md +7 -5
- package/plugins/src/base/skills/setup-atlassian/SKILL.md +316 -0
- package/plugins/src/base/skills/setup-confluence/SKILL.md +245 -0
- package/plugins/src/base/skills/setup-jira/SKILL.md +198 -0
- package/plugins/src/base/skills/setup-notion/SKILL.md +283 -0
- package/plugins/src/base/skills/task-decomposition/SKILL.md +2 -0
- package/plugins/src/base/skills/ticket-triage/SKILL.md +4 -1
- package/plugins/src/base/skills/tracker-evidence/SKILL.md +1 -0
- package/plugins/src/base/skills/verification-lifecycle/SKILL.md +2 -0
- 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
|
|
4
|
-
allowed-tools: ["Skill", "Bash", "
|
|
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 ready → in_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", "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
|
|
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 `
|
|
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 `
|
|
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 (
|
|
32
|
-
- Empty
|
|
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`
|
|
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
|
-
|
|
66
|
+
draft → ready → in_review → blocked | ticketed → shipped
|
|
40
67
|
(product) (us) (us) (product)
|
|
41
68
|
```
|
|
42
69
|
|
|
43
|
-
This skill ONLY transitions `
|
|
70
|
+
This skill ONLY transitions `ready → in_review`, then `in_review → blocked` or `in_review → ticketed`. 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.
|
|
53
|
-
- The
|
|
54
|
-
- Confirm the schema includes
|
|
55
|
-
3. Resolve
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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 `
|
|
90
|
-
4. Set
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 `
|
|
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
|
-
- `
|
|
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 `
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
-
|
|
241
|
+
- $TICKETED: <n>
|
|
190
242
|
- <PRD title> → <epic-key> + <story-count> stories + <subtask-count> sub-tasks (coverage: COMPLETE | COMPLETE_WITH_SCOPE_CREEP)
|
|
191
|
-
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
206
|
-
- **Claim-first ordering**:
|
|
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 `
|
|
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
|
|
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 +
|
|
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-
|
|
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 `
|
|
114
|
-
2. **Identify all Epic sub-pages** from the content (look for child page
|
|
115
|
-
3. **Fetch all Epic pages** in parallel
|
|
116
|
-
4. **Fetch full comments** from every page
|
|
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
|