fluid-core/conformance/handover_test.go
tegwick 78454c59d8 Reframe the handover around composed posts, and plan the pr- pattern
The Telegram channel publishes posts written from hall entries, not the
entries themselves, so the handover's pressure, competition and
guardrails are rebuilt around that. Composition sits outside the
interface because Blueprint 48.1 forbids an LLM in the mandatory request
path, and because a post about a named person's work deserves a human
read that a request-path step would never get.

Adds FLUID-WP-0009 for the pr- campaign repository convention and for
reducing the Hall of Helix case from the thing this framework is for to
an example of using it. The prefix deliberately includes "propaganda":
a campaign repository that cannot name what it is doing will not govern
it well.

The workplan starts only after the loop has closed once on real traffic.
Extracting a seam before using it is how you learn you cut it in the
wrong place.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014KmVxhJ35tCo7rE7UnLwWu

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1116572@bnt-lap001
Assistant-Session: 8ba9bb93-a72a-4883-b189-2499cce5c400
2026-09-04 11:59:30 +02:00

51 lines
1.4 KiB
Go

package conformance
import (
"os"
"testing"
"github.com/tegwick/fluid-core/internal/validate"
)
// TestTelegramHandoverContractCompiles checks that the contract shipped in the
// fluid-telegram handover is one this gateway can actually enforce.
//
// A handover that shipped a contract the framework cannot parse would fail at
// the first publication, after the bot and channel had already been created.
// The check is skipped when the sibling repository is absent, so CI in a bare
// checkout still passes.
func TestTelegramHandoverContractCompiles(t *testing.T) {
const path = "../../fluid-telegram/contracts/r1.openapi.yaml"
raw, err := os.ReadFile(path)
if err != nil {
t.Skipf("fluid-telegram not checked out beside fluid-core: %v", err)
}
c, err := validate.ParseOpenAPI(raw)
if err != nil {
t.Fatalf("the handover contract does not compile: %v", err)
}
ops := c.Operations()
want := map[string]bool{
"GET /v1/channel-posts": false,
"POST /v1/channel-posts": false,
"GET /v1/channel-posts/{post_id}": false,
}
for _, op := range ops {
if _, tracked := want[op]; tracked {
want[op] = true
}
}
for op, found := range want {
if !found {
t.Errorf("the contract does not declare %s; it has %v", op, ops)
}
}
// The interface's complexity budget allows a maximum of 8 operations.
if len(ops) > 8 {
t.Errorf("the contract declares %d operations, over the intent's budget of 8", len(ops))
}
}