Skip to content

fix(setup): stop the drafted profile from being unsavable - #30

Merged
ralyodio merged 1 commit into
mainfrom
fix/profile-save-caps
Aug 14, 2026
Merged

ralyodio merged 1 commit into
mainfrom
fix/profile-save-caps

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

What was wrong

/setup read the site, drafted a profile, and then refused to save it: "that profile is incomplete".

Every list in workspaceProfileSchema capped an entry at 120 characters. That is the right length for a job title and the wrong length for a value proposition — the model writes those as sentences. Reproduced on production against profullstack.com, whose draft came back with one 132-character value proposition:

PUT /api/v1/onboarding/profile
400 {"error":{"code":"bad_request","message":"that profile is incomplete",
     "details":{"offering":["String must contain at most 120 character(s)"]}}}

It was a dead end, not an inconvenience: valuePropositions had no input on the form, so the offending line could not be shortened, and the error named offering — not which of its six fields, or which line of it.

What changed

  • The contract distinguishes terms from sentences. ICP facets and competitors stay at 120; value propositions, likely pains and exclusions get 300. Limits are exported as profileLimits so the drafter and the schema cannot drift.
  • The drafter clamps to those limits, cutting on a word boundary and marking the cut with …. A chatty model now yields a shorter draft rather than an unsavable one — a draft the contract refuses must not be reachable.
  • The rejection is actionable. Keyed by full path (offering.valuePropositions.3), shown next to the save button instead of off-screen by the URL box, and value propositions are editable like everything else that gets saved.

Verification

  • The exact production payload that returned 400 now validates against the schema.
  • New round-trip test: whatever POST returns must be acceptable to PUT untouched.
  • bun run check green — format, typecheck, 550 tests; apps/web typechecks clean.

🤖 Generated with Claude Code

Reading a site produced a profile the save then rejected as "that profile
is incomplete". The cause: every list in the profile contract capped an
entry at 120 characters, which is right for a job title and wrong for a
value proposition — the model writes those as sentences, and one line of
132 characters failed the whole PUT. There was no way out of it from the
page, because valuePropositions had no input on the form and the error
named no field.

Three changes so it cannot recur:

- The contract distinguishes terms (120) from sentences (300). ICP facets
  and competitors stay terms; value propositions, pains and exclusions are
  sentences. Limits are exported so there is one source of truth.
- The drafter clamps every field to those limits on a word boundary, so a
  chatty model produces a shorter draft rather than an unsavable one.
- The rejection is keyed by full path (`offering.valuePropositions.3`)
  instead of by top-level object, the web form shows it next to the save
  button rather than off-screen by the URL box, and value propositions are
  editable like everything else that gets saved.

Verified against the payload that failed on production: it now validates.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit a98722d into main Aug 14, 2026
4 checks passed
@ralyodio
ralyodio deleted the fix/profile-save-caps branch August 16, 2026 17:33
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