M1: Jira fetch (REST) + JiraContext artifact #11

Merged
david merged 2 commits from issue-2/jira-fetch-rest into main 2026-07-24 03:34:58 +00:00
Owner

Summary

M1 — Jira fetch (REST) + prompt input (closes #2). Turns a Jira issue key into a validated JiraContext artifact (jira-context.json) using plain, deterministic, unit-tested orchestrator code — no pi session.

Changes

  • src/jiraJiraClient seam + JiraRestClient (Jira Cloud REST API v3, Basic auth via email + API token, injected fetch/clock).
    • ADF → plain-text flattening (flattenAdf).
    • Raw issue → JiraContext normalization (normalizeIssue): summary, description, acceptance criteria, labels, components, issue type, parent key, linked keys, url. Comments/attachments excluded (v1).
    • JiraError classification (kind/retriable/status) + HTTP-status mapper.
    • fetchJiraContext orchestrator with fail-fast JiraConfigError on missing creds.
  • src/shared/retry — generic withRetry (bounded attempts, exponential backoff, injectable sleep + isRetriable).
  • src/artifactswriteJiraContext / readJiraContext / validateJiraContext for jira-context.json (schema per DESIGN.md §3.4).
  • src/config — added JIRA_ACCEPTANCE_CRITERIA_FIELD_ID (Jira has no standard AC field; configurable custom field id), with masking coverage.

Error mapping (per policy)

  • 401/403 → auth (fail-fast, not retried)
  • 404 → not-found (fail-fast, not retried)
  • 429/5xx → transient (retried with backoff)

Testing

  • All tests pass — 102 unit tests (was 52; +50 new)
  • tsc --noEmit clean
  • eslint . clean
  • prettier --check . clean
  • Coverage: success, 401, 404, 429-retry, 5xx-exhaustion, malformed JSON, ADF flatten, normalize edge cases, artifact round-trip + schema rejection, retry backoff/attempts, config masking.

Checklist

  • Self-reviewed the diff
  • Follows vertical-slice module structure; cross-module imports only via barrels (§4)
  • Descriptive naming; no secret logging
  • Deterministic seams unit-tested per AGENTS.md

Notes

  • Added fetchJiraContext orchestrator beyond the literal task list to make the milestone usable end-to-end; still deterministic + tested.
  • error.json writing and CLI wiring are cross-cutting and deferred to M8; JiraError already carries kind/retriable/status.
## Summary M1 — Jira fetch (REST) + prompt input (closes #2). Turns a Jira issue key into a validated `JiraContext` artifact (`jira-context.json`) using plain, deterministic, unit-tested orchestrator code — no pi session. ## Changes - **`src/jira`** — `JiraClient` seam + `JiraRestClient` (Jira Cloud REST API v3, Basic auth via email + API token, injected `fetch`/clock). - ADF → plain-text flattening (`flattenAdf`). - Raw issue → `JiraContext` normalization (`normalizeIssue`): summary, description, acceptance criteria, labels, components, issue type, parent key, linked keys, url. Comments/attachments excluded (v1). - `JiraError` classification (kind/retriable/status) + HTTP-status mapper. - `fetchJiraContext` orchestrator with fail-fast `JiraConfigError` on missing creds. - **`src/shared/retry`** — generic `withRetry` (bounded attempts, exponential backoff, injectable sleep + `isRetriable`). - **`src/artifacts`** — `writeJiraContext` / `readJiraContext` / `validateJiraContext` for `jira-context.json` (schema per DESIGN.md §3.4). - **`src/config`** — added `JIRA_ACCEPTANCE_CRITERIA_FIELD_ID` (Jira has no standard AC field; configurable custom field id), with masking coverage. ## Error mapping (per policy) - `401/403` → auth (fail-fast, not retried) - `404` → not-found (fail-fast, not retried) - `429/5xx` → transient (retried with backoff) ## Testing - [x] All tests pass — **102** unit tests (was 52; +50 new) - [x] `tsc --noEmit` clean - [x] `eslint .` clean - [x] `prettier --check .` clean - Coverage: success, 401, 404, 429-retry, 5xx-exhaustion, malformed JSON, ADF flatten, normalize edge cases, artifact round-trip + schema rejection, retry backoff/attempts, config masking. ## Checklist - [x] Self-reviewed the diff - [x] Follows vertical-slice module structure; cross-module imports only via barrels (§4) - [x] Descriptive naming; no secret logging - [x] Deterministic seams unit-tested per AGENTS.md ## Notes - Added `fetchJiraContext` orchestrator beyond the literal task list to make the milestone usable end-to-end; still deterministic + tested. - `error.json` writing and CLI wiring are cross-cutting and deferred to M8; `JiraError` already carries `kind`/`retriable`/`status`.
- Add JiraClient seam + JiraRestClient (Jira Cloud REST v3, Basic auth,
  injected fetch, retry on 429/5xx, fail-fast on 401/403/404)
- ADF->text flattening, raw issue normalization into JiraContext
- JiraError classification (kind/retriable/status) per error-handling policy
- Generic withRetry helper (bounded, exponential backoff, injectable sleep)
- artifacts module: write/read/validate jira-context.json (schema per DESIGN.md 3.4)
- fetchJiraContext orchestrator + JiraConfigError (fail-fast on missing creds)
- config: JIRA_ACCEPTANCE_CRITERIA_FIELD_ID for the AC custom field

102 unit tests passing; tsc/eslint/prettier clean.
- Reject empty required key/url in validateJiraContext; normalizeIssue throws
  non-retriable JiraError on missing/empty key (no broken-but-valid artifacts)
- Add shared stripTrailingSlashes seam; dedup baseUrl normalization
- withRetry annotates rethrown errors with attempt count (getAttempts) for
  error.json; document retry-all-by-default footgun on isRetriable
- JiraRestClient constructor guards missing global fetch with a clear error
- Guard Array.isArray in acceptance-criteria renderer
- Fix fetchJiraContext docstring (JiraConfigError)
- Add 403 auth, email-only/token-only missing-cred, and attempts tests

119 unit tests passing; tsc/eslint/prettier clean.
david merged commit 4a9c017dcf into main 2026-07-24 03:34:58 +00:00
david deleted branch issue-2/jira-fetch-rest 2026-07-24 03:34:58 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
david/pi-loop!11
No description provided.