Skip to content

Resolve #74 merge conflict: sync .agent issue-fns.sh mirror with master (jira/ado) - #87

Merged
laird merged 8 commits into
feature/issue-71from
merge/issue-71-master
Aug 8, 2026
Merged

Resolve #74 merge conflict: sync .agent issue-fns.sh mirror with master (jira/ado)#87
laird merged 8 commits into
feature/issue-71from
merge/issue-71-master

Conversation

@laird

@laird laird commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Unblocks #74 (issue #71), which is currently CONFLICTING and cannot merge.

Base is feature/issue-71, not master — merging this into that branch clears the conflict without force-pushing over #74's history.

The conflict was semantic, not mechanical

One file conflicted: .agent/scripts/issue-fns.sh.

Resolving "ours" would have silently deleted Jira and Azure DevOps support from the .agent mirror. Worth flagging, because both sides look correct in isolation and the loss would not show up as a test failure on #74 alone.

Resolution

Took the canonical plugins/autocoder/scripts/issue-fns.sh from master verbatim — it is already the thin dispatcher and carries the jira / ado cases. .agent/scripts/ ships issues-jira.sh and issues-ado.sh, so those cases resolve.

This is not a judgment call: tests/test_agent_mirror_parity.sh (added by #74 itself) requires the shared files to be byte-identical across mirrors, which makes the canonical file the only valid resolution — and self-verifying.

Verification

$ bash tests/test_agent_mirror_parity.sh
Results: 13 passed, 0 failed      # incl. "issue-fns.sh identical across mirrors"
                                  # and "mirror issue-fns.sh defines all 9 contract verbs"

$ bash -n plugins/autocoder/scripts/*.sh && bash -n .agent/scripts/*.sh \
    && python3 -m py_compile plugins/autocoder/scripts/*.py
✅ syntax OK

$ for t in tests/test_*.sh; do bash "$t"; done
18/18 suites pass, 0 failures

Suites verified directly rather than through regression-test.sh: this branch predates #73, so the runner here can still report a false green and is not trustworthy as the gate.

Merge order

  1. this PR → feature/issue-71
  2. Fix #71: resync the .agent mirror issue layer; add a parity guard #74master (now conflict-free)

🤖 Generated with Claude Code

claude and others added 6 commits July 28, 2026 23:22
Adds a first-class `jira` issue source alongside `file` and `github`,
implementing the same uniform 9-verb backend contract (list, get, update,
comment, close, create, claim, release, any-claimable) against the Jira
REST API v2.

- issues-jira.sh: self-contained backend. Maps Jira issues (PROJ-N) to the
  gh-compatible JSON shape, exposing the numeric key suffix as `number` so it
  stays compatible with the swarm manifest and the rest of the workflow.
  Uses API v2 for plain-text descriptions. Non-secret connection settings
  (baseUrl, project) come from the `jira` object in .autocoder.json;
  credentials are env-only (JIRA_EMAIL + JIRA_API_TOKEN, or JIRA_AUTH_HEADER
  for Server/DC PATs) and never committed.
- Claimable/open JQL ORs in `labels is EMPTY` so label-less issues are not
  silently dropped — the Jira analogue of the GitHub `no:label` bug (#57).
- Registers `jira` in both dispatchers (plugins + .agent mirror),
  issue-source-lib.sh validation, and the set-issue-source command.
- test_issues_jira.sh: 35 assertions covering JQL, request shaping, output
  schema, and exit codes, with curl fully stubbed (no network).
- Updates CLAUDE.md/GEMINI.md, launcher help strings, and bumps autocoder
  4.5.2 -> 4.6.0 and the marketplace 3.26.0 -> 3.27.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zJKDkbj54vZeGaTWLJEHv
The unit test (test_issues_jira.sh) stubs curl and asserts request/JQL
shape; this adds real end-to-end coverage without any network:

- tests/fixtures/fake_jira.py: a small stdlib-only STATEFUL fake of the
  Jira REST API v2 covering exactly the endpoints issues-jira.sh calls
  (search, issue CRUD, comment, transitions, assignee, myself). It keeps
  issues in memory and evaluates the JQL the backend emits, so state
  filters and the lifecycle behave like real Jira. Binds an ephemeral
  loopback port (printed as "LISTENING <port>") so CI runs never collide.
- tests/test_issues_jira_integration.sh: starts the fake, exercises the
  full lifecycle (create → get → claim/release → comment → update → close)
  over real HTTP and asserts every state filter — including the label-less
  "labels is EMPTY" guard a stateless mock cannot exercise — then tears the
  server down. Skips cleanly if curl/python3 are absent. 17 assertions.
- plugins/autocoder/scripts/jira-smoke-test.sh: opt-in check against a REAL
  Jira instance (JIRA_* env). Kept out of tests/ so CI never needs egress.
- CLAUDE.md: document the three test layers.

Full shell suite green (15/15); server teardown leaves no stray process.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zJKDkbj54vZeGaTWLJEHv
Walks through creating a free Jira Cloud site, project, and API token;
wiring the non-secret baseUrl/project into .autocoder.json while keeping
credentials in the environment; verifying with jira-smoke-test.sh; and the
two hermetic CI tests. No secrets in the doc. Linked from CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zJKDkbj54vZeGaTWLJEHv
Adds a first-class `ado` issue source implementing the same uniform 9-verb
backend contract against the Azure DevOps Work Item Tracking REST API.

- issues-ado.sh: self-contained backend. Work item IDs are integers, so
  `number` maps to System.Id directly. Labels ↔ work-item Tags
  (System.Tags), state ↔ System.State (done-state set covers the default
  Agile/Basic/Scrum/CMMI processes). Uses WIQL for list/any-claimable,
  workitemsbatch for details, and json-patch for create/update. Non-secret
  orgUrl/project come from the `ado` object in .autocoder.json; the PAT is
  env-only (ADO_PAT) and never committed. Overridable work-item type and
  open/closed state names via env.
- WIQL `[System.Tags] NOT CONTAINS 'x'` already matches tag-less items, so
  untagged work stays claimable without a special empty clause (the ADO
  analogue of the GitHub no:label / Jira empty-labels traps) — asserted by
  both tests.
- Registers `ado` in both dispatchers (plugins + .agent mirror),
  issue-source-lib validation, the set-issue-source command, and launcher
  help strings.
- Tests (both hermetic, in CI): test_issues_ado.sh (28 assertions, stubs
  curl; WIQL + json-patch shape, schema, exit codes) and
  test_issues_ado_integration.sh (18 assertions; real HTTP against a stateful
  fake, tests/fixtures/fake_ado.py, full lifecycle + WIQL filtering).
- Docs: docs/ado-setup.md; updates CLAUDE.md/GEMINI.md. Bumps autocoder
  4.6.0 -> 4.7.0 and the marketplace 3.27.0 -> 3.28.0.

Full shell suite green (17/17).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zJKDkbj54vZeGaTWLJEHv
- docs/issue-backends.md: unified overview of the four built-in backends —
  the 9-verb contract, uniform JSON shape and exit codes, per-backend model
  mapping, secrets handling, configuration precedence, and the hermetic
  test layers. Links to the Jira and ADO setup guides.
- README: refresh the "Issue Backends" section — full 9-verb contract table
  (adds claim/release/any-claimable), point at the new docs, and use a
  genuinely custom name (linear) for the custom-backend example now that
  jira/ado are first-class.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zJKDkbj54vZeGaTWLJEHv
Add Jira and Azure DevOps issue backends (#81, #82)
laird and others added 2 commits July 29, 2026 10:37
Resolves .agent/scripts/issue-fns.sh to the canonical plugins version:
the thin 9-verb dispatcher WITH the jira/ado cases. Recorded as a real
two-parent merge so master's change is in the ancestry and the later
merge to master is clean.
Two gaps found by a dry-run of the full merge chain.

1. issue-source-lib.sh existed only under plugins/autocoder/scripts/.
   It is issue-source resolution used by the swarm launch/lifecycle
   scripts — shared issue-layer infrastructure, not platform-specific —
   so the mirror was incomplete. Copied verbatim.

2. The parity guard's SHARED list covered only the two original backends
   (file, gh). issues-jira.sh and issues-ado.sh arrived with #83 and were
   never checked, and neither was issue-source-lib.sh. A backend that
   ships only under plugins/ is invisible to the guard — which is exactly
   how the drift in #71 went unnoticed: the mirror looked healthy because
   nothing checked the files missing from it. SHARED now lists the whole
   issue layer (7 files).

Verification: parity guard 19/19, up from 13/13. Negative-tested both new
assertion classes — removing issue-source-lib.sh from the mirror fails 2
assertions, and perturbing issues-jira.sh fails the divergence check — so
the added coverage is not vacuous. 18/18 suites pass, build clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@laird
laird force-pushed the merge/issue-71-master branch from 2b134b1 to b214e16 Compare July 29, 2026 14:37
@laird

laird commented Jul 29, 2026

Copy link
Copy Markdown
Owner Author

Both dry-run findings folded in. Branch updated: b214e16.

1. #87 did not fully clear #74 — fixed

Confirmed, and the cause was mine. api-push.py builds commits with parents=[base_sha] — a single parent — so it flattened my real two-parent merge into one commit. Master was therefore not in the branch's ancestry, and git re-derived the identical conflict on the later merge to master:

$ git merge-tree $(git merge-base origin/merge/issue-71-master origin/master) \
    origin/merge/issue-71-master origin/master
changed in both
  base 6530e5e .agent/scripts/issue-fns.sh
  our  bd1194d
  their e8f38a3

The file content was already correct; only the ancestry was wrong. Rebuilt the branch through the Git Data API so the merge is recorded with both parents (c714eb9 = feature/issue-71, a4cc38b = master) rather than flattened.

$ git merge-base --is-ancestor origin/master origin/merge/issue-71-master && echo YES
YES

2. Mirror was short issue-source-lib.sh — fixed

Confirmed absent. It is issue-source resolution used by the swarm launch/lifecycle scripts — shared issue-layer infrastructure — so it belongs in the mirror. Copied verbatim.

Also widened the guard's SHARED list from 4 files to the whole issue layer (7): issues-jira.sh and issues-ado.sh arrived with #83 and were never checked, and neither was issue-source-lib.sh. A backend that ships only under plugins/ is invisible to this guard — which is precisely how the drift in #71 went unnoticed. The mirror looked healthy because nothing checked the files missing from it.

Acceptance

# 1. full chain merges clean
$ git merge origin/merge/issue-71-master     # -> feature/issue-71 : clean
$ git merge origin/master                    # -> Already up to date.
conflicts remaining: 0

# 2. parity guard covers the whole layer, verified in the MERGED state
$ bash tests/test_agent_mirror_parity.sh
Results: 19 passed, 0 failed        # was 13/13

$ for t in tests/test_*.sh; do bash "$t"; done
SUITES FAILED: 0 / 18

$ bash -n plugins/autocoder/scripts/*.sh && bash -n .agent/scripts/*.sh \
    && python3 -m py_compile plugins/autocoder/scripts/*.py
✅ syntax OK

Verification ran in a scratch worktree at the merged result, not on my branch, so it reflects what actually lands.

The new assertions were negative-tested rather than assumed: removing issue-source-lib.sh from the mirror fails 2 assertions, and perturbing issues-jira.sh fails the divergence check. They bite.

Still noted, not fixed here

.agent/scripts/start-parallel-agents.sh does not source issue-source-lib.sh, while master's plugins/ copy does — so that script's mirror is itself behind. Same drift class, but out of scope for this PR and it does not affect either acceptance criterion. Worth its own issue.

Merge order unchanged: this PR → feature/issue-71, then #74 → master.

🤖 Autonomous fix workflow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants