@codyswann/lisa 2.104.6 → 2.105.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 (46) hide show
  1. package/dist/utils/usage-accounting-rollup.d.ts +13 -0
  2. package/dist/utils/usage-accounting-rollup.d.ts.map +1 -0
  3. package/dist/utils/usage-accounting-rollup.js +46 -0
  4. package/dist/utils/usage-accounting-rollup.js.map +1 -0
  5. package/dist/utils/usage-accounting.d.ts +11 -1
  6. package/dist/utils/usage-accounting.d.ts.map +1 -1
  7. package/dist/utils/usage-accounting.js +23 -6
  8. package/dist/utils/usage-accounting.js.map +1 -1
  9. package/package.json +1 -1
  10. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  12. package/plugins/lisa/rules/config-resolution.md +7 -19
  13. package/plugins/lisa/rules/prd-lifecycle-rollup.md +16 -15
  14. package/plugins/lisa/scripts/queue-contract-resolution.mjs +0 -20
  15. package/plugins/lisa/skills/confluence-prd-intake/SKILL.md +14 -35
  16. package/plugins/lisa/skills/github-prd-intake/SKILL.md +13 -30
  17. package/plugins/lisa/skills/linear-prd-intake/SKILL.md +14 -32
  18. package/plugins/lisa/skills/notion-prd-intake/SKILL.md +12 -31
  19. package/plugins/lisa/skills/setup-confluence/SKILL.md +1 -1
  20. package/plugins/lisa/skills/verify-prd/SKILL.md +7 -7
  21. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  23. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  25. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  27. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  29. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  31. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  33. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  35. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  37. package/plugins/src/base/rules/config-resolution.md +7 -19
  38. package/plugins/src/base/rules/prd-lifecycle-rollup.md +16 -15
  39. package/plugins/src/base/scripts/queue-contract-resolution.mjs +0 -20
  40. package/plugins/src/base/skills/confluence-prd-intake/SKILL.md +14 -35
  41. package/plugins/src/base/skills/github-prd-intake/SKILL.md +13 -30
  42. package/plugins/src/base/skills/linear-prd-intake/SKILL.md +14 -32
  43. package/plugins/src/base/skills/notion-prd-intake/SKILL.md +12 -31
  44. package/plugins/src/base/skills/setup-confluence/SKILL.md +1 -1
  45. package/plugins/src/base/skills/verify-prd/SKILL.md +7 -7
  46. package/typescript/create-only/.github/workflows/claude.yml +3 -0
@@ -183,12 +183,12 @@ Otherwise apply the vendor-appropriate transition. This is the `shipped → veri
183
183
  ```bash
184
184
  gh issue edit <prd-num> --repo <org>/<repo> --remove-label "$SHIPPED" --add-label "$VERIFIED"
185
185
  ```
186
- Verify exactly **one** PRD-lifecycle label remains afterward (the single-label invariant `github-prd-intake` enforces) — a re-run must never leave both `$SHIPPED` and `$VERIFIED`, nor two copies of `$VERIFIED`. For Linear, set the project/issue label equivalently.
187
- - **Notion** — set the PRD page's `notion.statusProperty` (default `Status`) to the resolved `verified` value (default `Verified`). A status property holds exactly one value, so re-setting the same value is inherently a no-op.
188
- - **Confluence** — move the PRD page's `parentId` to `confluence.parents.verified` (the parent-page-based lifecycle; Atlassian scoped tokens cannot write labels — see `config-resolution`). A page has exactly one parent, so re-parenting to the same parent is a no-op.
189
- - **JIRA** — transition the PRD issue to the configured `verified` status. An issue holds exactly one status; if already `verified`, skip the transition.
186
+ Verify exactly **one** PRD-lifecycle label remains afterward (the single-label invariant `github-prd-intake` enforces) — a re-run must never leave both `$SHIPPED` and `$VERIFIED`, nor two copies of `$VERIFIED`. For GitHub, close the PRD issue immediately after the label transition with `gh issue close <prd-num> --repo <org>/<repo> --reason completed`; if it is already closed, record that native closure was already satisfied. For Linear, set the project/issue label equivalently, then archive/complete the project or issue using the vendor's native terminal mechanism where available.
187
+ - **Notion** — set the PRD page's `notion.statusProperty` (default `Status`) to the resolved `verified` value (default `Verified`). A status property holds exactly one value, so re-setting the same value is inherently a no-op. Then archive the page through `lisa:notion-access` where supported; if the page is already archived, record that native archival was already satisfied.
188
+ - **Confluence** — move the PRD page's `parentId` to `confluence.parents.verified` (the parent-page-based lifecycle; Atlassian scoped tokens cannot write labels — see `config-resolution`). A page has exactly one parent, so re-parenting to the same parent is a no-op. Then archive the page where the deployment supports archival; if archival is unavailable, report the capability-aware no-op or setup gap.
189
+ - **JIRA** — transition the PRD issue to the configured `verified` status. An issue holds exactly one status; if already `verified`, skip the transition. Then resolve/close the issue using the configured terminal workflow transition where supported.
190
190
 
191
- `verified` is the terminal, product-owned PRD state; this skill is the **only** automated writer of it (intake/rollup never set it). Do **not** close or archive the PRD here closure is governed separately by `prd.rollup.closeOnShipped` at the `shipped` hop, not the verify hop.
191
+ `verified` is the terminal, product-owned PRD state; this skill is the **only** automated writer of it (intake/rollup never set it). After the verified transition, close, archive, or complete the PRD natively where the source vendor supports it. This close-out is mandatory and idempotent; do not introduce a configuration flag to skip it.
192
192
 
193
193
  ### 6.3 — Post verification evidence on the PRD
194
194
 
@@ -317,7 +317,7 @@ The guards are woven into Phases 6 and 7 above; this phase collects them as one
317
317
 
318
318
  2. **Fix issues — dedupe by a stable marker, reference don't duplicate.** Each fix issue carries `<!-- lisa:verify-prd-fix prd=<prd-ref> req=<stable-req-id> -->`, keyed by the PRD ref + a stable requirement/AC identity. Before creating a fix issue, search for an **open** issue carrying that exact marker; if found, reference/update it instead of creating a second one (Phase 7.4). The dedupe key is the marker (a stable ref), **never the issue title** — a renamed fix issue is still matched by its marker, and two distinct requirements get two distinct markers even if their titles collide (`prd-lifecycle-rollup`: "Match by stable ref, never by title"). A *closed* prior fix issue does not suppress a new one (a re-failure after a closed fix is a genuine regression).
319
319
 
320
- 3. **Lifecycle transition — no-op when already at the target role.** The Phase 6.2 / 7.2 transition is keyed by the PRD's current state: if the PRD already carries `$VERIFIED` (PASS) or `$BLOCKED` (FAIL), the transition is a no-op — no re-label, no second copy of the label/status — mirroring `github-prd-intake` Phase 3f.1's "no-op if already shipped." After any transition, exactly **one** PRD-lifecycle label/status remains (the single-label invariant); a re-run never leaves both `$SHIPPED` and the target role, nor two copies of the target role. For Notion/Confluence/JIRA the single-value status/parent makes re-setting the same value inherently idempotent.
320
+ 3. **Lifecycle transition + verified native close-out — no-op when already satisfied.** The Phase 6.2 / 7.2 transition is keyed by the PRD's current state: if the PRD already carries `$VERIFIED` (PASS) or `$TICKETED` (FAIL), the transition is a no-op — no re-label, no second copy of the label/status — mirroring `github-prd-intake` Phase 3f.1's "no-op if already shipped." After any transition, exactly **one** PRD-lifecycle label/status remains (the single-label invariant); a re-run never leaves both `$SHIPPED` and the target role, nor two copies of the target role. For Notion/Confluence/JIRA the single-value status/parent makes re-setting the same value inherently idempotent. On the PASS path, provider-native closure/archive/completion is also idempotent: if it is already closed, archived, or completed, record the satisfied state and do not error.
321
321
 
322
322
  Because every Phase 6/7 write is one of these three idempotent operations, the **whole skill is idempotent**: the end state after N runs equals the end state after 1 run — one evidence-or-failure comment, one fix issue per still-failing requirement, one lifecycle label/status. Computing the verdict itself is a pure function of the PRD's current state and its children's current states, so recomputing it on a re-run is safe (`prd-lifecycle-rollup` idempotency rule).
323
323
 
@@ -368,7 +368,7 @@ shipped → ticketed (re-opened for fixes; round: N) fix tickets (ready): <
368
368
  - **Never reimplement spec conformance or verification.** Phase 4 invokes the `spec-conformance` skill (the single source of truth for the coverage matrix and the `CONFORMS`/`PARTIAL`/`DIVERGES` verdict); Phase 5 invokes `verification-lifecycle` (which in turn invokes `codify-verification` and, for UI, `product-walkthrough`). This skill orchestrates those skills against the PRD; it does not duplicate their logic.
369
369
  - **Quality gates are not verification.** Tests, typecheck, and lint are prerequisites enforced by hooks/CI. Phase 5 requires running the actual shipped system and observing results on a surface chosen from what the PRD delivered — never substituting a green test suite for empirical proof (`verification` rule).
370
370
  - **The verification surface is PRD-dependent.** Classify the empirical surface (browser/API/CLI/DB/logs/…) from what the PRD shipped; do not assume a fixed surface. A single-environment project with no deployed app verifies on its CLI/dry-run surface per the PRD's Empirical Verification Plan.
371
- - **`verified` is product-owned and terminal.** This skill is the only automated writer of the `verified` role; intake/rollup never set it. The PASS hop does not close or archive the PRD (closure is governed by `prd.rollup.closeOnShipped` at the `shipped` hop).
371
+ - **`verified` is product-owned and terminal.** This skill is the only automated writer of the `verified` role; intake/rollup never set it. The PASS hop also performs provider-native close/archive/completion where supported, and that close-out is mandatory and idempotent.
372
372
  - **Verification failure never uses `blocked`; it re-opens to `ticketed`.** The FAIL hop sets the existing `ticketed` PRD role (`config-resolution`) and creates build-ready fix tickets registered as the PRD's generated work, so the lifecycle stays small (`prd-lifecycle-rollup` "No extra failure states") and self-heals — the fix tickets auto-build, rollup re-ships the PRD, and a later cycle re-verifies. `blocked` remains the *intake* (ready-stage validation) failure role, not the verification one; the FAIL hop never closes or archives the PRD.
373
373
  - **Top-level only.** Exclude leaf Sub-tasks and Stories nested under a generated Epic. The PRD owns its top-level work; those top-level units own their descendants (`prd-lifecycle-rollup` generated-top-level-work contract).
374
374
  - **Cite, don't restate.** The generated-top-level-work boundary, the per-vendor terminal predicate, the env-keyed `done` resolution, the dedupe-by-child-ref idempotency key, and the `shipped → verified | ticketed` PRD-level verification hops all come from the `prd-lifecycle-rollup` rule; the `verified`/`shipped`/`blocked`/`ticketed` role vocabulary comes from `config-resolution`. This skill is a consumer of those contracts, not a second source of truth.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.104.6",
3
+ "version": "2.105.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-cdk",
3
- "version": "2.104.6",
3
+ "version": "2.105.0",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.104.6",
3
+ "version": "2.105.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-expo",
3
- "version": "2.104.6",
3
+ "version": "2.105.0",
4
4
  "description": "Expo and 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-harper-fabric",
3
- "version": "2.104.6",
3
+ "version": "2.105.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.104.6",
3
+ "version": "2.105.0",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.104.6",
3
+ "version": "2.105.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-nestjs",
3
- "version": "2.104.6",
3
+ "version": "2.105.0",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.104.6",
3
+ "version": "2.105.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.104.6",
3
+ "version": "2.105.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.104.6",
3
+ "version": "2.105.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-rails",
3
- "version": "2.104.6",
3
+ "version": "2.105.0",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop 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.104.6",
3
+ "version": "2.105.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"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.104.6",
3
+ "version": "2.105.0",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.104.6",
3
+ "version": "2.105.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.104.6",
3
+ "version": "2.105.0",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -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 config (`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
- Like every other vocabulary key, `prd.rollup` is **optional** a missing block inherits `closeOnShipped: false`. The `shipped` transition itself is unconditional on the all-terminal condition; only the close/archive step is gated by this flag.
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 → blocked` 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.
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 + config-gated close/archive** — when and how a PRD rolls up to its terminal state and is closed/archived.
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. Close the PRD issue only when `github.labels.prd.rollup.closeOnShipped` is `true`; the default is to leave it open. |
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. Archive or close the project only when `linear.labels.prd.rollup.closeOnShipped` is `true`; otherwise leave it active. |
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 / Done status only after all required generated top-level issues are in the Done status category. Native resolution / closure is config-gated through the PRD rollup close-on-shipped setting. |
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. Archive the page only when `confluence.rollup.closeOnShipped` is `true`; otherwise leave it active. |
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. Archive the page only when `notion.rollup.closeOnShipped` is `true`; otherwise leave it active. |
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 final lifecycle transition and optional close/archive. It evaluates terminal state using the destination tracker's predicate, then applies the source vendor's `shipped` transition and close-on-shipped behavior. |
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 + config-gated close/archive
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 terminal PRD-lifecycle state and, where configured, is closed/archived:
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 → blocked` (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. **Config-gated close/archive.** When the source tool supports closure/archival *and* the project configures it, also close (GitHub: close the issue; Linear: move to a closed/archived state; JIRA: transition to Done; Confluence/Notion: archive where supported). Closure is **gated on configuration** via `prd.rollup.closeOnShipped` (`config-resolution`): when false (the default), the PRD is set to `shipped` but left open for a human to close; when true, rollup closes/archives it after the `shipped` transition. Never close a PRD before all generated top-level work is terminal (PRD #525 non-goal).
91
- 3. **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.
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). A PRD that the project chose to close on ship (`*.rollup.closeOnShipped = true`) is out of the open verification queue — closing on ship is an explicit opt-out of the open loop. 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
+ 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 closure rollup** (`github-prd-intake`) — detect terminal/incomplete/blocked child sets, transition to `prd-shipped`, and close the PRD issue when `prd.rollup.closeOnShipped` is configured. *(LPC-1.3 #583)*
148
- - **Linear / Confluence / Notion PRD rollup** (`linear-prd-intake`, `confluence-prd-intake`, `notion-prd-intake`) — mirror the GitHub closure rollup with each vendor's terminal predicate and close/archive support. *(LPC-1.3 #584)*
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.
@@ -219,11 +219,6 @@ export function resolvePrdLifecycleRoles(
219
219
  DEFAULT_GITHUB_LINEAR_PRD_ROLES,
220
220
  { allowNull: false }
221
221
  ),
222
- rollup: {
223
- closeOnShipped: Boolean(
224
- config.github?.labels?.prd?.rollup?.closeOnShipped ?? false
225
- ),
226
- },
227
222
  };
228
223
  case "linear":
229
224
  return {
@@ -234,11 +229,6 @@ export function resolvePrdLifecycleRoles(
234
229
  DEFAULT_GITHUB_LINEAR_PRD_ROLES,
235
230
  { allowNull: false }
236
231
  ),
237
- rollup: {
238
- closeOnShipped: Boolean(
239
- config.linear?.labels?.prd?.rollup?.closeOnShipped ?? false
240
- ),
241
- },
242
232
  };
243
233
  case "notion":
244
234
  return {
@@ -250,11 +240,6 @@ export function resolvePrdLifecycleRoles(
250
240
  DEFAULT_NOTION_PRD_ROLES,
251
241
  { allowNull: false }
252
242
  ),
253
- rollup: {
254
- closeOnShipped: Boolean(
255
- config.notion?.rollup?.closeOnShipped ?? false
256
- ),
257
- },
258
243
  };
259
244
  case "confluence":
260
245
  return {
@@ -265,11 +250,6 @@ export function resolvePrdLifecycleRoles(
265
250
  DEFAULT_CONFLUENCE_PARENT_ROLES,
266
251
  { allowNull: true }
267
252
  ),
268
- rollup: {
269
- closeOnShipped: Boolean(
270
- config.confluence?.rollup?.closeOnShipped ?? false
271
- ),
272
- },
273
253
  };
274
254
  default:
275
255
  throw new Error(
@@ -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 closure 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.
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 closure rollup phase (3f)** re-parents a `ticketed` PRD to the `shipped` parent (and optionally archives it) 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.
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 closure rollup, Phase 3f — only when **all** generated top-level children are terminal)
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 unless `confluence.rollup.closeOnShipped` is configured `true` (default `false` re-parent under `shipped`, leave the page active).
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 closure rollup (config-gated)
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 Resolve closure config
293
+ ##### 3f.0 Shipped remains active for verification
307
294
 
308
- Closure is gated on `confluence.rollup.closeOnShipped` (default `false`), resolved via `read_rollup_flag` (defined in the Workflow resolution block, same local-overrides-global precedence the lifecycle parents use). Note the config lives under `confluence.rollup` (NOT `confluence.parents.rollup`):
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` (and is already archived, when `$CLOSE_ON_SHIPPED` is `true`), it is a **no-op** — do not re-parent, do not re-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.
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. **If `$CLOSE_ON_SHIPPED` is `true`**, archive the PRD page where the deployment supports archival. When `false`, leave it active.
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 the optional config-gated archive that follows it. 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.
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. A PRD archived on ship (`confluence.rollup.closeOnShipped = true`) is out of the open verification queue. 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.
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 deletes pages. It re-parents under `shipped` and may archive the PRD page **only** through the config-gated rollup phase (3f).
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` (and already archived when `closeOnShipped` is `true`) — no duplicate re-parent, no duplicate 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. Archival NEVER precedes the all-terminal condition.
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` (and archive the PRD page when `closeOnShipped` is configured) only from the rollup phase, and only when all generated top-level children are terminal per the `prd-lifecycle-rollup` rule. Never ship or archive on partial completion.
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.