forgejo-mcp/.beads/issues.jsonl

108 lines
151 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"_type":"issue","id":"forgejo-mcp-9r4","title":"promote-image-tag deletes build-tmp → cascades to delete v2.27.0 + latest manifest on Codeberg registry","description":"Forgejo/Codeberg container registry deletes the underlying MANIFEST when a tag is deleted. Since :build-tmp, :vX.Y.Z and :latest all share one digest, the 'skopeo delete :build-tmp' cleanup (added in f026f8c) removed all three tags. Result: v2.27.0 image absent from registry; only cosign .sig/.att survived. Fix (decided): eliminate build-tmp entirely — push directly to :vX.Y.Z, sign+attest in place, promote :latest; add finally-cleanup to delete :vX.Y.Z if sign/attest fail (preserves fail-closed).","status":"closed","priority":0,"issue_type":"bug","owner":"goern@b4mad.net","created_at":"2026-06-02T15:25:45Z","created_by":"Christoph Görn","updated_at":"2026-06-10T22:14:46Z","closed_at":"2026-06-10T22:14:46Z","close_reason":"Verified implemented + working; closing. The decided fix shipped in 748de51 ('push image version tag directly, never delete a staging tag') across both pipelines: (1) push-image-by-digest pushes :vX.Y.Z directly, no :build-tmp staging tag anywhere (grep clean); (2) cosign-sign + attach-sbom operate on the digest in place; (3) promote-image-tag only ADDS :latest (skipped for pre-releases), never deletes; (4) fail-closed finally task delete-tag-on-failure deletes :vX.Y.Z when attach-sbom status notin [Succeeded] — at that point :latest is unpromoted, so :vX.Y.Z is the manifest's only tag and the delete is safe. Wired identically in .tekton/on-tag-push-release.yaml (codeberg.org/goern/forgejo-mcp) and .tekton/release-tools-on-tag-publish.yaml (operate-first/release-tools). Empirical proof: registry now holds v2.28.0, v2.29.0, latest — two post-fix releases survived promotion+cleanup. Residue tracked separately: v2.27.0 image still absent, one orphaned .sig/.att pair remains.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-k5f","title":"Extend #136 scope: webhook resource-templates, not just tools","description":"Codeberg issue #136 (feat: expose repository webhook management tools) currently scopes only MCP *tools* for webhook CRUD (create/list/get/edit/delete/test_repo_hook). Per the project's resources convention (AGENTS.md / openspec/specs/mcp-resources-core), entities should ALSO be exposed as forgejo:// resource-templates — additive, instance-portable, coexisting with tools.\n\nAction: update #136 to add a resource-templates section alongside the tools section.\n\nProposed resource-templates:\n- forgejo://repos/{owner}/{repo}/hooks -\u003e embedded, bounded list of hooks\n- forgejo://repos/{owner}/{repo}/hooks/{id} -\u003e single hook\n\nRequirements carried from the resources convention:\n- Place under operation/\u003cdomain\u003e/resources*.go; use operation/resource helpers (ParseXxx, Bounded, MapForgejoError).\n- Embedded list MUST use operation/resource.Bounded (consistent truncation sentinel).\n- Bound the list resource per docs/design/output-bounding.md (client-controlled bound + resumability + documented params).\n- secret field MUST be masked in resource reads exactly as in the tool results (issue #136 already requires this for tools).","acceptance_criteria":"#136 body updated with a resource-templates section listing forgejo://repos/{owner}/{repo}/hooks and /hooks/{id}, plus the bounding + secret-masking + operation/resource helper requirements. Acceptance-criteria checklist in #136 extended to cover the resource-templates surface.","status":"closed","priority":0,"issue_type":"task","assignee":"goern","owner":"goern@b4mad.net","created_at":"2026-06-02T05:53:14Z","created_by":"Christoph Görn","updated_at":"2026-06-02T06:21:06Z","closed_at":"2026-06-02T06:21:06Z","close_reason":"Updated Codeberg #136: added Resource-templates section (forgejo://repo/{owner}/{repo}/hooks + /hooks/{id}) with bounding/secret-masking/operation-resource-helper requirements, extended acceptance-criteria checklist to cover resource surface, assigned goern, added Priority/High. Used singular 'repo' URI segment to match mcp-resources-core (deferral text's plural 'repos' was shorthand). Unblocks merge of mcp-resource-templates change which defers webhooks to #136.","external_ref":"codeberg-136","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-uc6","title":"Branch protection management: MCP tools + forgejo:// resource-templates","description":"OpenSpec change 'branch-protection-management' proposed (proposal/design/specs/tasks; validate --strict passes). Spec-only proposal PR opened on branch feat/branch-protection-uc6. Implementation is a follow-up (partial impl stashed locally: parse.go BP parsers + params.go BP descriptions). Decisions: self-contained branch-protection capability (no mcp-resources-core delta), new operation/branchprotection/ package, comma-separated status_check_contexts, edit PATCH pointer semantics, full CRUD in one impl PR.","acceptance_criteria":"Tools registered under operation/\u003cdomain\u003e/; list output bounded per docs/design/output-bounding.md; resource-templates under operation/\u003cdomain\u003e/resources*.go using operation/resource helpers (ParseXxx, Bounded, MapForgejoError); create/edit round-trips status_check_contexts correctly; covered by tests.","status":"closed","priority":0,"issue_type":"feature","assignee":"goern","owner":"goern@b4mad.net","created_at":"2026-06-02T05:40:32Z","created_by":"Christoph Görn","updated_at":"2026-06-02T14:40:20Z","closed_at":"2026-06-02T14:40:20Z","close_reason":"Shipped across #195 (proposal) -\u003e #196 (impl: 5 CRUD tools + 2 bounded forgejo:// resources + tests + showboat demo) -\u003e #197 (archive: live spec openspec/specs/branch-protection/spec.md + co-located demo). All merged, CI green. Forgejo SDK fully bound the endpoints (no upstream block).","dependencies":[{"issue_id":"forgejo-mcp-uc6","depends_on_id":"forgejo-mcp-f6h","type":"discovered-from","created_at":"2026-06-02T05:52:50Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-f6h","title":"Renovate/Gitea merges PR while required-less commit status is PENDING (main has no branch protection)","description":"PR #187 (Renovate docker-digest bump) merged 02:18:05 while Tekton build-and-test was still running; merge cancelled the PipelineRun (TaskRunCancelled). Root cause = two compounding holes.\n\nHOLE 1 — main has zero branch protection: GET /repos/goern/forgejo-mcp/branch_protections returns []. No required status checks; nothing gates merge on CI green.\n\nHOLE 2 — PaC posts no pending/running commit status at pipeline start, only a final status on completion. During the run window only the faster code-scans context exists (=success), so combined commit status = success. Renovate (default:automergeDigest + automergeSchedule '* * * * *') sees green branch and merges.\n\nStatuses on head 7279457:\n success | op1st Pipelines as Code / forgejo-mcp-code-scans | 02:17:31\n cancell | op1st Pipelines as Code / forgejo-mcp-on-pull-request | 02:18:10 (AFTER merge)\n\nbuild-and-test did NOT fail on merits — killed by the merge.","acceptance_criteria":"main branch protection requires both PaC status check contexts (forgejo-mcp-code-scans, forgejo-mcp-on-pull-request) with enable_status_check=true. A PR with an absent or non-success required check is not mergeable, including by Renovate automerge. Verified by re-running a Renovate digest PR and confirming it waits for build-and-test before merge.","notes":"Fix command (outward-facing config):\ncurl -X POST -H 'Authorization: token $CODEBERG_TOKEN' -H 'Content-Type: application/json' https://codeberg.org/api/v1/repos/goern/forgejo-mcp/branch_protections -d '{\"rule_name\":\"main\",\"enable_status_check\":true,\"status_check_contexts\":[\"op1st Pipelines as Code / forgejo-mcp-code-scans\",\"op1st Pipelines as Code / forgejo-mcp-on-pull-request\"]}'\n\nRequired-but-absent check blocks merge, closing both holes. Secondary hardening: have PaC emit a pending status at pipeline start.\n── CORRECTION 2026-06-02 (supersedes original Hole 2) ──\nOriginal bead claimed 'Hole 2 — PaC posts no pending status at pipeline start'. That is FALSE. Evidence:\n\nFull commit-status history (GET /commits/7279457/statuses, all entries):\n 02:16:49 pending | op1st PaC / forgejo-mcp-code-scans\n 02:16:49 pending | op1st PaC / forgejo-mcp-on-pull-request \u003c- PaC DID post pending\n 02:17:31 success | op1st PaC / forgejo-mcp-code-scans\n 02:18:10 cancelled | op1st PaC / forgejo-mcp-on-pull-request\n\nAt merge (02:18:05) the latest-per-context combined status = PENDING (on-pull-request still pending). PaC posts a pending status on in_progress — confirmed in source openshift-pipelines/pipelines-as-code pkg/provider/gitea/gitea.go (CreateStatus sets forgejo.StatusPending when status.Status=='in_progress', then calls CreateStatus).\n\nREAL ROOT CAUSE (single hole, confirmed): main has NO branch protection / NO required status checks. Because no check is *required*, the pending PaC status is non-blocking to the merge path, so the PR was merged while still yellow. With required status checks, a pending check =\u003e not mergeable =\u003e neither Renovate nor Gitea native automerge would merge.\n\nOPEN QUESTION (needs Renovate run logs to pin, does NOT change the fix): which merge path ignored the pending status —\n (a) Renovate client-side merge: with no required checks, Renovate's getBranchStatus/automerge did not treat the ambient pending status as blocking; or\n (b) Gitea/Forgejo native scheduled auto-merge: without branch protection Gitea has no definition of 'green', so it merged immediately.\nBoth are downstream of the missing required checks. FIX UNCHANGED: require both PaC contexts in main branch protection.","status":"closed","priority":0,"issue_type":"bug","assignee":"goern","owner":"goern@b4mad.net","created_at":"2026-06-02T05:40:22Z","created_by":"Christoph Görn","updated_at":"2026-06-02T05:52:51Z","closed_at":"2026-06-02T05:52:51Z","close_reason":"Fixed: created main branch protection rule (enable_status_check=true) requiring both PaC contexts (forgejo-mcp-code-scans, forgejo-mcp-on-pull-request). Verified live via GET branch_protections. Codeberg issue #188 closed. Pending/absent required check now blocks merge for both Renovate and Gitea native auto-merge.","external_ref":"codeberg-188","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-1b4","title":"Build dedicated release-tools container image for op1st Tekton release pipeline","description":"Currently .tekton/tasks/goreleaser-release.yaml installs syft + goreleaser at runtime in separate Tekton Steps, which fails (exit 127) because /usr/local/bin/ is per-container, not shared across Steps in a Pod. Workaround in current code is to collapse all installs+run into one Step (loses log granularity, repeats install on every release run, fragile to upstream URL changes). Proper fix: build a custom OCI image with pinned Go + syft + goreleaser + cosign + jq + curl + node22 + npx + @anthropic-ai/mcpb prefetched. Reference this image from all three Tasks (goreleaser-release, cosign-sign-release, mcpb-pack). Image rebuild on tool bump only. Likely lives in op1st-emea-b4mad or ghcr.io/operate-first/release-tools.","acceptance_criteria":"Image published at a stable registry path; .tekton/tasks/*.yaml reference it via params with versioned tag; release pipeline still passes; install-at-runtime removed; Renovate/dependabot config bumps the image tag","notes":"PR #155 merged into main as 550db7f. OpenSpec design + adversarial review now canonical. Implementation work begins on branch feat/release-tools-image-impl. Tracking via /var/home/goern/Source/codeberg.org/goern/forgejo-mcp-release-tools-impl worktree. Dev team release-tools-image-iter1 spawned for iteration 1 (source tree only; pipelines deferred to iter 2).","status":"closed","priority":0,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T11:47:01Z","created_by":"Christoph Görn","updated_at":"2026-05-25T22:20:29Z","started_at":"2026-05-25T12:09:21Z","closed_at":"2026-05-25T22:20:29Z","close_reason":"PR #157 merged (commit e02cf56). release-tools image built and pushed to codeberg.org/operate-first/release-tools:latest (sha256:b0387a762c54). All .tekton/tasks/ rewritten. OpenSpec change implemented end-to-end.","dependencies":[{"issue_id":"forgejo-mcp-1b4","depends_on_id":"forgejo-mcp-29g","type":"blocks","created_at":"2026-05-25T11:47:15Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":1,"dependent_count":5,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-puz","title":"fix: tekton go-ci lint step broken by golangci-lint v2 config migration","description":"Found checking .tekton/ after .golangci.yml v2 migration (commit 59c86b6). Earlier CI-impact check only grepped .forgejo/.github/Makefile/justfile and missed .tekton/.\n\nProblems in .tekton/tasks/go-ci.yaml:\n1. GOLANGCI_LINT_IMAGE default = docker.io/golangci/golangci-lint:v1.64-alpine — v1 binary cannot read version:\"2\" config: 'can't load config: unsupported version of the configuration'. Lint step exits nonzero on every run.\n2. LINT_REQUIRED default = \"false\" masks that failure as a warning — lint coverage silently zero in CI since migration.\n3. Version drift vs local toolchain (local golangci-lint 2.12.2).\n\nstaticcheck: not used standalone in .tekton (only as golangci-lint linter) — no action.\nGO_IMAGE golang:1.25 matches go.mod go 1.25.0 — OK.\n\nFix: bump image to v2.12.2-alpine (matches local exactly); flip LINT_REQUIRED default to \"true\" — task comment says 'Flip to true after baseline cleanup' and baseline is now 0 issues (commit dd9116f).","status":"closed","priority":1,"issue_type":"bug","owner":"goern@b4mad.net","created_at":"2026-06-10T22:10:03Z","created_by":"Christoph Görn","updated_at":"2026-06-10T22:11:05Z","closed_at":"2026-06-10T22:11:05Z","close_reason":"Fixed .tekton/tasks/go-ci.yaml: GOLANGCI_LINT_IMAGE default v1.64-alpine → v2.12.2-alpine (exact match to local 2.12.2; v1 could not parse the version:\"2\" .golangci.yml and failed every run, masked by warn-only mode). LINT_REQUIRED default false → true — baseline cleaned in dd9116f, and verified by replicating the CI step locally: 'podman run golangci-lint:v2.12.2-alpine golangci-lint run --timeout=5m ./...' → 0 issues, binary built with go1.26.2 (compatible with go.mod 1.25.0 + GOTOOLCHAIN=local). staticcheck has no standalone .tekton usage (runs as golangci-lint linter only). GO_IMAGE golang:1.25 unchanged, matches go.mod.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-fcm","title":"fix: page/limit defaulting uses wrong 'ok' variable in 4 handlers","description":"Copy-paste bug: 'if !ok { page = N }' tests the ok from an earlier unrelated type assertion (state/sha/all), not whether page/limit were provided. When the earlier param IS provided, page/limit stay 0 when omitted by the client.\n\nLocations:\n- operation/pull/pull.go:181,185 (ListRepoPullRequestsFn — ok from 'state')\n- operation/repo/commit.go:48,52 (ListRepoCommitsFn — ok from 'sha')\n- operation/user/notification.go:90,94 (CheckNotificationsFn — ok from 'all')\n- operation/user/notification.go:275,279 (ListRepoNotificationsFn — ok from 'all')\n\nFix: use the 'if page == 0 { page = 1 }' pattern used everywhere else.","status":"closed","priority":1,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-10T21:49:50Z","created_by":"Christoph Görn","updated_at":"2026-06-10T21:53:50Z","started_at":"2026-06-10T21:50:27Z","closed_at":"2026-06-10T21:53:50Z","close_reason":"Fixed: replaced 'if !ok' (stale ok from earlier type assertion) with 'if page == 0 / limit == 0' defaulting in operation/pull/pull.go (ListRepoPullRequestsFn), operation/repo/commit.go (ListRepoCommitsFn), operation/user/notification.go (CheckNotificationsFn + ListRepoNotificationsFn). Build/vet/tests pass.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-xjv","title":"track-downloads workflow: switch direct main push to PR + auto-merge (branch protection)","status":"closed","priority":1,"issue_type":"task","assignee":"@me","owner":"goern@b4mad.net","created_at":"2026-06-02T14:21:48Z","created_by":"Christoph Görn","updated_at":"2026-06-02T14:23:53Z","started_at":"2026-06-02T14:21:48Z","closed_at":"2026-06-02T14:23:53Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-773","title":"Implement label-crud OpenSpec change (tools + label resources)","description":"OpenSpec change 'label-crud' in PR #192 (branch feat/label-openspec, worktree ../forgejo-mcp-label-openspec). Adversarially reviewed by debate team 2026-06-02 (design.md Adversarial Review section). FINAL scope: (1) repo-label CRUD create_repo_label/edit_repo_label/delete_repo_label/get_repo_label via forgejo-sdk/v3 (renamed for symmetry — deviates from #190's create_label names, map on acceptance); (2) org-label CRUD create_org_label/edit_org_label/delete_org_label/get_org_label via pkg/forgejo DoJSON; (3) safe delete: delete_mode enum safe|force (NOT a boolean — reserves dry_run/reassign), in-use guard — repo count via SDK ListRepoIssues pagination (DoJSON discards X-Total-Count), org count best-effort/MAY-undercount token-invisible repos; (4) color 6-digit-only (3-digit unverified, gated); (5) resources forgejo://repo/{o}/{r}/labels{?page,limit} + /label/{id} + forgejo://org/{org}/labels{?page,limit} (renamed from owner→org root; page/limit client-controlled bound, EmbeddedListCap ceiling; scope-less label/{id} invalid); (6) mcp-resources-core MODIFIED Collection-resource requirement KEPT (goern decision; archive after mcp-resource-templates). Pre-code gates: org get-one endpoint, 3-digit hex. Out of scope: exclusive/is_archived (reserved optional). openspec validate --strict OK.","status":"closed","priority":1,"issue_type":"feature","owner":"goern@b4mad.net","created_at":"2026-06-02T07:44:00Z","created_by":"Christoph Görn","updated_at":"2026-06-10T06:59:51Z","started_at":"2026-06-10T06:27:41Z","closed_at":"2026-06-10T06:59:51Z","close_reason":"Closed","external_ref":"codeberg-190","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-8if","title":"Merge PR #185, finish stateless-http-auth smoke tests, archive change","description":"After PR #185 (fix: reject bare tokens) is reviewed by byteflavour and merged to main, complete the remaining stateless-http-auth tasks and archive the OpenSpec change.\n\nPR: https://codeberg.org/goern/forgejo-mcp/pulls/185\n\nRemaining tasks (openspec/changes/stateless-http-auth/tasks.md):\n- 6.4 Manual smoke: start server --transport http --url https://codeberg.org (no --token); two requests w/ distinct tokens; each get_my_user_info returns correct distinct identity.\n- 6.5 Manual smoke: Authorization: bearer xyz (lowercase) resolves to per-request identity, not global fallback (validates 2.4).\n- 6.6 Manual smoke: broken Forgejo URL so SDK version probe fails; request returns error, not silent global-token auth (validates 1.3).\n- 6.7 Archive: openspec archive stateless-http-auth (moves to openspec/changes/archive/\u003cdate\u003e-stateless-http-auth/).\n\nBlocker fixes 1.3, 2.4, 2.5, 4.2-4.4 already implemented (most on main, bare-token fix in #185). Build/test/validate all green.","status":"closed","priority":1,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-01T21:43:09Z","created_by":"Christoph Görn","updated_at":"2026-06-01T22:00:43Z","started_at":"2026-06-01T21:54:17Z","closed_at":"2026-06-01T22:00:43Z","close_reason":"PR #185 merged; smoke tests 6.4/6.5 passed E2E (valid-\u003egoern, bogus/no-auth-\u003eerror, lowercase bearer-\u003egoern), 6.6 covered by unit test 4.3; specs synced to openspec/specs/stateless-http-auth/; change archived to openspec/changes/archive/2026-06-02-stateless-http-auth/","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-wbw","title":"Fix PaC task annotation YAML folding bug in .tekton/release-tools-*.yaml","description":"PipelinesAsCode failed on PR #172 with 'annotations in pipeline are in wrong format: [git-clone,\\n .tekton/release-tools/tasks/build-image.yaml,...]'. Two PaC PipelineRun manifests use 'pipelinesascode.tekton.dev/task: \u003e-' with continuation lines indented one space deeper than the first content line. YAML folded scalar (\u003e-) preserves newlines when continuation lines are MORE indented than the first content line, so PaC sees a literal multi-line string instead of a flat bracketed list. Affects: .tekton/release-tools-on-pull-request-build.yaml and .tekton/release-tools-on-tag-publish.yaml.","notes":"Fix: collapse the bracketed task list to a single double-quoted string on the annotation line, e.g.:\n pipelinesascode.tekton.dev/task: \"[git-clone, .tekton/release-tools/tasks/build-image.yaml, .tekton/release-tools/tasks/verify-image-tools.yaml, .tekton/release-tools/tasks/syft-scan-image.yaml]\"\nPR #172 comment: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16027445","status":"closed","priority":1,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T15:35:11Z","created_by":"Christoph Görn","updated_at":"2026-05-28T15:36:11Z","started_at":"2026-05-28T15:35:15Z","closed_at":"2026-05-28T15:36:11Z","close_reason":"Fixed in 3a12931. PaC task annotations collapsed to single-line inline lists in release-tools-on-pull-request-build.yaml + release-tools-on-tag-publish.yaml.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-kva","title":"fix: cosign-sign task fails with --output-signature deprecated","description":"cosign v2.4+ deprecated --output-signature in favor of --bundle. When new-bundle-format is active (now default), --output-signature is silently ignored and cosign tries to write bundle to empty path → 'create bundle file: open : no such file or directory'. Fix: replace --output-signature with --bundle in .tekton/tasks/cosign-sign-release.yaml (and .forgejo/workflows/release.yml for consistency). External: PipelineRun on-tag-push-release-srlfm, task cosign-sign.","status":"closed","priority":1,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-26T06:19:20Z","created_by":"Christoph Görn","updated_at":"2026-05-26T06:19:52Z","started_at":"2026-05-26T06:19:22Z","closed_at":"2026-05-26T06:19:52Z","close_reason":"Fixed: --output-signature → --bundle in cosign-sign-release.yaml and release.yml. Committed cee6465.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-aps","title":"Fix build-image task: remove privileged, use rootless buildah","description":"build-image.yaml sets securityContext.privileged: true which is rejected by OpenShift container-build SCC bound to the pipeline SA. Fix: remove privileged: true, run as UID 1000, use --isolation=chroot --storage-driver=vfs so buildah works rootless under container-build SCC.","status":"closed","priority":1,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T23:10:09Z","created_by":"Christoph Görn","updated_at":"2026-05-26T00:14:57Z","started_at":"2026-05-25T23:10:13Z","closed_at":"2026-05-26T00:14:57Z","close_reason":"PR #163 open. All task bugs fixed and validated by run11. build/push/sign/sbom/promote all succeeded.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-8sz","title":"Move release-tools PipelineRuns to .tekton/ root — PaC v0.42.0 does not scan subdirectories","description":"PaC v0.42.0 only reads PipelineRun YAMLs from .tekton/*.yaml (root level). .tekton/release-tools/on-tag-publish.yaml and on-pull-request-build.yaml are invisible to PaC and never trigger. Fix: move both PipelineRun files to .tekton/ root with release-tools- prefix. Task YAMLs in .tekton/release-tools/tasks/ stay in place (PaC fetches them by explicit path in the task annotation).","status":"closed","priority":1,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T22:53:37Z","created_by":"Christoph Görn","updated_at":"2026-05-25T22:59:33Z","started_at":"2026-05-25T22:53:40Z","closed_at":"2026-05-25T22:59:33Z","close_reason":"PR #160 merged — PipelineRuns moved to .tekton/ root, CEL fixed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-00o","title":"Restore cosign fail-closed signing after release-tools/v1.0.0 bootstrap ships","description":"Bootstrap exception: the first release-tools/v1.0.0 publish run will be invoked with SKIP_SIGN=true PipelineRun param so signing is skipped (allowed per D4 of design.md — chicken-egg unknowns at first end-to-end run). After v1.0.0 is published and pullable, run a smoke release-tools/v1.0.1 (no-op image bump or tooling rev) with SKIP_SIGN=false (default) to confirm cosign-signing-key Secret shape matches and signature objects land in codeberg.org/operate-first/release-tools registry. Verify cosign verify --key \u003cop1st-pub\u003e against the v1.0.1 manifest. Once green: remove the SKIP_SIGN param from on-tag-publish.yaml entirely (revert to spec.md A3 fail-closed posture exactly).","acceptance_criteria":"release-tools/v1.0.1 (or later) published with SKIP_SIGN=false. cosign verify succeeds. SKIP_SIGN param removed from on-tag-publish.yaml. Bead closes when commit landing the removal merges.","notes":"PR #158 created: https://codeberg.org/goern/forgejo-mcp/pulls/158. Code removes SKIP_SIGN param, validate-skip-sign task, and all when: guards — cosign-sign/attach-sbom now unconditional. Pre-merge: operator must verify release-tools/v1.0.1 publishes with signing enabled and cosign verify passes.","status":"closed","priority":1,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T17:08:31Z","created_by":"Christoph Görn","updated_at":"2026-05-26T00:14:57Z","started_at":"2026-05-25T22:34:46Z","closed_at":"2026-05-26T00:14:57Z","close_reason":"PR #158 merged. v1.0.1 published with signing enabled (run11 succeeded). SKIP_SIGN removed from on-tag-publish.yaml. A3 fail-closed posture restored.","dependencies":[{"issue_id":"forgejo-mcp-00o","depends_on_id":"forgejo-mcp-1b4","type":"blocks","created_at":"2026-05-25T17:08:36Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-j52","title":"Split cosign keypair: separate release-tools-image signing from release-artifact signing","description":"Origin: L4 from release-tools-image adversarial review. v1.0.0 of the image is signed with the same cosign-signing-key Secret used to sign forgejo-mcp release artifacts. The release-tools image is consumed by .tekton/tasks/cosign-sign-release.yaml at release time, so a compromised image (via Containerfile change, transitive dep, or npm-package takeover) has access to the signing key and can sign attacker-supplied binaries. Mitigation: provision a second keypair in op1st-pipelines (e.g. cosign-signing-key-images vs cosign-signing-key-artifacts) so a release-tools image compromise cannot forge release artifact signatures. Coordinate with op1st-emea-b4mad maintainers for the second secret + reflector ruleset.","notes":"Blocked on op1st-emea-b4mad-yn5 (op1st-emea-b4mad beads, P1): 'Provision second cosign keypair to isolate release-tools image signing from forgejo-mcp artifact signing'. That task covers Secret provisioning + reflector ruleset. forgejo-mcp-j52 unblocks once op1st-emea-b4mad-yn5 is complete and both Secrets exist in op1st-pipelines.","status":"closed","priority":1,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T13:52:20Z","created_by":"Christoph Görn","updated_at":"2026-05-26T09:18:37Z","started_at":"2026-05-26T09:05:07Z","closed_at":"2026-05-26T09:18:37Z","close_reason":"PR #164 merged, cosign-signing-key-artifacts + cosign-signing-key-images confirmed in op1st-pipelines, v2.25.1 released with correct key separation.","dependencies":[{"issue_id":"forgejo-mcp-j52","depends_on_id":"forgejo-mcp-1b4","type":"blocks","created_at":"2026-05-25T13:52:44Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-3h2","title":"Tighten release-tools pinning: vendor goreleaser, SHA256-verify curl-installed binaries","description":"Origin: L2 from release-tools-image adversarial review. The v1.0.0 image installs goreleaser via 'go install \u003ctag\u003e' which re-resolves transitive deps from proxy.golang.org on every build; syft and cosign installed via curl by tag only (no SHA256 verify). A transitive-dep takeover in goreleaser's module graph OR a CDN poisoning of anchore/sigstore release URLs would ship unnoticed. Fix: vendor goreleaser source at pinned SHA (build via 'go build' from a committed go.mod/go.sum), and SHA256-verify all curl-downloaded binaries against checksums recorded in VERSIONS.md before installing them.","notes":"PR #159: https://codeberg.org/goern/forgejo-mcp/pulls/159. goreleaser: go install → prebuilt tarball + dual SHA256 verify. syft: curl|sh → direct tarball + dual SHA256 verify. Hashes in VERSIONS.md + Containerfile ARG defaults. cosign unchanged.","status":"closed","priority":1,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T13:52:15Z","created_by":"Christoph Görn","updated_at":"2026-05-26T00:14:57Z","started_at":"2026-05-25T22:37:39Z","closed_at":"2026-05-26T00:14:57Z","close_reason":"PR #159 merged. goreleaser+syft now SHA256-verified via dual check against repo hash and publisher checksums.txt. Filename bug fixed in PR #162.","dependencies":[{"issue_id":"forgejo-mcp-3h2","depends_on_id":"forgejo-mcp-1b4","type":"blocks","created_at":"2026-05-25T13:52:44Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-aun","title":"Hummingbird base health monitoring: SLO on hi/go tag lag + scheduled CVE rescan","description":"Origin: A6 + L6 from release-tools-image adversarial review (openspec/changes/release-tools-image/review.md). Hummingbird is young; hi/go may lag upstream Go releases. Renovate bumps tags but does NOT surface CVEs landing between bumps. Need: (a) documented SLO for acceptable lag between upstream Go GA and hi/go:\u003cver\u003e-builder availability, (b) second-source mirror policy if Red Hat pulls a tag mid-cycle, (c) scheduled PipelineRun (e.g. weekly) that pulls the published release-tools image and runs grype or trivy against it, opening issues on findings. Defer until release-tools-image v1.0.0 ships + one CVE-cycle of operational data exists.","notes":"Tracked in design.md Open Questions as forgejo-mcp-bd-A6L6 placeholder. Filed under Status/Blocked per acceptance criteria of release-tools-image change.","status":"open","priority":1,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-25T13:52:10Z","created_by":"Christoph Görn","updated_at":"2026-05-25T13:52:10Z","dependencies":[{"issue_id":"forgejo-mcp-aun","depends_on_id":"forgejo-mcp-1b4","type":"blocks","created_at":"2026-05-25T13:52:44Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-trb","title":"Fix goreleaser-release Task: move Go cache out of git checkout to avoid dirty-tree","description":"GoReleaser run on v2.24.1 failed: 'git is in a dirty state' caused by GOCACHE=/workspace/src/.gocache + GOMODCACHE=/workspace/src/.gomodcache placing untracked dirs inside the repo. GoReleaser checks git status before publishing and bails on any uncommitted/untracked content. Fix: move caches to /tmp/gocache + /tmp/gomodcache (per-step but acceptable; release runs once per tag).","acceptance_criteria":"goreleaser release succeeds on v2.24.2; cosign-sign + mcpb-pack downstream Tasks complete; all 8 assets uploaded","status":"closed","priority":1,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T11:54:05Z","created_by":"Christoph Görn","updated_at":"2026-05-25T11:55:30Z","started_at":"2026-05-25T11:54:05Z","closed_at":"2026-05-25T11:55:30Z","close_reason":"PR #154 merged. Go cache moved to /tmp. v2.24.2 cut next.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-29g","title":"Fix goreleaser-release Task: collapse install steps to survive Pod step-isolation","description":"Path B workaround for forgejo-mcp-1b4. Step containers in a Tekton Pod don't share /usr/local/bin/, so syft + goreleaser installed in install-* steps disappear before the release step runs (exit 127 'goreleaser: command not found' on first v2.24.0 run). Collapse install-syft + install-goreleaser + release into a single Step that installs both tools inline and then invokes goreleaser release. Smoke-test stays separate (reads from dist/ on workspace). Proper image-based fix tracked in forgejo-mcp-1b4.","acceptance_criteria":"goreleaser-release Task succeeds end-to-end on v2.24.1; all 8 release assets uploaded to Codeberg; cosign-sign + mcpb-pack downstream Tasks complete","status":"closed","priority":1,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T11:47:11Z","created_by":"Christoph Görn","updated_at":"2026-05-25T11:49:15Z","started_at":"2026-05-25T11:47:15Z","closed_at":"2026-05-25T11:49:15Z","close_reason":"PR #153 merged. Inline syft+goreleaser install in release Step; v2.24.1 cut next to validate.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-hvr","title":"Fix release workflow smoke-test: --help + dead ldflags break v2.23.0 release","description":"Release run 172 (tag v2.23.0) failed at smoke-test step in .forgejo/workflows/release.yml. Two compounding bugs:\n\n1. main.go declares 'var Version = \"dev\"' but .goreleaser.yml ldflags inject '-X main.BuildTag={{.Version}}' (and BuildCommit/BuildDate). Symbol main.BuildTag is not defined anywhere — grep returns zero hits. So Version stays 'dev' in shipped binaries.\n\n2. Smoke-test runs '$BIN --help' but the CLI uses flag.NewFlagSet with ExitOnError; --help is undefined, exits non-zero with 'flag provided but not defined: -help' on stderr and Usage banner. The expected regex '^forgejo-mcp ${VERSION}([+-]|$)' never matches.\n\nFix:\n- .goreleaser.yml: rewrite ldflags to -X main.Version={{.Version}} (drop dead BuildCommit/BuildDate or wire them to real vars).\n- .forgejo/workflows/release.yml: invoke '$BIN version' (the 'version' subcommand documented in cmd.go isVersionRequest) instead of '--help'.\n\nTracks: https://codeberg.org/goern/forgejo-mcp/actions/runs/172","notes":"PR #149 opened: https://codeberg.org/goern/forgejo-mcp/pulls/149. Fix verified locally (ldflags + 'version' subcommand). Awaiting merge + next release tag to re-cut release pipeline.","status":"closed","priority":1,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T08:28:14Z","created_by":"Christoph Görn","updated_at":"2026-05-25T08:37:38Z","started_at":"2026-05-25T08:28:17Z","closed_at":"2026-05-25T08:37:38Z","close_reason":"PR #149 merged into main (merge commit 332b989). Release pipeline fixed; next semantic-release tag (v2.23.1+) will re-cut a clean release.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-5x8","title":"fix: add pull_request event to Codeberg webhook for op1st PaC","description":"Codeberg repo webhook (id 60326) to op1st Pipelines-as-Code controller only subscribes to push event. No pull_request event delivered, so on-pull-request, openspec-validate-pr, code-scans PR pipelines never fire on any open PR (#126, #138, #139). Push pipelines on main work fine (verified on 4f57c57). Fix: PATCH hook events to include pull_request (and pull_request_comment for /ok-to-test on fork PRs).","notes":"Verified via curl: events=['push']. Root cause of all three open PRs lacking PaC statuses.","status":"closed","priority":1,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-24T07:13:31Z","created_by":"Christoph Görn","updated_at":"2026-05-24T07:16:46Z","started_at":"2026-05-24T07:15:18Z","closed_at":"2026-05-24T07:16:46Z","close_reason":"Patched webhook 60326 events from ['push'] to push+pull_request+pull_request_comment (plus auto-expanded subevents). Verified: /test comment on PR #139 triggered op1st Pipelines as Code / on-pull-request status (pending). All future PR opens/syncs/comments will now reach PaC.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-f37","title":"CI: add lint, race, mod-tidy, govulncheck to go-ci task","description":"Current .tekton/tasks/go-ci.yaml only does build+test. Missing critical correctness gates. Add golangci-lint (gofmt, errcheck, staticcheck, ineffassign, gosec), go test -race -shuffle=on -count=1, go mod tidy drift check, govulncheck ./...","acceptance_criteria":"go vet runs, golangci-lint runs (warning-only first pass acceptable), race detector on, govulncheck zero high-severity findings, go.mod/go.sum drift fails build","notes":"PR opened: https://codeberg.org/goern/forgejo-mcp/pulls/142 (mergeable). Bead stays in_progress until merge — close on merge.","status":"closed","priority":1,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-24T07:06:30Z","created_by":"Christoph Görn","updated_at":"2026-05-24T07:24:57Z","started_at":"2026-05-24T07:06:57Z","closed_at":"2026-05-24T07:24:57Z","close_reason":"Merged via PR #142 (rebase). Step 1 hardening live in main.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-r7h","title":"fix: -debug flag defaults to true, FORGEJO_DEBUG env is dead code","description":"cmd/cmd.go:84-95 — fs.BoolVar(\u0026debug, \"d\"/\"debug\", true, ...). Debug-level logging always on by default; the FORGEJO_DEBUG/GITEA_DEBUG env fallback (lines 170-190) only runs when debug==false, which requires explicitly passing -debug=false. Default for a debug flag should be false.\n\nFix: default both flags to false.","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-10T21:50:20Z","created_by":"Christoph Görn","updated_at":"2026-06-10T21:53:53Z","started_at":"2026-06-10T21:50:28Z","closed_at":"2026-06-10T21:53:53Z","close_reason":"Fixed: -d/-debug flag default changed true→false (cmd/cmd.go). Debug logging now opt-in; FORGEJO_DEBUG / deprecated GITEA_DEBUG env fallback path is reachable again. Build/vet/tests pass.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-3nu","title":"fix: search_users and search_org_teams ignore page/limit params","description":"operation/search/search.go: both tools advertise page/limit with defaults; handlers never set ListOptions. SDK SearchUsersOption and SearchTeamsOptions both embed ListOptions.\n\nFix: parse page/limit (to.Float64 + zero-default) and set ListOptions in both handlers.","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-10T21:50:19Z","created_by":"Christoph Görn","updated_at":"2026-06-10T21:53:52Z","started_at":"2026-06-10T21:50:27Z","closed_at":"2026-06-10T21:53:52Z","close_reason":"Fixed: SearchUserFn and SearchOrgTeamsFn now parse page/limit (default 1/100, matching schema defaults) and set embedded ListOptions on SearchUsersOption / SearchTeamsOptions (operation/search/search.go). Also added missing log.Debugf to SearchUserFn. Build/vet/tests pass.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-7f8","title":"fix: label resources ignore documented {?page,limit} query params","description":"operation/issue/resources_label.go pageLimit() is a stub: always returns page=1, limit=EmbeddedListCap. Template descriptions + AGENTS.md resource table document forgejo://repo/{owner}/{repo}/labels{?page,limit} and forgejo://org/{org}/labels{?page,limit} as client-controlled. Output-bounding design requires client-controlled bound.\n\nFix: parse query from req.Params.URI (url.Parse → Query()), clamp limit to EmbeddedListCap, default page=1.","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-10T21:50:19Z","created_by":"Christoph Görn","updated_at":"2026-06-10T21:53:53Z","started_at":"2026-06-10T21:50:28Z","closed_at":"2026-06-10T21:53:53Z","close_reason":"Fixed: pageLimit() in operation/issue/resources_label.go now parses ?page,limit from req.Params.URI via url.Parse; limit clamped to EmbeddedListCap (30), malformed/absent values fall back to defaults. Added unit tests (resources_label_pagelimit_test.go): defaults, query values, clamp, malformed. {?page,limit} contract in template descriptions + AGENTS.md now honored. Build/vet/tests pass.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-9ii","title":"fix: list_repo_issues 'type' parameter parsed but never applied","description":"operation/issue/issue.go:282-285 — issueType is read from args, then an empty if-block does nothing. SDK ListIssueOption has 'Type IssueType' (issue.go:66 in forgejo-sdk v3). Tool schema advertises type=(issues|pulls) but filter is silently ignored.\n\nFix: set opt.Type = forgejo_sdk.IssueType(issueType).","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-10T21:50:19Z","created_by":"Christoph Görn","updated_at":"2026-06-10T21:53:51Z","started_at":"2026-06-10T21:50:27Z","closed_at":"2026-06-10T21:53:51Z","close_reason":"Fixed: ListRepoIssuesFn now sets opt.Type = forgejo_sdk.IssueType(issueType) when type arg provided (operation/issue/issue.go). SDK v3 ListIssueOption.Type confirmed. Build/vet/tests pass.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-cdf","title":"fix: list_repo_pull_requests advertises milestone+labels but ignores both","description":"operation/pull/pull.go ListRepoPullRequestsFn: 'milestone' and 'labels' params in tool schema; handler reads neither (comments claim SDK doesn't support). SDK v3 ListPullRequestsOptions HAS Milestone int64. Labels is genuinely unsupported by SDK.\n\nFix: wire milestone (parse to int64, set opt.Milestone); remove 'labels' from tool schema so schema matches behavior.","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-10T21:50:19Z","created_by":"Christoph Görn","updated_at":"2026-06-10T21:53:51Z","started_at":"2026-06-10T21:50:27Z","closed_at":"2026-06-10T21:53:51Z","close_reason":"Fixed: ListRepoPullRequestsFn parses milestone arg to int64 and sets opt.Milestone (SDK v3 supports it). Removed 'labels' from list_repo_pull_requests tool schema — SDK ListPullRequestsOptions has no labels filter, so the param was unimplementable; schema now matches behavior. Build/vet/tests pass.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-tc6","title":"fix: delete_file advertises new_branch_name but drops it","description":"operation/repo/file.go DeleteFileFn: tool schema includes new_branch_name (params.NewBranchName); handler never reads it, FileOptions.NewBranchName never set — delete always commits to branch_name directly.\n\nFix: read arg, set FileOptions.NewBranchName like CreateFileFn/UpdateFileFn do.","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-10T21:50:19Z","created_by":"Christoph Görn","updated_at":"2026-06-10T21:53:52Z","started_at":"2026-06-10T21:50:28Z","closed_at":"2026-06-10T21:53:52Z","close_reason":"Fixed: DeleteFileFn reads new_branch_name and sets FileOptions.NewBranchName (operation/repo/file.go), matching CreateFileFn/UpdateFileFn. Build/vet/tests pass.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-6ua","title":"track-downloads: daily snapshot PRs stick when required 'on-pull-request' check never posts a status","description":"## Problem\n\nThe track-downloads workflow (.forgejo/workflows/track-downloads.yml) opens a daily snapshot PR against protected `main` and relies on Forgejo auto-merge to land it unattended. Verified live 2026-06-02 via workflow_dispatch (run #249).\n\nTwo failure modes observed, only the first is fixed:\n\n1. FIXED (#201): immediate merge returns HTTP 405 while required Tekton checks are still pending. Workflow now tries immediate merge, else schedules `merge_when_checks_succeed`.\n\n2. OPEN: `goern/main` branch protection requires the `op1st Pipelines as Code / forgejo-mcp-on-pull-request` status check, but on PR #199 only `forgejo-mcp-code-scans` posted a status — `on-pull-request` never reported on the data-only commit (likely a path filter skipping docs/downloads/*). Result: required check is permanently 'pending/missing', merge 405s forever, and scheduled auto-merge never fires (no future status event). #199 had to be force-merged manually.\n\nIf on-pull-request systematically skips docs/downloads-only commits, EVERY daily bot PR will stick and need manual force-merge — defeating the unattended design.\n\n## Options to fix\n- Exempt the bot's docs/downloads path from the 'on-pull-request' required-status-check rule on main (branch protection config), OR\n- Drop on-pull-request from required checks for these PRs, OR\n- Have the workflow force-merge its own data-only PR (curl merge with force_merge=true) after opening it, accepting the protection bypass for this narrow path, OR\n- Make the on-pull-request Tekton pipeline post a (trivially-passing) status even on docs-only changes.\n\n## Repro\n1. Dispatch track-downloads when counts have moved.\n2. Workflow opens bot/downloads-\u003cdate\u003e PR.\n3. Observe: only code-scans posts a commit status; merge stays 405.\n\n## Refs\n- Fixed merge-pending: PR #201 (merged)\n- Stuck PR example: #199 (force-merged 2026-06-02)\n- Initial rework: PR #198","status":"open","priority":2,"issue_type":"bug","owner":"goern@b4mad.net","created_at":"2026-06-02T16:54:25Z","created_by":"Christoph Görn","updated_at":"2026-06-02T16:54:25Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-0zl","title":"README §4 verify-blob fetches renamed cosign key (cosign-signing-key.pub now 404)","description":"operate-first/op1st-emea-b4mad split the single cosign key into cosign-signing-key-artifacts.pub (blob/artifacts) + cosign-signing-key-images.pub (images) on 2026-06-02. README §4 (verify-blob, ~L417-418) still fetches cosign-signing-key.pub from branch/main, which now 404s. Fix: point §4 at cosign-signing-key-artifacts.pub. README §5/§6 (cosign-signing-key-images.pub) are already correct. Pinned-commit URL (8a3c55e) for the old name still resolves, so this only breaks the branch/main fetch. Discovered during signed-sbom-attestation archive (PR #189 follow-up). See bd memory signed-sbom-key-drift.","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-02T13:13:47Z","created_by":"Christoph Görn","updated_at":"2026-06-02T13:52:26Z","started_at":"2026-06-02T13:47:30Z","closed_at":"2026-06-02T13:52:26Z","close_reason":"Merged in PR #194. README §2 fetches cosign-signing-key-artifacts.pub (branch-tip + re-pinned commit cd3715f); prose clarifies artifact vs image key. All key URLs 200; no stale cosign-signing-key.pub refs.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-tcy","title":"CLI resource-read path (--cli read forgejo://...) for resource-template parity","description":"Codeberg #191. --cli mode (cmd/cli.go) reaches tools (registerToolsWithDomains + cliExec dispatch by name) but NOT resources: registerToolsWithDomains registers tools only, no forgejo:// reader, no 'read' subcommand. All shipped resources (repo/commit/status/issue/pr/comment/owner) are MCP-only, invisible from CLI. Add 'forgejo-mcp --cli read \u003cforgejo-uri\u003e' wired to the same resource handlers (shared registerResourcesWithDomains, no MCP-vs-CLI divergence), honour output-bounding contract, surface templates in --cli list. Cross-cutting: blocks resource-template halves of #136 (webhook) and #190 (label). Tool CLI parity already automatic. Showboat demo must read \u003e=1 resource over --cli.","status":"open","priority":2,"issue_type":"feature","owner":"goern@b4mad.net","created_at":"2026-06-02T06:39:22Z","created_by":"Christoph Görn","updated_at":"2026-06-02T06:39:22Z","external_ref":"codeberg-191","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-3y1","title":"OpenSpec: update release-tools-image SBOM requirement for signed cosign attest","description":"Archived + live spec synced in PR #193 (branch openspec/archive-signed-sbom-attestation), follows merged #189. Showboat demo added (real cosign attest/verify-attestation roundtrip). Key-split README §4 follow-up filed as forgejo-mcp-0zl. Keep open until #193 merges.","acceptance_criteria":"An OpenSpec change updates the 'SBOM attached as registry artifact' requirement + scenario in release-tools-image/spec.md to: (a) state the SBOM is a signed cosign attestation (cosign attest --type cyclonedx), (b) replace the 'cosign download sbom' retrieval contract with 'cosign verify-attestation --type cyclonedx' (and/or download attestation). Change validated and archived; main spec synced. README already updated under aa6.","notes":"Code already migrated (aa6, .tekton/release-tools/tasks/cosign-attach-sbom.yaml). README consumer block already updated under aa6. Remaining drift is the governed spec only.\nPR #189 opened (branch openspec/signed-sbom-attestation, commit 5207bd9): https://codeberg.org/goern/forgejo-mcp/pulls/189\nOpenSpec change 'signed-sbom-attestation' — 1 MODIFIED delta on release-tools-image. openspec validate --strict passes. Spec-only (task+README already landed under aa6/b2619fc).\nRemaining (tasks.md 3.2): after merge, archive change + sync openspec/specs/release-tools-image/spec.md. Keep 3y1 open until merged+archived.","status":"closed","priority":2,"issue_type":"task","assignee":"goern","owner":"goern@b4mad.net","created_at":"2026-06-02T05:58:49Z","created_by":"Christoph Görn","updated_at":"2026-06-02T13:42:28Z","closed_at":"2026-06-02T13:42:28Z","close_reason":"Merged in PR #193 (merge commit on main). Live release-tools-image spec synced to signed cosign attest --type cyclonedx + verify-attestation; change archived 2026-06-02-signed-sbom-attestation; real showboat demo committed. README §4 key-rename remains as follow-up forgejo-mcp-0zl.","external_ref":"codeberg-pr-189","dependencies":[{"issue_id":"forgejo-mcp-3y1","depends_on_id":"forgejo-mcp-aa6","type":"discovered-from","created_at":"2026-06-02T05:59:07Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-o5b","title":"Gate image :latest promotion to stable releases only","description":"promote-image-tag (.tekton/release-tools/tasks/promote-image-tag.yaml) unconditionally tags BOTH :vX.Y.Z and :latest. The release pipeline triggers on any refs/tags/v[0-9], including pre-releases (alpha/beta/rc). Result: a pre-release would move :latest to a non-stable image. For v2.27.0-alpha.1 (2026-06-01) :latest was deliberately skipped via a manual skopeo copy. Fix: skip the :latest promotion when TAG matches a pre-release pattern (contains '-'), or pass a PROMOTE_LATEST flag from the pipeline computed from the tag.","status":"closed","priority":2,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-06-01T08:59:32Z","created_by":"Christoph Görn","updated_at":"2026-06-01T09:08:59Z","closed_at":"2026-06-01T09:08:59Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-01e","title":"Add OWNERS file to authorize PaC CI triggering","description":"PR #178 (author: byteflavour) is blocked with 'User byteflavour is not allowed to trigger CI via pull_request in this repo'. This is Pipelines as Code (op1st-pipelines ns), which reads a Prow-style OWNERS file from the default branch to decide who may trigger a PipelineRun without /ok-to-test. Add OWNERS listing goern, byteflavour, b4mad-renovate, op1st-gitops so their PRs trigger CI automatically.","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-31T19:00:57Z","created_by":"Christoph Görn","updated_at":"2026-05-31T19:02:06Z","started_at":"2026-05-31T19:01:00Z","closed_at":"2026-05-31T19:02:06Z","close_reason":"OWNERS file added on main branch; PaC will now auto-trigger for goern, byteflavour, b4mad-renovate, op1st-gitops PRs. Unblocks PR #178.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-vbz","title":"Update Containerfile to use hummingbird-project based containers","description":"Migrate Containerfile base images from registry.access.redhat.com (go builder + core-runtime) to hummingbird-project based containers. Affects both build stage and runtime stage. Verify build still works (make build, CGO_ENABLED=0) and image runs the forgejo-mcp entrypoint.","notes":"Project Hummingbird = Red Hat hardened images (gitlab.com/redhat/hummingbird/containers), public mirror quay.io/hummingbird/*, non-root. Current Containerfile uses registry.access.redhat.com/hi/* (same images, RH registry). Migration = repoint to quay mirror. Mapping: build stage /hi/go:1.26.3-builder -\u003e quay.io/hummingbird/go:\u003cver\u003e-builder ; runtime /hi/core-runtime:2.42 -\u003e quay.io/hummingbird/core-runtime (or quay.io/hummingbird/static, binary is CGO_ENABLED=0 static). Decide static vs core-runtime, pin tags + digests. Verify: make build (CGO_ENABLED=0), image runs /app/forgejo-mcp entrypoint.","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-31T18:39:10Z","created_by":"Christoph Görn","updated_at":"2026-05-31T19:23:43Z","started_at":"2026-05-31T18:44:31Z","closed_at":"2026-05-31T19:23:43Z","close_reason":"Done in PR (branch feat/hummingbird-containers, commit 988398a). Containerfile repointed to quay.io/hummingbird/{go,core-runtime} (identical digests); VERSION injected via build-arg fixing empty version/--version output.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-5zy","title":"Track + visualize release asset download counts","description":"Forgejo API exposes cumulative download_count per release asset, but keeps no history. Snapshot daily into JSONL (git = time-series DB), then visualize per-release and feat-vs-fix (semver-bump classification) in a static Chart.js dashboard. Scheduler: one reintroduced Forgejo Actions cron workflow (Tekton-only stack otherwise; user accepted the tradeoff).","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-31T14:55:18Z","created_by":"Christoph Görn","updated_at":"2026-05-31T15:06:14Z","started_at":"2026-05-31T14:55:22Z","closed_at":"2026-05-31T15:06:14Z","close_reason":"Shipped via PR #177 — daily download tracking + Chart.js dashboard","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-dn0","title":"Extend release pipeline to build and push an OCI container image","description":"The app release pipeline (.tekton/on-tag-push-release.yaml, fired on tag push) builds binaries via GoReleaser + cosign-signs + packs mcpb, but does NOT build or publish an OCI container image for forgejo-mcp itself. A multi-stage root Containerfile already exists and builds a working runtime image — it's just never built/pushed on release.\n\nScope:\n- On tag push, build the OCI image from the root Containerfile (binary already produced by 'make build').\n- Push by digest to a registry (Codeberg package/OCI registry under goern/forgejo-mcp, or quay — decide), tagged with the release version + a moving tag (e.g. latest).\n- Sign the image with cosign and attach an SBOM, matching the binary-release security posture.\n- REUSE the existing Tekton tasks already in-repo for the release-tools image: .tekton/release-tools/tasks/{build-image,push-image-by-digest,cosign-sign-image-by-digest,cosign-attach-sbom,promote-image-tag}.yaml — wire them into the app release pipeline rather than authoring new ones.\n- Document the published image (registry path, supported tags, cosign verify command) in README.\n\nOpen decisions: target registry + namespace; whether to build multi-arch (amd64/arm64); tag scheme (semver + latest); whether image publish gates on the same tag event as GoReleaser or a separate pipeline.\n\nWhy: ship a runnable container so users can 'podman run' the MCP server without building from source; aligns app distribution with the already-containerized release-tools image and the signed-binary posture.","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-31T14:45:07Z","created_by":"Christoph Görn","updated_at":"2026-06-01T06:49:21Z","started_at":"2026-06-01T06:29:55Z","closed_at":"2026-06-01T06:49:21Z","close_reason":"Implemented: tag-push release pipeline now builds, signs, SBOM-attaches and publishes the OCI image to codeberg.org/goern/forgejo-mcp by reusing the release-tools tasks. Commit bdfd968.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-fd6","title":"Label tools + label resource templates","description":"forgejo-mcp exposes list_repo_labels / list_org_labels / add_issue_labels / remove_issue_labels, but has NO label CRUD: cannot create, edit, or delete a repo/org label. Surfaced 2026-05-31 while creating the 'RFC - Request For Comments' label for #176 — had to fall back to raw curl against the Forgejo REST API because no MCP tool exists. (Reactions read was the same gap.)\n\nScope:\n- Tools: create_label, edit_label, delete_label for repo labels (POST/PATCH/DELETE /repos/{o}/{r}/labels[/{id}]); consider org-label equivalents (/orgs/{org}/labels).\n- Resource templates: forgejo://repo/{owner}/{repo}/label/{id} and/or a labels listing resource, so labels are URI-addressable like the existing issue/pr/commit resources. Follow operation/resource conventions (ParseXxx, Bounded, MapForgejoError) and docs/design/output-bounding.md.\n- Implement via forgejo-sdk where available, else pkg/forgejo raw-HTTP (DoJSON) like the wiki/attachment precedent.\n- Surface in README tool+resource tables and AGENTS.md.\n\nWhy: closes a real CRUD gap (label management currently impossible via MCP) and extends the resource-template surface to labels for discoverability.","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-31T14:40:12Z","created_by":"Christoph Görn","updated_at":"2026-06-02T06:35:37Z","started_at":"2026-06-02T06:33:08Z","closed_at":"2026-06-02T06:35:28Z","close_reason":"Created well-prepared Codeberg #190 (feat: label CRUD tools + label resource-templates), labeled Kind/Feature + Priority/Medium, assigned goern. Issue captures: repo-label CRUD via SDK v3 (CreateLabel/EditLabel/DeleteLabel/GetRepoLabel — already in pinned dep), org-label CRUD via pkg/forgejo raw-HTTP DoJSON (no SDK method, mirrors fetchOrgLabels), resource-templates forgejo://repo/{owner}/{repo}/labels + /label/{id} (singular repo, EmbeddedListCap+Bounded, output-bounding). Notes exclusive/is_archived out of scope (SDK v3 doesn't model). Ready to base OpenSpec change on; change NOT created per instruction.","external_ref":"codeberg-190","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-3ph","title":"OpenSpec: wiki tools via direct API + wiki page resource template","description":"Codeberg issue #32 (goern/forgejo-mcp). Author an OpenSpec change proposing wiki support implemented via direct Forgejo REST API calls (pkg/forgejo/rawhttp.go DoJSON helpers) rather than forgejo-sdk v3 (which has NO wiki methods — current operation/wiki/wiki.go behind //go:build wiki tag does not compile). Scope: 6 wiki tools (list/get/get_revisions/create/update/delete), a forgejo://repo/{owner}/{repo}/wiki/{pageName} resource template, output-bounding compliance, discovery surfacing (README+AGENTS.md), and a showboat demo. This bead covers authoring the spec only.","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-31T12:49:49Z","created_by":"Christoph Görn","updated_at":"2026-05-31T12:54:17Z","started_at":"2026-05-31T12:49:53Z","closed_at":"2026-05-31T12:54:17Z","close_reason":"OpenSpec change add-wiki-support authored, validated (--strict), pushed as PR #176; minutes on Codeberg #32. Implementation tracked by the spec tasks.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-pkz","title":"demos: mcp-resource-templates walkthrough for forgejo:// URIs","description":"PR #172 shipped 7 resource templates on the forgejo:// scheme (owner, repo, commit, commit-status, issue, comment, pr), but no entry in demos/ covers them. Other features in demos/ all have one-file-per-feature walkthroughs (see demos/README.md). This is the gap that aligns with the deferred OpenSpec task 1.11 (manual client verification).\n\nDeliverable: demos/mcp-resource-templates.md following the structure in demos/README.md:\n1. Background / what resource templates are and why (instance-portable forgejo:// URIs, additive to tools, JSON + markdown sidecar)\n2. Setup (export FORGEJO_URL, FORGEJO_ACCESS_TOKEN, make build)\n3. Walkthrough — one shell block per URI template (7 total) with REAL output captured against codeberg.org/goern/forgejo-mcp. Note: --cli does NOT support resources, so use stdio JSON-RPC: echo a resources/list or resources/read request, pipe to ./forgejo-mcp -t stdio -url $FORGEJO_URL -token $FORGEJO_ACCESS_TOKEN, parse with jq/python.\n4. End-to-end / autonomous agent workflow — how an MCP client uses templates instead of tools (e.g. fetch repo metadata + recent commits via templates, fall back to list_repo_commits for pagination).\n\nConstraints:\n- Must use real codeberg.org payloads, not fabricated.\n- Must show both JSON and markdown sidecar where applicable (commit/issue/pr/comment).\n- Must document the EmbeddedListCap=30 truncation sentinel + comments_list_tool escape hatch.\n- Keep payloads excerpted where huge (use jq/python to slice).\n- Follow demos/bounded-responses.md style for tone.\n\nRelated: PR #172 (forgejo-mcp-13x), follow-ups forgejo-mcp-7ra (subscribe) and forgejo-mcp-7de (cap telemetry). Closes part of deferred OpenSpec task 1.11.","notes":"PR #173 opened — https://codeberg.org/goern/forgejo-mcp/pulls/173. Branch: demo-resource-templates. Commit: 945b54b. Bead stays in_progress until PR merges. Bead closes at merge time per workflow-issue-pr-create-bead. Security: gitleaks clean, no token leaks, only commit SHAs in 40+ char matches.","status":"closed","priority":2,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-28T15:59:40Z","created_by":"Christoph Görn","updated_at":"2026-05-28T22:29:09Z","started_at":"2026-05-28T15:59:54Z","closed_at":"2026-05-28T22:29:09Z","close_reason":"Merged via PR #173 (commit 12613c1a). Demo file demos/mcp-resource-templates.md shipped on main. Gitleaks clean, CI green, op1st-gitops PaC pipelines all success.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-ylb","title":"Address all PR #172 code review findings (fix-pull_172)","description":"Umbrella bead tracking all 13 fix beads created from the automated code review on https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165. Closes when all child fix beads are closed. Two clusters dominate the findings: (1) truncation sentinel never fires because 4 SDK call sites pass empty options and Forgejo's default PageSize=30 == EmbeddedListCap; (2) parse errors in 4 sibling handlers wrap with fmt.Errorf instead of resource.MapForgejoError, losing -32602. Plus errors.go substring-classification, owner fallback, parse.go empty-segment handling, and a typo.","notes":"Children (13 beads):\n\nHigh-impact (P2, 5 beads):\n- forgejo-mcp-cmw — Fix double-wrapped ResourceError in resources_commit.go:51\n- forgejo-mcp-u3y — Pass PageSize \u003e EmbeddedListCap to ListIssueComments (issue/resources.go:93)\n- forgejo-mcp-ghr — Pass PageSize \u003e EmbeddedListCap to ListIssueComments (pull/resources.go:108)\n- forgejo-mcp-5dz — Pass PageSize \u003e EmbeddedListCap to ListPullReviews (pull/resources.go:111)\n- forgejo-mcp-827 — Pass PageSize \u003e EmbeddedListCap to ListStatuses (resources_status.go:73)\n\nMedium-impact (P3, 8 beads):\n- forgejo-mcp-vzz — Map parse error via MapForgejoError (resources_commit.go:39)\n- forgejo-mcp-s2g — Map parse error via MapForgejoError (resources_repo.go:61)\n- forgejo-mcp-g5s — Map parse error via MapForgejoError (resources_status.go:65)\n- forgejo-mcp-iqi — Map parse error via MapForgejoError (resources_owner.go:56)\n- forgejo-mcp-wgs — Replace substring-based HTTP classification (errors.go:26)\n- forgejo-mcp-91j — Fix user→org fallback masking + nil-userErr (resources_owner.go:96)\n- forgejo-mcp-16t — Reject empty/whitespace URI segments (parse.go:220)\n- forgejo-mcp-8ia — Fix CommmentsTruncated typo (pull/resources.go:79)","status":"closed","priority":2,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-28T13:48:49Z","created_by":"Christoph Görn","updated_at":"2026-05-28T14:18:53Z","closed_at":"2026-05-28T14:18:53Z","close_reason":"All 13 review findings fixed in commits 683404c..182898a. PR #172 review-fix chain complete.","dependencies":[{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-16t","type":"blocks","created_at":"2026-05-28T13:48:54Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-5dz","type":"blocks","created_at":"2026-05-28T13:48:53Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-827","type":"blocks","created_at":"2026-05-28T13:48:53Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-8ia","type":"blocks","created_at":"2026-05-28T13:48:54Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-91j","type":"blocks","created_at":"2026-05-28T13:48:53Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-cmw","type":"blocks","created_at":"2026-05-28T13:48:52Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-g5s","type":"blocks","created_at":"2026-05-28T13:48:53Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-ghr","type":"blocks","created_at":"2026-05-28T13:48:53Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-iqi","type":"blocks","created_at":"2026-05-28T13:48:53Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-s2g","type":"blocks","created_at":"2026-05-28T13:48:53Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-u3y","type":"blocks","created_at":"2026-05-28T13:48:52Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-vzz","type":"blocks","created_at":"2026-05-28T13:48:53Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-ylb","depends_on_id":"forgejo-mcp-wgs","type":"blocks","created_at":"2026-05-28T13:48:53Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":13,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-5dz","title":"Pass PageSize \u003e EmbeddedListCap to ListPullReviews in operation/pull/resources.go:111","description":"ListPullReviews with empty options — reviews capped at server default 30 = EmbeddedListCap so reviews_truncated/reviews_list_tool sentinel never fires. ReviewCount: len(reviews) also wrong (first-page count, not total). Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 92).","notes":"Fix: at operation/pull/resources.go:111, pass forgejo_sdk.ListPullReviewsOptions{ListOptions: forgejo_sdk.ListOptions{PageSize: resource.EmbeddedListCap + 1}}. For accurate ReviewCount when truncated, either omit the field when truncated or paginate fully (probably out of scope for v1; document the caveat).","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:46:42Z","created_by":"Christoph Görn","updated_at":"2026-05-28T14:18:53Z","started_at":"2026-05-28T14:17:15Z","closed_at":"2026-05-28T14:18:53Z","close_reason":"All 13 review findings fixed in commits 683404c..182898a. PR #172 review-fix chain complete.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-827","title":"Pass PageSize \u003e EmbeddedListCap to ListStatuses in operation/repo/resources_status.go:73","description":"ListStatuses with empty ListStatusesOption{} — server pages at default 30 = EmbeddedListCap so the \u003ecap truncation check never fires for SHAs with many status contexts. AGENTS.md output-bounding rule violated. Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 90).","notes":"Fix: at operation/repo/resources_status.go:73, pass forgejo_sdk.ListStatusesOption{ListOptions: forgejo_sdk.ListOptions{PageSize: resource.EmbeddedListCap + 1}}.","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:46:42Z","created_by":"Christoph Görn","updated_at":"2026-05-28T14:14:17Z","started_at":"2026-05-28T14:11:59Z","closed_at":"2026-05-28T14:14:17Z","close_reason":"Fixed in ee1217d. PageSize=cap+1; truncation sentinel surfaces correctly.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-cmw","title":"Fix double-wrapped ResourceError in operation/repo/resources_commit.go:51","description":"commitResourceHandler does 'return nil, fmt.Errorf(\"%w\", mappedErr)' where mappedErr is *resource.ResourceError. Downstream code using err.(*resource.ResourceError) gets (nil, false) — so -32603 internal error surfaces instead of the intended -32003/-32002 for commit URIs only. Every other handler returns the ResourceError directly. Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 92).","notes":"Fix: at operation/repo/resources_commit.go:50-51, replace\n mappedErr := resource.MapForgejoError(uri, fmt.Errorf(\"%d %s\", resp.StatusCode, err.Error()))\n return nil, fmt.Errorf(\"%w\", mappedErr)\nwith\n return nil, resource.MapForgejoError(uri, fmt.Errorf(\"%d %s\", resp.StatusCode, err.Error()))","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:46:42Z","created_by":"Christoph Görn","updated_at":"2026-05-28T13:57:03Z","started_at":"2026-05-28T13:55:39Z","closed_at":"2026-05-28T13:57:03Z","close_reason":"Fixed in f8d661e. ResourceError now returned directly; type-assertion surfaces correct JSON-RPC code.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-ghr","title":"Pass PageSize \u003e EmbeddedListCap to ListIssueComments in operation/pull/resources.go:108","description":"Same defect as issue handler — PR comments ListIssueComments uses empty options so server caps at default 30 = EmbeddedListCap, sentinel never fires. Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 92).","notes":"Fix: at operation/pull/resources.go:108, pass forgejo_sdk.ListIssueCommentOptions{ListOptions: forgejo_sdk.ListOptions{PageSize: resource.EmbeddedListCap + 1}}.","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:46:42Z","created_by":"Christoph Görn","updated_at":"2026-05-28T14:17:15Z","started_at":"2026-05-28T14:15:49Z","closed_at":"2026-05-28T14:17:15Z","close_reason":"Fixed in 9e5b930.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-u3y","title":"Pass PageSize \u003e EmbeddedListCap to ListIssueComments in operation/issue/resources.go:93","description":"ListIssueComments called with default ListIssueCommentOptions{}. Forgejo's default PageSize=30 == EmbeddedListCap, so the \u003ecap truncation check NEVER fires. Issues with \u003e30 comments silently lose the recent_comments_truncated/list_tool sentinel. AGENTS.md output-bounding rule violated. Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 92).","notes":"Fix: at operation/issue/resources.go:93, pass an explicit PageSize:\n comments, _, _ := client.ListIssueComments(params.Owner, params.Repo, params.Index,\n forgejo_sdk.ListIssueCommentOptions{ListOptions: forgejo_sdk.ListOptions{PageSize: resource.EmbeddedListCap + 1}})\nVerify via a new test that 31 mock comments produce truncated=true.","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:46:42Z","created_by":"Christoph Görn","updated_at":"2026-05-28T14:15:49Z","started_at":"2026-05-28T14:14:17Z","closed_at":"2026-05-28T14:15:49Z","close_reason":"Fixed in 321b1a0.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-13x","title":"Implement all 7 slices of mcp-resource-templates (resource framework + 7 entity resources + docs)","description":"Implement the first two slices of the mcp-resource-templates OpenSpec change merged via PR #148. Slice 1 (mcp-resources-core): server.WithResourceCapabilities(false,false), operation/resource/ package (parse, register, bound, errors helpers), RegisterCoreResources stub wired in operation/operation.go, plus unit tests. Slice 2 (mcp-resource-commit): operation/repository/resources_commit.go with RegisterCommitResource, forgejo://repo/{owner}/{repo}/commit/{sha} template, JSON + markdown sidecar handler, unit tests, wiring, README row. Verifier: go build ./... \u0026\u0026 go test ./... . Driven via team:dev-loop.","notes":"Originally scoped to slices 1+2. Team:dev-loop completed all 7 slices in one session. PR #172 opened: https://codeberg.org/goern/forgejo-mcp/pulls/172. Awaiting CI + review. Follow-ups: forgejo-mcp-7ra (subscribe=true), forgejo-mcp-7de (EmbeddedListCap).","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T12:15:54Z","created_by":"Christoph Görn","updated_at":"2026-05-28T15:49:26Z","started_at":"2026-05-28T12:15:58Z","closed_at":"2026-05-28T15:49:26Z","close_reason":"PR #172 merged to main (commit 872d4c5). 7 slices shipped. Follow-ups tracked in 7ra/7de. Manual client verification (task 1.11) remains post-merge work.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-1tc","title":"Fix openspec spec/release-tools-image format (missing Purpose+Requirements headers)","description":"The archived spec at openspec/specs/release-tools-image/spec.md (introduced in bd92d21) starts with '## ADDED Requirements' (the change-delta format), but openspec validate --strict requires top-level specs to have '## Purpose' and '## Requirements' headers. This breaks the Tekton openspec-validate gate on any PR that merges main, including PR #148. Fix: rewrite spec headers to conventional spec format. Land via PR #148 to unblock it.","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T12:02:16Z","created_by":"Christoph Görn","updated_at":"2026-05-28T12:03:06Z","started_at":"2026-05-28T12:02:19Z","closed_at":"2026-05-28T12:03:06Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-het","title":"Dashboard: focus mode highlights node + neighbours in subway map","description":"When user clicks an issue card in the registry, highlight that bead node plus its transitive dependencies and dependants in the dependency graph. Dim unrelated nodes/edges. Clicking the same card again clears focus.","acceptance_criteria":"Clicking an issue card highlights the matching subway-map station and its full upstream + downstream chain; unrelated stations and edges dim; clicking the focused card again or any non-station SVG area clears focus.","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-26T13:39:15Z","created_by":"Christoph Görn","updated_at":"2026-05-26T13:42:48Z","started_at":"2026-05-26T13:39:18Z","closed_at":"2026-05-26T13:42:48Z","close_reason":"focus-mode shipped in 8fc1e75 — card click dims unrelated dep-graph nodes, highlights full ancestor+descendant chain; SVG background click clears focus","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-3a9","title":"Dashboard: subway-map dependency graph","description":"Replace the flat text edge list in beads-dashboard.html with a layered SVG subway-map view of issue dependencies. Goals: visualise upstream→downstream chains, colour 'lines' per source issue, click station to jump to that issue card.","acceptance_criteria":"SVG renders all dep edges with no overlapping stations; click on a station selects and scrolls to the matching issue; nodes coloured by status (closed/in_progress/open); responsive layout (page still usable at 800px width).","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T23:08:05Z","created_by":"Christoph Görn","updated_at":"2026-05-25T23:10:21Z","started_at":"2026-05-25T23:08:09Z","closed_at":"2026-05-25T23:10:21Z","close_reason":"subway-map dep view shipped in beads-dashboard.html — layered SVG with orthogonal routing, status-coloured stations, click-to-jump.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-wqm","title":"Rewrite .tekton/tasks/ to use release-tools image (drop runtime installs)","description":"All 5 tasks in .tekton/tasks/ still install tools at runtime (microdnf, curl, go install, npx -y, npm install -g). With govulncheck and openspec now baked into the release-tools image, all runtime installs can be removed. Tasks to rewrite: goreleaser-release (syft+goreleaser go install), cosign-sign-release (microdnf jq+curl in upload step), mcpb-pack (npx -y mcpb + apt-get jq), go-ci (govulncheck go install), openspec-validate (npm install -g openspec). Each task should use RELEASE_TOOLS_IMAGE param defaulting to codeberg.org/operate-first/release-tools:latest. External PR: https://codeberg.org/goern/forgejo-mcp/pulls/157","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T21:21:01Z","created_by":"Christoph Görn","updated_at":"2026-05-25T21:24:08Z","started_at":"2026-05-25T21:21:04Z","closed_at":"2026-05-25T21:24:08Z","close_reason":"All 5 tasks rewritten in commit 0dcb2e1. No runtime installs remain. Minutes posted to PR #157.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-6t6","title":"Fix code review issues from PR #157 automated review","description":"Address all 11 inline review comments from the automated multi-agent review on PR #157 (release-tools image + Tekton pipelines). Comments span: (1) build-image IMAGE_DIGEST extraction broken, (2) syft-scan-image tries registry pull for unpushed image, (3) push-image-by-digest TOCTOU concern, (4) Containerfile floating base tag, (5) syft installer from main branch, (6) cosign no integrity verify, (7) npm install -g re-resolves transitive deps, (8-9) cosign-sign + cosign-attach-sbom unverified downloads, (10) SKIP_SIGN ungated, (11) mutable cosign.pub URL in README. External PR: https://codeberg.org/goern/forgejo-mcp/pulls/157","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T21:04:41Z","created_by":"Christoph Görn","updated_at":"2026-05-25T21:12:09Z","started_at":"2026-05-25T21:04:45Z","closed_at":"2026-05-25T21:12:09Z","close_reason":"All 11 review findings fixed in commit d59b910, pushed to feat/release-tools-pipelines, minutes posted to PR #157","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-46j","title":"Publish SLSA provenance attestation for release-tools image via Tekton Chains","description":"Origin: L5 from release-tools-image adversarial review. Tekton Chains is deployed in op1st-pipelines (per ADR docs/design/release-pipeline-migration.md and op1st-emea-b4mad manifests/applications/op1st-pipelines/tekton-chains.yaml) but the release-tools publish pipeline does not consume its in-toto SLSA v1.0 attestations. Cosign signature alone attests signer-holds-key, NOT build-provenance binding image digest → PipelineRun → git commit → builder identity. With key-split (L4) still pending, the provenance gap is exploitable. Fix: enable Chains annotations on the publish PipelineRun (chains.tekton.dev/transparency-upload: true), have Chains produce SLSA v1.0 provenance, attach as cosign attestation, document 'cosign verify-attestation --type slsaprovenance' in README.","notes":"PR #165 opened: https://codeberg.org/goern/forgejo-mcp/pulls/165. Changes: chains.tekton.dev/transparency-upload annotation, IMAGE_URL+IMAGE_DIGEST pipeline results, push-image-by-digest IMAGE_URL result, README verify-attestation section, ADR addendum.","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T13:52:26Z","created_by":"Christoph Görn","updated_at":"2026-05-26T13:09:04Z","started_at":"2026-05-26T13:04:36Z","closed_at":"2026-05-26T13:09:04Z","close_reason":"PR #165 merged — Tekton Chains SLSA provenance enabled for release-tools image","dependencies":[{"issue_id":"forgejo-mcp-46j","depends_on_id":"forgejo-mcp-1b4","type":"blocks","created_at":"2026-05-25T13:52:44Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-a2y","title":"Remove in-repo secrets/ + use op1st-emea-b4mad as normative source for cosign public key","description":"Delete secrets/cosign.pub, secrets/cosign-signing-key.enc.yaml, secrets/.gitkeep (and the dir). Cosign-signing-key public key normative source moves to https://codeberg.org/operate-first/op1st-emea-b4mad/raw/.../cosign-signing-key.pub, matching the Tekton release pipeline's signing key in op1st-pipelines namespace. Note: legacy releases signed via Forgejo Actions (Codeberg Actions COSIGN_PRIVATE_KEY) used a different keypair (now-deleted secrets/cosign.pub) — historical verification still possible via git history of commit 791ef6d.","acceptance_criteria":"secrets/ directory removed from main; .gitignore rules for secrets/ cleaned up; README Verifying Releases chapter points at op1st-emea-b4mad URL; ADR + runbook references updated; legacy-key note explains historical signature verification","notes":"PR opened: https://codeberg.org/goern/forgejo-mcp/pulls/152 (branch chore/remove-stale-secrets). Stale secrets/ + scripts/cosign-keygen.sh removed; README + ADR + runbook now point at op1st-emea-b4mad/.../cosign-signing-key.pub (commit 8a3c55e5).","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T11:33:54Z","created_by":"Christoph Görn","updated_at":"2026-05-25T11:38:24Z","started_at":"2026-05-25T11:34:01Z","closed_at":"2026-05-25T11:38:24Z","close_reason":"PR #152 merged. secrets/ + scripts/cosign-keygen.sh removed; README + ADR + runbook now point at op1st-emea-b4mad/.../cosign-signing-key.pub as normative source.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-n85","title":"Disable Forgejo Actions release workflow auto-trigger (soft cutover)","description":"Switch .forgejo/workflows/release.yml trigger from 'push tags v*' to 'workflow_dispatch' only. Stops auto-firing on tag push while preserving the file as a manual fallback if the op1st Tekton release pipeline (added in PR #150) fails. Full file deletion deferred to forgejo-mcp-gdz once 2 successful Tekton releases prove the cutover.","acceptance_criteria":".forgejo/workflows/release.yml on=workflow_dispatch only; ADR addendum noting soft-disable date; PR opened","notes":"PR opened: https://codeberg.org/goern/forgejo-mcp/pulls/151 (branch chore/disable-forgejo-release). Trigger switched to workflow_dispatch only; ADR moved to Accepted (soft-cutover phase). Close on merge.","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T11:29:02Z","created_by":"Christoph Görn","updated_at":"2026-05-25T11:31:15Z","started_at":"2026-05-25T11:29:06Z","closed_at":"2026-05-25T11:31:15Z","close_reason":"PR #151 merged. Trigger now workflow_dispatch only; Tekton sole auto-firing release path; Forgejo workflow preserved as manual fallback.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-d4b","title":"Migrate Forgejo release workflow to op1st Tekton pipeline","description":"Port .forgejo/workflows/release.yml to .tekton/ as a PipelinesAsCode release pipeline triggered on tag push v*. Cover all current features: GoReleaser w/ syft SBOMs, smoke-test of linux/amd64 binary, cosign sign-blob of checksums.txt + upload, .mcpb pack per platform (linux/darwin × amd64/arm64) + upload to Codeberg release. Run in parallel with existing Forgejo Actions release; cutover deferred. Add ADR + migration notes.","design":"PipelinesAsCode on-event=push with on-target-branch=refs/tags/v* (matches forgejo-mcp-33k cross-repo spike pattern only if PaC supports tag-push; falls back to tag-push directly). Three new tasks mirroring go-ci.yaml structure. Secrets: RELEASE_TOKEN, COSIGN_PRIVATE_KEY/PASSWORD assumed present in op1st-pipelines namespace. Existing release.yml stays untouched.","acceptance_criteria":"release pipeline yaml in .tekton/ triggered by tag push v*; reusable tasks for goreleaser, cosign-sign-blob, mcpb-pack defined under .tekton/tasks/; docs/design/release-pipeline-migration.md ADR explaining parallel-run + cutover criteria; PR opened on Codeberg","notes":"PR #150: https://codeberg.org/goern/forgejo-mcp/pulls/150. Secret validation done 2026-05-25: op1st-release-token + cosign-signing-key both confirmed in op1st-pipelines (shape + scope + cosign.pub match). Pipeline ready; next v* tag triggers parallel Tekton run. Close after 2 successful Tekton releases satisfy ADR cutover criteria.","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T09:10:22Z","created_by":"Christoph Görn","updated_at":"2026-05-25T11:28:00Z","started_at":"2026-05-25T09:10:26Z","closed_at":"2026-05-25T11:28:00Z","close_reason":"PR #150 merged (commit 6c824c9). All acceptance criteria met: .tekton release PipelineRun + 3 reusable Tasks + ADR + runbook + README verification chapter all in main. Parallel-run begins on next v* tag. Cutover decision tracked in forgejo-mcp-gdz.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-dhd","title":"ci: gitleaks allowlist for placeholder tokens in demo docs","description":"gitleaks 'generic-api-key' rule flags 'Authorization: token invalid_token' on demos/multi-tenant-http.md:109 (commit bd08d6147 on fork branch byteflavour/stateless-token, incoming PR). The token is intentional test data — request 4 in the multi-tenant HTTP demo shows what an invalid token does. Add a path+regex-scoped allowlist so demo docs can use placeholder tokens (invalid_token, changeme, etc.) without tripping the scanner, while real generic-api-key detection stays intact elsewhere.","acceptance_criteria":"gitleaks scan over demos/multi-tenant-http.md returns 0 leaks. Real secret patterns elsewhere in repo still flagged. Allowlist scope limited to demos/*.md.","notes":"PR opened: https://codeberg.org/goern/forgejo-mcp/pulls/147 (mergeable). Per-rule allowlist on curl-auth-header scoped to demos/*.md + placeholder regexes. Local gitleaks v8.30.1 negative test confirms real github-pat still flagged.","status":"closed","priority":2,"issue_type":"bug","owner":"goern@b4mad.net","created_at":"2026-05-25T07:21:45Z","created_by":"Christoph Görn","updated_at":"2026-05-25T07:46:29Z","closed_at":"2026-05-25T07:46:29Z","close_reason":"PR #147 merged 2026-05-25T09:45:33+02:00; worktree + local branch ci/gitleaks-allowlist-demos cleaned up","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-phn","title":"Set Codeberg Actions secrets COSIGN_PRIVATE_KEY and COSIGN_PASSWORD","description":"Mirror cosign signing material from SOPS-encrypted secrets/cosign-signing-key.enc.yaml into Codeberg Actions repo secrets so the release pipeline can sign artifacts. Source-of-truth stays in SOPS; this is one-way sync to CI.","notes":"Decrypt with sops, extract via yq, PUT to Forgejo API /repos/goern/forgejo-mcp/actions/secrets/{name}. Never write plaintext to disk.","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-24T11:09:58Z","created_by":"Christoph Görn","updated_at":"2026-05-24T11:11:01Z","started_at":"2026-05-24T11:10:08Z","closed_at":"2026-05-24T11:11:01Z","close_reason":"Both Codeberg Actions secrets created (HTTP 201). Verified via API list. Source-of-truth remains secrets/cosign-signing-key.enc.yaml (SOPS).","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-p1p","title":"ci: bump x/net + jsonparser to clear govulncheck advisories (run #151)","description":"Forgejo Actions ci.yml run #151 (https://codeberg.org/goern/forgejo-mcp/actions/runs/151) flagged govulncheck findings. Local scan (govulncheck v1.3.0) shows 7 findings: 0 reachable, 2 package-level (x/net/idna GO-2026-5026, buger/jsonparser GO-2026-4514), 5 module-level (x/net/html GO-2026-5025..5030). Default govulncheck exits 0 on non-reachable findings, so the CI failure may be from a stricter flag/version on the runner — fix in this PR clears them regardless. Bump x/net to v0.55.0 (clears 6), add direct require for buger/jsonparser v1.1.2 to override transitive (clears 1).","acceptance_criteria":"govulncheck ./... locally returns 0 findings at all tiers OR only retains findings not present in advisories. Next ci.yml run on a fresh PR passes the govulncheck step.","notes":"PR opened: https://codeberg.org/goern/forgejo-mcp/pulls/145 (mergeable). Local govulncheck verified clean at all tiers.","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-24T11:06:20Z","created_by":"Christoph Görn","updated_at":"2026-05-25T22:28:25Z","started_at":"2026-05-24T11:06:27Z","closed_at":"2026-05-25T22:28:25Z","close_reason":"PR #145 merged 2026-05-25 (612da9f). govulncheck ./... on main: no vulnerabilities. All 7 advisories cleared.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-1l5","title":"RFC: introduce MCP resource templates for core entities (owner, repo, commit, issue, pr, comment, status)","description":"## Why\n\nforgejo-mcp is currently tool-only. No MCP resources registered in operation/operation.go. Core Forgejo entities (owner, repo, commit, issue, pr, comment, status) are noun-like, addressable, and often immutable or stable — natural fit for MCP resource templates. Exposing them as resources unlocks:\n\n- URI-based references the LLM can auto-resolve (e.g. PR diff mentions a sha → fetch commit resource)\n- Cacheable, content-addressable lookup (commits especially)\n- Cleaner composition: a PR resource can link to commit + comment resources instead of forcing tool-call ceremony\n\nDoing this piecemeal (one entity at a time) creates an inconsistent server. A coherent design pass covering all seven entities at once avoids that.\n\n## What\n\nProduce an OpenSpec proposal that designs MCP resource templates for:\n\n- owner (user or org): `forgejo://owner/{name}`\n- repo: `forgejo://repo/{owner}/{repo}`\n- commit: `forgejo://repo/{owner}/{repo}/commit/{sha}`\n- issue: `forgejo://repo/{owner}/{repo}/issue/{index}`\n- pr: `forgejo://repo/{owner}/{repo}/pr/{index}`\n- comment: `forgejo://repo/{owner}/{repo}/{issue|pr}/{index}/comment/{id}`\n- status: `forgejo://repo/{owner}/{repo}/commit/{sha}/status` (combined) + `.../statuses` (list)\n\nURI scheme above is illustrative — proposal must justify final scheme.\n\n## Acceptance criteria\n\n- OpenSpec change proposal created via /openspec-propose covering all 7 entity templates\n- Proposal includes: URI scheme rationale, capability registration changes to operation/operation.go, handler pattern, MIME type per resource, relationship to existing tools (coexist or replace?), output bounding strategy (AGENTS.md docs/design/output-bounding.md), client compatibility matrix, migration/rollout plan\n- design.md addresses: listable vs template-only per entity, subscription semantics (do we support resource updates?), error handling for missing/private entities, auth scope\n- Specs cover behavior for each of the 7 entities\n- Tasks broken down per-entity so implementation can land incrementally even though design is unified\n\n## Out of scope\n\n- Implementation (this bead = design only)\n- Wiki/projects resources (blocked upstream per docs/plans/)\n- Webhook/event resources\n\n## Notes\n\nDriven by session discussion 2026-05-24 around replacing curl-based commit status fetches with proper MCP surface. Decision: design resources holistically rather than one-off per entity.","notes":"OpenSpec change created at openspec/changes/mcp-resource-templates/ on branch worktree-rfc-resource-templates. 4/4 artifacts pass strict validation (proposal, design, 8 spec files, tasks). 13 design decisions documented. 7-slice rollout plan in tasks.md. Ready for /opsx:apply to start implementation.","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-24T07:35:50Z","created_by":"Christoph Görn","updated_at":"2026-05-25T08:04:39Z","started_at":"2026-05-25T07:30:03Z","closed_at":"2026-05-25T08:04:39Z","close_reason":"OpenSpec proposal complete: proposal.md, design.md, 8 spec files, tasks.md all pass strict validation. Branch: worktree-rfc-resource-templates.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-e9i","title":"CI: investigate Forgejo Actions ci.yml failure on PR #143","description":"First run of .forgejo/workflows/ci.yml (run #147, SHA d711f32) failed at 3m43s. Merged anyway. No per-step detail available via Codeberg API. Need to: (1) open https://codeberg.org/goern/forgejo-mcp/actions/runs/147 in browser, identify which step failed; (2) fix root cause (likely candidates: golangci-lint-action@v6 incompatibility on Codeberg runner, cache mount permissions, missing toolchain, setup-go@v6 quirk); (3) verify on follow-up PR.","acceptance_criteria":"ci.yml run on a fresh PR completes with all steps green (lint warn-only acceptable). Document root cause in bd notes.","status":"closed","priority":2,"issue_type":"bug","owner":"goern@b4mad.net","created_at":"2026-05-24T07:35:45Z","created_by":"Christoph Görn","updated_at":"2026-05-26T09:18:37Z","closed_at":"2026-05-26T09:18:37Z","close_reason":"ci.yml deleted — Forgejo Actions CI superseded by Tekton PaC pipeline. Failure moot.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-51l","title":"CI: harden release pipeline (SBOM, cosign, smoke-test)","description":"release.yml ships .mcpb per platform but never verifies binary boots. Add: syft SBOM upload as release asset, cosign sign binaries+containers (keyless via OIDC if available, else key from secret), smoke-test ./forgejo-mcp --version per arch before .mcpb upload.","acceptance_criteria":"SBOM uploaded per release, signatures verifiable, smoke-test runs on linux/amd64 at minimum","notes":"PR opened: https://codeberg.org/goern/forgejo-mcp/pulls/144 (mergeable). Branch ci/step3-release-hardening. 3 commits:\n1. .goreleaser.yml: checksums + per-archive CycloneDX SBOMs via syft\n2. release.yml: syft + cosign install, smoke-test linux/amd64 binary, conditional cosign sign-blob on checksums.txt\n3. scripts/cosign-keygen.sh: SOPS-encrypted k8s Secret keypair generator (tmpfs + shred + no-echo password)\n\nSigning gated on COSIGN_PRIVATE_KEY + COSIGN_PASSWORD repo secrets — releases keep working until secret provisioned. Activation steps in PR body.\n\nLocal verification:\n- goreleaser check → 1 configuration file(s) validated\n- YAML lint → OK\n- bash -n on script → OK (no shellcheck available locally)\n\nUntested in PR (require tagged release): SBOM upload path, smoke-test on real built binary, cosign sign flow.","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-24T07:06:38Z","created_by":"Christoph Görn","updated_at":"2026-05-24T10:59:53Z","started_at":"2026-05-24T10:30:14Z","closed_at":"2026-05-24T10:59:53Z","close_reason":"Merged via PR #144 (commit b2c67f8). Activation pending: run scripts/cosign-keygen.sh, add COSIGN_PRIVATE_KEY + COSIGN_PASSWORD to Codeberg Actions secrets, then signing kicks in on next v* tag.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-9n2","title":"CI: add Forgejo Actions PR workflow with Go cache","description":"Tekton has no cross-run Go cache (PVC ephemeral). Add .forgejo/workflows/ci.yml mirroring go-ci gates on codeberg-small runner using actions/setup-go cache. Run parallel to Tekton 2 weeks, then decide canonical.","acceptance_criteria":"ci.yml runs on pull_request + push to main, uses setup-go cache, runs build/test/lint/race/govulncheck, completes \u003c5min on cache hit","notes":"PR opened: https://codeberg.org/goern/forgejo-mcp/pulls/143 (mergeable). Will close on merge. First Forgejo Actions run will be cold-cache; verify \u003c5min on second run.","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-24T07:06:34Z","created_by":"Christoph Görn","updated_at":"2026-05-24T07:35:56Z","started_at":"2026-05-24T07:25:05Z","closed_at":"2026-05-24T07:35:56Z","close_reason":"Merged via PR #143 (rebase, force_merge — run #147 failed, fix tracked in forgejo-mcp-e9i).","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-33k","title":"C5 spike: verify cross-repo workflow_call on Codeberg Forgejo v11.x","description":"Battle-test of forgejo-action-code-review deferred this spike. Spike scaffolding under openspec/changes/forgejo-action-code-review/spikes/c5-cross-repo-workflow-call/. Library + consumer repos already exist on Codeberg (goern/c5-spike-lib, goern/c5-spike-consumer). Remaining steps: (1) create tag v0.0.1 on c5-spike-lib main, (2) set repo secret SPIKE_SECRET on both repos, (3) push trigger commit to c5-spike-consumer main, (4) observe whether cross-repo uses: resolves, secret propagates, event context shape. Result drives design.md D9: keep Path B as recommended, or demote to experimental.","status":"open","priority":2,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-13T06:33:23Z","created_by":"Christoph Görn","updated_at":"2026-05-24T06:02:27Z","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-673","title":"Implement forgejo-action-code-review workflow","description":"OpenSpec change forgejo-action-code-review has spec deltas (8 capability requirements, PR specs/action-code-review/spec.md) but no implementation. The workflow file .forgejo/workflows/claude-code-review.yml does not exist. Need to ship the reusable Forgejo Actions workflow that runs Claude Code with forgejo-mcp on PR events, installs CC, registers forgejo-mcp as MCP server, runs /code-review skill in -p mode, and posts findings via create_pull_review. Depends on forgejo-code-review-skill (delivered). See openspec/changes/forgejo-action-code-review/ for proposal + specs.","status":"open","priority":2,"issue_type":"feature","owner":"goern@b4mad.net","created_at":"2026-05-12T13:37:41Z","created_by":"Christoph Görn","updated_at":"2026-05-12T13:37:41Z","dependencies":[{"issue_id":"forgejo-mcp-673","depends_on_id":"forgejo-mcp-33k","type":"blocks","created_at":"2026-05-13T06:33:31Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-fdx","title":"Migrate openspec validate from Forgejo Actions to op1st Tekton","description":"Pivot PR 132: drop .forgejo/workflows/openspec.yml, add Tekton PipelineRuns for openspec validate using op1st-pipelines (PaC). Path-gated via CEL on openspec/** and .tekton/*openspec* changes. Same trigger semantics: push to main + PR open/sync.","acceptance_criteria":"- .tekton/tasks/openspec-validate.yaml runs openspec@1.3.1 validate --all --strict --no-interactive\n- .tekton/on-pull-request-openspec.yaml + on-push-to-main-openspec.yaml gate on path changes via CEL\n- .forgejo/workflows/openspec.yml deleted\n- PR 132 retitled to reflect Tekton migration","status":"closed","priority":2,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-12T07:46:04Z","created_by":"Christoph Görn","updated_at":"2026-05-12T07:48:35Z","closed_at":"2026-05-12T07:48:35Z","close_reason":"Landed in PR 132 commit fbd1203 on feat/openspec-workflow. on-pull-request-openspec PipelineRun green (24s). Old .forgejo/workflows/openspec.yml deleted.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-43k","title":"Replace .forgejo/workflows/go.yml with op1st Tekton CI","description":"Codeberg Forgejo runners enforce strict job time limits. Move CI to op1st-pipelines (Pipelines-as-Code on OpenShift). Run go build + go test on every push to main and every PR change. Follow patterns from goern/epaper-service and feeldata/feeldata.app.","acceptance_criteria":"- .tekton/repository.yaml registers repo with op1st-pipelines\n- .tekton/on-push-to-main.yaml triggers go build + go test on push to main\n- .tekton/on-pull-request.yaml triggers go build + go test on PR open/sync\n- Custom go-ci task uses docker.io/library/golang:1.25\n- PaC secrets reuse codeberg-runner-openshift-pac + codeberg-org-op1st-pipelines\n- .forgejo/workflows/go.yml deleted","notes":"Tracked on Codeberg as goern/forgejo-mcp#133 (https://codeberg.org/goern/forgejo-mcp/issues/133). Implementation in commit ae35a30. Remaining: Repository CR apply in op1st-pipelines namespace (cluster-side, out-of-band).","status":"closed","priority":2,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-12T06:38:01Z","created_by":"Christoph Görn","updated_at":"2026-05-12T06:40:54Z","closed_at":"2026-05-12T06:39:55Z","close_reason":"Implemented in commit ae35a30. .tekton/ PaC config + go-ci task replace .forgejo/workflows/go.yml.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-zwr","title":"Complete add-bounded-text-responses change for Codeberg #124","description":"Pre-existing scaffold at openspec/changes/add-bounded-text-responses/ has only proposal.md. Codeberg issue #124 (\"Add paged or per-file diff\", reporter fiesh, Kind/Enhancement, Reviewed/Confirmed) is still open.\n\nProposal scope:\n- Add optional `file_path` param to get_pull_request_diff (per-file slicing on `diff --git` boundaries)\n- Add optional `start_line` + `end_line` to get_file_content (1-indexed inclusive line slice)\n- README updates for missing tool entries\n\nRemaining work:\n- Add design.md, specs/bounded-pr-diff/spec.md, specs/bounded-file-content/spec.md, tasks.md\n- Implement in operation/pull/pull.go + operation/repo/file.go\n- Optional pkg/diff/ helper for unified-diff splitting\n- Tests per proposal's Impact section\n\nCurrently fails `openspec validate --all --strict` with 'no deltas found', so it blocks forgejo-mcp-6jc (workflow).\n\nUpstream: https://codeberg.org/goern/forgejo-mcp/issues/124","status":"closed","priority":2,"issue_type":"feature","owner":"goern@b4mad.net","created_at":"2026-05-11T14:32:54Z","created_by":"Christoph Görn","updated_at":"2026-05-24T06:02:27Z","closed_at":"2026-05-11T14:58:24Z","close_reason":"Impl + tests landed in PR #131 (commit dda4ba1). New pkg/diff splitter; get_pull_request_diff gained file_path; get_file_content gained start_line/end_line with clamping. 11 new unit tests; full suite green. README tool table updated incl previously-missing entries.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-6jc","title":"Add Forgejo Actions workflow for openspec validate","description":"Add `.forgejo/workflows/openspec.yml` running `openspec validate --all --strict --no-interactive` on PRs touching `openspec/**` or the workflow file itself. Reference: https://codeberg.org/goern/epaper-service/src/branch/main/.forgejo/workflows/openspec.yml\n\nPinned version: `@fission-ai/openspec@1.3.1` (current local).\n\nBlocked by the 4 spec/change cleanup tasks (forgejo-mcp-6un, forgejo-mcp-a0p, forgejo-mcp-517, forgejo-mcp-cpb) — workflow strict would fail on day 1 otherwise.","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-11T14:18:58Z","created_by":"Christoph Görn","updated_at":"2026-05-11T15:04:35Z","started_at":"2026-05-11T15:03:34Z","closed_at":"2026-05-11T15:04:35Z","close_reason":"Landed in PR #132 (commit 16ca60f). Workflow runs openspec validate --all --strict on openspec/** and workflow file changes, modeled on epaper-service workflow. Pre-existing failures (4 specs/changes) were cleaned up first so gate is green from day one.","dependencies":[{"issue_id":"forgejo-mcp-6jc","depends_on_id":"forgejo-mcp-517","type":"blocks","created_at":"2026-05-11T14:19:03Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-6jc","depends_on_id":"forgejo-mcp-6un","type":"blocks","created_at":"2026-05-11T14:19:02Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-6jc","depends_on_id":"forgejo-mcp-a0p","type":"blocks","created_at":"2026-05-11T14:19:02Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-6jc","depends_on_id":"forgejo-mcp-cpb","type":"blocks","created_at":"2026-05-11T14:19:03Z","created_by":"Christoph Görn","metadata":"{}"},{"issue_id":"forgejo-mcp-6jc","depends_on_id":"forgejo-mcp-zwr","type":"blocks","created_at":"2026-05-11T14:33:02Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":5,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-cpb","title":"Fix openspec change: forgejo-action-code-review has no deltas","description":"openspec/changes/forgejo-action-code-review/ fails validation:\n\n```\n✗ [ERROR] file: Change must have at least one delta. No deltas found.\nEnsure your change has a specs/ directory with capability folders containing .md files\nthat use delta headers (## ADDED/MODIFIED/REMOVED/RENAMED Requirements) and that each\nrequirement includes at least one \"#### Scenario:\" block.\n```\n\nAdd a `specs/\u003ccapability\u003e/spec.md` with `## ADDED Requirements` deltas and scenarios reflecting the change's intent. Probably has design.md but no spec delta.","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-11T14:18:52Z","created_by":"Christoph Görn","updated_at":"2026-05-24T06:02:27Z","started_at":"2026-05-11T14:40:50Z","closed_at":"2026-05-11T14:42:00Z","close_reason":"Landed in commit a83a033. Added specs/action-code-review/spec.md with 8 capability requirements + scenarios. openspec validate forgejo-action-code-review --strict passes.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-517","title":"Fix openspec spec: pr-review-write missing Purpose/Requirements headers","description":"openspec/specs/pr-review-write/spec.md fails validation with the same missing-headers error as cli-mode and merge-pull-request. Add `## Purpose` and `## Requirements` sections.","status":"closed","priority":2,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-11T14:18:45Z","created_by":"Christoph Görn","updated_at":"2026-05-24T06:02:27Z","closed_at":"2026-05-11T14:30:43Z","close_reason":"Landed in commit c8a7883. Both specs now carry Purpose + Requirements headers; openspec validate --strict passes.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-a0p","title":"Fix openspec spec: merge-pull-request missing Purpose/Requirements headers","description":"openspec/specs/merge-pull-request/spec.md fails strict + non-strict validation with the same missing-headers error as cli-mode. Add `## Purpose` and `## Requirements` sections.","status":"closed","priority":2,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-11T14:18:41Z","created_by":"Christoph Görn","updated_at":"2026-05-24T06:02:27Z","closed_at":"2026-05-11T14:30:43Z","close_reason":"Landed in commit c8a7883. Both specs now carry Purpose + Requirements headers; openspec validate --strict passes.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-6un","title":"Fix openspec spec: cli-mode missing Purpose/Requirements headers","description":"openspec/specs/cli-mode/spec.md fails strict + non-strict validation:\n\n```\n✗ [ERROR] file: Spec must have a Purpose section.\nMissing required sections. Expected headers: \"## Purpose\" and \"## Requirements\"\n```\n\nAdd the two missing top-level section headers. Content already implies a purpose — promote it. Prerequisite for forgejo-mcp-NEW-workflow.","status":"closed","priority":2,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-11T14:18:36Z","created_by":"Christoph Görn","updated_at":"2026-05-24T06:02:27Z","closed_at":"2026-05-11T14:29:36Z","close_reason":"Landed in commit 23db899. cli-mode spec now has Purpose + Requirements headers; openspec validate cli-mode --strict passes.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-0ep","title":"Add MCP tools for Forgejo releases","description":"Codeberg issue #127: surface release operations (list, get, create, edit, delete, list assets) as MCP tools to help generate release notes and changelogs.\n\nUpstream: https://codeberg.org/goern/forgejo-mcp/issues/127","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-11T13:26:17Z","created_by":"Christoph Görn","updated_at":"2026-05-12T14:56:12Z","started_at":"2026-05-11T13:26:22Z","closed_at":"2026-05-12T14:56:12Z","close_reason":"PR #134 merged (https://codeberg.org/goern/forgejo-mcp/pulls/134); 14 tools live","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-efo","title":"Fix update_issue tool: assignee field ignored by Forgejo API","description":"The mcp__codeberg__update_issue tool exposes a singular 'assignee' parameter, but Forgejo's EditIssueOption ignores the deprecated singular field in current API versions and only honors the 'assignees' array.\n\nObserved in issue goern/forgejo-mcp#127: calling update_issue with assignee=goern returned HTTP 200 but a follow-up GET still shows assignees:null.\n\nWhat needs to be done:\n- Locate the update_issue handler in operation/issue/ (or wherever EditIssue is wired)\n- Change the SDK call to pass assignees=[]string{assignee} (or expose an 'assignees' parameter directly)\n- Keep the singular 'assignee' param for backward compat, but convert to array before SDK call\n- Add an integration test that asserts the assignee actually persists after update\n\nAcceptance:\n- update_issue with assignee=\u003cuser\u003e results in assignees containing that user on subsequent GET\n- Upstream tracking: codeberg.org/goern/forgejo-mcp#\u003cTBD\u003e","status":"closed","priority":2,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-11T13:24:23Z","created_by":"Christoph Görn","updated_at":"2026-05-11T13:29:56Z","started_at":"2026-05-11T13:25:58Z","closed_at":"2026-05-11T13:29:56Z","close_reason":"Fix landed in commit 6291213. Singular 'assignee' now wired to opt.Assignees=[]string{assignee}. New 'assignees' CSV param overrides. Unit tests in operation/issue/issue_test.go cover singular, CSV, clear, and omit cases. Upstream: codeberg.org/goern/forgejo-mcp#128.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-e0j","title":"docs(design): codify output-bounding rule from #124","description":"Issue #124 surfaced unbounded MCP tool outputs (diffs, files, pull-files lists) blowing up context windows. Codify the rule derived in triage as a design doc and reference it from AGENTS.md so every new tool considers output bounding by default. Three sub-rules: no silent truncation, bound by domain shape (line/per-file/page), always resumable.","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-10T14:09:42Z","created_by":"Christoph Görn","updated_at":"2026-05-10T14:12:04Z","started_at":"2026-05-10T14:09:45Z","closed_at":"2026-05-10T14:12:04Z","close_reason":"Landed in 1412cbe — docs/design/output-bounding.md + AGENTS.md checklist update.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-xv0","title":"OpenSpec change for org-label support in list_repo_labels","description":"Sub-task of forgejo-mcp-7ch. Author OpenSpec change covering:\n- New tool list_org_labels(org, page, limit)\n- Augmentation of list_repo_labels with include_org_labels bool (default true) and scope tag on each label\n- Use pkg/forgejo.DoJSONList against /orgs/{org}/labels (no SDK upgrade)\n- Test plan: httptest server fixtures for repo-only, org-only, merged, 404→empty\n\nOutput: artifacts under openspec/changes/\u003cchange-id\u003e/ following experimental workflow (proposal, design, tasks, deltas).","status":"closed","priority":2,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-09T20:38:32Z","created_by":"Christoph Görn","updated_at":"2026-05-24T06:02:27Z","closed_at":"2026-05-09T20:43:52Z","close_reason":"OpenSpec change add-org-label-support authored on branch issues/125","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-7ch","title":"list_repo_labels missing org-level labels (#125)","description":"Codeberg issue #125: list_repo_labels exposes only repo-scoped labels. Forgejo API also exposes /orgs/{org}/labels which SDK v3 does not bind. For org-owned repos, org labels are usable on issues but invisible to MCP — model cannot discover their IDs.\n\nImpl path:\n- Add new tool list_org_labels(org, page, limit) using pkg/forgejo.DoJSONList against /orgs/{org}/labels.\n- Augment list_repo_labels with bool include_org_labels (default true). When repo owner is org, merge org labels and tag each with scope=repo|org.\n- No SDK upgrade required — same pattern as attachments raw-HTTP path.\n- Tests via httptest server matching pkg/forgejo/*_test.go patterns.\n\nAcceptance:\n- list_repo_labels of an org-owned repo returns repo+org labels with scope tag.\n- list_org_labels callable standalone.\n- 404 from org endpoint maps to empty (no error).\n- include_org_labels=false suppresses merge.\n- Tests cover both tools.","acceptance_criteria":"list_repo_labels returns org labels when repo owner is org; new list_org_labels tool callable; tests cover both","notes":"Merged in PR #130 (squash, 2026-05-12). Closes Codeberg #125.","status":"closed","priority":2,"issue_type":"bug","owner":"goern@b4mad.net","created_at":"2026-05-09T20:38:27Z","created_by":"Christoph Görn","updated_at":"2026-05-12T08:41:22Z","closed_at":"2026-05-11T14:48:41Z","dependencies":[{"issue_id":"forgejo-mcp-7ch","depends_on_id":"forgejo-mcp-xv0","type":"blocks","created_at":"2026-05-09T20:38:35Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-9y4","title":"Wire .mcpb build into release pipeline","description":"PR #118 adds extension/ scaffolding for Claude Desktop Extension (.mcpb) but does NOT produce .mcpb on release. Maintainer must extend release.yml so users get downloadable .mcpb per release.\n\nRequired:\n1. Inject release tag into extension/manifest.json version field (currently hardcoded 2.20.0). Use jq before mcpb pack.\n2. Build per-platform .mcpb archives OR single .mcpb with server.mcp_config.platform_overrides bundling all 4 binaries (linux/darwin x amd64/arm64).\n3. Attach resulting .mcpb file(s) to Codeberg release alongside existing tar.gz archives.\n4. Optional: sign with npx @anthropic-ai/mcpb sign.\n\nWhy: PR #118 leaves this explicitly as follow-up. Without it, end users on releases page see only tar.gz binaries, no drag-and-drop install artifact. Extension story incomplete from end-user POV.\n\nHow to apply: extend .forgejo/workflows/release.yml with post-goreleaser job. Use dist/ artifacts produced by goreleaser as input. See PR #118 review for concrete shell snippet.","acceptance_criteria":"- Each tagged release on codeberg.org/goern/forgejo-mcp/releases includes .mcpb artifact(s)\n- manifest.json version matches release tag at pack time (no hardcoded version drift)\n- .mcpb installs cleanly in Claude Desktop on at least linux-amd64 and darwin-arm64\n- Smoke test (extension/test_smoke.py) runs in CI before pack","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-07T20:23:07Z","created_by":"Christoph Görn","updated_at":"2026-05-07T21:02:47Z","started_at":"2026-05-07T20:25:53Z","closed_at":"2026-05-07T21:02:47Z","close_reason":"Shipped in PR #122 (commit fdc6305): release.yml builds and attaches per-platform .mcpb (linux/darwin x amd64/arm64) with jq-based manifest version injection. Local make target added in commit 679d593.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-vsm","title":"E2E test script for attachment tools","description":"Shell script in test/e2e/attachments.sh that exercises ./forgejo-mcp --cli end-to-end against live Codeberg: create issue, upload attachment, list, get, verify browser_download_url, cleanup. Validates v2.19.0-alpha.1 attachment tools work in real deployment as referenced in issue #106.","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-04-27T06:54:05Z","created_by":"Christoph Görn","updated_at":"2026-04-27T06:55:37Z","started_at":"2026-04-27T06:54:10Z","closed_at":"2026-04-27T06:55:37Z","close_reason":"Script at test/e2e/attachments.sh, passes live against Codeberg, committed 8ec35e5.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-zhi","title":"Amend issue-attachments spec: lower inline cap to 1 MiB and always include download URL","description":"Follow-up to heathen711's feedback on https://codeberg.org/goern/forgejo-mcp/issues/106. After discussion (comments 13562510, 13701827, 13703888), the agreed scope is two narrow changes to docs/plans/issue-attachments.md: (1) lower MaxInlineDownloadBytes from 10 MiB to 1 MiB, (2) always include browser_download_url in download_*_attachment responses regardless of size. Files under the cap return base64-encoded bytes inline (current MCP-protocol-native behavior); files over the cap return metadata + URL only, and the LLM is expected to fall through to a curl/Bash fetch using its existing token. Earlier proposals — save_to_path parameter and inline:true flag — dropped per heathen711's reasoning: file-path returns introduce tmpfile hygiene + cross-container permission problems, which is exactly why MCP standardised on pipe-based binary delivery; size-cap discrimination already gives the metadata-vs-bytes split without an extra flag. Must land before forgejo-mcp-ydg implementation starts.","design":"Two-line behavioural change: const MaxInlineDownloadBytes = 1 * 1024 * 1024 (was 10 * 1024 * 1024); download_*_attachment response shape always carries browser_download_url alongside metadata, with bytes only if size \u003c cap. No new tool-surface parameters. Open Question #2 in the spec (private-repo auth on browser_download_url) becomes load-bearing — the fall-through-to-curl pattern only works if the URL accepts Authorization: token $TOKEN; verify in Part 1 of the implementation.","acceptance_criteria":"docs/plans/issue-attachments.md updated with save_to_path parameter, 1 MiB cap, always-include-download-url rule, and metadata-default behavior. Parameter matrix reflects the new column. Acceptance criteria section includes save_to_path round-trip test. heathen711 notified of the amendment on issue #106.","status":"closed","priority":2,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-04-24T14:14:05Z","created_by":"Christoph Görn","updated_at":"2026-05-24T06:02:27Z","started_at":"2026-04-26T10:45:34Z","closed_at":"2026-04-26T10:46:59Z","close_reason":"Spec amended in docs/plans/issue-attachments.md: cap lowered to 1 MiB, browser_download_url always included, Open Question #2 promoted to load-bearing Part-1 verification step, acceptance criteria updated to cover both under-cap and over-cap paths. Implementation issue forgejo-mcp-ydg is now unblocked.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-ya6","title":"Issue/PR time tracking: tracked-time + stopwatch MCP tools","description":"Adds 10 MCP tools wrapping forgejo-sdk/v3's tracked-time and stopwatch APIs. Covers list/add/reset/delete tracked-time entries on issues and PRs (which share index space in Forgejo), plus start/stop/cancel/list_my stopwatches. No raw-HTTP helper needed — SDK has full coverage. Spec: docs/plans/issue-time-tracking.md.","design":"SDK-wrapping approach (not raw HTTP): forgejo-sdk/v3 exposes AddTime/ListIssueTrackedTimes/ResetIssueTime/DeleteTime + StartIssueStopWatch/StopIssueStopWatch/DeleteIssueStopwatch/GetMyStopwatches. Verbs mirror API primitives (chose option B over 'set' convenience wrapper to avoid non-atomic reset+add race on shared state). Duration parsing via stdlib time.ParseDuration — no extra dep. Issue/PR unified: single tool set covers both because Forgejo shares index namespace.","acceptance_criteria":"All 10 tools registered and callable; add_issue_time accepts either 'seconds' (int) or 'duration' (string like '15m'); list_issue_tracked_times returns entries with id/time/user; reset clears all entries; delete removes one; stopwatch start→stop produces a tracked-time entry visible via list; cancel discards without creating an entry; make build + go test ./... pass; both demo files run cleanly.","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-04-21T20:38:06Z","created_by":"Christoph Görn","updated_at":"2026-04-21T20:48:54Z","started_at":"2026-04-21T20:42:04Z","closed_at":"2026-04-21T20:48:54Z","close_reason":"Implemented in commit (see git log); 10 MCP tools + tests + 2 showboat demos + README update.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-ydg","title":"Issue \u0026 comment attachments: full CRUD MCP tools","description":"Closes upstream Codeberg issue goern/forgejo-mcp#106: attachments on issues are invisible to the MCP because GET /issues/{index} does not embed them, and forgejo-sdk/v3 has zero issue-attachment methods. Spec: docs/plans/issue-attachments.md (amended per forgejo-mcp-zhi). Delivers 12 new tools (list/get/download/create/edit/delete × issue + comment), a raw-HTTP helper (pkg/forgejo/rawhttp.go), binary content return via mcp.BlobResourceContents with a 1 MiB inline cap, browser_download_url always included for over-cap fall-through, and two Showboat demos (demos/issue-attachments.md, demos/comment-attachments.md). Part 1 of implementation must verify private-repo auth on browser_download_url before Part 3 begins (load-bearing — see Open Question #2 in spec).","design":"Approach 2: raw HTTP inside forgejo-mcp (chosen over upstream-first and replace-directive hybrid). Rationale: attachment endpoints are stable Gitea/Forgejo routes, raw-HTTP surface is small and contained behind one helper package, shipping time beats SDK-consistency. Risk (field drift) mitigated by reusing forgejo_sdk.Attachment as DTO + demos as live-integration canaries.","acceptance_criteria":"All 12 tools registered and callable; list_issue_attachments on goern/forgejo-mcp#106 returns the uploaded PDF metadata; download_issue_attachment round-trips bytes sha256-identical; edit/delete round-trip works for both issues and comments; list on empty entity returns []; make build + go test ./... pass; both demo files run cleanly end-to-end.","status":"closed","priority":2,"issue_type":"feature","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-04-21T20:29:49Z","created_by":"Christoph Görn","updated_at":"2026-04-26T11:11:40Z","started_at":"2026-04-26T10:58:41Z","closed_at":"2026-04-26T11:11:40Z","close_reason":"Implemented in PR #109 (feature/issue-attachments). 12 tools, rawhttp helper, all tests green, live-verified against Codeberg API.","dependencies":[{"issue_id":"forgejo-mcp-ydg","depends_on_id":"forgejo-mcp-zhi","type":"blocks","created_at":"2026-04-24T14:14:10Z","created_by":"Christoph Görn","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-hc9","title":"chore: triage golangci-lint v2 backlog (207 findings)","description":"Updated local linters (staticcheck v0.4.6→v0.7.0/2026.1, golangci-lint 1.53.3→2.12.2) and migrated .golangci.yml to v2 config ('golangci-lint migrate'). Lint now runs again and surfaces pre-existing backlog:\n\n- 188 errorlint: fmt.Errorf with %v instead of %w for errors. Mechanical sweep BUT changes semantics — %w exposes wrapped errors to errors.Is/As in MCP clients/tests. Decide policy first (wrap everywhere vs keep %v + lint exclusion).\n- 14 staticcheck QF/ST hints: tagged switches, De Morgan, Fprintf-instead-of-WriteString, omit 'any' type. Pure style.\n- 2 govet inline: reflect.Ptr → reflect.Pointer (deprecated alias) in pkg/ptr/ptr.go.\n- 2 errcheck: fs.Parse (cmd/cmd.go:97, ExitOnError makes it moot — ignore or check), zap Logger.Sync deferred (conventional to ignore; add //nolint or _ =).\n\nS1039 (attachment.go:491) already fixed in tool-update commit.","status":"closed","priority":3,"issue_type":"chore","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-10T21:58:43Z","created_by":"Christoph Görn","updated_at":"2026-06-10T22:03:25Z","started_at":"2026-06-10T22:00:02Z","closed_at":"2026-06-10T22:03:25Z","close_reason":"Fixed entire lint backlog, not just errorlint. Method: 'golangci-lint run --fix' (auto-applied errorlint %v→%w in ~30 files, errors.Is for context.Canceled, staticcheck QF quickfixes, govet reflect.Ptr→reflect.Pointer, ST1023). Manual repairs after autofix: (1) missing 'errors' imports in cmd/cmd.go + 4 test files (goimports -w); (2) autofix BROKE 4 test assertions — dropped '\u0026\u0026 re.Code != X' from 'if re, ok := err.(*T); ok \u0026\u0026 re.Code != X' patterns, inverting test logic — restored as errors.As + explicit Code check, normalized 10 sites to 'var re *resource.ResourceError'; (3) 2 errcheck: '_ = fs.Parse' (ExitOnError) + deferred zap Sync wrapped; (4) 2 QF1001 De Morgan: hoisted hex checks into 'isHex' predicate (label.go normalizeColor, parse.go validateSHA). Final: golangci-lint 0 issues, staticcheck clean, vet ok, all tests pass. Policy: %w wrapping adopted — handler errors now expose wrapped SDK/HTTP errors to errors.Is/As.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-cv4","title":"fix: comment/review excerpts truncate at byte 200, can split UTF-8 rune","description":"operation/issue/resources.go:110-112 and operation/pull/resources.go:125-127,151-153 — excerpt[:200] slices bytes, not runes. Multibyte char straddling the boundary yields invalid UTF-8; json.Marshal replaces with U+FFFD.\n\nFix: truncate on rune boundary (e.g. convert through []rune or walk back with utf8.RuneStart).","status":"closed","priority":3,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-10T21:50:20Z","created_by":"Christoph Görn","updated_at":"2026-06-10T21:53:53Z","started_at":"2026-06-10T21:50:28Z","closed_at":"2026-06-10T21:53:53Z","close_reason":"Fixed: added resource.Excerpt(s, max) (operation/resource/excerpt.go) that truncates on rune boundary via utf8.RuneStart walk-back; replaced 3 byte-slice truncations in operation/issue/resources.go and operation/pull/resources.go. Unit tests added (excerpt_test.go) incl. multibyte-straddle case. Build/vet/tests pass.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-yea","title":"docs: stale/incorrect comments in pkg/forgejo/rawhttp.go and resource/parse.go","description":"1. pkg/forgejo/rawhttp.go DoJSON doc comment describes a 'boolean isList' parameter that does not exist (the 404-as-empty-list behavior lives in DoJSONList).\n2. operation/resource/parse.go validateSHA doc says 'exactly 40 lowercase hex characters' but the code (correctly) accepts uppercase A-F too; ParseCommit doc repeats the lowercase claim.\n\nFix doc comments to match behavior.","status":"closed","priority":3,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-06-10T21:50:20Z","created_by":"Christoph Görn","updated_at":"2026-06-10T21:53:54Z","started_at":"2026-06-10T21:50:28Z","closed_at":"2026-06-10T21:53:54Z","close_reason":"Fixed: DoJSON doc no longer references nonexistent isList param (points to DoJSONList); ParseCommit/validateSHA docs say '40 hex characters' instead of 'lowercase'. Comment-only change.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-aa6","title":"Migrate cosign attach sbom to cosign attest","description":"cosign-attach-sbom.yaml uses 'cosign attach sbom', which cosign deprecated (removal slated soon after 2024-02-22, see sigstore/cosign#2755) and which does NOT sign the SBOM. Migrate to 'cosign attest --predicate \u003csbom\u003e --type cyclonedx --key \u003ckey\u003e' so the SBOM is a signed attestation. Surfaced as a WARNING during v2.27.0-alpha.1 SBOM attach (2026-06-01).","status":"closed","priority":3,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-06-01T08:59:34Z","created_by":"Christoph Görn","updated_at":"2026-06-02T05:59:55Z","closed_at":"2026-06-02T05:59:55Z","close_reason":"Done in commit b2619fc. Migrated .tekton/release-tools/tasks/cosign-attach-sbom.yaml from deprecated 'cosign attach sbom' (unsigned) to 'cosign attest --predicate \u003csbom\u003e --type cyclonedx --key' (signed in-toto attestation, same key as image signing). README consumer block updated to verify-attestation. CI-pipeline task (used by on-tag-push-release.yaml attach-image-sbom). Governed spec update tracked in forgejo-mcp-3y1.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-hxv","title":"MCP tool get_forgejo_mcp_server_version may always report 'dev'","description":"operation/version/version.go reads pkg/flag.Version. cmd/cmd.go injects the build version into the user-agent and operation.Run, but verify whether pkg/flag.Version is ever assigned. If not, get_forgejo_mcp_server_version returns 'dev' even when the CLI version/--version command reports the real injected version (now fixed for containers via build-arg in PR feat/hummingbird-containers). Wire flag.Version from the injected main.Version if missing.","status":"open","priority":3,"issue_type":"bug","owner":"goern@b4mad.net","created_at":"2026-05-31T19:23:37Z","created_by":"Christoph Görn","updated_at":"2026-05-31T19:23:37Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-16t","title":"Reject empty/whitespace URI segments in operation/resource/parse.go:220","description":"splitPath silently collapses empty segments — forgejo://repo/foo//bar (double slash) and forgejo://repo/foo/bar/ (trailing slash) parse as the canonical forgejo://repo/foo/bar. PR promotes these URIs as content-addressable cache keys but multiple distinct URIs map to the same resource. URL-decoded whitespace-only segments (forgejo://repo/%20/%20/...) pass blank/whitespace owner/repo to the SDK, surfacing as 404 instead of -32602. Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 80).","notes":"Fix: at operation/resource/parse.go:220, change splitPath to either (a) reject empty/whitespace segments (return error to parseForgejoURI which already returns error), OR (b) document canonicalisation explicitly. Recommend (a) — strictness preserves URI identity for caching. Add parse_test.go cases: double slash, trailing slash, percent-encoded whitespace owner/repo.","status":"closed","priority":3,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:47:09Z","created_by":"Christoph Görn","updated_at":"2026-05-28T13:58:38Z","started_at":"2026-05-28T13:57:03Z","closed_at":"2026-05-28T13:58:38Z","close_reason":"Fixed in 55a39f4. parseForgejoURI rejects empty/whitespace segments; test cases added; full suite green.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-91j","title":"Fix user→org fallback masking real errors + nil-userErr edge case in operation/user/resources_owner.go:96","description":"Two failure modes: (a) when GetOrg fails with orgResp==nil (network/DNS/context-cancel), handler returns MapForgejoError(uri, userErr) — surfacing original 404 instead of the real transport error; (b) if userErr is nil (u==nil err==nil SDK edge), MapForgejoError(nil)=nil and handler returns (nil, nil), violating MCP semantics. Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 82).","notes":"Fix: at operation/user/resources_owner.go:90-97, restructure:\n if orgErr != nil {\n if orgResp != nil \u0026\u0026 orgResp.StatusCode == 404 {\n // both 404 — surface explicit not-found\n return nil, \u0026resource.ResourceError{URI: uri, Code: -32003, Message: \"owner not found: \" + req.Params.URI}\n }\n if orgResp != nil {\n return nil, resource.MapForgejoError(uri, fmt.Errorf(\"%d %s\", orgResp.StatusCode, orgErr.Error()))\n }\n return nil, resource.MapForgejoError(uri, orgErr) // prefer the real orgErr over original userErr\n }","status":"closed","priority":3,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:47:09Z","created_by":"Christoph Görn","updated_at":"2026-05-28T14:11:59Z","started_at":"2026-05-28T14:09:36Z","closed_at":"2026-05-28T14:11:59Z","close_reason":"Fixed in 19f1efd.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-g5s","title":"Map parse error via resource.MapForgejoError in operation/repo/resources_status.go:65","description":"Same parse-error inconsistency. Malformed status URIs (including short SHA) lose -32602. Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 88).","notes":"Fix: at operation/repo/resources_status.go:64-65, replace the fmt.Errorf wrap with resource.MapForgejoError(uri, err).","status":"closed","priority":3,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:47:09Z","created_by":"Christoph Görn","updated_at":"2026-05-28T14:03:29Z","started_at":"2026-05-28T14:02:12Z","closed_at":"2026-05-28T14:03:29Z","close_reason":"Fixed in 10c8403.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-iqi","title":"Map parse error via resource.MapForgejoError in operation/user/resources_owner.go:56","description":"Same parse-error inconsistency. Malformed owner URIs lose -32602. Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 88).","notes":"Fix: at operation/user/resources_owner.go:55-56, replace the fmt.Errorf wrap with resource.MapForgejoError(uri, err).","status":"closed","priority":3,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:47:09Z","created_by":"Christoph Görn","updated_at":"2026-05-28T14:05:07Z","started_at":"2026-05-28T14:03:29Z","closed_at":"2026-05-28T14:05:07Z","close_reason":"Fixed in 6cecf67.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-s2g","title":"Map parse error via resource.MapForgejoError in operation/repo/resources_repo.go:61","description":"Same parse-error inconsistency as commit handler. Malformed repo URIs lose -32602. Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 88).","notes":"Fix: at operation/repo/resources_repo.go:60-61, replace the fmt.Errorf wrap with resource.MapForgejoError(uri, err).","status":"closed","priority":3,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:47:09Z","created_by":"Christoph Görn","updated_at":"2026-05-28T14:02:11Z","started_at":"2026-05-28T14:00:47Z","closed_at":"2026-05-28T14:02:11Z","close_reason":"Fixed in 0c177af. Same pattern as vzz.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-wgs","title":"Replace substring-based HTTP classification in operation/resource/errors.go:26","description":"MapForgejoError classifies HTTP results by substring search on the formatted error string. Two failure modes: (1) URIs/error bodies legitimately containing '404' or 'Forbidden' get misclassified; (2) parser errors of shape 'invalid URI: expected forgejo://...' do NOT match any -32602 substring so wrong-shape URIs fall through to -32603 internal-error instead of -32602 invalid-params. Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 88).","notes":"Fix: change MapForgejoError signature to accept an HTTP status int (handlers already have resp.StatusCode at the call site) — e.g. MapForgejoError(uri string, status int, err error) — and dispatch on status, not substring. For parser errors, use a sentinel error type (var ErrInvalidParams = errors.New(\"invalid params\")) and errors.Is for the -32602 path. Update all 7 handler call sites.","status":"closed","priority":3,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:47:09Z","created_by":"Christoph Görn","updated_at":"2026-05-28T14:09:35Z","started_at":"2026-05-28T14:05:08Z","closed_at":"2026-05-28T14:09:35Z","close_reason":"Fixed in 1aa797a. ErrInvalidParams sentinel introduced; -32602 surfaces correctly.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-vzz","title":"Map parse error via resource.MapForgejoError in operation/repo/resources_commit.go:39","description":"Parse-error path uses fmt.Errorf instead of resource.MapForgejoError. Malformed commit URIs lose the -32602 invalid-params JSON-RPC code. Inconsistent with issue/pr handlers. Review: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 88).","notes":"Fix: at operation/repo/resources_commit.go:38-39, replace\n if err != nil {\n return nil, fmt.Errorf(\"invalid commit resource URI: %w\", err)\n }\nwith\n if err != nil {\n return nil, resource.MapForgejoError(uri, err)\n }","status":"closed","priority":3,"issue_type":"bug","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:47:08Z","created_by":"Christoph Görn","updated_at":"2026-05-28T14:00:47Z","started_at":"2026-05-28T13:58:38Z","closed_at":"2026-05-28T14:00:47Z","close_reason":"Fixed in 81d1945. Parse errors now mapped via MapForgejoError; type-assertion surfaces *ResourceError. -32602 elevation pending forgejo-mcp-wgs.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-8ia","title":"Fix CommmentsTruncated typo in operation/pull/resources.go:79","description":"Rename prResourcePayload.CommmentsTruncated (three m's) to CommentsTruncated. JSON tag comments_truncated keeps wire format. Cosmetic but easy to mis-reference. Review comment: https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165 (conf 95).","notes":"Fix: edit operation/pull/resources.go line 79 — replace 'CommmentsTruncated bool' with 'CommentsTruncated bool'. Also update the assignment site (search for CommmentsTruncated:). Run go build \u0026\u0026 go test ./operation/pull/...","status":"closed","priority":3,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-28T13:46:21Z","created_by":"Christoph Görn","updated_at":"2026-05-28T13:55:39Z","started_at":"2026-05-28T13:54:08Z","closed_at":"2026-05-28T13:55:39Z","close_reason":"Fixed in commit 683404c on PR #172 branch. Field renamed CommmentsTruncated → CommentsTruncated; JSON tag unchanged; tests pass.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-mzr","title":"Move beads-dashboard.html into .beads/ as dashboard.html","description":"Relocate the standalone dashboard from repo root into the .beads/ directory so the dashboard ships next to its data source. Update fetch path from '.beads/issues.jsonl' to 'issues.jsonl' (now sibling). No other consumers (CHANGELOG line is history).","acceptance_criteria":"File served at .beads/dashboard.html loads .beads/issues.jsonl successfully (HTTP 200, fetch resolves).","status":"closed","priority":3,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-26T13:44:56Z","created_by":"Christoph Görn","updated_at":"2026-05-26T13:45:33Z","started_at":"2026-05-26T13:45:01Z","closed_at":"2026-05-26T13:45:33Z","close_reason":"moved beads-dashboard.html → .beads/dashboard.html; fetch path updated to sibling issues.jsonl; HTTP 200 verified","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-gdz","title":"Decide Tekton release pipeline cutover after 2 successful runs","description":"Followup to forgejo-mcp-d4b. After 2 consecutive v* releases where the op1st Tekton pipeline succeeds end-to-end and produces assets matching the Forgejo Actions output, decide canonical release path per docs/design/release-pipeline-migration.md cutover criteria. If Tekton wins: open PR removing .forgejo/workflows/release.yml. If not: file follow-up bugs explaining why and revisit.","acceptance_criteria":"ADR addendum or new commit on docs/design/release-pipeline-migration.md recording the decision; redundant pipeline (.forgejo/workflows/release.yml OR the .tekton release pipeline) removed in a single PR","notes":"Validation state after first live run cycle:\n- v2.24.0: phantom tag, no Release on Codeberg (goreleaser exit 127)\n- v2.24.1: phantom tag, no Release on Codeberg (goreleaser dirty-tree)\n- v2.24.2: 13/14 assets on Codeberg, no .sig (cosign step distroless-no-shell). Counts as partial first Tekton release.\n\nCutover criteria require 2 consecutive end-to-end successes including .sig. v2.24.2 does not qualify. Next clean Tekton release must come AFTER forgejo-mcp-1b4 (release-tools image). Once that lands, need 2 clean releases before deleting .forgejo/workflows/release.yml. Until then: pipeline stays parallel-ready, Forgejo release.yml stays as workflow_dispatch fallback.","status":"closed","priority":3,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-25T11:27:33Z","created_by":"Christoph Görn","updated_at":"2026-05-26T09:30:22Z","closed_at":"2026-05-26T09:30:22Z","close_reason":"ADR addendum written in docs/design/release-pipeline-migration.md. Hard cutover executed after v2.25.1 (first clean end-to-end Tekton run). .forgejo/workflows/release.yml deleted commit 1777cca.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-02o","title":"Label Codeberg PR #145 via codeberg-label skill","description":"Test new codeberg-label skill end-to-end on https://codeberg.org/goern/forgejo-mcp/pulls/145. Sonnet subagent picks labels; main session applies via forgejo-mcp.","status":"closed","priority":3,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-25T07:23:23Z","created_by":"Christoph Görn","updated_at":"2026-05-25T07:24:59Z","started_at":"2026-05-25T07:23:30Z","closed_at":"2026-05-25T07:24:59Z","close_reason":"Labeled PR #145 with Kind/Security + Priority/Critical via codeberg-label skill; minutes posted.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-e8e","title":"CI: coverage report + pre-commit parity job","description":"Post coverage as PR comment (codecov-cli or go tool cover artifact). Add CI job that runs .pre-commit-config.yaml hooks so they're enforced beyond local dev.","status":"open","priority":3,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-24T07:06:47Z","created_by":"Christoph Görn","updated_at":"2026-05-24T07:06:47Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-zuh","title":"CI: container build sanity on PR + edge tag on main","description":"Containerfile builds only via Konflux currently. Add PR job that builds container image as sanity check (no push). On push to main, push :edge tag to registry.","status":"open","priority":3,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-24T07:06:45Z","created_by":"Christoph Görn","updated_at":"2026-05-24T07:06:45Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-1p1","title":"CI: add go-licenses + conventional commits PR title check","description":"Catch GPL contamination via go-licenses check. Gate Conventional Commits PR title earlier than .releaserc post-merge (use commitlint or equivalent action).","notes":"PR #166 opened: https://codeberg.org/goern/forgejo-mcp/pulls/166. Changes: go-licenses v1.6.0 in release-tools image + license-check step in go-ci (forbidden/restricted denied); new commit-title-check task validates PR title via PAC {{ body.pull_request.title }} AND all PR branch commits; on-pull-request pipeline wires it parallel to build-and-test.","status":"closed","priority":3,"issue_type":"task","assignee":"Christoph Görn","owner":"goern@b4mad.net","created_at":"2026-05-24T07:06:42Z","created_by":"Christoph Görn","updated_at":"2026-05-26T13:30:59Z","started_at":"2026-05-26T13:12:18Z","closed_at":"2026-05-26T13:30:59Z","close_reason":"PR #166 merged","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-td8","title":"CI: decide canonical PR gate (Tekton vs Forgejo Actions)","description":"After 2 weeks of parallel Forgejo Actions + Tekton PR gates, evaluate reliability/speed/contributor-visibility and pick one as canonical. Keep Tekton/Konflux only for signed container builds if Forgejo Actions wins.","acceptance_criteria":"ADR or design note in docs/design/ recording decision + rationale, redundant pipeline removed","status":"closed","priority":3,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-24T07:06:40Z","created_by":"Christoph Görn","updated_at":"2026-05-26T09:18:37Z","closed_at":"2026-05-26T09:18:37Z","close_reason":"Decision made: Tekton is canonical PR gate. Forgejo Actions workflows removed in commit 1777cca.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-p0y","title":"Cleanup C4 spike state on Codeberg","description":"Battle-test of forgejo-action-code-review created throwaway repos: goern/c4-spike-target and fork tinytalesshop/c4-spike-target. Both should be deleted once team confirms spike findings have been preserved in battle-test.md and design.md (already done). Also: PR #2 on goern/c4-spike-target is open; close it. Also: tag v0.0.1 not yet created on c5-spike-lib (and secrets not set on c5-spike-lib/c5-spike-consumer) — see related C5 spike issue. Delete all 3 c5 repos when C5 spike completes too.","status":"open","priority":3,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-13T06:33:26Z","created_by":"Christoph Görn","updated_at":"2026-05-13T06:33:26Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-7de","title":"Revisit EmbeddedListCap (currently 30) when resource usage telemetry is available","description":"Slice 1 of mcp-resource-templates set operation/resource.EmbeddedListCap = 30 per design.md D8. The cap was chosen by analogy to existing list_* tools, without telemetry. This follow-up tracks revisiting the constant once we have real usage data (issue/PR comment-count distribution, truncation hit rate). Likely outcomes: keep 30, raise to 50, or expose per-resource override.","status":"open","priority":4,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-28T13:18:35Z","created_by":"Christoph Görn","updated_at":"2026-05-28T13:18:35Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-7ra","title":"Revisit WithResourceCapabilities(subscribe=true) once a real subscription use case appears","description":"Slice 1 of mcp-resource-templates registered server.WithResourceCapabilities(false, false) per design.md D5 — read-on-demand only, no subscriptions. This follow-up tracks revisiting the subscribe=true path when a real consumer use case appears (e.g., dashboard pushing live updates). Out-of-scope for the initial 7-entity rollout; gating signal is concrete client demand, not telemetry.","status":"open","priority":4,"issue_type":"task","owner":"goern@b4mad.net","created_at":"2026-05-28T13:18:29Z","created_by":"Christoph Görn","updated_at":"2026-05-28T13:18:29Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"forgejo-mcp-7g9","title":"Refactor release-tools image into smaller purpose-specific images","description":"release-tools image has grown to include goreleaser, syft, cosign, go, node, npm, mcpb, jq, curl, govulncheck, and openspec. This is a monolithic image that does not follow SRP. Refactor into smaller purpose-specific images: e.g. build-release (goreleaser+syft+go), sign-release (cosign), pack-release (node+npm+mcpb), validate (openspec), scan (govulncheck+syft). Each image should be smaller, faster to pull, and easier to audit. Coordinate with the release-pipeline-use-release-tools-image change and the forgejo-mcp-gdz cutover criteria. Do not start until at least 2 successful releases using the monolithic image confirm operational correctness.","status":"open","priority":4,"issue_type":"feature","owner":"goern@b4mad.net","created_at":"2026-05-25T21:17:18Z","created_by":"Christoph Görn","updated_at":"2026-05-25T21:17:18Z","dependency_count":0,"dependent_count":0,"comment_count":0}