@codyswann/lisa 2.104.5 → 2.104.7
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 +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/rules/config-resolution.md +7 -19
- package/plugins/lisa/rules/prd-lifecycle-rollup.md +16 -15
- package/plugins/lisa/scripts/queue-contract-resolution.mjs +24 -29
- package/plugins/lisa/skills/confluence-prd-intake/SKILL.md +14 -35
- package/plugins/lisa/skills/github-prd-intake/SKILL.md +13 -30
- package/plugins/lisa/skills/linear-prd-intake/SKILL.md +14 -32
- package/plugins/lisa/skills/notion-prd-intake/SKILL.md +12 -31
- package/plugins/lisa/skills/setup-confluence/SKILL.md +1 -1
- package/plugins/lisa/skills/verify-prd/SKILL.md +7 -7
- 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-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.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/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/src/base/rules/config-resolution.md +7 -19
- package/plugins/src/base/rules/prd-lifecycle-rollup.md +16 -15
- package/plugins/src/base/scripts/queue-contract-resolution.mjs +24 -29
- package/plugins/src/base/skills/confluence-prd-intake/SKILL.md +14 -35
- package/plugins/src/base/skills/github-prd-intake/SKILL.md +13 -30
- package/plugins/src/base/skills/linear-prd-intake/SKILL.md +14 -32
- package/plugins/src/base/skills/notion-prd-intake/SKILL.md +12 -31
- package/plugins/src/base/skills/setup-confluence/SKILL.md +1 -1
- package/plugins/src/base/skills/verify-prd/SKILL.md +7 -7
package/package.json
CHANGED
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"lodash": ">=4.18.1"
|
|
83
83
|
},
|
|
84
84
|
"name": "@codyswann/lisa",
|
|
85
|
-
"version": "2.104.
|
|
85
|
+
"version": "2.104.7",
|
|
86
86
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
87
87
|
"main": "dist/index.js",
|
|
88
88
|
"exports": {
|
|
@@ -58,8 +58,7 @@ fi
|
|
|
58
58
|
"verified": "<page-id>"
|
|
59
59
|
},
|
|
60
60
|
"dashboardPageId": "<page-id>",
|
|
61
|
-
"feedbackPageId": "<page-id>"
|
|
62
|
-
"rollup": { "closeOnShipped": false }
|
|
61
|
+
"feedbackPageId": "<page-id>"
|
|
63
62
|
},
|
|
64
63
|
"github": {
|
|
65
64
|
"org": "<org-or-user>",
|
|
@@ -86,8 +85,7 @@ fi
|
|
|
86
85
|
"ready": "prd-ready", "in_review": "prd-in-review",
|
|
87
86
|
"blocked": "prd-blocked", "ticketed": "prd-ticketed",
|
|
88
87
|
"shipped": "prd-shipped", "verified": "prd-verified",
|
|
89
|
-
"sentinel": "prd-intake-feedback"
|
|
90
|
-
"rollup": { "closeOnShipped": false }
|
|
88
|
+
"sentinel": "prd-intake-feedback"
|
|
91
89
|
}
|
|
92
90
|
}
|
|
93
91
|
},
|
|
@@ -99,8 +97,7 @@ fi
|
|
|
99
97
|
"draft": "Draft", "ready": "Ready", "in_review": "In Review",
|
|
100
98
|
"blocked": "Blocked", "ticketed": "Ticketed", "shipped": "Shipped",
|
|
101
99
|
"verified": "Verified"
|
|
102
|
-
}
|
|
103
|
-
"rollup": { "closeOnShipped": false }
|
|
100
|
+
}
|
|
104
101
|
},
|
|
105
102
|
"linear": {
|
|
106
103
|
"workspace": "<workspace-slug>",
|
|
@@ -118,8 +115,7 @@ fi
|
|
|
118
115
|
"ready": "prd-ready", "in_review": "prd-in-review",
|
|
119
116
|
"blocked": "prd-blocked", "ticketed": "prd-ticketed",
|
|
120
117
|
"shipped": "prd-shipped", "verified": "prd-verified",
|
|
121
|
-
"sentinel": "prd-intake-feedback"
|
|
122
|
-
"rollup": { "closeOnShipped": false }
|
|
118
|
+
"sentinel": "prd-intake-feedback"
|
|
123
119
|
}
|
|
124
120
|
}
|
|
125
121
|
},
|
|
@@ -291,17 +287,9 @@ Every lifecycle skill operates on a fixed set of **roles** (`ready`, `claimed`,
|
|
|
291
287
|
| `verified` | Shipped product empirically checked against the PRD | `Verified` (status) | `prd-verified` (label); parent-page lookup (Confluence) |
|
|
292
288
|
| `sentinel` | (PRD-intake feedback issue marker, GitHub/Linear self-host only) | — | `prd-intake-feedback` |
|
|
293
289
|
|
|
294
|
-
### PRD rollup
|
|
295
|
-
|
|
296
|
-
PRD lifecycle completion is **derived** from the PRD's generated top-level work, not set independently — see the `prd-lifecycle-rollup` rule for the full contract (generated-top-level-work definition, per-vendor terminal-state predicate, the `shipped` transition, and the child-ref idempotency key). When all required generated top-level children are terminal, rollup transitions the PRD to its `shipped` role; the `prd.rollup` block configures the optional close/archive step that follows.
|
|
297
|
-
|
|
298
|
-
The `rollup` object lives in each PRD-source vendor section (`github.labels.prd.rollup`, `linear.labels.prd.rollup`, `notion.rollup`, `confluence.rollup`):
|
|
299
|
-
|
|
300
|
-
| Key | Required | Default | Notes |
|
|
301
|
-
|-----|----------|---------|-------|
|
|
302
|
-
| `closeOnShipped` | no | `false` | When `true`, rollup closes/archives the PRD after the `shipped` transition (GitHub: close the issue; Linear: move to a closed/archived state; JIRA: transition to Done; Confluence/Notion: archive where supported). When `false` (the default), the PRD is set to `shipped` but left open for a human to close. Closure never happens before all generated top-level work is terminal. |
|
|
290
|
+
### PRD rollup behavior
|
|
303
291
|
|
|
304
|
-
|
|
292
|
+
PRD lifecycle completion is **derived** from the PRD's generated top-level work, not set independently — see the `prd-lifecycle-rollup` rule for the full contract (generated-top-level-work definition, per-vendor terminal-state predicate, the `shipped` transition, verified native closure, and the child-ref idempotency key). When all required generated top-level children are terminal, rollup transitions the PRD to its `shipped` role and leaves it open/active for `/lisa:verify-prd`. There is no project-configurable close-on-shipped flag: provider-native closure/archive/completion happens only after `/lisa:verify-prd` passes and moves the PRD to `verified`.
|
|
305
293
|
|
|
306
294
|
### Repair intake config (`intake.repair`)
|
|
307
295
|
|
|
@@ -370,7 +358,7 @@ The true terminal `done` value is also the only value that triggers provider-nat
|
|
|
370
358
|
### What's configurable, what's not
|
|
371
359
|
|
|
372
360
|
- **Status / label NAMES** are configurable per project — that's the point of the vocabulary maps.
|
|
373
|
-
- **Role SEMANTICS and TRANSITIONS** are not. The build lifecycle is always `ready → claimed → done` (with optional `review` for label-driven systems). The PRD lifecycle is always `ready → in_review → (blocked | ticketed) → shipped`, then verification may move `shipped → verified` on a pass or `shipped →
|
|
361
|
+
- **Role SEMANTICS and TRANSITIONS** are not. The build lifecycle is always `ready → claimed → done` (with optional `review` for label-driven systems). The PRD lifecycle is always `ready → in_review → (blocked | ticketed) → shipped`, then verification may move `shipped → verified` on a pass or `shipped → ticketed` on a failed verification. `verified` is terminal and product-owned like `draft` and `shipped`; Lisa does not add `prd-verifying` or `prd-verification-failed` states. Skills hardcode these transitions because they encode the design intent of the framework, not the project's preferences.
|
|
374
362
|
- **Extra statuses/labels** the project uses outside these roles are fine — lisa never touches them.
|
|
375
363
|
|
|
376
364
|
### Defaults vs. requirements
|
|
@@ -6,7 +6,7 @@ It defines four coupled things:
|
|
|
6
6
|
|
|
7
7
|
1. **Generated top-level work** — what a PRD owns as children (its created Epics / top-level Stories), explicitly **excluding** leaf Sub-tasks.
|
|
8
8
|
2. **Per-vendor terminal-state predicate** — how "this generated child is done" is decided for each source/tracker.
|
|
9
|
-
3. **PRD `shipped` transition +
|
|
9
|
+
3. **PRD `shipped` transition + verified native closure** — when and how a PRD rolls up to shipped, remains eligible for verification, and closes only after verified.
|
|
10
10
|
4. **Idempotency dedupe key** — the child-ref identity that makes linking and rollup safe to re-run.
|
|
11
11
|
|
|
12
12
|
This is the PRD-level companion to `leaf-only-lifecycle`: that rule governs the *build* lifecycle of leaf work units and how a **parent container** rolls up from its leaf children; this rule governs the *PRD* lifecycle and how the **PRD** rolls up from its generated top-level children. The two share the rollup shape (terminal children → parent advances) and the multi-env terminal handling, applied at different levels of the hierarchy.
|
|
@@ -52,12 +52,12 @@ Use this matrix when implementing or auditing a PRD-source integration. It descr
|
|
|
52
52
|
|
|
53
53
|
| PRD source / tracker shape | Native hierarchy mechanism | Documented fallback | Closure behavior |
|
|
54
54
|
|---|---|---|---|
|
|
55
|
-
| **GitHub Issues (source and tracker in the same repo)** | Link generated top-level work as native sub-issues of the PRD issue when the repo supports GitHub sub-issues. The PRD's direct sub-issues are the generated top-level child set; descendants under those children are excluded from PRD rollup. | Always maintain the machine-readable `## Tickets` / `## Generated Work` section keyed by `owner/repo#number`, and use it when sub-issues are unavailable, disabled, or incomplete. | Rollup changes the PRD lifecycle label from `prd-ticketed` to `prd-shipped` when every required generated top-level issue is terminal
|
|
56
|
-
| **Linear** | Use Linear native grouping where the PRD also lives in Linear: generated top-level Issues are related through `parentId`, or a generated Project groups the generated Issues. Read only top-level Issues for PRD rollup. | Use the PRD's machine-readable generated-work section when the destination tracker is not Linear or native project / parent relationships cannot represent the PRD-to-work link. Entries are keyed by Linear issue or project identifier / UUID. | Rollup removes `prd-ticketed` and adds `prd-shipped` to the PRD project when every required generated top-level Issue / Project is completed
|
|
57
|
-
| **JIRA / Atlassian tracker work** | Prefer native Epic / parent fields, or a documented issue-link type where the PRD-to-Epic relationship can be represented in JIRA. JIRA child terminal state is read from the issue's Done status category. | If the PRD source is not JIRA or the native link cannot attach tracker work to the PRD artifact, record generated top-level JIRA issue keys in the PRD's generated-work section. | Rollup may transition a JIRA-hosted PRD to the configured shipped
|
|
58
|
-
| **Confluence PRDs** | No native issue hierarchy for tracker work. Confluence's native structure is used for PRD lifecycle lanes by parent page, not for destination work children. | The Confluence page's machine-readable `## Tickets` / `## Generated Work` section is the primary child source. Top-level generated work entries are keyed by destination ticket ref. | Rollup re-parents the PRD page from the `ticketed` parent to the `shipped` parent when every required generated-work entry is marked done
|
|
59
|
-
| **Notion PRDs** | No native issue hierarchy for tracker work. Notion's native status/select property stores PRD lifecycle state, not generated ticket parentage. | The Notion page's machine-readable `## Tickets` / `## Generated Work` section is the primary child source. Top-level generated work entries are keyed by destination ticket ref. | Rollup sets the configured Notion status/select value to `Shipped` when every required generated-work entry is marked done
|
|
60
|
-
| **Cross-vendor PRD -> tracker** | Native hierarchy cannot cross systems, so the destination ticket is not expected to become a native child of the PRD artifact. Native tracker hierarchy still applies inside the destination system among generated Epics, Stories, and Sub-tasks. | The source PRD artifact's generated-work section is authoritative for the PRD-to-top-level-work child set, and each entry links to the destination ticket URL / key. | The PRD source owns the
|
|
55
|
+
| **GitHub Issues (source and tracker in the same repo)** | Link generated top-level work as native sub-issues of the PRD issue when the repo supports GitHub sub-issues. The PRD's direct sub-issues are the generated top-level child set; descendants under those children are excluded from PRD rollup. | Always maintain the machine-readable `## Tickets` / `## Generated Work` section keyed by `owner/repo#number`, and use it when sub-issues are unavailable, disabled, or incomplete. | Rollup changes the PRD lifecycle label from `prd-ticketed` to `prd-shipped` when every required generated top-level issue is terminal and leaves the issue open for `/lisa:verify-prd`. Verified PASS closes the issue natively. |
|
|
56
|
+
| **Linear** | Use Linear native grouping where the PRD also lives in Linear: generated top-level Issues are related through `parentId`, or a generated Project groups the generated Issues. Read only top-level Issues for PRD rollup. | Use the PRD's machine-readable generated-work section when the destination tracker is not Linear or native project / parent relationships cannot represent the PRD-to-work link. Entries are keyed by Linear issue or project identifier / UUID. | Rollup removes `prd-ticketed` and adds `prd-shipped` to the PRD project when every required generated top-level Issue / Project is completed and leaves it active for `/lisa:verify-prd`. Verified PASS archives/completes it natively. |
|
|
57
|
+
| **JIRA / Atlassian tracker work** | Prefer native Epic / parent fields, or a documented issue-link type where the PRD-to-Epic relationship can be represented in JIRA. JIRA child terminal state is read from the issue's Done status category. | If the PRD source is not JIRA or the native link cannot attach tracker work to the PRD artifact, record generated top-level JIRA issue keys in the PRD's generated-work section. | Rollup may transition a JIRA-hosted PRD to the configured shipped status only after all required generated top-level issues are in the Done status category. Verified PASS performs native completion where supported. |
|
|
58
|
+
| **Confluence PRDs** | No native issue hierarchy for tracker work. Confluence's native structure is used for PRD lifecycle lanes by parent page, not for destination work children. | The Confluence page's machine-readable `## Tickets` / `## Generated Work` section is the primary child source. Top-level generated work entries are keyed by destination ticket ref. | Rollup re-parents the PRD page from the `ticketed` parent to the `shipped` parent when every required generated-work entry is marked done and leaves the page active for `/lisa:verify-prd`. Verified PASS archives it where supported. |
|
|
59
|
+
| **Notion PRDs** | No native issue hierarchy for tracker work. Notion's native status/select property stores PRD lifecycle state, not generated ticket parentage. | The Notion page's machine-readable `## Tickets` / `## Generated Work` section is the primary child source. Top-level generated work entries are keyed by destination ticket ref. | Rollup sets the configured Notion status/select value to `Shipped` when every required generated-work entry is marked done and leaves the page active for `/lisa:verify-prd`. Verified PASS archives it where supported. |
|
|
60
|
+
| **Cross-vendor PRD -> tracker** | Native hierarchy cannot cross systems, so the destination ticket is not expected to become a native child of the PRD artifact. Native tracker hierarchy still applies inside the destination system among generated Epics, Stories, and Sub-tasks. | The source PRD artifact's generated-work section is authoritative for the PRD-to-top-level-work child set, and each entry links to the destination ticket URL / key. | The PRD source owns the lifecycle transition. It evaluates terminal state using the destination tracker's predicate, applies the source vendor's `shipped` transition, leaves the PRD open/active, then `/lisa:verify-prd` owns verified native closure. |
|
|
61
61
|
|
|
62
62
|
## Per-vendor terminal-state predicate
|
|
63
63
|
|
|
@@ -82,13 +82,14 @@ Where a vendor's terminal predicate references the build-status `done` role (Git
|
|
|
82
82
|
|
|
83
83
|
**Single-environment collapse (this repo).** Lisa's own deploy has only `main`/`production` (`deploy.branches = production: main`, no dev/staging), so `done` is a single value, not a map, and the build lifecycle collapses to one chain: `ready → claimed (in-progress) → review (code-review) → done`. A generated top-level child is terminal when it reaches the single `status:done`; rollup never resolves a `dev` or `staging` `done` in this repo. This is the *collapsed* case of the generic rule, not a different rule — projects with more environments keep the env-keyed map.
|
|
84
84
|
|
|
85
|
-
## PRD `shipped` transition
|
|
85
|
+
## PRD `shipped` transition and verified native closure
|
|
86
86
|
|
|
87
|
-
When **all required** generated top-level children are terminal, the PRD rolls up to its
|
|
87
|
+
When **all required** generated top-level children are terminal, the PRD rolls up to its `shipped` PRD-lifecycle state and remains open/active for the initiative-level verification loop:
|
|
88
88
|
|
|
89
|
-
1. **Transition to `shipped`.** Set the PRD to the configured `shipped` role (`config-resolution` PRD-lifecycle roles: `prd-shipped` label for GitHub/Linear, `Shipped` status for Notion, the shipped parent page for Confluence). The PRD lifecycle is `ready → in_review → (blocked | ticketed) → shipped → verified`; rollup performs the `ticketed → shipped` hop only, and only on the all-terminal condition. The subsequent `shipped → verified` (pass) / `shipped →
|
|
90
|
-
2. **
|
|
91
|
-
3. **
|
|
89
|
+
1. **Transition to `shipped`.** Set the PRD to the configured `shipped` role (`config-resolution` PRD-lifecycle roles: `prd-shipped` label for GitHub/Linear, `Shipped` status for Notion, the shipped parent page for Confluence). The PRD lifecycle is `ready → in_review → (blocked | ticketed) → shipped → verified`; rollup performs the `ticketed → shipped` hop only, and only on the all-terminal condition. The subsequent `shipped → verified` (pass) / `shipped → ticketed` (fail) hops are owned by PRD-level verification (`/lisa:verify-prd`), **not** by this rollup — see "PRD-level verification vs ticket verification" below.
|
|
90
|
+
2. **Leave `shipped` open for verification.** Rollup never closes, archives, or completes the PRD at the `shipped` hop. `shipped` is the queue for `/lisa:verify-prd`, so closing here would hide the PRD from the acceptance gate.
|
|
91
|
+
3. **Verified closes natively.** When `/lisa:verify-prd` passes, it transitions `shipped → verified` and then closes, archives, or completes the PRD where the source tool supports a native terminal action. The verified native close is mandatory and idempotent; there is no project-configurable close-on-verified escape hatch.
|
|
92
|
+
4. **Partial completion is a no-op + report.** If only some required children are terminal, leave the PRD in its current state and report the incomplete/blocked child set. Do not advance, do not close.
|
|
92
93
|
|
|
93
94
|
The PRD never advances to `shipped` on its own authority — it is **derived** from the generated-top-level-child set, exactly as a container's state is derived from its leaves in `leaf-only-lifecycle`.
|
|
94
95
|
|
|
@@ -118,7 +119,7 @@ The PRD never advances to `shipped` on its own authority — it is **derived** f
|
|
|
118
119
|
|
|
119
120
|
**The self-healing FAIL loop.** When verify-prd fails it re-opens the PRD `shipped → ticketed` and creates **build-ready** fix tickets (registered as the PRD's generated work). Because the fix tickets are build-ready they are auto-claimed by the build queue with no human promotion; once they reach terminal, the `ticketed → shipped` rollup (Phase 3f) re-ships the PRD, and the next cycle's verify dispatch (Phase 3g) re-verifies. PASS ends at `verified`; FAIL starts another round. The loop **never auto-halts** (the failure report carries a verification-round count for human visibility) and **never** parks the PRD in `blocked`.
|
|
120
121
|
|
|
121
|
-
Bounded, like the ready claim: `/lisa:verify-prd` is a heavy full flow (spec-conformance + empirical verification + fix-ticket creation), so a scanner verifies **one shipped PRD per cycle** and lets the scheduler drain the rest — the same one-item-per-cycle discipline the `ready` claim uses. After verify-prd runs, the PRD leaves `shipped` (to `verified` on pass, or `ticketed` on fail), so it is not re-picked by the shipped query that cycle; a PRD whose generated work is not actually terminal is guard-stopped by verify-prd and left `shipped` (verify-prd's gate, not the scanner's).
|
|
122
|
+
Bounded, like the ready claim: `/lisa:verify-prd` is a heavy full flow (spec-conformance + empirical verification + fix-ticket creation), so a scanner verifies **one shipped PRD per cycle** and lets the scheduler drain the rest — the same one-item-per-cycle discipline the `ready` claim uses. After verify-prd runs, the PRD leaves `shipped` (to `verified` on pass, or `ticketed` on fail), so it is not re-picked by the shipped query that cycle; a PRD whose generated work is not actually terminal is guard-stopped by verify-prd and left `shipped` (verify-prd's gate, not the scanner's). This dispatch is **behaviorally identical across all four PRD-intake skills** (the `github` / `linear` / `notion` / `confluence` `*-prd-intake` Phase 3g); only the `shipped`-role query surface differs.
|
|
122
123
|
|
|
123
124
|
## Idempotency dedupe key
|
|
124
125
|
|
|
@@ -144,8 +145,8 @@ Skills that link generated work to a PRD or roll a PRD up cite this rule by slug
|
|
|
144
145
|
|
|
145
146
|
- **PRD backlink / native linking** (`prd-backlink`) — record generated top-level work as native PRD children where supported; always write the documented generated-work fallback; dedupe by child-ref. *(LPC-1.1 #580, LPC-1.2 #582)*
|
|
146
147
|
- **PRD coverage** (`prd-ticket-coverage`) — read the generated top-level child set deterministically from the recorded relationship, not from free-form comments.
|
|
147
|
-
- **GitHub PRD
|
|
148
|
-
- **Linear / Confluence / Notion PRD rollup** (`linear-prd-intake`, `confluence-prd-intake`, `notion-prd-intake`) — mirror the GitHub
|
|
148
|
+
- **GitHub PRD shipped rollup** (`github-prd-intake`) — detect terminal/incomplete/blocked child sets, transition to `prd-shipped`, and leave the PRD open for `/lisa:verify-prd`. *(LPC-1.3 #583)*
|
|
149
|
+
- **Linear / Confluence / Notion PRD shipped rollup** (`linear-prd-intake`, `confluence-prd-intake`, `notion-prd-intake`) — mirror the GitHub shipped rollup with each vendor's terminal predicate and keep the PRD active for verification. *(LPC-1.3 #584)*
|
|
149
150
|
- **Repair close-out** (`repair-intake`) — re-run the same generated-top-level-work terminal
|
|
150
151
|
predicate to close out PRDs that were left open after all associated child work became terminal,
|
|
151
152
|
without setting the product-owned `verified` role.
|
|
@@ -216,13 +216,9 @@ export function resolvePrdLifecycleRoles(
|
|
|
216
216
|
kind: "labels",
|
|
217
217
|
roles: resolveObjectRoles(
|
|
218
218
|
config.github?.labels?.prd,
|
|
219
|
-
DEFAULT_GITHUB_LINEAR_PRD_ROLES
|
|
219
|
+
DEFAULT_GITHUB_LINEAR_PRD_ROLES,
|
|
220
|
+
{ allowNull: false }
|
|
220
221
|
),
|
|
221
|
-
rollup: {
|
|
222
|
-
closeOnShipped: Boolean(
|
|
223
|
-
config.github?.labels?.prd?.rollup?.closeOnShipped ?? false
|
|
224
|
-
),
|
|
225
|
-
},
|
|
226
222
|
};
|
|
227
223
|
case "linear":
|
|
228
224
|
return {
|
|
@@ -230,13 +226,9 @@ export function resolvePrdLifecycleRoles(
|
|
|
230
226
|
kind: "labels",
|
|
231
227
|
roles: resolveObjectRoles(
|
|
232
228
|
config.linear?.labels?.prd,
|
|
233
|
-
DEFAULT_GITHUB_LINEAR_PRD_ROLES
|
|
229
|
+
DEFAULT_GITHUB_LINEAR_PRD_ROLES,
|
|
230
|
+
{ allowNull: false }
|
|
234
231
|
),
|
|
235
|
-
rollup: {
|
|
236
|
-
closeOnShipped: Boolean(
|
|
237
|
-
config.linear?.labels?.prd?.rollup?.closeOnShipped ?? false
|
|
238
|
-
),
|
|
239
|
-
},
|
|
240
232
|
};
|
|
241
233
|
case "notion":
|
|
242
234
|
return {
|
|
@@ -245,13 +237,9 @@ export function resolvePrdLifecycleRoles(
|
|
|
245
237
|
statusProperty: config.notion?.statusProperty || "Status",
|
|
246
238
|
roles: resolveObjectRoles(
|
|
247
239
|
config.notion?.values,
|
|
248
|
-
DEFAULT_NOTION_PRD_ROLES
|
|
240
|
+
DEFAULT_NOTION_PRD_ROLES,
|
|
241
|
+
{ allowNull: false }
|
|
249
242
|
),
|
|
250
|
-
rollup: {
|
|
251
|
-
closeOnShipped: Boolean(
|
|
252
|
-
config.notion?.rollup?.closeOnShipped ?? false
|
|
253
|
-
),
|
|
254
|
-
},
|
|
255
243
|
};
|
|
256
244
|
case "confluence":
|
|
257
245
|
return {
|
|
@@ -259,13 +247,9 @@ export function resolvePrdLifecycleRoles(
|
|
|
259
247
|
kind: "parent-pages",
|
|
260
248
|
roles: resolveObjectRoles(
|
|
261
249
|
config.confluence?.parents,
|
|
262
|
-
DEFAULT_CONFLUENCE_PARENT_ROLES
|
|
250
|
+
DEFAULT_CONFLUENCE_PARENT_ROLES,
|
|
251
|
+
{ allowNull: true }
|
|
263
252
|
),
|
|
264
|
-
rollup: {
|
|
265
|
-
closeOnShipped: Boolean(
|
|
266
|
-
config.confluence?.rollup?.closeOnShipped ?? false
|
|
267
|
-
),
|
|
268
|
-
},
|
|
269
253
|
};
|
|
270
254
|
default:
|
|
271
255
|
throw new Error(
|
|
@@ -374,13 +358,24 @@ export function resolveQueueContract(input = {}) {
|
|
|
374
358
|
/**
|
|
375
359
|
* @param {Record<string, any> | undefined} values
|
|
376
360
|
* @param {Record<string, any>} defaults
|
|
361
|
+
* @param {{ readonly allowNull?: boolean }} [options]
|
|
377
362
|
* @returns {Record<string, any>}
|
|
378
363
|
*/
|
|
379
|
-
function resolveObjectRoles(values, defaults) {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
364
|
+
function resolveObjectRoles(values, defaults, options = {}) {
|
|
365
|
+
const resolved = { ...defaults };
|
|
366
|
+
|
|
367
|
+
for (const [key, value] of Object.entries(values ?? {})) {
|
|
368
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
369
|
+
resolved[key] = value;
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (options.allowNull === true && value === null) {
|
|
374
|
+
resolved[key] = value;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return resolved;
|
|
384
379
|
}
|
|
385
380
|
|
|
386
381
|
/**
|
|
@@ -59,26 +59,13 @@ current_role_for_prd() {
|
|
|
59
59
|
done
|
|
60
60
|
echo "unknown"
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
# Resolve a boolean rollup flag. Local overrides global per-key; default when unset.
|
|
64
|
-
# NOTE: Confluence rollup config lives under `confluence.rollup` (NOT
|
|
65
|
-
# `confluence.parents.rollup`) — see the config-resolution rule.
|
|
66
|
-
read_rollup_flag() {
|
|
67
|
-
local key="$1" default="$2"
|
|
68
|
-
local local_v global_v
|
|
69
|
-
local_v=$(jq -r ".confluence.rollup.${key} // empty" .lisa.config.local.json 2>/dev/null)
|
|
70
|
-
global_v=$(jq -r ".confluence.rollup.${key} // empty" .lisa.config.json 2>/dev/null)
|
|
71
|
-
echo "${local_v:-${global_v:-$default}}"
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
CLOSE_ON_SHIPPED=$(read_rollup_flag closeOnShipped false)
|
|
75
62
|
```
|
|
76
63
|
|
|
77
64
|
In prose below, the role names refer to the resolved parent-page IDs: e.g. "the `ready` parent" means whatever `confluence.parents.ready` resolves to.
|
|
78
65
|
|
|
79
|
-
This skill is the Confluence counterpart of `lisa:notion-prd-intake`, and shares its PRD
|
|
66
|
+
This skill is the Confluence counterpart of `lisa:notion-prd-intake`, and shares its PRD shipped rollup phase (3f) with `lisa:github-prd-intake` and `lisa:linear-prd-intake`. The phases, gates, comment templates, and rules are identical — the only differences are (1) the lifecycle is encoded as **parent-page placement** instead of a status property, and (2) the fetch / comment / update tools route through `lisa:atlassian-access`. Keep all four intake skills behaviorally aligned: when changing intake logic — including the rollup phase — change them together.
|
|
80
67
|
|
|
81
|
-
The **PRD
|
|
68
|
+
The **PRD shipped rollup phase (3f)** re-parents a `ticketed` PRD to the `shipped` parent once all its generated top-level work is terminal, per the `prd-lifecycle-rollup` rule. This is the Confluence leg of the same vendor-neutral rollup that `lisa:github-prd-intake` implements for GitHub (LPC-1.3 #584); only the vendor surface (parent-page placement + documented generated-work section, since Confluence has no native ticket hierarchy) differs.
|
|
82
69
|
|
|
83
70
|
## Confirmation policy
|
|
84
71
|
|
|
@@ -118,9 +105,9 @@ This skill transitions:
|
|
|
118
105
|
- `in_review` → `blocked` (gate failures or coverage gaps)
|
|
119
106
|
- `in_review` → `ticketed` (success)
|
|
120
107
|
- `ticketed` → `blocked` (post-write coverage gaps from Phase 3e)
|
|
121
|
-
- `ticketed` → `shipped` (PRD
|
|
108
|
+
- `ticketed` → `shipped` (PRD shipped rollup, Phase 3f — only when **all** generated top-level children are terminal)
|
|
122
109
|
|
|
123
|
-
It never re-parents PRDs into or out of the `draft` or `verified` parents — those parents are owned by product (`verified` is set by `/lisa:verify-prd` after empirical PRD-level acceptance). The `shipped` parent is set by this skill's **rollup phase (3f)** when, and only when, the PRD's generated top-level work is all terminal — per the `prd-lifecycle-rollup` rule; product may also re-parent there by hand. Rollup never advances a PRD to `shipped` on partial completion, and never archives a PRD page
|
|
110
|
+
It never re-parents PRDs into or out of the `draft` or `verified` parents — those parents are owned by product (`verified` is set by `/lisa:verify-prd` after empirical PRD-level acceptance). The `shipped` parent is set by this skill's **rollup phase (3f)** when, and only when, the PRD's generated top-level work is all terminal — per the `prd-lifecycle-rollup` rule; product may also re-parent there by hand. Rollup never advances a PRD to `shipped` on partial completion, and never archives a PRD page at shipped. `/lisa:verify-prd` archives the page only after a verified PASS.
|
|
124
111
|
|
|
125
112
|
A "transition" means: update the PRD's `parentId` to the new role's parent-page id via `lisa:atlassian-access` `operation: write-page payload: { id, parentId, title, version: { number: <next> } }`. The v2 PUT endpoint requires the next version number and the page title in the payload; the body content is not strictly required for a re-parent-only edit, but some Atlassian deployments reject PUTs without a body. The skill MUST therefore GET the page first via `read-page`, capture title + current version + current body, then PUT with `parentId` swapped and `version.number` bumped — preserving body content is non-negotiable, this skill never edits PRD content. See `transition_prd` helper in Phase 3a for the canonical implementation.
|
|
126
113
|
|
|
@@ -297,25 +284,19 @@ Per-ticket gates prove each ticket is well-formed; they do NOT prove the *set* o
|
|
|
297
284
|
|
|
298
285
|
3. The created tickets remain in the destination tracker regardless of the verdict — they are valid in their own right. The audit only tells us whether *more* are needed.
|
|
299
286
|
|
|
300
|
-
#### 3f. PRD
|
|
287
|
+
#### 3f. PRD shipped rollup
|
|
301
288
|
|
|
302
289
|
A PRD's lifecycle terminal state (`shipped`) is **derived** from whether the work it generated is done — it is never set by hand here on its own authority. This phase implements the Confluence leg of that derivation, per the `prd-lifecycle-rollup` rule (cite it by slug; do not restate its taxonomy or terminal-state semantics here). It is behaviorally identical to `lisa:github-prd-intake`'s Phase 3f — only the vendor surface (parent-page re-parenting via `lisa:atlassian-access` + the documented generated-work section) differs from GitHub's (issue close + labels via `gh`).
|
|
303
290
|
|
|
304
291
|
Rollup runs over PRD pages that are already under the `ticketed` parent (the only state from which a PRD can ship): the freshly-ticketed PRD from Phase 3c, and — because rollup also catches PRDs whose children finished in a *later* cycle — every page currently parented under `$TICKETED_PARENT`. (Re-read its direct children via `lisa:atlassian-access` `operation: read-page-descendants id: $TICKETED_PARENT`.) Process each independently; one PRD never blocks another's rollup.
|
|
305
292
|
|
|
306
|
-
##### 3f.0
|
|
293
|
+
##### 3f.0 Shipped remains active for verification
|
|
307
294
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
```bash
|
|
311
|
-
CLOSE_ON_SHIPPED=$(read_rollup_flag closeOnShipped false)
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
When `false` (the default), rollup re-parents the PRD under `$SHIPPED_PARENT` but leaves the page **active** for a human to archive. When `true`, rollup also archives the page (where the deployment supports archival) after the `shipped` re-parent. Closure NEVER happens before all generated top-level work is terminal (`prd-lifecycle-rollup` rule; PRD #525 non-goal).
|
|
295
|
+
There is no archive configuration at the shipped hop. Rollup re-parents the PRD under `$SHIPPED_PARENT` and leaves the page **active** so Phase 3g can dispatch `/lisa:verify-prd`. Provider-native archival is owned by `/lisa:verify-prd` after it transitions the PRD to the verified parent on a PASS.
|
|
315
296
|
|
|
316
297
|
##### 3f.1 Idempotency guard (no-op if already shipped)
|
|
317
298
|
|
|
318
|
-
Rollup is keyed by the PRD's current state. If the PRD is already parented under `$SHIPPED_PARENT
|
|
299
|
+
Rollup is keyed by the PRD's current state. If the PRD is already parented under `$SHIPPED_PARENT`, it is a **no-op** — do not re-parent, do not archive, do not re-comment. Record it as `already shipped (no-op)` in the cycle summary and move on. This is what makes re-running intake safe.
|
|
319
300
|
|
|
320
301
|
##### 3f.2 Read the generated top-level child set
|
|
321
302
|
|
|
@@ -340,7 +321,7 @@ The set of **required** children for the all-terminal check is the top-level chi
|
|
|
340
321
|
**All required children terminal** (every required top-level child is terminal; at least one required child exists):
|
|
341
322
|
|
|
342
323
|
1. Re-parent to `shipped`: `transition_prd "$PRD_ID" shipped` (GET-then-PUT via `lisa:atlassian-access` preserving the body verbatim). After the re-parent, re-read the page and confirm `parentId` matches `$SHIPPED_PARENT` (the single-parent invariant).
|
|
343
|
-
2.
|
|
324
|
+
2. Leave the PRD active for `/lisa:verify-prd`; do not archive at the shipped hop.
|
|
344
325
|
3. Post a short rollup footer comment via `lisa:atlassian-access` `operation: comment-page kind: footer` naming the terminal child set and (when dropped children exist) the dropped set, so the audit trail records *why* the PRD shipped. Lead with `"Shipped by Claude — all generated top-level work is complete."`
|
|
345
326
|
|
|
346
327
|
**Any required child incomplete / blocked**:
|
|
@@ -350,7 +331,7 @@ The set of **required** children for the all-terminal check is the top-level chi
|
|
|
350
331
|
|
|
351
332
|
##### 3f.5 Rollup cites the rule
|
|
352
333
|
|
|
353
|
-
This phase implements exactly one PRD-lifecycle hop — `ticketed → shipped` — and
|
|
334
|
+
This phase implements exactly one PRD-lifecycle hop — `ticketed → shipped` — and deliberately leaves native archival to `/lisa:verify-prd` after the verified PASS. All terminal-state semantics, the generated-top-level-work boundary, and the dedupe-by-child-ref idempotency come from the `prd-lifecycle-rollup` rule; this skill is its Confluence implementation, not a second source of truth.
|
|
354
335
|
|
|
355
336
|
#### 3g. PRD verification dispatch (close the loop on shipped PRDs)
|
|
356
337
|
|
|
@@ -360,7 +341,7 @@ Re-query the PRDs currently parented under the shipped lifecycle parent via `lis
|
|
|
360
341
|
|
|
361
342
|
**Per-cycle combined bound:** each scheduler cycle dispatches at most one ready PRD (the Phase 3 single-ready-PRD claim) **and** at most one shipped PRD for verification (this Phase 3g dispatch), for a maximum of two PRD operations per cycle. Ready intake runs first (Phase 3), then shipped verify (Phase 3g).
|
|
362
343
|
|
|
363
|
-
`lisa:verify-prd` owns the outcome: on a CONFORMS verdict with all empirical checks passing it transitions the PRD to the verified parent and posts evidence; on a conformance miss or a failing/unavailable check it **re-parents the PRD shipped → ticketed** (never the blocked parent) and creates **build-ready** fix tickets registered as the PRD's generated work, then posts a failure report — the fix tickets auto-build, rollup (3f) re-ships the PRD once they are terminal, and a later cycle re-verifies (the self-healing loop). Either branch moves the PRD out of the shipped parent, so it is not re-picked this cycle; a PRD whose generated work is not actually terminal is guard-stopped by `lisa:verify-prd` (left under shipped) — that is verify-prd's gate, not this skill's.
|
|
344
|
+
`lisa:verify-prd` owns the outcome: on a CONFORMS verdict with all empirical checks passing it transitions the PRD to the verified parent and posts evidence; on a conformance miss or a failing/unavailable check it **re-parents the PRD shipped → ticketed** (never the blocked parent) and creates **build-ready** fix tickets registered as the PRD's generated work, then posts a failure report — the fix tickets auto-build, rollup (3f) re-ships the PRD once they are terminal, and a later cycle re-verifies (the self-healing loop). Either branch moves the PRD out of the shipped parent, so it is not re-picked this cycle; a PRD whose generated work is not actually terminal is guard-stopped by `lisa:verify-prd` (left under shipped) — that is verify-prd's gate, not this skill's. This phase, like 3f, is **behaviorally identical across all four intake skills** (`github-prd-intake`, `linear-prd-intake`, `notion-prd-intake`, `confluence-prd-intake`) — only the `$SHIPPED` query surface differs; keep them aligned. Record the dispatched PRD + verify-prd's verdict in the summary.
|
|
364
345
|
|
|
365
346
|
### Phase 4 — Summary report
|
|
366
347
|
|
|
@@ -390,11 +371,11 @@ Print to the agent's output. Do not write this summary to Confluence or the dest
|
|
|
390
371
|
## Idempotency & safety
|
|
391
372
|
|
|
392
373
|
- **One item per cycle**: this skill processes the first eligible ready PRD from Phase 2, then exits. New or remaining PRDs under the `ready` parent are picked up by later scheduler invocations.
|
|
393
|
-
- **No writes outside the lifecycle**: this skill only ever writes to the destination tracker via `lisa:confluence-to-tracker` (which delegates to `lisa:tracker-write`), and only ever re-parents PRDs among `in_review`, `blocked`, `ticketed`, and `shipped` (the last via the rollup phase 3f only) via `lisa:atlassian-access` `operation: write-page`. It never edits PRD body content, never re-parents into or out of `draft`, never
|
|
374
|
+
- **No writes outside the lifecycle**: this skill only ever writes to the destination tracker via `lisa:confluence-to-tracker` (which delegates to `lisa:tracker-write`), and only ever re-parents PRDs among `in_review`, `blocked`, `ticketed`, and `shipped` (the last via the rollup phase 3f only) via `lisa:atlassian-access` `operation: write-page`. It never edits PRD body content, never re-parents into or out of `draft`, never archives pages at the shipped hop, and never deletes pages.
|
|
394
375
|
- **Claim-first ordering**: the re-parent to `in_review` happens BEFORE validation runs, so a re-entrant call won't double-process.
|
|
395
376
|
- **Failure handling**: an exception processing the selected PRD is caught and recorded under "Errors" in the summary, then the cycle exits. The PRD that errored is left under whatever parent it currently occupies (usually `in_review` if claim succeeded) — the human investigates from there.
|
|
396
377
|
- **Single-parent invariant**: a page has exactly one parent by construction in Confluence — the multi-state ambiguity that label-based systems can hit (two `prd-*` labels simultaneously) cannot occur here. After every transition, re-read the page and confirm `parentId` matches the expected role; if not, surface as an Error and skip.
|
|
397
|
-
- **Rollup idempotency**: rollup (Phase 3f) is a no-op on a PRD already parented under `$SHIPPED_PARENT`
|
|
378
|
+
- **Rollup idempotency**: rollup (Phase 3f) is a no-op on a PRD already parented under `$SHIPPED_PARENT` — no duplicate re-parent, no shipped-time archive, no duplicate comment. The all-terminal condition is a pure function of the children's current states (deduped by child-ref identity), so recomputing it is safe to re-run. Native archival only follows verified PASS in `/lisa:verify-prd`.
|
|
398
379
|
|
|
399
380
|
## Configuration
|
|
400
381
|
|
|
@@ -413,13 +394,11 @@ Destination tracker config (jira / github / linear) is consumed by `lisa:tracker
|
|
|
413
394
|
| `.lisa.config.json` `confluence.parents.ticketed` | yes | Parent page id for "successfully ticketed" |
|
|
414
395
|
| `.lisa.config.json` `confluence.parents.draft` | recommended | Parent page id for PRDs still being drafted by product |
|
|
415
396
|
| `.lisa.config.json` `confluence.parents.shipped` | recommended | Parent page id the rollup phase (3f) re-parents delivered PRDs under; product may also use it by hand |
|
|
416
|
-
| `.lisa.config.json` `confluence.rollup.closeOnShipped` | no (default `false`) | When `true`, rollup archives the PRD page after the `shipped` re-parent; when `false`, re-parents under `shipped` and leaves the page active |
|
|
417
|
-
|
|
418
397
|
## Rules
|
|
419
398
|
|
|
420
399
|
- Never write to the destination tracker outside of `lisa:confluence-to-tracker` → `lisa:tracker-write`. The validator's verdict gates progress; bypassing it produces broken tickets.
|
|
421
400
|
- Never re-parent a PRD into a lifecycle parent this skill doesn't own (`in_review`, `blocked`, `ticketed`, and `shipped` via the rollup phase only). Product owns `draft` and `ready` (as the entry signal); product and the rollup phase (3f) both re-parent under `shipped`.
|
|
422
|
-
- Re-parent under `shipped`
|
|
401
|
+
- Re-parent under `shipped` only from the rollup phase, and only when all generated top-level children are terminal per the `prd-lifecycle-rollup` rule. Never ship on partial completion and never archive at shipped.
|
|
423
402
|
- Never edit the PRD's body. Communication with product happens only through Confluence comments. The `write-page` call preserves the body verbatim — fetch then PUT with body unchanged.
|
|
424
403
|
- Never post a single page-level dump of all gate failures. One inline comment per `prd_anchor` group (or one footer summary for unanchored failures only). Comments must be inline-anchored where possible, categorized, plain-language, and contain a concrete recommendation.
|
|
425
404
|
- Never include a gate ID, internal skill name, or engineering shorthand in a comment body.
|
|
@@ -39,7 +39,7 @@ In prose below, the role names refer to the resolved labels: e.g. "the `ready` l
|
|
|
39
39
|
|
|
40
40
|
This skill is the GitHub counterpart of `lisa:notion-prd-intake`, `lisa:confluence-prd-intake`, and `lisa:linear-prd-intake`. Phases, gates, comment templates, and rules are identical — the only differences are (1) the lifecycle is encoded as **issue labels** (mirroring Linear's project labels and Confluence's page labels), (2) the fetch / update tools are the `gh` CLI, and (3) clarifying-question comments land directly on the source PRD issue (because GitHub Issues *do* have native comments — no sentinel issue required, unlike Linear). Keep all four skills behaviorally aligned: when changing intake logic, change them together.
|
|
41
41
|
|
|
42
|
-
The **PRD
|
|
42
|
+
The **PRD shipped rollup phase (3f)** transitions a `$TICKETED` PRD to `$SHIPPED` once all its generated top-level work is terminal, per the `prd-lifecycle-rollup` rule. This phase is GitHub-only here because its vendor surface (issue close + labels via `gh`) is GitHub-specific; the Linear / Confluence / Notion intake skills carry the **same** vendor-neutral rollup with their own surfaces (sibling sub-task #584, now landed). All four intake skills are behaviorally aligned across the rollup phase too — keep them in sync when changing rollup logic.
|
|
43
43
|
|
|
44
44
|
## Confirmation policy
|
|
45
45
|
|
|
@@ -79,9 +79,9 @@ This skill transitions:
|
|
|
79
79
|
- `$IN_REVIEW` → `$BLOCKED` (gate failures or coverage gaps)
|
|
80
80
|
- `$IN_REVIEW` → `$TICKETED` (success)
|
|
81
81
|
- `$TICKETED` → `$BLOCKED` (post-write coverage gaps from Phase 3e)
|
|
82
|
-
- `$TICKETED` → `$SHIPPED` (PRD
|
|
82
|
+
- `$TICKETED` → `$SHIPPED` (PRD shipped rollup, Phase 3f — only when **all** generated top-level children are terminal)
|
|
83
83
|
|
|
84
|
-
The `draft` and `verified` labels are owned by product and are never touched here (`verified` is set by `/lisa:verify-prd` after empirical PRD-level acceptance). The `shipped` label is set by this skill's **rollup phase (3f)** when, and only when, the PRD's generated top-level work is all terminal — per the `prd-lifecycle-rollup` rule; product may also set it by hand. Rollup never advances a PRD to `shipped` on partial completion, and never closes a PRD issue
|
|
84
|
+
The `draft` and `verified` labels are owned by product and are never touched here (`verified` is set by `/lisa:verify-prd` after empirical PRD-level acceptance). The `shipped` label is set by this skill's **rollup phase (3f)** when, and only when, the PRD's generated top-level work is all terminal — per the `prd-lifecycle-rollup` rule; product may also set it by hand. Rollup never advances a PRD to `shipped` on partial completion, and never closes a PRD issue at shipped. `/lisa:verify-prd` closes the issue only after a verified PASS.
|
|
85
85
|
|
|
86
86
|
A "transition" means: remove the old lifecycle label and add the new one (`gh issue edit <num> --remove-label <old> --add-label <new>`). The skill MUST verify exactly one lifecycle label is present after the update.
|
|
87
87
|
|
|
@@ -245,34 +245,19 @@ Per-ticket gates prove each ticket is well-formed; they do NOT prove the *set* o
|
|
|
245
245
|
|
|
246
246
|
3. The created tickets remain in the destination tracker regardless of the verdict. The audit only tells us whether *more* are needed.
|
|
247
247
|
|
|
248
|
-
#### 3f. PRD
|
|
248
|
+
#### 3f. PRD shipped rollup
|
|
249
249
|
|
|
250
250
|
A PRD's lifecycle terminal state (`shipped`) is **derived** from whether the work it generated is done — it is never set by hand here on its own authority. This phase implements the GitHub leg of that derivation, per the `prd-lifecycle-rollup` rule (cite it by slug; do not restate its taxonomy or terminal-state semantics here). Linear / Confluence / Notion rollup is a sibling sub-task (#584) and is out of scope for this skill.
|
|
251
251
|
|
|
252
252
|
Rollup runs over PRD issues that are already `$TICKETED` (the only state from which a PRD can ship): the freshly-ticketed PRD from Phase 3c, and — because rollup also catches PRDs whose children finished in a *later* cycle — every issue currently carrying `$TICKETED`. Process each independently; one PRD never blocks another's rollup.
|
|
253
253
|
|
|
254
|
-
##### 3f.0
|
|
254
|
+
##### 3f.0 Shipped remains open for verification
|
|
255
255
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
```bash
|
|
259
|
-
# Resolve a boolean rollup flag. Local overrides global per-key; default when unset.
|
|
260
|
-
read_rollup_flag() {
|
|
261
|
-
local key="$1" default="$2"
|
|
262
|
-
local local_v global_v
|
|
263
|
-
local_v=$(jq -r ".github.labels.prd.rollup.${key} // empty" .lisa.config.local.json 2>/dev/null)
|
|
264
|
-
global_v=$(jq -r ".github.labels.prd.rollup.${key} // empty" .lisa.config.json 2>/dev/null)
|
|
265
|
-
echo "${local_v:-${global_v:-$default}}"
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
CLOSE_ON_SHIPPED=$(read_rollup_flag closeOnShipped false)
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
When `false` (the default), rollup sets `$SHIPPED` but leaves the PRD issue **open** for a human to close. When `true`, rollup also closes the PRD issue after the `$SHIPPED` transition. Closure NEVER happens before all generated top-level work is terminal (`prd-lifecycle-rollup` rule; PRD #525 non-goal).
|
|
256
|
+
There is no close/archive configuration at the shipped hop. Rollup sets `$SHIPPED` and leaves the PRD issue **open** so Phase 3g can dispatch `/lisa:verify-prd`. Provider-native issue closure is owned by `/lisa:verify-prd` after it transitions `$SHIPPED → verified` on a PASS.
|
|
272
257
|
|
|
273
258
|
##### 3f.1 Idempotency guard (no-op if already shipped)
|
|
274
259
|
|
|
275
|
-
Rollup is keyed by the PRD's current state. If the PRD already carries `$SHIPPED
|
|
260
|
+
Rollup is keyed by the PRD's current state. If the PRD already carries `$SHIPPED`, it is a **no-op** — do not re-transition, do not close, do not re-comment. Record it as `already shipped (no-op)` in the cycle summary and move on. This is what makes re-running intake safe.
|
|
276
261
|
|
|
277
262
|
##### 3f.2 Read the generated top-level child set
|
|
278
263
|
|
|
@@ -326,7 +311,7 @@ The set of **required** children for the all-terminal check is the top-level chi
|
|
|
326
311
|
**All required children terminal** (every required top-level child is terminal; at least one required child exists):
|
|
327
312
|
|
|
328
313
|
1. Transition labels: `gh issue edit <prd-num> --repo <org>/<repo> --remove-label "$TICKETED" --add-label "$SHIPPED"`. Verify exactly one lifecycle label remains (the single-label invariant).
|
|
329
|
-
2.
|
|
314
|
+
2. Leave the PRD issue open for `/lisa:verify-prd`; do not close at the shipped hop.
|
|
330
315
|
3. Post a short rollup comment naming the terminal child set and (when dropped children exist) the dropped set, so the audit trail records *why* the PRD shipped. Lead with `"Shipped by Claude — all generated top-level work is complete."`
|
|
331
316
|
|
|
332
317
|
**Any required child incomplete / blocked**:
|
|
@@ -336,7 +321,7 @@ The set of **required** children for the all-terminal check is the top-level chi
|
|
|
336
321
|
|
|
337
322
|
##### 3f.5 Rollup is GitHub-only and cites the rule
|
|
338
323
|
|
|
339
|
-
This phase only touches GitHub PRD issues. It implements exactly one PRD-lifecycle hop — `$TICKETED → $SHIPPED` — and
|
|
324
|
+
This phase only touches GitHub PRD issues. It implements exactly one PRD-lifecycle hop — `$TICKETED → $SHIPPED` — and deliberately leaves native closure to `/lisa:verify-prd` after `$SHIPPED → verified`. All terminal-state semantics, the generated-top-level-work boundary, the env-keyed `done` resolution, and the dedupe-by-child-ref idempotency come from the `prd-lifecycle-rollup` rule; this skill is its GitHub implementation, not a second source of truth.
|
|
340
325
|
|
|
341
326
|
#### 3g. PRD verification dispatch (close the loop on shipped PRDs)
|
|
342
327
|
|
|
@@ -348,8 +333,6 @@ Re-query the PRDs currently carrying `$SHIPPED` via `gh issue list --repo <org>/
|
|
|
348
333
|
|
|
349
334
|
`lisa:verify-prd` owns the outcome: on a CONFORMS verdict with all empirical checks passing it transitions `$SHIPPED → verified` and posts evidence; on a conformance miss or a failing/unavailable check it **re-opens the PRD `$SHIPPED → ticketed`** (never `blocked`) and creates **build-ready** fix tickets registered as the PRD's generated work, then posts a failure report — the fix tickets auto-build, rollup (3f) re-ships the PRD once they are terminal, and a later cycle re-verifies (the self-healing loop). Either branch moves the PRD out of `$SHIPPED`, so it is not re-picked this cycle; a PRD whose generated work is not actually terminal is guard-stopped by `lisa:verify-prd` (left `$SHIPPED`) — that is verify-prd's gate, not this skill's.
|
|
350
335
|
|
|
351
|
-
**`closeOnShipped` constraint:** when `github.labels.prd.rollup.closeOnShipped = true`, issues are closed immediately after reaching `$SHIPPED`. This Phase 3g query (`--state open`) will not find them, so those PRDs are permanently excluded from `lisa:verify-prd` dispatch. If PRD verification is required, set `github.labels.prd.rollup.closeOnShipped = false` (or omit it); closing on ship is an explicit opt-out of the shipped→verified verification loop.
|
|
352
|
-
|
|
353
336
|
This phase, like 3f, is **behaviorally identical across all four intake skills** (`github-prd-intake`, `linear-prd-intake`, `notion-prd-intake`, `confluence-prd-intake`) — only the `$SHIPPED` query surface differs; keep them aligned. Record the dispatched PRD + verify-prd's verdict in the summary.
|
|
354
337
|
|
|
355
338
|
### Phase 4 — Summary report
|
|
@@ -371,7 +354,7 @@ PRDs processed: <n>
|
|
|
371
354
|
|
|
372
355
|
Rollup (Phase 3f):
|
|
373
356
|
- $SHIPPED: <n>
|
|
374
|
-
- <issue-ref> "<title>" → all <child-count> top-level children terminal (<dropped-count> dropped);
|
|
357
|
+
- <issue-ref> "<title>" → all <child-count> top-level children terminal (<dropped-count> dropped); left open for verify-prd
|
|
375
358
|
- Held open (incomplete children): <n>
|
|
376
359
|
- <issue-ref> "<title>" → <incomplete-count> of <child-count> top-level children still open
|
|
377
360
|
- Already shipped (no-op): <n>
|
|
@@ -394,11 +377,11 @@ When the configured destination tracker is GitHub Issues AND the PRD repo is the
|
|
|
394
377
|
## Idempotency & safety
|
|
395
378
|
|
|
396
379
|
- **One item per cycle**: this skill processes the first eligible ready PRD issue from Phase 2, then exits. New or remaining ready issues are picked up by later scheduler invocations.
|
|
397
|
-
- **No writes outside the lifecycle**: this skill only ever writes to the destination tracker via `lisa:github-to-tracker` (which delegates to `lisa:tracker-write`), only ever changes labels among `$IN_REVIEW`, `$BLOCKED`, `$TICKETED`, `$SHIPPED`, only ever comments on the source PRD issue. It never edits PRD bodies
|
|
380
|
+
- **No writes outside the lifecycle**: this skill only ever writes to the destination tracker via `lisa:github-to-tracker` (which delegates to `lisa:tracker-write`), only ever changes labels among `$IN_REVIEW`, `$BLOCKED`, `$TICKETED`, `$SHIPPED`, only ever comments on the source PRD issue. It never edits PRD bodies, never touches the `draft` label, never closes PRD issues at the shipped hop, and never deletes any issue.
|
|
398
381
|
- **Claim-first ordering**: the label flip to `$IN_REVIEW` happens BEFORE validation runs.
|
|
399
382
|
- **Failure handling**: an exception processing the selected PRD is caught and recorded under "Errors" in the summary, then the cycle exits. The PRD that errored is left labeled `$IN_REVIEW` — humans investigate from there.
|
|
400
383
|
- **Single-label invariant**: after every transition, verify exactly one lifecycle label is present.
|
|
401
|
-
- **Rollup idempotency**: rollup (Phase 3f) is a no-op on a PRD already carrying `$SHIPPED`
|
|
384
|
+
- **Rollup idempotency**: rollup (Phase 3f) is a no-op on a PRD already carrying `$SHIPPED` — no duplicate transition, no shipped-time close, no duplicate comment. The all-terminal condition is a pure function of the children's current states, so recomputing it is safe to re-run. Native closure only follows verified PASS in `/lisa:verify-prd`.
|
|
402
385
|
|
|
403
386
|
## Configuration
|
|
404
387
|
|
|
@@ -421,7 +404,7 @@ Destination tracker config (jira / github / linear) is consumed by `lisa:tracker
|
|
|
421
404
|
|
|
422
405
|
- Never write to the destination tracker outside of `lisa:github-to-tracker` → `lisa:tracker-write`.
|
|
423
406
|
- Never add or remove a label this skill doesn't own (`$IN_REVIEW`, `$BLOCKED`, `$TICKETED`, and `$SHIPPED` via the rollup phase only). Product owns the `draft` and `ready` PRD labels; product and the rollup phase (3f) both set `shipped`.
|
|
424
|
-
- Set `$SHIPPED`
|
|
407
|
+
- Set `$SHIPPED` only from the rollup phase, and only when all generated top-level children are terminal per the `prd-lifecycle-rollup` rule. Never ship on partial completion and never close at shipped.
|
|
425
408
|
- Never edit a PRD's body. Communication with product happens only via comments.
|
|
426
409
|
- Never post a single dump of all gate failures on one comment. One comment per `prd_anchor` group, plus one rollup for unanchored failures.
|
|
427
410
|
- Never include a gate ID, internal skill name, or engineering shorthand in a comment body.
|