Second debate round (convergence) hardened the C-series fixes: - C2: limit+1 over-fetch is unsound at the server page-size ceiling — send limit+1 explicit, compute has_next from effective rows, pin limit<=ceiling-1 (task 5.3 extended) - C5: encoded-slash sub-page round-trip is server-dependent (proxies/AllowEncodedSlashes may reject %2F) — documented fallback to get_wiki_page tool (new task 5.7); ParseWiki MUST read EscapedPath, never splitPath(u.Path); test asserts RawPath populated - C7/C3: parenthetical pinning that resource degrade-to-empty (page-GET-first) does not collide with the revisions tool's 404-is-missing-page - 2xx-vs-204 delete drift: lifted demo.md + proposal.md to '2xx (204 canonical)' to match spec/tasks - C6 doc-policy task 4.6: extend output-bounding.md to resource content blocks openspec validate --strict passes. Refs: #32
6 KiB
Why
Codeberg issue #32 asks for wiki
support. The repository already ships operation/wiki/wiki.go, but it is dead code:
it sits behind a //go:build wiki tag and calls client.ListWikiPages,
client.CreateWikiPage, client.EditWikiPage, CreateWikiPageOption, and
EditWikiPageOption — none of which exist in forgejo-sdk/forgejo/v3 (verified:
the SDK has no wiki*.go and defines no wiki types or methods). The build tag exists
solely to stop the broken file from breaking make build. That is why the issue
carries Status/Blocked.
The prior plan (docs/plans/wiki-support.md) proposed unblocking by contributing wiki
methods upstream to forgejo-sdk first — a 1–2 week external dependency on someone
else's review cycle. We can unblock today instead: pkg/forgejo/rawhttp.go already
provides DoJSON / DoJSONList helpers (built for issue attachments when the SDK fell
short) that hit the Forgejo REST API directly with the same auth, user-agent, and
error-mapping the SDK path uses. Wiki is the identical situation, so we use the same
escape hatch. No upstream dependency, no new external module.
The Forgejo/Gitea wiki API is stable and documented. Implementing against it directly
gives us all six wiki operations now, plus a forgejo:// resource template so humans
and agents can reference a wiki page by URI without an explicit tool call.
What Changes
- Replace the broken SDK-based wiki package with a direct-API implementation. Remove
the
//go:build wikitag fromoperation/wiki/wiki.go; reimplement all handlers on top offorgejo.DoJSON/forgejo.DoJSONList(raw REST), dropping theforgejo-sdkwiki imports entirely. Register the package fromoperation/operation.go(it is currently never wired in). - Ship six wiki tools (the create/update tools already exist in name; this change
makes them compile and adds three read tools + delete):
Tool Method + endpoint Notes list_wiki_pagesGET /repos/{o}/{r}/wiki/pagesBounded: page+limit,has_nextget_wiki_pageGET /repos/{o}/{r}/wiki/page/{pageName}base64-decoded content; start_line/end_linebound +total_linesget_wiki_revisionsGET /repos/{o}/{r}/wiki/revisions/{pageName}Bounded: page+limitcreate_wiki_pagePOST /repos/{o}/{r}/wiki/newbase64-encodes content update_wiki_pagePATCH /repos/{o}/{r}/wiki/page/{pageName}base64-encodes content delete_wiki_pageDELETE /repos/{o}/{r}/wiki/page/{pageName}2xx → success (204 canonical) - Add a wiki-page resource template
forgejo://repo/{owner}/{repo}/wiki/{pageName}returning page metadata + atext/markdowncontent sidecar (decoded) + a boundedrecent_revisionsarray (cap 30, sentinel namesget_wiki_revisions). This lets a page name dropped in chat resolve to its content with no tool call, consistent with the existing issue/pr/commit resources. - Honor the output-bounding contract (
docs/design/output-bounding.md) on every new tool:list_wiki_pagesandget_wiki_revisionsusepage/limitpaging;get_wiki_pagecontent is data-proportional so it reuses thestart_line/end_lineline-range vocabulary fromget_file_contentand returnstotal_linesfor resumability. - Make the feature discoverable to humans and agents (explicit issue requirement):
a new Wiki section in the README tool table, a wiki row in the README Resources
table, a Wiki note in
AGENTS.md, rich per-tool/per-parameter descriptions, and an update todocs/plans/wiki-support.mdrecording that the SDK-contribution path is superseded by direct API calls. The change also removes theStatus/Blockedlabel from issue #32 on archive. - Ship a showboat demo (explicit issue requirement): a copy-pasteable end-to-end
script (
demo.md) that creates a page, lists pages, reads it through both the tool and theforgejo://…/wiki/…resource URI, edits it, and shows the revision history — proving the full surface and the agent-discovery story in one run.
Capabilities
New Capabilities
wiki-tools: Six MCP tools for Forgejo wiki page CRUD + revision history, implemented via direct REST calls, each output-bounded perdocs/design/output-bounding.md.mcp-resource-wiki:forgejo://repo/{owner}/{repo}/wiki/{pageName}resource template — single wiki page content + metadata + bounded recent revisions.
Modified Capabilities
Impact
- Affected code:
operation/wiki/wiki.go(rewrite, drop build tag), newoperation/wiki/resources.go(resource template),operation/resource/parse.go(ParseWiki+WikiParams),operation/operation.go(wireRegisterWikiToolandRegisterWikiResource),pkg/forgejo(a smallWiki*helper layer or inlineDoJSONcalls),operation/params/(wiki param descriptions already exist; addpage/limit/line-range reuse). - No new external dependencies. Uses the existing raw-HTTP helper and
mcp-go. - No breaking changes. Additive surface; clients without resource-template support use the new tools.
- Documentation: README (tools + resources),
AGENTS.md,docs/plans/wiki-support.md, CHANGELOG, and thedemo.mdshowboat script. - Load-bearing risk: the base64 (
content_base64) field name and the page-name URL encoding (spaces → dashes) are asserted from the documented Gitea/Forgejo API and must be confirmed against a live instance — captured as an explicit verification task, not assumed. - Out of scope: a wiki index resource (
forgejo://repo/{o}/{r}/wikilisting all pages — enumeration stays the job oflist_wiki_pages, matching the established "resources fetch single entities, tools enumerate" rule); wiki attachments; rendered HTML (we return raw markdown).