Skip to content

fix(solicitation-create): align with current labs reality + document ideal end-state (connect-labs#212)#405

Merged
jjackson merged 1 commit into
mainfrom
emdash/e2e-malaria-itn-app-k3rt6
May 22, 2026
Merged

fix(solicitation-create): align with current labs reality + document ideal end-state (connect-labs#212)#405
jjackson merged 1 commit into
mainfrom
emdash/e2e-malaria-itn-app-k3rt6

Conversation

@jjackson
Copy link
Copy Markdown
Owner

Summary

Companion to jjackson/connect-labs#212 (filed). Three labs-side gaps surfaced during the malaria-itn-app/20260521-1400 Phase 8 republish (solicitation 3140) need inline workarounds in this skill until #212 ships.

Cross-ref

Labs issue: jjackson/connect-labs#212 — "solicitation MCP: align proxy inputSchema with deployed validation; add framing + criterion.id as first-class." Four asks: (1) atom inputSchema vs server validation alignment, (2) questions[].framing as first-class structured field, (3) evaluation_criteria[].id documented as required (or auto-derived from name), (4) is_public: true solicitation detail pages truly unauthenticated.

What this PR changes

Step 6 — wire-shape fallback

Atom inputSchema declares {program_id, data: {...solicitation fields...}}. Deployed labs server expects fields flat at JSON-RPC params level and rejects the data envelope with unknown fields: ['data']. Documents both paths:

questions[].framing — inline-prefix convention

Server rejects a structured framing key. Until #212 lands, framing goes inline in text using the literal anchor Why we're asking: <framing>\\n\\n<actual-prompt>. The blank-line gap is load-bearing — solicitation-review parses the framing back out on this anchor. Documented in both the payload table (Step 2) and the question shape (Step 4).

evaluation_criteria[].id — required field

Server enforces id even though the atom inputSchema doesn't currently declare it. Added id as REQUIRED in the criterion shape with slugify(name) as the derivation fallback. Documented in the payload table (Step 2) and the criterion shape (Step 3).

Step 7a verifier — round-trip instead of curl-the-public-URL

The original Step 7a curl'd the public URL and grep'd for rendered sections. Labs now 302s the public-detail page to /labs/login/ even when is_public: true, so vanilla curl gets the login page. Rewritten to use get_solicitation round-trip as the structural verifier:

  • Read every persisted field via mcp__connect-labs__get_solicitation.
  • Assert title / description (≥80% length) / scope_of_work (string, ≥80% length) / dates / contact_email / is_public / status / connect_opportunity_id all round-trip.
  • Assert each question has id + text (with Why we're asking: anchor) + required + type.
  • Assert each criterion has id + name + weight + scoring_guide + linked_questions; sum(weights) == 100.

Any miss → [BLOCKER] naming the missing/mutated field + probable cause. Provides the same drift detection at the persistence layer instead of the rendered layer.

Removal plan when #212 ships

Change Log entry documents the rollback path: drop the inline workarounds, emit framing as a structured key, drop the wire-shape fallback paragraph, restore the curl-the-public-URL verifier as a second post-round-trip check (the original Step 7a, surfaced as the structural backstop for the rendered layer rather than just the persistence layer).

Test plan

  • Re-run /ace:step solicitation-create malaria-itn-app/20260521-1400 against the new SKILL.md; verify the round-trip verifier passes.
  • When connect-labs#212 ships, re-test: structured framing field round-trips; atom-as-documented call succeeds without flat-shape fallback; curl-the-public-URL verifier runs cleanly.

🤖 Generated with Claude Code

…ideal end-state (connect-labs#212)

Surfaced during the malaria-itn-app/20260521-1400 Phase 8 republish
(solicitation 3140). Three labs-side gaps required inline workarounds
in the skill until jjackson/connect-labs#212 ships:

(a) Wire-shape drift. Atom inputSchema declares {data: {...fields...}}
    but deployed labs server expects fields flat at JSON-RPC params
    level. Step 6 now documents both paths: try the MCP atom as
    documented first; if labs returns "unknown fields: ['data']",
    fallback to direct JSON-RPC POST with flat shape.

(b) questions[].framing rejected as unknown key. Adopted the literal
    'Why we're asking: <framing>\n\n<text>' inline anchor convention
    in the text field. Load-bearing for solicitation-review which
    parses the framing back out on this anchor.

(c) evaluation_criteria[].id required by server but undocumented in
    atom inputSchema. Added id as a required field on the criterion
    shape with slugify(name) as the derivation fallback.

Step 7a verifier rewritten from "curl the public URL" to
"get_solicitation round-trip" — the labs public-detail page now 302s
to /labs/login/ even when is_public: true (also tracked in #212), so
the curl-grep verifier can't run. The round-trip via
get_solicitation provides the same structural check at the
persistence layer.

When all four #212 items ship: drop the inline workarounds, emit
framing as a structured key, drop the wire-shape fallback paragraph,
restore the curl-the-public-URL verifier as a second post-round-trip
check.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@jjackson jjackson enabled auto-merge May 22, 2026 08:56
@jjackson jjackson merged commit d9c52a6 into main May 22, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant