@codyswann/lisa 2.1.1 → 2.3.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.
Files changed (27) hide show
  1. package/dist/utils/postinstall-trampoline.d.ts +3 -1
  2. package/dist/utils/postinstall-trampoline.d.ts.map +1 -1
  3. package/dist/utils/postinstall-trampoline.js +9 -2
  4. package/dist/utils/postinstall-trampoline.js.map +1 -1
  5. package/package.json +1 -1
  6. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  7. package/plugins/lisa/agents/jira-build-intake.md +4 -0
  8. package/plugins/lisa/agents/notion-prd-intake.md +4 -0
  9. package/plugins/lisa/skills/intake/SKILL.md +17 -0
  10. package/plugins/lisa/skills/jira-build-intake/SKILL.md +17 -0
  11. package/plugins/lisa/skills/jira-validate-ticket/SKILL.md +53 -4
  12. package/plugins/lisa/skills/notion-prd-intake/SKILL.md +73 -13
  13. package/plugins/lisa/skills/notion-to-jira/SKILL.md +18 -1
  14. package/plugins/lisa/skills/prd-ticket-coverage/SKILL.md +11 -3
  15. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  20. package/plugins/src/base/agents/jira-build-intake.md +4 -0
  21. package/plugins/src/base/agents/notion-prd-intake.md +4 -0
  22. package/plugins/src/base/skills/intake/SKILL.md +17 -0
  23. package/plugins/src/base/skills/jira-build-intake/SKILL.md +17 -0
  24. package/plugins/src/base/skills/jira-validate-ticket/SKILL.md +53 -4
  25. package/plugins/src/base/skills/notion-prd-intake/SKILL.md +73 -13
  26. package/plugins/src/base/skills/notion-to-jira/SKILL.md +18 -1
  27. package/plugins/src/base/skills/prd-ticket-coverage/SKILL.md +11 -3
@@ -1,3 +1,4 @@
1
+ import { spawn } from "node:child_process";
1
2
  /**
2
3
  * Known package managers whose lockfiles must be regenerated when Lisa's apply
3
4
  * mutates package.json (e.g., adds/updates resolutions or overrides entries).
@@ -114,7 +115,8 @@ export declare function hashFile(filePath: string): string | null;
114
115
  * @param projectDir - Absolute path to the project directory Lisa will reconcile
115
116
  * @param lisaDistDir - Absolute path to Lisa's dist directory (where index.js lives)
116
117
  * @param parentPid - PID of the package-manager process to wait on (usually process.ppid)
118
+ * @param spawnFn - Optional spawn implementation; defaults to node:child_process spawn. Tests pass a vi.fn() spy here as a dependency-injection seam, avoiding the unreliable vi.doMock-on-builtins pattern that breaks under v8 coverage in CI runners.
117
119
  * @returns Promise that resolves immediately after spawning the detached child
118
120
  */
119
- export declare function scheduleReconciliationChild(projectDir: string, lisaDistDir: string, parentPid: number): Promise<void>;
121
+ export declare function scheduleReconciliationChild(projectDir: string, lisaDistDir: string, parentPid: number, spawnFn?: typeof spawn): Promise<void>;
120
122
  //# sourceMappingURL=postinstall-trampoline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"postinstall-trampoline.d.ts","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"AAmCA;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AA6DD;;;;;GAKG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAAI,OAAO,CASvC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uCAAuC,CACrD,MAAM,EAAE,OAAO,GACd,OAAO,CAIT;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,GACjB,SAAS,cAAc,EAAE,CAI3B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,cAAc,GAAG,iBAAiB,CAE1E;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOxD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAgCf"}
1
+ {"version":3,"file":"postinstall-trampoline.d.ts","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAmC3C;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AA6DD;;;;;GAKG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAAI,OAAO,CASvC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uCAAuC,CACrD,MAAM,EAAE,OAAO,GACd,OAAO,CAIT;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,GACjB,SAAS,cAAc,EAAE,CAI3B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,cAAc,GAAG,iBAAiB,CAE1E;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOxD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAMjB,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,IAAI,CAAC,CAgCf"}
@@ -219,9 +219,16 @@ export function hashFile(filePath) {
219
219
  * @param projectDir - Absolute path to the project directory Lisa will reconcile
220
220
  * @param lisaDistDir - Absolute path to Lisa's dist directory (where index.js lives)
221
221
  * @param parentPid - PID of the package-manager process to wait on (usually process.ppid)
222
+ * @param spawnFn - Optional spawn implementation; defaults to node:child_process spawn. Tests pass a vi.fn() spy here as a dependency-injection seam, avoiding the unreliable vi.doMock-on-builtins pattern that breaks under v8 coverage in CI runners.
222
223
  * @returns Promise that resolves immediately after spawning the detached child
223
224
  */
224
- export async function scheduleReconciliationChild(projectDir, lisaDistDir, parentPid) {
225
+ export async function scheduleReconciliationChild(projectDir, lisaDistDir, parentPid,
226
+ // Dependency-injection seam: callers can override the spawn function for
227
+ // testing. Default is the real node:child_process spawn. Production callers
228
+ // pass nothing; tests pass a vi.fn() spy and assert on it directly without
229
+ // relying on vi.doMock for node builtins (which is flaky in CI under v8
230
+ // coverage). The seam is invisible to production callers.
231
+ spawnFn = spawn) {
225
232
  const nodeBin = process.execPath;
226
233
  const lisaEntry = path.join(lisaDistDir, "index.js");
227
234
  const trampolineSource = buildTrampolineSource({
@@ -235,7 +242,7 @@ export async function scheduleReconciliationChild(projectDir, lisaDistDir, paren
235
242
  trampolineEnvVar: TRAMPOLINE_ENV_VAR,
236
243
  lockfileRegenPlans: LOCKFILE_REGEN_PLANS,
237
244
  });
238
- const child = spawn(nodeBin, ["-e", trampolineSource], {
245
+ const child = spawnFn(nodeBin, ["-e", trampolineSource], {
239
246
  cwd: projectDir,
240
247
  detached: true,
241
248
  stdio: "ignore",
@@ -1 +1 @@
1
- {"version":3,"file":"postinstall-trampoline.js","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"postinstall-trampoline.js","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -78,7 +78,7 @@
78
78
  "lodash": ">=4.18.1"
79
79
  },
80
80
  "name": "@codyswann/lisa",
81
- "version": "2.1.1",
81
+ "version": "2.3.0",
82
82
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
83
83
  "main": "dist/index.js",
84
84
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -17,6 +17,10 @@ skills:
17
17
 
18
18
  You are a JIRA build-intake agent. Your single job is to run one cycle against a JIRA project / JQL filter — find Ready tickets, dispatch each through the build flow, transition successful builds to On Dev — then report what happened.
19
19
 
20
+ ## Confirmation policy
21
+
22
+ Once you have a project key or JQL, RUN. Do not ask the caller whether to proceed, do not preview projected scope (ticket counts, PR counts, build estimates), do not offer "proceed / skip / dry-run" choices. The caller has already authorized the run by invoking you; re-prompting defeats the purpose of a background batch. The pre-flight `Blocked` outcome owned by `jira-agent` is a valid terminal state of the per-ticket lifecycle, not a failure mode — large queues and complex tickets are exactly what this skill is for. The `jira-build-intake` skill defines the only legitimate early-exit conditions (missing query, misconfigured workflow, empty Ready set); ask only when one of those applies.
23
+
20
24
  ## Workflow
21
25
 
22
26
  ### 1. Receive the query
@@ -15,6 +15,10 @@ skills:
15
15
 
16
16
  You are a PRD intake agent. Your single job is to run one intake cycle against the Notion PRD database whose URL is given to you, then report what happened.
17
17
 
18
+ ## Confirmation policy
19
+
20
+ Once you have a database URL, RUN. Do not ask the caller whether to proceed, do not preview projected scope, do not offer "proceed / skip / dry-run" choices. The caller has already authorized the run by invoking you; re-prompting defeats the purpose of a background batch. `Blocked` is a valid terminal state of the lifecycle, not a failure mode — large PRDs and PRDs full of open questions are exactly what this skill is for. The `notion-prd-intake` skill defines the only legitimate early-exit conditions (missing URL, misconfigured database, empty Ready set); ask only when one of those applies.
21
+
18
22
  ## Workflow
19
23
 
20
24
  ### 1. Receive the database URL
@@ -8,6 +8,23 @@ allowed-tools: ["Skill", "Bash", "mcp__claude_ai_Notion__notion-fetch", "mcp__cl
8
8
 
9
9
  Run one batch-intake cycle against the queue identified by `$ARGUMENTS`. Scans for `Status = Ready`, claims each item, and dispatches to the appropriate single-item lifecycle skill.
10
10
 
11
+ ## Confirmation policy
12
+
13
+ Do NOT ask the caller whether to proceed. Once invoked with a queue, run the cycle to completion. The caller (a human at the CLI or a scheduled cron) has already authorized the run by invoking the skill; re-prompting defeats the purpose of a background batch.
14
+
15
+ Specifically forbidden:
16
+
17
+ - Previewing projected scope (number of items, projected ticket counts, write counts) and asking whether to continue.
18
+ - Offering A/B/C-style choices like "proceed / skip / dry-run only" — the documented behavior IS the default. Dry-run is a different skill, not an option here.
19
+ - Pausing because the queue is large, items have many open questions, or items are likely to end in `Blocked`. `Blocked` is a valid terminal state of the downstream lifecycles, not a failure mode — routing items to `Blocked` with clarifying comments is success.
20
+ - Pausing because validation looks expensive. The cost of one cycle is bounded; the cost of stalling a scheduled cron waiting on a human is unbounded.
21
+
22
+ The only legitimate reasons to stop early:
23
+
24
+ - Missing required input (no queue argument, missing project configuration). Surface the missing value and exit.
25
+ - The queue itself is misconfigured (Status property missing expected values, JIRA workflow can't reach required transitions). Surface and exit.
26
+ - Empty `Ready` set. Exit cleanly with the idle-case message.
27
+
11
28
  ## Orchestration: agent team
12
29
 
13
30
  If you are NOT already operating inside an agent team (no prior `TeamCreate` in this session, not spawned via `Agent` with `team_name`), your FIRST tool call MUST be `TeamCreate`. Do not call `TaskCreate`, `Agent`, or implementation tools before the team exists.
@@ -13,6 +13,23 @@ allowed-tools: ["Skill", "Bash", "mcp__atlassian__getAccessibleAtlassianResource
13
13
 
14
14
  Run one build-intake cycle. Each Ready ticket is claimed, built via the `lisa:jira-agent` flow, and transitioned to `On Dev` (or the equivalent next-status for that project). The cycle is the symmetric mirror of `lisa:notion-prd-intake`: humans flip `Ready`, agents pick up and progress.
15
15
 
16
+ ## Confirmation policy
17
+
18
+ Do NOT ask the caller whether to proceed. Once invoked with a project key or JQL, run the cycle to completion — claim, dispatch each ticket through `lisa:jira-agent`, transition successful builds to `On Dev`, 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.
19
+
20
+ Specifically forbidden:
21
+
22
+ - Previewing projected scope (ticket count, projected PR count, build duration) and asking whether to continue.
23
+ - Offering A/B/C-style choices like "proceed / skip a few / dry-run only" — the documented behavior IS the default.
24
+ - Pausing because the queue is large, tickets look complex, or tickets are likely to be `Blocked` by `lisa:jira-agent`'s pre-flight gate. The pre-flight `Blocked` outcome is a valid terminal state of the per-ticket lifecycle (owned by `lisa:jira-agent`), not a failure mode — surfacing those tickets to humans is success.
25
+ - Pausing because the build flow looks expensive. The cost of one cycle is bounded; the cost of stalling a scheduled cron waiting on a human is unbounded.
26
+
27
+ The only legitimate reasons to stop early:
28
+
29
+ - Missing project key / JQL or required configuration. Surface the missing value and exit.
30
+ - Workflow misconfigured (pre-flight check finds `In Progress` or `On Dev` not reachable, or `Ready` status absent). Surface and exit.
31
+ - Empty `Ready` set. Exit cleanly with `"No tickets with Status=Ready. Nothing to do."`
32
+
16
33
  ## Lifecycle assumed
17
34
 
18
35
  The JIRA workflow has these statuses (or equivalents — see Configuration for renaming):
@@ -66,6 +66,39 @@ If the caller passes only a ticket key, fetch the ticket via `mcp__atlassian__ge
66
66
 
67
67
  Gates are grouped into **Specification** (spec-only checks, no JIRA lookups) and **Feasibility** (requires JIRA lookups). The dry-run path may opt to run Specification gates only; the write path runs both.
68
68
 
69
+ Each gate is tagged with a fixed `category` and a `product_relevant` boolean. Categories drive how downstream callers (notably `lisa:notion-prd-intake`) translate failures into product-facing comments; `product_relevant=false` failures indicate internal data-quality problems (broken parent links, missing core fields) that the agent should fix itself rather than ask product to clarify.
70
+
71
+ | Gate | Category | Product-relevant |
72
+ |------|----------|------------------|
73
+ | S1 Required core fields | `structural` | false |
74
+ | S2 Summary format | `structural` | false |
75
+ | S3 Description three audiences | `product-clarity` | true |
76
+ | S4 Acceptance criteria in Gherkin | `acceptance-criteria` | true |
77
+ | S5 Bug-specific content | `product-clarity` | true |
78
+ | S6 Spike-specific content | `scope` | true |
79
+ | S7 Epic parent declared | `structural` | false |
80
+ | S8 Target Backend Environment | `technical` | false |
81
+ | S9 Sign-in Required | `technical` | false |
82
+ | S10 Single-repo scope | `scope` | true |
83
+ | S11 Validation Journey | `acceptance-criteria` | true |
84
+ | S12 Source Precedence | `design-ux` | true |
85
+ | S13 Relationship Search | `dependency` | true |
86
+ | F1 Issue type valid in project | `structural` | false |
87
+ | F2 Epic parent exists and is an Epic | `structural` | false |
88
+ | F3 Linked tickets exist | `structural` | false |
89
+ | F4 Required custom fields populated | `structural` | false |
90
+
91
+ Category values are drawn from this fixed set:
92
+
93
+ - `product-clarity` — feature behavior or user intent unclear in the PRD
94
+ - `acceptance-criteria` — pass/fail conditions missing or ambiguous
95
+ - `design-ux` — visual or interaction spec missing
96
+ - `scope` — boundary unclear, items overlap, split needed
97
+ - `dependency` — blocked by another team / system / decision
98
+ - `data` — data source / shape / volume unspecified
99
+ - `technical` — engineering decision required (rare from PRD path; mostly internal)
100
+ - `structural` — internal data-quality problem the agent must fix itself, not surface to product
101
+
69
102
  ### Specification Gates
70
103
 
71
104
  #### S1 — Required core fields
@@ -209,16 +242,32 @@ Output is a single fenced text block. Callers parse it; do not add free-form pro
209
242
 
210
243
  ### Verdict: PASS | FAIL
211
244
  ### Failures: <count>
212
- ### Remediation
213
- - <gate-id>: <concrete fix the caller can apply or surface to the user>
214
- - <gate-id>: <concrete fix>
245
+ ### Failure details
246
+ - gate: <gate-id>
247
+ category: <product-clarity|acceptance-criteria|design-ux|scope|dependency|data|technical|structural>
248
+ product_relevant: <true|false>
249
+ what: <plain-language description of what is missing or wrong, no gate-IDs, no JIRA terminology — written so a non-engineer product owner understands the issue>
250
+ recommendation: <1–3 concrete options the caller (or downstream product team) can pick from. Never "clarify this" — always a specific suggested resolution.>
251
+ - gate: <gate-id>
252
+ category: ...
253
+ ...
215
254
  ```
216
255
 
217
256
  The verdict is `PASS` if and only if every applicable gate is `PASS`. Any `FAIL` makes the verdict `FAIL`. `N/A` does not affect the verdict.
218
257
 
258
+ ### Failure-detail fields
259
+
260
+ - **gate**: the gate ID (`S1`–`S13`, `F1`–`F4`).
261
+ - **category**: the gate's fixed category from the table above. Callers use this to label or filter comments — `product-clarity`, `acceptance-criteria`, `design-ux`, `scope`, `dependency`, `data`, `technical`, or `structural`.
262
+ - **product_relevant**: matches the gate's table entry. `false` means the failure is an internal data-quality problem (e.g., the agent built a malformed spec, an issue type is invalid in the project) and the caller should fix it without bothering the product team. `true` means the PRD needs product input to resolve.
263
+ - **what**: plain-language description of the issue. No gate IDs, no JIRA jargon, no engineering shorthand. A product owner reading this on a Notion comment should understand what is unclear and why.
264
+ - **recommendation**: 1–3 concrete options the reader can pick from, not a generic "please clarify." If the answer is genuinely open-ended, list the most plausible candidate resolutions you considered, even if speculative.
265
+
219
266
  ## Rules
220
267
 
221
268
  - Never write to JIRA. The `allowed-tools` list intentionally excludes `createJiraIssue`, `editJiraIssue`, `createIssueLink`, `addCommentToJiraIssue`.
222
269
  - Never auto-fix the spec. This skill reports gaps; callers decide what to do (block, ask the human, regenerate the spec).
223
270
  - Never silently skip a gate. If a gate genuinely doesn't apply, return `N/A` with the reason; never omit it.
224
- - The remediation lines must be concrete and actionable — the dry-run path turns each one into a Notion comment, so vague guidance is useless.
271
+ - The `what` and `recommendation` fields must be concrete and product-readable — the dry-run path turns each failure into a Notion comment, and the audience for those comments is the product team, not engineers. Vague guidance ("clarify this", "decide how to handle X") is useless; always give 1–3 candidate resolutions.
272
+ - Never emit a category outside the fixed set. If a new gate doesn't fit, propose adding the category to the taxonomy in this skill rather than inventing one inline.
273
+ - `product_relevant` is determined by the gate, not by the failure context. Do not flip it per-failure.
@@ -14,6 +14,23 @@ https://www.notion.so/geminisports/28fd00244d7d47c5866876f7de48c0fe?v=34eba63a28
14
14
 
15
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).
16
16
 
17
+ ## Confirmation policy
18
+
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.
20
+
21
+ Specifically forbidden:
22
+
23
+ - Previewing projected scope (epic count, story count, write count) and asking whether to continue.
24
+ - 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.
26
+ - 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
+
28
+ The only legitimate reasons to stop early:
29
+
30
+ - Missing database URL or required configuration (`JIRA_PROJECT`, `JIRA_SERVER`, `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."`
33
+
17
34
  ## Lifecycle assumed
18
35
 
19
36
  The PRD database has a `Status` property whose value drives this skill:
@@ -84,7 +101,7 @@ Per-ticket gates prove each ticket is well-formed; they do NOT prove the *set* o
84
101
  |---------|--------|
85
102
  | `COMPLETE` | Done. Leave `Status = Ticketed`. Move to next PRD. |
86
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`. |
87
- | `GAPS_FOUND` | The created ticket set is incomplete. (a) For each gap, post a Notion comment naming the missing PRD item and where it appears in the PRD, with the suggested fix from the audit report. (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`. |
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`. |
88
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. |
89
106
 
90
107
  3. The created tickets remain in JIRA regardless of the verdict — they are valid in their own right (they passed `lisa:jira-validate-ticket`). The audit only tells us whether *more* are needed.
@@ -93,24 +110,65 @@ The audit's report should be summarized in the cycle summary alongside the per-P
93
110
 
94
111
  **If `FAIL`** (one or more planned tickets failed one or more gates):
95
112
 
96
- 1. Group the failures by planned ticket.
97
- 2. For each failed ticket, post a Notion comment via `notion-create-comment` with this format:
113
+ The audience for these comments is the **product team**, not engineers. They are not familiar with JIRA gate IDs, validator vocabulary, or skill internals. Follow the rules below strictly — the goal is for a non-engineer product owner to read a comment, understand what is unclear, and know what to do next.
114
+
115
+ ##### 3c.1 Partition failures
116
+
117
+ 1. Drop every failure where `product_relevant = false`. Those are internal data-quality problems — the agent should fix its own spec rather than ask product to clarify a missing core field. Record the dropped failures under `Errors` in the cycle summary so engineers can see them; never surface them on the PRD.
118
+ 2. Group the remaining product-relevant failures by `prd_anchor` (the snippet from `notion-to-jira`'s dry-run report). Failures that share an anchor become one comment thread on that block. Failures with `prd_anchor: null` are batched into one page-level summary comment, since they have no source section to attach to.
119
+
120
+ ##### 3c.2 Render each comment
121
+
122
+ For each anchored group, post via `mcp__claude_ai_Notion__notion-create-comment` with:
123
+ - `page_id`: the PRD page ID
124
+ - `selection_with_ellipsis`: the `prd_anchor` value (e.g. `"# User taps Fol...esume action"`)
125
+ - `rich_text`: the body, formatted using the template below
126
+
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.
128
+
129
+ ##### 3c.3 Comment template
130
+
131
+ Each comment body MUST contain these four parts, in this order, no exceptions:
132
+
133
+ ```text
134
+ [<Category badge>] <prd_section heading text>
135
+
136
+ **What's unclear:** <validator's `what` field, verbatim — already product-readable>
137
+
138
+ **Recommendation:** <validator's `recommendation` field, verbatim — must contain 1–3 concrete options, never a generic "please clarify">
139
+
140
+ **Action:** Update this section in the PRD, then set Status back to `Ready` and Claude will re-run intake.
141
+ ```
142
+
143
+ 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.
144
+
145
+ ##### 3c.4 Category badges
146
+
147
+ Use these exact badge labels — they are the validator's category values translated for product readers:
98
148
 
99
- ```text
100
- **Blocker — planned ticket: <ticket-summary>**
149
+ | Validator category | Badge label |
150
+ |---------------------|-------------|
151
+ | `product-clarity` | `[Product clarity]` |
152
+ | `acceptance-criteria` | `[Acceptance criteria]` |
153
+ | `design-ux` | `[Design / UX]` |
154
+ | `scope` | `[Scope]` |
155
+ | `dependency` | `[Dependency]` |
156
+ | `data` | `[Data]` |
157
+ | `technical` | `[Technical]` |
101
158
 
102
- The PRD as written can't produce a valid JIRA ticket for this scope. Specifically:
159
+ `structural` failures must never reach this step (filtered in 3c.1). If you see one here, treat it as an Error and surface internally.
103
160
 
104
- - **<gate-id> (<gate-name>)**: <reason>. *Fix:* <concrete remediation>.
105
- - **<gate-id> (<gate-name>)**: <reason>. *Fix:* <concrete remediation>.
161
+ ##### 3c.5 Forbidden in product comments
106
162
 
107
- Once these are addressed in the PRD, set Status back to `Ready` and Claude will re-run intake.
108
- ```
163
+ - Gate IDs (`S4`, `F2`, etc.). Never appear in a comment body.
164
+ - JIRA terminology that has no product meaning (e.g. "Gherkin", "epic parent", "issue link", "validation journey", "sub-task hierarchy"). If the validator's `what` field uses one of these terms, paraphrase before posting; do not pass through verbatim.
165
+ - Internal skill names (`lisa:jira-validate-ticket`, `notion-to-jira`).
166
+ - Engineering shorthand (`AC`, `OOS`, `repo`, `env var`).
167
+ - "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.
109
168
 
110
- 3. Set `Status = Blocked` via `notion-update-page`.
111
- 4. Do NOT write any JIRA tickets.
169
+ ##### 3c.6 Status transition
112
170
 
113
- Each comment must name the specific planned ticket and the specific gate vague guidance is useless to product. The remediation field on the validator's report is already concrete; pass it through.
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.
114
172
 
115
173
  #### 3d. Continue
116
174
 
@@ -165,5 +223,7 @@ This skill reads project configuration from environment variables (or `$ARGUMENT
165
223
  - Never write to JIRA outside of `lisa:notion-to-jira` → `lisa:jira-write-ticket`. The validator's verdict gates progress; bypassing it produces broken tickets.
166
224
  - Never set Notion `Status` to a value this skill doesn't own (`In Review`, `Blocked`, `Ticketed`). Product owns `Draft`, `Ready`, `Shipped`.
167
225
  - Never edit the PRD's body. Communication with product happens only through Notion comments.
226
+ - 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.
227
+ - 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.
168
228
  - 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.)
169
229
  - If `lisa:notion-to-jira` returns errors (e.g. unreachable artifact, malformed PRD structure), treat them as gate failures: comment + Blocked. Don't silently fail.
@@ -28,19 +28,36 @@ Dry-run output format:
28
28
 
29
29
  ### Planned hierarchy
30
30
  - Epic: <summary>
31
+ prd_section: "<heading text from the PRD that produced this epic>"
32
+ prd_anchor: "<first ~10 chars>...<last ~10 chars>" # for selection_with_ellipsis; null if no specific section
31
33
  - Story 1.1: <summary>
34
+ prd_section: "<heading or user-story line>"
35
+ prd_anchor: "<start>...<end>"
32
36
  - Sub-task [<repo>]: <summary>
37
+ prd_section: "<heading or AC bullet>"
38
+ prd_anchor: "<start>...<end>"
33
39
  - ...
34
40
  - Story 1.2: ...
35
41
 
36
42
  ### Per-ticket validation
37
43
  - <ticket-id>: PASS | FAIL — <count> failures
38
- - <gate-id>: <one-line reason and remediation>
44
+ prd_section: "<heading text>"
45
+ prd_anchor: "<start>...<end>" # mirrored from Planned hierarchy for caller convenience
46
+ failures:
47
+ - gate: <gate-id>
48
+ category: <category from validator>
49
+ product_relevant: <true|false>
50
+ what: <plain-language description from validator>
51
+ recommendation: <1–3 candidate resolutions from validator>
39
52
 
40
53
  ### Verdict: PASS | FAIL
41
54
  ### Total failures: <n>
42
55
  ```
43
56
 
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.
58
+
59
+ 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
+
44
61
  The dry-run mode never writes to JIRA and never calls `mcp__atlassian__createJiraIssue`. It also never sets a Notion status — that is the orchestrating skill's responsibility.
45
62
 
46
63
  ## Hard Rule: All Writes Go Through `lisa:jira-write-ticket`
@@ -115,9 +115,13 @@ Atomic PRD items extracted: <n>
115
115
  | ... | ... |
116
116
 
117
117
  ### Gaps (PRD items with zero ticket coverage — blocks Ticketed status)
118
- - <item-id> (<type>) — <text>
119
- - *Source:* <PRD section reference>
120
- - *Suggested fix:* <add a ticket scoped to X / extend ticket Y to cover this / clarify whether this is in scope>
118
+ - item: <item-id> (<type>)
119
+ text: <text>
120
+ prd_section: "<heading text from the PRD>"
121
+ prd_anchor: "<first ~10 chars>...<last ~10 chars>" # for selection_with_ellipsis; null if no specific section
122
+ category: <product-clarity|acceptance-criteria|design-ux|scope|dependency|data|technical|structural>
123
+ what: <plain-language description of the gap, no JIRA jargon — written for the product team>
124
+ recommendation: <1–3 candidate resolutions: add a ticket scoped to X / extend ticket Y to cover this / mark out-of-scope explicitly. Never "clarify this".>
121
125
 
122
126
  ### Scope creep (tickets without PRD trace — informational, does not block)
123
127
  - <ticket-key> — <summary>
@@ -128,6 +132,10 @@ Atomic PRD items extracted: <n>
128
132
  ### Scope-creep count: <n>
129
133
  ```
130
134
 
135
+ `prd_anchor` and `prd_section` are built the same way as in `lisa:notion-to-jira` — the start/end snippets locate the source heading or bullet for `selection_with_ellipsis`. Set both to `null` only when the gap is not anchored to any specific section (rare).
136
+
137
+ `category` is drawn from the same fixed taxonomy used by `lisa:jira-validate-ticket` so downstream callers can apply one consistent comment-formatting policy. Most coverage gaps map to `scope` (item not represented in any ticket) or `product-clarity` (item too vague to map). Use `acceptance-criteria` for missing pass/fail conditions and `design-ux` for missing visuals.
138
+
131
139
  ## Rules
132
140
 
133
141
  - Read-only — never write to JIRA, never write to Notion (callers do that based on the verdict).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -17,6 +17,10 @@ skills:
17
17
 
18
18
  You are a JIRA build-intake agent. Your single job is to run one cycle against a JIRA project / JQL filter — find Ready tickets, dispatch each through the build flow, transition successful builds to On Dev — then report what happened.
19
19
 
20
+ ## Confirmation policy
21
+
22
+ Once you have a project key or JQL, RUN. Do not ask the caller whether to proceed, do not preview projected scope (ticket counts, PR counts, build estimates), do not offer "proceed / skip / dry-run" choices. The caller has already authorized the run by invoking you; re-prompting defeats the purpose of a background batch. The pre-flight `Blocked` outcome owned by `jira-agent` is a valid terminal state of the per-ticket lifecycle, not a failure mode — large queues and complex tickets are exactly what this skill is for. The `jira-build-intake` skill defines the only legitimate early-exit conditions (missing query, misconfigured workflow, empty Ready set); ask only when one of those applies.
23
+
20
24
  ## Workflow
21
25
 
22
26
  ### 1. Receive the query
@@ -15,6 +15,10 @@ skills:
15
15
 
16
16
  You are a PRD intake agent. Your single job is to run one intake cycle against the Notion PRD database whose URL is given to you, then report what happened.
17
17
 
18
+ ## Confirmation policy
19
+
20
+ Once you have a database URL, RUN. Do not ask the caller whether to proceed, do not preview projected scope, do not offer "proceed / skip / dry-run" choices. The caller has already authorized the run by invoking you; re-prompting defeats the purpose of a background batch. `Blocked` is a valid terminal state of the lifecycle, not a failure mode — large PRDs and PRDs full of open questions are exactly what this skill is for. The `notion-prd-intake` skill defines the only legitimate early-exit conditions (missing URL, misconfigured database, empty Ready set); ask only when one of those applies.
21
+
18
22
  ## Workflow
19
23
 
20
24
  ### 1. Receive the database URL
@@ -8,6 +8,23 @@ allowed-tools: ["Skill", "Bash", "mcp__claude_ai_Notion__notion-fetch", "mcp__cl
8
8
 
9
9
  Run one batch-intake cycle against the queue identified by `$ARGUMENTS`. Scans for `Status = Ready`, claims each item, and dispatches to the appropriate single-item lifecycle skill.
10
10
 
11
+ ## Confirmation policy
12
+
13
+ Do NOT ask the caller whether to proceed. Once invoked with a queue, run the cycle to completion. The caller (a human at the CLI or a scheduled cron) has already authorized the run by invoking the skill; re-prompting defeats the purpose of a background batch.
14
+
15
+ Specifically forbidden:
16
+
17
+ - Previewing projected scope (number of items, projected ticket counts, write counts) and asking whether to continue.
18
+ - Offering A/B/C-style choices like "proceed / skip / dry-run only" — the documented behavior IS the default. Dry-run is a different skill, not an option here.
19
+ - Pausing because the queue is large, items have many open questions, or items are likely to end in `Blocked`. `Blocked` is a valid terminal state of the downstream lifecycles, not a failure mode — routing items to `Blocked` with clarifying comments is success.
20
+ - Pausing because validation looks expensive. The cost of one cycle is bounded; the cost of stalling a scheduled cron waiting on a human is unbounded.
21
+
22
+ The only legitimate reasons to stop early:
23
+
24
+ - Missing required input (no queue argument, missing project configuration). Surface the missing value and exit.
25
+ - The queue itself is misconfigured (Status property missing expected values, JIRA workflow can't reach required transitions). Surface and exit.
26
+ - Empty `Ready` set. Exit cleanly with the idle-case message.
27
+
11
28
  ## Orchestration: agent team
12
29
 
13
30
  If you are NOT already operating inside an agent team (no prior `TeamCreate` in this session, not spawned via `Agent` with `team_name`), your FIRST tool call MUST be `TeamCreate`. Do not call `TaskCreate`, `Agent`, or implementation tools before the team exists.
@@ -13,6 +13,23 @@ allowed-tools: ["Skill", "Bash", "mcp__atlassian__getAccessibleAtlassianResource
13
13
 
14
14
  Run one build-intake cycle. Each Ready ticket is claimed, built via the `lisa:jira-agent` flow, and transitioned to `On Dev` (or the equivalent next-status for that project). The cycle is the symmetric mirror of `lisa:notion-prd-intake`: humans flip `Ready`, agents pick up and progress.
15
15
 
16
+ ## Confirmation policy
17
+
18
+ Do NOT ask the caller whether to proceed. Once invoked with a project key or JQL, run the cycle to completion — claim, dispatch each ticket through `lisa:jira-agent`, transition successful builds to `On Dev`, 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.
19
+
20
+ Specifically forbidden:
21
+
22
+ - Previewing projected scope (ticket count, projected PR count, build duration) and asking whether to continue.
23
+ - Offering A/B/C-style choices like "proceed / skip a few / dry-run only" — the documented behavior IS the default.
24
+ - Pausing because the queue is large, tickets look complex, or tickets are likely to be `Blocked` by `lisa:jira-agent`'s pre-flight gate. The pre-flight `Blocked` outcome is a valid terminal state of the per-ticket lifecycle (owned by `lisa:jira-agent`), not a failure mode — surfacing those tickets to humans is success.
25
+ - Pausing because the build flow looks expensive. The cost of one cycle is bounded; the cost of stalling a scheduled cron waiting on a human is unbounded.
26
+
27
+ The only legitimate reasons to stop early:
28
+
29
+ - Missing project key / JQL or required configuration. Surface the missing value and exit.
30
+ - Workflow misconfigured (pre-flight check finds `In Progress` or `On Dev` not reachable, or `Ready` status absent). Surface and exit.
31
+ - Empty `Ready` set. Exit cleanly with `"No tickets with Status=Ready. Nothing to do."`
32
+
16
33
  ## Lifecycle assumed
17
34
 
18
35
  The JIRA workflow has these statuses (or equivalents — see Configuration for renaming):
@@ -66,6 +66,39 @@ If the caller passes only a ticket key, fetch the ticket via `mcp__atlassian__ge
66
66
 
67
67
  Gates are grouped into **Specification** (spec-only checks, no JIRA lookups) and **Feasibility** (requires JIRA lookups). The dry-run path may opt to run Specification gates only; the write path runs both.
68
68
 
69
+ Each gate is tagged with a fixed `category` and a `product_relevant` boolean. Categories drive how downstream callers (notably `lisa:notion-prd-intake`) translate failures into product-facing comments; `product_relevant=false` failures indicate internal data-quality problems (broken parent links, missing core fields) that the agent should fix itself rather than ask product to clarify.
70
+
71
+ | Gate | Category | Product-relevant |
72
+ |------|----------|------------------|
73
+ | S1 Required core fields | `structural` | false |
74
+ | S2 Summary format | `structural` | false |
75
+ | S3 Description three audiences | `product-clarity` | true |
76
+ | S4 Acceptance criteria in Gherkin | `acceptance-criteria` | true |
77
+ | S5 Bug-specific content | `product-clarity` | true |
78
+ | S6 Spike-specific content | `scope` | true |
79
+ | S7 Epic parent declared | `structural` | false |
80
+ | S8 Target Backend Environment | `technical` | false |
81
+ | S9 Sign-in Required | `technical` | false |
82
+ | S10 Single-repo scope | `scope` | true |
83
+ | S11 Validation Journey | `acceptance-criteria` | true |
84
+ | S12 Source Precedence | `design-ux` | true |
85
+ | S13 Relationship Search | `dependency` | true |
86
+ | F1 Issue type valid in project | `structural` | false |
87
+ | F2 Epic parent exists and is an Epic | `structural` | false |
88
+ | F3 Linked tickets exist | `structural` | false |
89
+ | F4 Required custom fields populated | `structural` | false |
90
+
91
+ Category values are drawn from this fixed set:
92
+
93
+ - `product-clarity` — feature behavior or user intent unclear in the PRD
94
+ - `acceptance-criteria` — pass/fail conditions missing or ambiguous
95
+ - `design-ux` — visual or interaction spec missing
96
+ - `scope` — boundary unclear, items overlap, split needed
97
+ - `dependency` — blocked by another team / system / decision
98
+ - `data` — data source / shape / volume unspecified
99
+ - `technical` — engineering decision required (rare from PRD path; mostly internal)
100
+ - `structural` — internal data-quality problem the agent must fix itself, not surface to product
101
+
69
102
  ### Specification Gates
70
103
 
71
104
  #### S1 — Required core fields
@@ -209,16 +242,32 @@ Output is a single fenced text block. Callers parse it; do not add free-form pro
209
242
 
210
243
  ### Verdict: PASS | FAIL
211
244
  ### Failures: <count>
212
- ### Remediation
213
- - <gate-id>: <concrete fix the caller can apply or surface to the user>
214
- - <gate-id>: <concrete fix>
245
+ ### Failure details
246
+ - gate: <gate-id>
247
+ category: <product-clarity|acceptance-criteria|design-ux|scope|dependency|data|technical|structural>
248
+ product_relevant: <true|false>
249
+ what: <plain-language description of what is missing or wrong, no gate-IDs, no JIRA terminology — written so a non-engineer product owner understands the issue>
250
+ recommendation: <1–3 concrete options the caller (or downstream product team) can pick from. Never "clarify this" — always a specific suggested resolution.>
251
+ - gate: <gate-id>
252
+ category: ...
253
+ ...
215
254
  ```
216
255
 
217
256
  The verdict is `PASS` if and only if every applicable gate is `PASS`. Any `FAIL` makes the verdict `FAIL`. `N/A` does not affect the verdict.
218
257
 
258
+ ### Failure-detail fields
259
+
260
+ - **gate**: the gate ID (`S1`–`S13`, `F1`–`F4`).
261
+ - **category**: the gate's fixed category from the table above. Callers use this to label or filter comments — `product-clarity`, `acceptance-criteria`, `design-ux`, `scope`, `dependency`, `data`, `technical`, or `structural`.
262
+ - **product_relevant**: matches the gate's table entry. `false` means the failure is an internal data-quality problem (e.g., the agent built a malformed spec, an issue type is invalid in the project) and the caller should fix it without bothering the product team. `true` means the PRD needs product input to resolve.
263
+ - **what**: plain-language description of the issue. No gate IDs, no JIRA jargon, no engineering shorthand. A product owner reading this on a Notion comment should understand what is unclear and why.
264
+ - **recommendation**: 1–3 concrete options the reader can pick from, not a generic "please clarify." If the answer is genuinely open-ended, list the most plausible candidate resolutions you considered, even if speculative.
265
+
219
266
  ## Rules
220
267
 
221
268
  - Never write to JIRA. The `allowed-tools` list intentionally excludes `createJiraIssue`, `editJiraIssue`, `createIssueLink`, `addCommentToJiraIssue`.
222
269
  - Never auto-fix the spec. This skill reports gaps; callers decide what to do (block, ask the human, regenerate the spec).
223
270
  - Never silently skip a gate. If a gate genuinely doesn't apply, return `N/A` with the reason; never omit it.
224
- - The remediation lines must be concrete and actionable — the dry-run path turns each one into a Notion comment, so vague guidance is useless.
271
+ - The `what` and `recommendation` fields must be concrete and product-readable — the dry-run path turns each failure into a Notion comment, and the audience for those comments is the product team, not engineers. Vague guidance ("clarify this", "decide how to handle X") is useless; always give 1–3 candidate resolutions.
272
+ - Never emit a category outside the fixed set. If a new gate doesn't fit, propose adding the category to the taxonomy in this skill rather than inventing one inline.
273
+ - `product_relevant` is determined by the gate, not by the failure context. Do not flip it per-failure.
@@ -14,6 +14,23 @@ https://www.notion.so/geminisports/28fd00244d7d47c5866876f7de48c0fe?v=34eba63a28
14
14
 
15
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).
16
16
 
17
+ ## Confirmation policy
18
+
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.
20
+
21
+ Specifically forbidden:
22
+
23
+ - Previewing projected scope (epic count, story count, write count) and asking whether to continue.
24
+ - 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.
26
+ - 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
+
28
+ The only legitimate reasons to stop early:
29
+
30
+ - Missing database URL or required configuration (`JIRA_PROJECT`, `JIRA_SERVER`, `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."`
33
+
17
34
  ## Lifecycle assumed
18
35
 
19
36
  The PRD database has a `Status` property whose value drives this skill:
@@ -84,7 +101,7 @@ Per-ticket gates prove each ticket is well-formed; they do NOT prove the *set* o
84
101
  |---------|--------|
85
102
  | `COMPLETE` | Done. Leave `Status = Ticketed`. Move to next PRD. |
86
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`. |
87
- | `GAPS_FOUND` | The created ticket set is incomplete. (a) For each gap, post a Notion comment naming the missing PRD item and where it appears in the PRD, with the suggested fix from the audit report. (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`. |
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`. |
88
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. |
89
106
 
90
107
  3. The created tickets remain in JIRA regardless of the verdict — they are valid in their own right (they passed `lisa:jira-validate-ticket`). The audit only tells us whether *more* are needed.
@@ -93,24 +110,65 @@ The audit's report should be summarized in the cycle summary alongside the per-P
93
110
 
94
111
  **If `FAIL`** (one or more planned tickets failed one or more gates):
95
112
 
96
- 1. Group the failures by planned ticket.
97
- 2. For each failed ticket, post a Notion comment via `notion-create-comment` with this format:
113
+ The audience for these comments is the **product team**, not engineers. They are not familiar with JIRA gate IDs, validator vocabulary, or skill internals. Follow the rules below strictly — the goal is for a non-engineer product owner to read a comment, understand what is unclear, and know what to do next.
114
+
115
+ ##### 3c.1 Partition failures
116
+
117
+ 1. Drop every failure where `product_relevant = false`. Those are internal data-quality problems — the agent should fix its own spec rather than ask product to clarify a missing core field. Record the dropped failures under `Errors` in the cycle summary so engineers can see them; never surface them on the PRD.
118
+ 2. Group the remaining product-relevant failures by `prd_anchor` (the snippet from `notion-to-jira`'s dry-run report). Failures that share an anchor become one comment thread on that block. Failures with `prd_anchor: null` are batched into one page-level summary comment, since they have no source section to attach to.
119
+
120
+ ##### 3c.2 Render each comment
121
+
122
+ For each anchored group, post via `mcp__claude_ai_Notion__notion-create-comment` with:
123
+ - `page_id`: the PRD page ID
124
+ - `selection_with_ellipsis`: the `prd_anchor` value (e.g. `"# User taps Fol...esume action"`)
125
+ - `rich_text`: the body, formatted using the template below
126
+
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.
128
+
129
+ ##### 3c.3 Comment template
130
+
131
+ Each comment body MUST contain these four parts, in this order, no exceptions:
132
+
133
+ ```text
134
+ [<Category badge>] <prd_section heading text>
135
+
136
+ **What's unclear:** <validator's `what` field, verbatim — already product-readable>
137
+
138
+ **Recommendation:** <validator's `recommendation` field, verbatim — must contain 1–3 concrete options, never a generic "please clarify">
139
+
140
+ **Action:** Update this section in the PRD, then set Status back to `Ready` and Claude will re-run intake.
141
+ ```
142
+
143
+ 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.
144
+
145
+ ##### 3c.4 Category badges
146
+
147
+ Use these exact badge labels — they are the validator's category values translated for product readers:
98
148
 
99
- ```text
100
- **Blocker — planned ticket: <ticket-summary>**
149
+ | Validator category | Badge label |
150
+ |---------------------|-------------|
151
+ | `product-clarity` | `[Product clarity]` |
152
+ | `acceptance-criteria` | `[Acceptance criteria]` |
153
+ | `design-ux` | `[Design / UX]` |
154
+ | `scope` | `[Scope]` |
155
+ | `dependency` | `[Dependency]` |
156
+ | `data` | `[Data]` |
157
+ | `technical` | `[Technical]` |
101
158
 
102
- The PRD as written can't produce a valid JIRA ticket for this scope. Specifically:
159
+ `structural` failures must never reach this step (filtered in 3c.1). If you see one here, treat it as an Error and surface internally.
103
160
 
104
- - **<gate-id> (<gate-name>)**: <reason>. *Fix:* <concrete remediation>.
105
- - **<gate-id> (<gate-name>)**: <reason>. *Fix:* <concrete remediation>.
161
+ ##### 3c.5 Forbidden in product comments
106
162
 
107
- Once these are addressed in the PRD, set Status back to `Ready` and Claude will re-run intake.
108
- ```
163
+ - Gate IDs (`S4`, `F2`, etc.). Never appear in a comment body.
164
+ - JIRA terminology that has no product meaning (e.g. "Gherkin", "epic parent", "issue link", "validation journey", "sub-task hierarchy"). If the validator's `what` field uses one of these terms, paraphrase before posting; do not pass through verbatim.
165
+ - Internal skill names (`lisa:jira-validate-ticket`, `notion-to-jira`).
166
+ - Engineering shorthand (`AC`, `OOS`, `repo`, `env var`).
167
+ - "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.
109
168
 
110
- 3. Set `Status = Blocked` via `notion-update-page`.
111
- 4. Do NOT write any JIRA tickets.
169
+ ##### 3c.6 Status transition
112
170
 
113
- Each comment must name the specific planned ticket and the specific gate vague guidance is useless to product. The remediation field on the validator's report is already concrete; pass it through.
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.
114
172
 
115
173
  #### 3d. Continue
116
174
 
@@ -165,5 +223,7 @@ This skill reads project configuration from environment variables (or `$ARGUMENT
165
223
  - Never write to JIRA outside of `lisa:notion-to-jira` → `lisa:jira-write-ticket`. The validator's verdict gates progress; bypassing it produces broken tickets.
166
224
  - Never set Notion `Status` to a value this skill doesn't own (`In Review`, `Blocked`, `Ticketed`). Product owns `Draft`, `Ready`, `Shipped`.
167
225
  - Never edit the PRD's body. Communication with product happens only through Notion comments.
226
+ - 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.
227
+ - 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.
168
228
  - 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.)
169
229
  - If `lisa:notion-to-jira` returns errors (e.g. unreachable artifact, malformed PRD structure), treat them as gate failures: comment + Blocked. Don't silently fail.
@@ -28,19 +28,36 @@ Dry-run output format:
28
28
 
29
29
  ### Planned hierarchy
30
30
  - Epic: <summary>
31
+ prd_section: "<heading text from the PRD that produced this epic>"
32
+ prd_anchor: "<first ~10 chars>...<last ~10 chars>" # for selection_with_ellipsis; null if no specific section
31
33
  - Story 1.1: <summary>
34
+ prd_section: "<heading or user-story line>"
35
+ prd_anchor: "<start>...<end>"
32
36
  - Sub-task [<repo>]: <summary>
37
+ prd_section: "<heading or AC bullet>"
38
+ prd_anchor: "<start>...<end>"
33
39
  - ...
34
40
  - Story 1.2: ...
35
41
 
36
42
  ### Per-ticket validation
37
43
  - <ticket-id>: PASS | FAIL — <count> failures
38
- - <gate-id>: <one-line reason and remediation>
44
+ prd_section: "<heading text>"
45
+ prd_anchor: "<start>...<end>" # mirrored from Planned hierarchy for caller convenience
46
+ failures:
47
+ - gate: <gate-id>
48
+ category: <category from validator>
49
+ product_relevant: <true|false>
50
+ what: <plain-language description from validator>
51
+ recommendation: <1–3 candidate resolutions from validator>
39
52
 
40
53
  ### Verdict: PASS | FAIL
41
54
  ### Total failures: <n>
42
55
  ```
43
56
 
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.
58
+
59
+ 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
+
44
61
  The dry-run mode never writes to JIRA and never calls `mcp__atlassian__createJiraIssue`. It also never sets a Notion status — that is the orchestrating skill's responsibility.
45
62
 
46
63
  ## Hard Rule: All Writes Go Through `lisa:jira-write-ticket`
@@ -115,9 +115,13 @@ Atomic PRD items extracted: <n>
115
115
  | ... | ... |
116
116
 
117
117
  ### Gaps (PRD items with zero ticket coverage — blocks Ticketed status)
118
- - <item-id> (<type>) — <text>
119
- - *Source:* <PRD section reference>
120
- - *Suggested fix:* <add a ticket scoped to X / extend ticket Y to cover this / clarify whether this is in scope>
118
+ - item: <item-id> (<type>)
119
+ text: <text>
120
+ prd_section: "<heading text from the PRD>"
121
+ prd_anchor: "<first ~10 chars>...<last ~10 chars>" # for selection_with_ellipsis; null if no specific section
122
+ category: <product-clarity|acceptance-criteria|design-ux|scope|dependency|data|technical|structural>
123
+ what: <plain-language description of the gap, no JIRA jargon — written for the product team>
124
+ recommendation: <1–3 candidate resolutions: add a ticket scoped to X / extend ticket Y to cover this / mark out-of-scope explicitly. Never "clarify this".>
121
125
 
122
126
  ### Scope creep (tickets without PRD trace — informational, does not block)
123
127
  - <ticket-key> — <summary>
@@ -128,6 +132,10 @@ Atomic PRD items extracted: <n>
128
132
  ### Scope-creep count: <n>
129
133
  ```
130
134
 
135
+ `prd_anchor` and `prd_section` are built the same way as in `lisa:notion-to-jira` — the start/end snippets locate the source heading or bullet for `selection_with_ellipsis`. Set both to `null` only when the gap is not anchored to any specific section (rare).
136
+
137
+ `category` is drawn from the same fixed taxonomy used by `lisa:jira-validate-ticket` so downstream callers can apply one consistent comment-formatting policy. Most coverage gaps map to `scope` (item not represented in any ticket) or `product-clarity` (item too vague to map). Use `acceptance-criteria` for missing pass/fail conditions and `design-ux` for missing visuals.
138
+
131
139
  ## Rules
132
140
 
133
141
  - Read-only — never write to JIRA, never write to Notion (callers do that based on the verdict).