---
name: confluence-sync-decision-log
description: "📖 CONFLUENCE: Sync decision log — scan Fireflies, Slack & Jira for new decisions, then propose precise additions and status updates to a project's Confluence Decision Log. Use whenever asked to update, review, or audit a project's decision log. Triggers include: \"update the decision log\", \"check what's new for the decision log\", \"scan for decisions since last update\", \"what decisions have been made recently\", \"sync the decision log\", \"audit the decision log\", \"zaktualizuj decision log\", or any time new decisions or major updates on a project need to be captured in Confluence. Proposes all changes with full rationale for review — nothing is written to Confluence without explicit approval."
---

# Confluence Decision Log Sync Skill

## Purpose
Automate the discovery of new decisions and decision updates for any project, then propose
precise, well-formatted changes to a Confluence Decision Log — before writing anything.
All changes require explicit approval before being committed.

---

## Step 0: Resolve project context

If not already clear from conversation, ask:
1. **Project name** — which project's decision log to update
2. **Confluence Decision Log page** — URL or page ID (or search for it)
3. **Scan window** — default: since the page was last modified

**Page discovery** (if not provided):
```
CQL: title ~ "Decision Log" AND space = "<project_space>" ORDER BY lastModified DESC
```

### If no Decision Log page is found

If the CQL search returns no results **and** the user hasn't provided a URL or page ID, do not proceed to Step 1. Instead:

1. **Inform the user clearly:**
   > "I couldn't find a Decision Log page in the `<project_space>` space on Confluence. Would you like me to create one, or would you prefer to create it yourself and share the link?"

2. **If the user wants Claude to create it**, propose the page before creating anything:
   - Show the full table structure (columns: ID, Decision Title, Status, Approval Required, Decision Date, Decision Maker, Rationale)
   - Confirm the target Confluence space and parent page (ask if unknown)
   - Ask: *"Shall I create this page in `<project_space>` under `<parent page>`?"*
   - Only after explicit confirmation: call `createConfluencePage` with the standard table as the body (ADF format), then proceed to Step 1 using the newly created page.

3. **If the user prefers to create it manually**, provide the standard table structure (see **Decision Log Table Structure** section below) as a reference, and ask them to share the URL or page ID once it's ready.

**Never skip this gate and proceed to Step 1 with no page.**

---

## Key Constants (shared)

- **Confluence Cloud ID:** use the Atlassian Cloud ID from your project context (e.g. `yourorg.atlassian.net`). If not set, ask the user before querying Confluence.

---

## What Qualifies as a Decision Log Entry

A decision or update **belongs in the log** if it:
- Has meaningful impact on scope, cost, timeline, or architecture
- Requires client approval or involves a vendor/partner commitment
- Is irreversible or hard to change once made
- Creates a dependency on another team (client dev, logistics, legal, or a partner)
- Changes the status of an existing pending item (approved / declined / new info)

**Does NOT belong:** day-to-day UX micro-decisions, implementation details, internal process
tweaks, or clarifications that don't affect the above criteria.

---

## Execution Workflow

### Step 1: Read the current Decision Log

Fetch the Confluence page in **ADF format** (`contentFormat: "adf"`):

```
getConfluencePage(pageId, contentFormat: "adf")
```

From the response, capture:
- The **full raw ADF body** — treat this as sacred; it will be used as the base for all writes
- The **version number** — needed for the update call
- The `version.createdAt` timestamp — this is the **cutoff date** for scanning
- The existing decision table: parse out each row's ID, title, and status for reference

**The ADF body must never be reconstructed or paraphrased.** It is copied verbatim into every write call and only the specific targeted nodes are modified.

### Step 2: Determine the scan window

Use `version.createdAt` from the Confluence page as the `fromDate` for Fireflies and the
`oldest` timestamp for Slack. Convert to:
- ISO 8601 for Fireflies: e.g. `"2026-05-06"`
- Unix timestamp for Slack `oldest` param: e.g. `1746576000`

### Step 3: Scan Fireflies

Search for meetings related to the project:
```
fireflies_get_transcripts(keyword="<project_name>", fromDate=<cutoff>, limit=10, scope="all")
```
Try alternative keywords if the primary returns no results (e.g. project alias, client name).

For each meeting found, read the summary (`fireflies_get_summary`). Focus on:
- Decisions made or confirmed
- Status changes on known open items
- New blockers or risks that should be tracked
- Any mentions of vendors, partners, payments, integrations, legal

### Step 4: Scan Slack channels

Scan project-related channels with `oldest: <cutoff_unix_ts>`, `limit: 50`.
If channel IDs aren't known, search:
```
slack_search_channels(query="<project_name>")
```
Look for channels like `#proj-<name>`, `#<name>-operational`, `#<name>-mgmt`, etc.

Also run a targeted search for high-signal content:
```
query: "<project_name> decision OR agreed OR confirmed OR approved OR declined after:<cutoff_date>"
```

For any message matching these signals, read the full thread — decisions are frequently confirmed or reversed in replies, not in the original message:
```
slack_read_thread(channel_id: "<channel-id>", thread_ts: "<ts>")
```

### Step 5: Synthesise findings

Cross-reference everything found against the existing Decision Log. For each finding, classify:

- **NEW DECISION** — a net-new item not yet in the log
- **STATUS UPDATE** — an existing Pending item has been approved, declined, or has important new info
- **UPDATE ADDITION** — an existing entry needs a new "Update (DD.MM.YY):" line appended to its rationale cell

For **status updates** and **update additions**, always reference the specific Decision ID from the table's sequential integer ID column (e.g. 11).

### Step 6: Present proposed changes

Before touching Confluence, present all findings as a clear summary:

```
## Proposed Decision Log Changes

### NEW ENTRIES
**[NEW] Decision: <Title>**
Status: Pending / Approved / Declined
Decision Maker: <name or TBC>
Date: <DD.MM.YY or TBC>
Rationale: <1-2 sentence summary>
Source: <Fireflies meeting title | Slack #channel | date>

### UPDATES TO EXISTING ENTRIES
**D-<ID> — <Decision Title>** (currently: <status>)
Proposed change: [Status change to X] / [Add update text]
Update text: "Update <DD.MM.YY>: <text>"
Source: <source>

### NO ACTION NEEDED
- <Decision title>: no new developments found
```

Always include a **"Sources scanned"** section at the end listing all Fireflies meetings and
Slack channels checked, with date range.

Ask: *"Shall I apply all of these, or would you like to modify any before I write to Confluence?"*

### Step 7: Write to Confluence (only after explicit approval)

**The golden rule: the ADF body fetched in Step 1 is the ground truth. Every write operation starts from that exact body and modifies only the approved nodes. Nothing else changes.**

#### 7a. Locate target nodes in the ADF

The ADF body is a nested JSON structure. The decision table is a `table` node inside `content`. Each row is a `tableRow` with `tableCell` children. Columns map to: ID, Title, Status, Approval Required, Decision Date, Decision Maker, Rationale.

To apply an **update addition** to an existing row:
1. Find the `tableRow` whose first cell contains the matching decision ID (e.g. `"3"`)
2. Locate the **last** `tableCell` in that row — this is the Rationale cell
3. Find the last `paragraph` node inside that cell
4. **Append** a new `paragraph` node after it with the update text formatted as bold prefix + plain text:

```json
{
  "type": "paragraph",
  "content": [
    {
      "type": "text",
      "text": "Update DD.MM.YY: ",
      "marks": [{ "type": "strong" }]
    },
    {
      "type": "text",
      "text": "<update text here>"
    }
  ]
}
```

To apply a **status change** to an existing row:
1. Find the `tableRow` for the matching decision ID
2. Locate the third `tableCell` (Status column)
3. Replace only the `status` inline node within it. Match the casing and color of existing status nodes in the document — do not invent new color codes.

To **add a new row**:
1. Locate the closing of the `table` node
2. Append a complete new `tableRow` before it, matching the column structure of existing rows exactly. Use plain `text` nodes for all cells. For the Status cell, use the same `status` inline node structure as existing rows.

#### 7b. Construct the write payload

Take the **full ADF body from Step 1 verbatim**. Apply only the surgical node modifications described in 7a. Do not reformat, reorder, or touch any other node.

Call `updateConfluencePage` with:
- `contentFormat: "adf"`
- `body`: the modified ADF JSON (full document, with only targeted nodes changed)
- `versionMessage`: `"Decision Log update <today's date> — automated scan"`

**Never submit the body in markdown format** — doing so will strip Confluence-native elements (status lozenges, smart links, inline images) from untouched rows.

#### 7c. Verify

After writing, fetch the page again and confirm:
- The targeted rows contain the new update text / status
- The untouched rows are byte-for-byte identical to what was fetched in Step 1
- The version number incremented by 1

If any untouched row differs, report the discrepancy to the user before proceeding.

---

## Decision Log Table Structure (standard)

| Column | Notes |
|---|---|
| ID | Sequential integer |
| Decision Title | Short, descriptive title |
| Status | `approved` / `Pending` / `declined` — match casing and color of existing entries |
| Approval Required | Leave blank for new entries |
| Decision Date | `DD.MM.YY` format or blank if pending |
| Decision Maker | Name or blank if pending |
| Rationale (Summary) / Link | Full narrative + `**Update DD.MM.YY:** text` lines + links |

---

## Writing Quality Standards

### Decision Titles

A good title answers: *"What was decided?"* — not *"What was discussed?"*

- Aim for 5–10 words. Specific, outcome-oriented.
- Start with the subject of the decision, not the domain.

| ❌ Bad | ✅ Good |
|---|---|
| Authentication | JWT chosen over session tokens for auth |
| Payment provider discussion | Stripe selected as primary payment provider |
| Timeline | MVP delivery moved to June 15 |
| Partner API | Partner API integration deferred to Phase 2 |

### Rationale Text

Every entry should answer three questions in 2–4 sentences:
1. **What** was decided (restate briefly — the title is short, the rationale can expand)
2. **Why** — the reasoning, constraint, or evidence that drove the decision
3. **What was NOT chosen** — the alternative considered, if any (this is what prevents re-litigation)

- ✅ Good: "The team selected Stripe over Adyen after comparing integration complexity and fee structures. Stripe's pre-built components reduce frontend work by ~2 weeks and are already familiar to the dev team. Adyen was considered but requires a longer onboarding process that doesn't fit the current timeline."
- ❌ Bad: "Stripe was chosen for payment processing."

**Rationale length:** 2–4 sentences for a new entry. Update lines should be 1–2 sentences max.

### Update Lines

When appending an update to an existing entry:
- Format: `**Update DD.MM.YY:** [what changed, who confirmed it]`
- Include what prompted the update (new info, client approval, change of scope)
- **Never rewrite the existing rationale text** — only append new paragraph nodes after it
- ✅ Good: `**Update 12.05.26:** Client approved Stripe integration in call on 11.05. Contract signing expected by end of week.`
- ❌ Bad: `**Update 12.05.26:** Update to the previous decision.`

---

## Decision Criteria Quick Reference

When evaluating whether something is a Decision Log item, ask:

1. Does it change what we're building, how we're building it, or who is responsible?
2. Does the client need to sign off, or have they already?
3. Could it block another team if not resolved?
4. Is it a vendor, partner, or legal commitment?
5. Would not having it documented cause confusion or re-work later?

If 2+ of these are true → it belongs in the log.