Skip to content

idea-intake's acceptanceHints has no length cap, unlike the structurally identical constraints field #7243

Description

@JSONbored

Context

packages/loopover-engine/src/idea-intake.ts:12-14 states the module's own invariant:

Intake bounds — mirror the manifest text-slot handling (focus-manifest.ts): a renter's freeform text is length-capped so one submission can never dominate a public surface.

This is enforced for title (IDEA_TITLE_MAX_CHARS, line 15), body (IDEA_BODY_MAX_CHARS, line 16), and constraints (IDEA_CONSTRAINT_MAX_CHARS, line 18 — enforced at validateIdeaSubmission, line 102: else if (constraints.some((c) => c.length > IDEA_CONSTRAINT_MAX_CHARS)) errors.push("constraint_too_long");).

acceptanceHints (also a renter-supplied string[], same shape as constraints) has no equivalent cap. validateIdeaSubmission's check at lines 104-107 only validates that the field is an array of strings:

const acceptanceHints = input.acceptanceHints;
if (acceptanceHints !== undefined && (!Array.isArray(acceptanceHints) || !acceptanceHints.every((h) => typeof h === "string"))) {
  errors.push("acceptance_hints_invalid");
}

No per-entry length check exists — an individual hint of arbitrary length passes validation. acceptanceHints entries are later folded verbatim into AcceptanceCriterion.statement (see the fold at idea-intake.ts:206 and surrounding code), which becomes part of the public constituent-issue body a contributor reads. An unbounded hint can dominate or bloat that public surface exactly the way the module's stated invariant says it shouldn't be able to.

Note: this is distinct from the already-fixed #6766 (blank/whitespace-only hints being wrongly accepted as an objective signal) — that issue was about content quality (blank string), this one is about the missing length bound (arbitrarily long string), a different, still-open gap in the same validation block.

Requirements

  • Add a length cap for each acceptanceHints entry, analogous to IDEA_CONSTRAINT_MAX_CHARS for constraints. Reuse IDEA_CONSTRAINT_MAX_CHARS itself (both are short freeform renter strings of the same shape) rather than introducing a new unrelated constant, unless there's a documented reason acceptanceHints needs a different bound.
  • validateIdeaSubmission must push a new distinct error code (e.g. acceptance_hint_too_long) when any hint exceeds the cap, following the existing pattern where constraint_too_long is a separate code from constraints_invalid.
  • The check must run only when the array-of-strings shape check already passed (mirroring how constraint_too_long is only checked in the else if branch after the shape check), so a malformed input still surfaces the shape error, not a length error.

Deliverables

  • Length cap applied to each acceptanceHints entry in validateIdeaSubmission (packages/loopover-engine/src/idea-intake.ts)
  • New acceptance_hint_too_long error code returned in errors when violated
  • Regression tests: an acceptanceHints entry at exactly the cap passes; one character over the cap returns acceptance_hint_too_long; the existing "all errors collected in one pass" behavior (not short-circuited) still holds when combined with other invalid fields

Test Coverage Requirements

This repo's Codecov patch gate is 99%+ hard (branch-counted) on every changed line/branch in src/**/packages/**. Cover both the pass and fail boundary conditions listed above, plus the interaction with the array-shape check.

Expected Outcome

A renter can no longer submit an unbounded-length acceptanceHints entry — every renter-supplied freeform text field (title, body, constraints, acceptanceHints) is now length-capped, matching the module's own stated invariant.

Links & Resources

packages/loopover-engine/src/idea-intake.ts:12-18 (the stated invariant + existing constants), :100-107 (the validation block, showing constraints' enforcement vs. acceptanceHints' gap), :206 (where hints are folded into public acceptance-criteria statements). Related, not duplicate: #6766 (blank/whitespace hints, already fixed).

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions