Skip to content

feat(config): hints — a first-class switch for next-step guidance - #58

Merged
justinhelmer merged 2 commits into
mainfrom
feat/hints-config
Aug 20, 2026
Merged

feat(config): hints — a first-class switch for next-step guidance#58
justinhelmer merged 2 commits into
mainfrom
feat/hints-config

Conversation

@justinhelmer

@justinhelmer justinhelmer commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

The feature

hints is a new boolean config capability naming a category of output this CLI already produces but had no switch for: next-step guidance for humans — the post-sign-in "Next steps" box, and future "connect any time later"-style nudges. It is defined by what it never touches: data (the stdout JSON contract), status lines ("✓ connected"), errors, prompts, and consent notices (the terms notice is legal text, not a hint).

How it works

Same model as telemetry: POLYLANE_HINTS env → hints in ~/.polylane/config.json → default on. Managed via polylane config set --key hints --value off and visible in config show. No CLI flag yet — a per-invocation need hasn't shown up, and env covers orchestrators. First consumers: the two nextSteps boxes in auth signup, whose suppression switches from the POLYLANE_ONBOARDING_RUN check (#57) to this key — an attribution channel shouldn't double as a UX switch, so the run id goes back to meaning attribution only.

The research

Best-in-class CLIs model this as a capability toggle, never caller identity:

  • git names the category advice.* (~40 keys suppressing exactly this class of hint, data/status untouched) — the naming precedent hints follows
  • Homebrew HOMEBREW_NO_ENV_HINTS; npm per-nag toggles (fund, update-notifier, audit); gcloud splits prompts from output (--quiet = never prompt, not less output); AWS CLI pager/auto-prompt as separate switches
  • CI=true is the ecosystem's "an orchestrator is driving" preset that flips several such toggles — presets compose out of capabilities, not the other way round

An orchestrator shouldn't declare who it is; it should declare what it wants: "no hints, keep status, keep prompts." Toggles with narrow semantics evolve independently; a documented "mode" freezes its bundle of behaviors forever.

How it will be used first

The install script owns the onboarding journey (connects, mapping, topology link), so it exports POLYLANE_HINTS=0 for its CLI invocations (polylanedotcom companion PR).

306/306 tests, typecheck + lint clean.

🤖 Generated with Claude Code

hints is git's advice.* category for this CLI: human guidance about
what to do next, distinct from data (stdout contract), status lines,
errors, prompts, and consent notices, which it never gates. Resolved
env (POLYLANE_HINTS) → config file → default on, same boolean model as
telemetry. First consumers: the post-sign-in next-steps boxes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM: Correct implementation of the hints capability — env/config precedence matches telemetry, underInstaller()/POLYLANE_ONBOARDING_RUN is cleanly split back to attribution-only with no orphaned references, and the two nextSteps() gates are the only call sites touched, consistent with the PR's stated scope.

Verified (procedure per REVIEW.md):

  • npm ci && npm run codegen && npm run typecheck && npm run lint && npm test all clean locally; 306/306 tests pass (matches the PR's claim). CI is green on Node 20.x/22.x/24.x (checks / Test & typecheck).
  • POLYLANE_HINTS env → hints key in ~/.polylane/config.json → default true, same precedence shape as telemetry (src/config/loader.ts:104-112).
  • underInstaller() is fully deleted. The only remaining uses of POLYLANE_ONBOARDING_RUN (src/auth/onboarding-run.ts, src/commands/auth/signup.ts:267,283) are the one-shot attribution ride-along on the signup POST body — never read as a boolean UX gate anywhere in the tree. Matches the PR's stated intent exactly.
  • Both new config.hints gates (src/commands/auth/signup.ts:217,303) wrap only the "Next steps" guidance box. The JSON data path (emitResult(...)) above and the outro(...) status line below each stay unconditional — no data/status/error/prompt output got swept in.

Nits (non-blocking):

  1. nextSteps()'s first line ("Signed in. Session valid until <expiresAt>") is status-shaped content living inside the now-suppressible box — a small drift from the PR's own "never gates status" framing. Not an actual data-loss regression: polylane auth status (src/commands/auth/status.ts:64-72) exposes the same expiry unconditionally regardless of hints. Still, worth hoisting that line above the if (config.hints) check (or dropping it, since auth status already covers it) in a follow-up.
  2. The new README line documents 0/false/off as disabling values for POLYLANE_HINTS, but parseEnvBoolean (src/config/loader.ts:40-43) only treats the exact lowercase strings '', '0', 'false', 'no' as false — off (and any uppercase variant) actually leaves hints enabled. This is copy-pasted from the pre-existing POLYLANE_TELEMETRY README line, which has the identical mismatch, so it's a consistent (if incorrect) existing pattern rather than a new bug — but worth fixing both together.
  3. skill/SKILL.md's "Configuration precedence" table (baked into src/generated/skill.ts at build time) still doesn't list POLYLANE_HINTS, unlike README.md which this PR updates. Minor doc-completeness gap for agents relying on the skill guide; doesn't affect runtime behavior and this diff doesn't touch build-related files so no build/smoke leg was required.

None of the above bear on the correctness of the core gating logic or the underInstaller() removal.


Generated by Claude Code

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-approved: Claude reviewed this PR and posted an LGTM verdict (see its review). A repo admin enabled this via the auto-approve workflow.


Generated by Claude Code

…eview

parseEnvBoolean accepts 'off' and any casing, matching what the README
documents for POLYLANE_TELEMETRY and POLYLANE_HINTS. nextSteps drops
its status-shaped expiry line (auth status owns that). SKILL.md gains
the POLYLANE_HINTS row.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@justinhelmer

Copy link
Copy Markdown
Contributor Author

All three nits taken:

  1. nextSteps() no longer opens with the status-shaped "Session valid until …" line — expiry belongs to auth status, which already prints it unconditionally.
  2. parseEnvBoolean now accepts off and any casing, so the README's documented disabling values (0/false/off) are actually true — for POLYLANE_TELEMETRY and POLYLANE_HINTS both, fixing the pre-existing mismatch in one place.
  3. skill/SKILL.md's configuration-precedence table gains the POLYLANE_HINTS row.

306/306 tests, typecheck + lint clean.

@justinhelmer
justinhelmer merged commit 4c69af4 into main Aug 20, 2026
3 checks passed
@justinhelmer
justinhelmer deleted the feat/hints-config branch August 20, 2026 17:43
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