docs/plans/agent-native/002-generate-skill-offer.md
prisma generateOffer existing projects (which never ran the new prisma init) a one-time, interactive,
time-limited prompt to install the Prisma skills, shown after a successful prisma generate.
Reuses the NPS survey infrastructure wholesale: same gating, same timeout pattern, same
persistence location.
packages/cli/src/utils/nps/survey.ts (handleNpsSurvey), triggered only from
packages/cli/src/Generate.ts after a successful non-watch generate, unless --no-hints:
isInteractive() from packages/internals/src/utils/isInteractive.ts
(stdin.isTTY && TERM !== 'dumb'), plus a Deno guard.isCi(), maybeInGitHook(), isInNpmLifecycleHook(),
isInContainer() (all in packages/internals/src/utils/), and
daysSinceFirstCommand(...) >= 1 via packages/cli/src/utils/commandState.ts.promptTimeoutSecs = 30; a timeout() helper races the readline answer against
a timer resolving undefined (survey.ts:199-210).env-paths('prisma').config (e.g.
~/.config/prisma-nodejs/ on Linux): nps.json (acknowledgement) and commands.json
(first-command timestamp).PosthogEventCapture (packages/cli/src/utils/nps/capture.ts).packages/cli/src/utils/skills/skills-offer.ts exposing
handleSkillsOffer(): Promise<void>, mirroring handleNpsSurvey's shape (injectable into
Generate for tests, like the existing surveyHandler constructor parameter).skills-offer.json in the config dir.skills-lock.json and no .claude/skills/prisma-* or
.agents/skills/prisma-* in the project.isInteractive(), not Deno, !isCi(), !maybeInGitHook(), !isInNpmLifecycleHook(),
!isInContainer(), daysSinceFirstCommand(...) >= 1.timeout() helper
(extract it from survey.ts into a shared util rather than duplicating). Default and
timeout answer is No.skills-offer.json ({ offeredAt, accepted }) in the same config dir,
unconditionally after the prompt resolves — the offer fires once ever per machine,
unlike the NPS survey's once-per-timeframe.skills_offer_shown / skills_offer_accepted via the existing
PosthogEventCapture path (decide project key during review).packages/cli/src/utils/skills/skills-offer.ts (new) — gating, prompt, persistence.packages/cli/src/utils/nps/survey.ts — extract the timeout() helper (and possibly the
readline safety proxy) into a shared module under packages/cli/src/utils/.packages/cli/src/Generate.ts — invoke the offer next to handleNpsSurvey (same
--no-hints / watch-mode / generator-error guards), with the one-prompt-per-run rule.packages/cli/src/__tests__/ — tests mirroring nps.test.ts: each gate, timeout path,
accept path (runner mocked), persistence write, NPS mutual exclusion.survey.ts.skills-offer.ts with the gates and persistence above.Generate.ts with the mutual-exclusion rule.--no-hints and watch mode fully suppress the offer.prisma dev should also be an offer surface later (out of scope here).