Skip to content

Cursor bootstrap declares a planning harness; doctor and plan view read per-role bindings #414

Closed

Description

@DanielNetzer

Slice 2 of #388. Depends on slice 1 (the role-override proposal code).

Problem

  1. Bootstrap with a coding harness that can't do read-only ticket analysis (Cursor) saves and approves a Formula whose intake can never run. Seen with forgecell init --harness cursor in a fresh Forgecell home: the proposal holds only harness: {binding: cursor}, and run then blocks at intake with Cursor's analysis refusal.
  2. Doctor and init summary report GitHub Issue workflow: unsupported for a Lab whose Formula declares harnesses.analysis on a ready Claude Code or Codex. Candidate.WorkflowCapability (lab/internal/onboarding/binding.go) reads only the default harness, but that Lab's loop works end to end.
  3. The plan view prints Claude Code coding allowlist (approved with this plan; …) (lab/internal/cli/cli.go, the CodingAllowlist block) even when coding is bound to Codex or Cursor.

Change

  1. Bootstrap: when the chosen coding harness can't do analysis, the bootstrap proposal declares harnesses.analysis on the first ready analysis-capable harness, in the order claude-code, then codex. The proposal note says why and how to change it (slice 1's --harness ID --role analysis). If none is ready, refuse without saving a proposal, with the coding adapter's reason and the next step (install or sign in to Claude Code or Codex). The setup UI calls the same onboarding.Prepare, so it gets this too; UI wording is slice 3.
  2. Workflow capability: when the Formula declares harnesses.analysis, the GitHub Issue workflow capability comes from that role's binding, and coding readiness from the coding binding. Doctor JSON keeps its fields; only the computed state and reason change.
  3. Allowlist label: name the coding binding's harness. Where the allowlist doesn't apply to that harness, say so in one line instead of listing entries as if they were enforced. Check in lab/internal/harness which adapters actually apply CodingAllowlist before writing the wording.
  4. Docs: docs/install.md First run step 3.2 and the README say Cursor codes only, and that setup pairs it with Claude Code or Codex for planning.

Done when

  • Tests cover: the bootstrap proposal declaring analysis for Cursor (with Claude Code ready, and with only Codex ready); the refusal when neither is ready; no change for Claude Code or Codex bootstraps; doctor's workflow state for a Formula with an analysis override; and the allowlist line for each coding binding.
  • A fresh Lab set up with init --harness cursor and approved runs intake on the planning harness without hand edits.

Review checklist (read before coding)

The adversarial review checks these every time. Recent slices failed review on all of them, so build them in from the start:

  • Bounds: sizes, counts, time and total work are bounded, and hitting a bound fails safe (incomplete or truncated, never silently accepted).
  • Filesystem safety: paths cannot traverse. Use Lstat and O_NOFOLLOW, and check symlinks and ownership. Watch for TOCTOU races on shared dirs (/tmp). Only ever delete Forgecell-owned, marked paths.
  • Untrusted input: issue text, repository files, model and tool output, and ledgers can be malformed, huge or hostile. Validate them, never interpolate them into HTML or a shell, and never let them trigger retries or approvals.
  • No local leaks: no absolute local paths, environment variables or credentials in output, logs, the UI or ledgers.
  • Contract changes: a changed adapter invocation bumps the protocol, and approved digests still bind exactly what was shown.
  • Tests: deterministic. Use no wall-clock budgets (use readiness markers or seams), write nothing into the user's real temp or home, and cover the failure path as well as the happy path.

Plan checks (for intake)

Check category must be one of regression, candidate or setup. Use targeted package tests only as plain go test -timeout 20m commands (for example go test -timeout 20m ./internal/<pkg>/...; without -timeout, go test stops a package after 10 minutes, and cli and molecule exceed that on a loaded machine); the protected view adds -json itself when protected deltas are declared. The Formula baseline already runs the full suite once, so don't add another full go test ./... check, and don't repeat its go vet or gofmt checks. A plan may hold at most 16 checks in total, counting the 5 Formula baseline checks, so prefer one combined targeted command over one check per package.

  • Keep base tests compiling: the protected view runs the base _test.go files against your code. Never change the signature of an existing function, method or type that a base test file calls. Add a new function or field instead. A protected build failure can't be declared as an expected delta.
  • Keep base tests runnable: changed defaults or behaviour must not make a base test hang or panic. A package that aborts in the protected view hides every test after it, and nothing can be declared. Keep the old default when unconfigured and opt in to the new one.
  • Plan checks: the operator's visual or browser check is a manual step after delivery, never a plan check. Every check leaves reviewedAcceptance and independentProvenance empty.
  • Plan structure: new files need a parent component (in this repo, under lab/; a new root-level file blocks intake). A check's definitions must never include a file the change edits. A file the check only reads as data under test is not a definition.
  • Scope lists files, not directories: list every new file path, including each golden fixture under testdata/. A directory entry doesn't cover the files inside it, and the scope audit blocks them.

Activity

  1. DanielNetzer commented on Nov 8, 2026

    @DanielNetzer
    OwnerAuthor

    Merged as #417.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions