Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion skills/Jira/Workflows/SearchIssues.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@ jtk issues list --project KEY --sprint current --id | xargs -I{} jtk issues get
# Collect ALL keys across pages by iterating the stderr continuation token
token=""
while :; do
keys=$(jtk issues list --project KEY --id ${token:+--next-page-token "$token"} 2>/tmp/jtk-page-info)
if ! keys=$(jtk issues list --project KEY --id ${token:+--next-page-token "$token"} 2>/tmp/jtk-page-info); then
echo "jtk issues list failed; aborting to avoid a partial result set" >&2
exit 1
fi
printf '%s\n' "$keys"
token=$(grep -oE 'next: [^)]+' /tmp/jtk-page-info | cut -d' ' -f2) || break
[ -z "$token" ] && break
Expand Down
16 changes: 2 additions & 14 deletions tools/cfl/chaos-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@
**Started:** 2026-01-03
**Focus:** Read-only operations (list, view, download)

> **Historical note (#392):** The `-o json` rows below describe behavior from
> a session that pre-dates the removal of resource-read JSON. As of #392 the
> closed set is `{table, plain}`; the `-o json` and `-o yaml` rows below are
> no longer reproducible — both now error at the root with the same
> "invalid output format" message.

---

## Bugs Found
Expand All @@ -17,8 +11,6 @@
|----|----------|-------------|-------------|--------|
| BUG-001 | Medium | `--limit 0` silently uses default (25) instead of returning 0 or error | `cfl space list --limit 0` | **FIXED** |
| BUG-002 | Medium | `--limit -1` silently uses default (25) instead of error | `cfl space list --limit -1` | **FIXED** |
| BUG-003 | High | JSON output for `space list` includes trailing message, breaking JSON parsing | `cfl space list -o json \| jq .` fails | **FIXED** |
| BUG-004 | Low | `-o yaml` silently falls back to table format instead of erroring | `cfl space list -o yaml` | **FIXED** |
| BUG-005 | Low | Confluence macro parameters leak into markdown output | View page with TOC macro, see "12" artifact | **FIXED** |
| BUG-006 | **CRITICAL** | `attachment download` panics - flag shorthand conflict | `cfl attachment download <id>` crashes with `-o` conflict | **FIXED** |

Expand Down Expand Up @@ -65,9 +57,7 @@ Things where the current behavior might be correct, but we should confirm:
| `--type personal` | PASS | Filters correctly |
| `--type GLOBAL` | PASS | Case insensitive (API handles) |
| `--type invalid` | PASS | Good error from API |
| `-o json` | BUG | Invalid JSON due to trailing message |
| `-o plain` | PASS | Tab-separated, but has trailing message |
| `-o yaml` | BUG | Silently falls back to table |

### Page Listing (`cfl page list`)
| Test | Result | Notes |
Expand All @@ -84,7 +74,6 @@ Things where the current behavior might be correct, but we should confirm:
| Non-numeric ID (abc) | PASS | Good 400 error |
| Missing page ID | PASS | "accepts 1 arg(s)" error |
| `--body-format xhtml` mode | PASS | Shows exact Confluence storage XHTML |
| `-o json` | PASS | Valid JSON (no trailing message!) |
| Confluence macros | BUG-005 | TOC macro params leak through |

### Attachments
Expand All @@ -106,11 +95,10 @@ Things where the current behavior might be correct, but we should confirm:

## Summary

**6 bugs found (ALL FIXED):**
**4 bugs found (ALL FIXED):**
- 1 CRITICAL (panic crash) - FIXED: Changed `-o` shorthand to `-O` for `--output-file`
- 1 HIGH (broken JSON output) - FIXED: Pagination message now goes to stderr
- 2 MEDIUM (silent limit issues) - FIXED: Limit validation (negative = error, 0 = empty list)
- 2 LOW (minor UX issues) - FIXED: Output format validation + macro stripping
- 1 LOW (macro UX) - FIXED: Confluence macro stripping

**Tests passed:** ~25
**Tests failed:** 0 (all bugs fixed)
Expand Down
24 changes: 1 addition & 23 deletions tools/cfl/integration-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

This document catalogs the manual integration test suite for `cfl`. These tests verify real-world behavior against a live Confluence instance and catch edge cases that are difficult to cover with unit tests.

> **#392 update:** Rows that exercise `-o json` / `--output json` on resource commands are obsolete — the resource JSON surface has been removed. They now error at the root with `invalid output format: "json" (valid formats: table, plain)`. Skip those rows. The surviving JSON surface is `cfl set-credential --json` (control-plane envelope per cli-common §1.5.2); test that one normally.

## Auth Methods

cfl supports two authentication methods. The full integration test suite should be run with both:
Expand Down Expand Up @@ -63,7 +61,6 @@ All cfl commands should work with both auth methods (no scope limitations for Co
|-----------|---------|-----------------|
| List pages in space | `cfl page list --space confluence` | Shows table of pages with ID, title, status, version |
| List with limit | `cfl page list --space confluence --limit 5` | Shows only 5 pages with "showing first N results" message |
| ~~JSON output~~ (#392 removed) | `cfl page list --space confluence --output json` | Errors: invalid output format |
| Plain output | `cfl page list --space confluence --output plain` | Tab-separated values |
| List trashed pages | `cfl page list --space confluence --status trashed` | Shows deleted pages |
| List archived pages | `cfl page list --space confluence --status archived` | Shows archived pages |
Expand All @@ -76,13 +73,11 @@ All cfl commands should work with both auth methods (no scope limitations for Co
| View page content | `cfl page view <page-id>` | Shows title, ID, version, and markdown content |
| View exact XHTML | `cfl page view <page-id> --body-format xhtml` | Shows exact Confluence storage XHTML |
| View exact ADF | `cfl page view <page-id> --body-format adf` | Shows exact ADF JSON |
| ~~JSON output~~ (#392 removed) | `cfl page view <page-id> --output json` | Errors: invalid output format |
| Non-existent page | `cfl page view 99999999999` | Error: 404 not found |
| View content only | `cfl page view <id> --content-only` | Markdown only, no Title/ID/Version headers |
| Content only with XHTML | `cfl page view <id> --content-only --body-format xhtml` | XHTML only, no headers |
| Content only with macros | `cfl page view <id> --content-only --show-macros` | Markdown with [TOC] etc., no headers |
| Roundtrip macros (content-only) | `cfl page view <id> --show-macros --content-only \| cfl page edit <id> --legacy` | Macros preserved |
| ~~Content only JSON error~~ (#392 removed; -o json itself errors before --content-only checks) | `cfl page view <id> --content-only -o json` | Errors: invalid output format |
| Content only web error | `cfl page view <id> --content-only --web` | Error: incompatible flags |

### page create
Expand Down Expand Up @@ -155,7 +150,6 @@ All cfl commands should work with both auth methods (no scope limitations for Co
|-----------|---------|-----------------|
| List attachments | `cfl attachment list --page <id>` | Table of attachments with ID, title, type, size |
| No attachments | List on page with none | "No attachments found" |
| ~~JSON output~~ (#392 removed) | `cfl attachment list --page <id> --output json` | Errors: invalid output format |
| List unused attachments | `cfl attachment list --page <id> --unused` | Only attachments not referenced in page content |
| No unused attachments | `--unused` on page using all attachments | "No unused attachments found" |

Expand Down Expand Up @@ -199,15 +193,13 @@ All cfl commands should work with both auth methods (no scope limitations for Co
| Test Case | Command | Expected Result |
|-----------|---------|-----------------|
| List all spaces | `cfl space list` | Table of spaces with key, name, type |
| ~~JSON output~~ (#392 removed) | `cfl space list --output json` | Errors: invalid output format |
| Limit results | `cfl space list --limit 5` | Shows first 5 spaces |

### space view

| Test Case | Command | Expected Result |
|-----------|---------|-----------------|
| View space by key | `cfl space view confluence` | Key-value pairs: KEY, NAME, ID, TYPE, STATUS, DESCRIPTION |
| ~~JSON output~~ (#392 removed) | `cfl space view confluence -o json` | Errors: invalid output format |
| Non-existent space | `cfl space view NONEXISTENT` | Error: Space with key 'NONEXISTENT' not found |
| View personal space | `cfl space view ~accountid` | Shows personal space details (if accessible) |
| Alias: get | `cfl space get confluence` | Same output as `space view` |
Expand All @@ -217,7 +209,6 @@ All cfl commands should work with both auth methods (no scope limitations for Co
| Test Case | Command | Expected Result |
|-----------|---------|-----------------|
| Create global space | `cfl space create --key INTTEST --name "[Test] Integration" --description "Test space"` | Space created, shows KEY, NAME, URL |
| ~~Create with JSON output~~ (#392 removed) | `cfl space create --key INTTEST2 --name "[Test] Int2" -o json` | Errors: invalid output format |
| Missing key flag | `cfl space create --name "Test"` | Error: required flag(s) "key" not set |
| Missing name flag | `cfl space create --key TST` | Error: required flag(s) "name" not set |
| Duplicate key | `cfl space create --key INTTEST --name "Duplicate"` (after creating INTTEST) | Error: API rejects duplicate key |
Expand All @@ -229,7 +220,6 @@ All cfl commands should work with both auth methods (no scope limitations for Co
| Update name | `cfl space update INTTEST --name "[Test] Updated Name"` | Shows updated key and name |
| Update description | `cfl space update INTTEST --description "Updated description"` | Shows updated key and name |
| Update both | `cfl space update INTTEST --name "[Test] Both" --description "Both updated"` | Both name and description changed |
| ~~JSON output~~ (#392 removed) | `cfl space update INTTEST --name "[Test] JSON" -o json` | Errors: invalid output format |
| No flags provided | `cfl space update INTTEST` | Error: at least one of --name or --description required |
| Non-existent space | `cfl space update NONEXISTENT --name "X"` | Error: not found |
| Verify update | `cfl space view INTTEST` | Shows new name and description |
Expand All @@ -241,7 +231,6 @@ All cfl commands should work with both auth methods (no scope limitations for Co
| Delete with confirmation | `cfl space delete INTTEST` (type "y") | Space deleted after confirmation prompt |
| Delete cancelled | `cfl space delete INTTEST` (type "n") | "Deletion cancelled" message |
| Delete with --force | `cfl space delete INTTEST --force` | Space deleted without confirmation |
| ~~JSON output~~ (#392 removed) | `cfl space delete INTTEST --force -o json` | Errors: invalid output format |
| Non-existent space | `cfl space delete NONEXISTENT --force` | Error: not found |

### Space CRUD End-to-End (sequential)
Expand All @@ -253,7 +242,7 @@ All cfl commands should work with both auth methods (no scope limitations for Co
| 3. Update name | `cfl space update INTTEST --name "[Test] Updated"` | Name updated |
| 4. Verify update | `cfl space view INTTEST` | Shows new name |
| 5. Update desc | `cfl space update INTTEST --description "New description"` | Description updated |
| 6. List includes it | `cfl space list \| grep INTTEST` | Space appears in list (was `-o json \| jq` pre-#392) |
| 6. List includes it | `cfl space list \| grep INTTEST` | Space appears in list |
| 7. Delete | `cfl space delete INTTEST --force` | "Deleted space INTTEST" |
| 8. Verify gone | `cfl space view INTTEST` | Error: not found |

Expand All @@ -272,7 +261,6 @@ All cfl commands should work with both auth methods (no scope limitations for Co
| Search by label | `cfl search --label test-label` | Content with specified label |
| Combined filters | `cfl search "deploy" --space DEV --type page` | Filtered results |
| Raw CQL | `cfl search --cql "type=page AND space=DEV"` | CQL executed directly |
| ~~JSON output~~ (#392 removed) | `cfl search "test" -o json` | Errors: invalid output format |
| Plain output | `cfl search "test" -o plain` | Tab-separated values |
| Limit results | `cfl search "test" --limit 5` | Max 5 results |
| No results | `cfl search "xyznonexistent123"` | "No results found" message |
Expand Down Expand Up @@ -534,7 +522,6 @@ Copies in the TEST space (originals from INT, CUS, PROD, PLAYBOOK):
|-----------|---------|-----------------|
| View ADF page (default) | `cfl page view <adf-id>` | Shows markdown content (not "(No content)") |
| View ADF page (ADF) | `cfl page view <adf-id> --body-format adf` | Shows exact ADF JSON |
| ~~View ADF page (JSON)~~ (#392 removed) | `cfl page view <adf-id> -o json` | Errors: invalid output format |
| View ADF page (content-only) | `cfl page view <adf-id> --content-only` | Shows content without headers |
| View legacy page (no regression) | `cfl page view <legacy-id>` | Shows markdown content via storage path |

Expand Down Expand Up @@ -581,7 +568,6 @@ Copies in the TEST space (originals from INT, CUS, PROD, PLAYBOOK):
| Format | Flag | Verified With |
|--------|------|---------------|
| Table (default) | (none) | Visual inspection |
| ~~JSON~~ (#392 removed) | `--output json` | errors at root |
| Plain | `--output plain` | Tab-separated, scriptable |

---
Expand Down Expand Up @@ -623,7 +609,6 @@ All cfl commands work with both auth methods (no scope restrictions for Confluen
#### ADF Body Fallback (#150)
- [ ] View ADF page with empty storage → content displayed via ADF fallback
- [ ] View ADF page with `--body-format adf` → shows exact ADF JSON
- [ ] ~~View ADF page (JSON output)~~ (#392 removed)
- [ ] Edit ADF page (title only) → ADF body preserved
- [ ] Edit ADF page (new content) → submitted as ADF
- [ ] View/edit legacy page → no regression (storage path used)
Expand All @@ -649,15 +634,12 @@ All cfl commands work with both auth methods (no scope restrictions for Confluen
- [ ] Full-text search returns results
- [ ] Space filter works
- [ ] Type filter works
- [ ] ~~JSON output is valid~~ (#392 removed; -o json errors at root)
- [ ] Raw CQL works

#### Space CRUD
- [ ] View space (table output)
- [ ] ~~View space (JSON output)~~ (#392 removed)
- [ ] View non-existent space (expect error)
- [ ] Create space with key, name, description
- [ ] ~~Create space (JSON output)~~ (#392 removed)
- [ ] Create duplicate key (expect error)
- [ ] Update space name
- [ ] Update space description
Expand Down Expand Up @@ -716,7 +698,6 @@ All cfl commands work with both auth methods (no scope restrictions for Confluen
#### ADF Body Fallback (#150)
- [ ] View ADF page with empty storage → content displayed via ADF fallback
- [ ] View ADF page with `--body-format adf` → shows exact ADF JSON
- [ ] ~~View ADF page (JSON output)~~ (#392 removed)
- [ ] Edit ADF page (title only) → ADF body preserved
- [ ] Edit ADF page (new content) → submitted as ADF
- [ ] View/edit legacy page → no regression (storage path used)
Expand All @@ -742,15 +723,12 @@ All cfl commands work with both auth methods (no scope restrictions for Confluen
- [ ] Full-text search returns results
- [ ] Space filter works
- [ ] Type filter works
- [ ] ~~JSON output is valid~~ (#392 removed; -o json errors at root)
- [ ] Raw CQL works

#### Space CRUD
- [ ] View space (table output)
- [ ] ~~View space (JSON output)~~ (#392 removed)
- [ ] View non-existent space (expect error)
- [ ] Create space with key, name, description
- [ ] ~~Create space (JSON output)~~ (#392 removed)
- [ ] Create duplicate key (expect error)
- [ ] Update space name
- [ ] Update space description
Expand Down
3 changes: 1 addition & 2 deletions tools/cfl/internal/cmd/attachment/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,7 @@ func TestRunList_Empty(t *testing.T) {

err := runList(context.Background(), opts)
testutil.RequireNoError(t, err)
// The empty-results banner used to be suppressed under -o json; #392
// removed that skip, so the banner now always prints to stderr.
// The empty-results banner always prints to stderr.
testutil.Contains(t, rootOpts.Stderr.(*bytes.Buffer).String(), "No attachments found.")
}

Expand Down
6 changes: 1 addition & 5 deletions tools/cfl/test-plan-writes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ The documentation (readme.md, cfl-intro.md) makes numerous claims about write op

This document inventories all untested assertions and provides comprehensive test cases.

> **#392 update:** Rows that exercise `-o json` / `--output json` on resource commands are obsolete — the resource JSON surface has been removed. They now error at the root. Skip those rows; the `cfl page create` ID-capture pattern (test 4.2.2) should be re-run by parsing the `ID:` key-value line from the default text output instead.

---

## Untested Claims Inventory
Expand Down Expand Up @@ -177,7 +175,6 @@ This document inventories all untested assertions and provides comprehensive tes
| # | Test Case | Command | Expected | Priority |
|---|-----------|---------|----------|----------|
| 1.8.1 | Default output | `cfl page create -s SPACE -t "Test" -f test.md` | Success message with ID, URL | HIGH |
| 1.8.2 | ~~JSON output~~ (#392 removed) | `cfl page create -s SPACE -t "Test" -f test.md -o json` | Errors: invalid output format | OBSOLETE |
| 1.8.3 | Plain output | `cfl page create -s SPACE -t "Test" -f test.md -o plain` | Tab-separated | LOW |

---
Expand Down Expand Up @@ -216,7 +213,6 @@ This document inventories all untested assertions and provides comprehensive tes
|---|-----------|---------|----------|----------|
| 2.3.1 | List page with attachments | `cfl attachment list -p PAGE_ID` | Table with ID, name, type, size | HIGH |
| 2.3.2 | List page without attachments | `cfl attachment list -p PAGE_NO_ATT` | "No attachments" message | MEDIUM |
| 2.3.3 | ~~JSON output~~ (#392 removed) | `cfl attachment list -p PAGE_ID -o json` | Errors: invalid output format | OBSOLETE |

---

Expand Down Expand Up @@ -269,7 +265,7 @@ This document inventories all untested assertions and provides comprehensive tes
| # | Test Case | Command | Expected | Priority |
|---|-----------|---------|----------|----------|
| 4.2.1 | Pipe file content | `cat notes.md \| cfl page create -s SPACE -t "Test"` | Page created | HIGH |
| 4.2.2 | Capture created ID | `cfl page create -s SPACE -t "Test" -f x.md \| awk -F': ' '/^ID:/ {print $2; exit}'` | Extracts page ID (was `-o json \| jq -r .id` pre-#392) | HIGH |
| 4.2.2 | Capture created ID | `cfl page create -s SPACE -t "Test" -f x.md \| awk -F': ' '/^ID:/ {print $2; exit}'` | Extracts page ID | HIGH |
| 4.2.3 | Script: create many pages | Loop creating 10 pages | All succeed | MEDIUM |

---
Expand Down
Loading