Back to Prisma

Brief: S2-D1 — offer module and shared timeout helper

projects/agent-native/slices/generate-skill-offer/briefs/d1-r1.md

7.9.0-dev.172.9 KB
Original Source

Brief: S2-D1 — offer module and shared timeout helper

Task

On a new branch tml-2971-s2-one-time-skill-offer-on-prisma-generate created from the S1 branch head, implement the generate-time skills offer module per the S2 slice spec (projects/agent-native/slices/generate-skill-offer/spec.md in the main checkout — read it first; it is the contract), extract the timeout() helper from nps/survey.ts into packages/cli/src/utils/prompt-timeout.ts, and unit-test the module.

Scope

In: packages/cli/src/utils/skills/skills-offer.ts (new); packages/cli/src/utils/prompt-timeout.ts (new); packages/cli/src/utils/nps/survey.ts (import swap only); packages/cli/src/__tests__/skills-offer.vitest.ts (new).

Out: Generate.ts (dispatch 2); any other NPS change; live network or real PostHog in tests; the init path.

Completed when

  • handleSkillsOffer(): Promise<{ prompted: boolean }> implements the spec's gate order (acknowledgement file → already-installed detection with already-installed acknowledgement write → isInteractive → Deno guard → isCimaybeInGitHookisInNpmLifecycleHookisInContainerdaysSinceFirstCommand >= 1), the 30s prompt (default/timeout = No), the four-outcome skills-offer.json persistence in env-paths('prisma').config, the accept path via S1's installSkills with the non-fatal manual-command warning, and skills_offer_resolved telemetry through the existing PosthogEventCapture path only when prompted. The whole body never throws.
  • Injectability: dependencies (fs/env detection context, capture, runner, prompt IO) are injectable with real defaults, following the established injection-over-mocking pattern.
  • timeout() lives in prompt-timeout.ts with a doc comment; survey.ts imports it; NPS tests still green.
  • Unit tests: each gate short-circuits (incl. already-installed writing its acknowledgement); timeout resolves No and persists timeout; decline persists declined; accept invokes the injected runner and persists accepted; telemetry fires only when prompted; a thrown injected dependency does not propagate.
  • Gates: packages/cli pnpm run tsc; pnpm exec vitest run src/__tests__/skills-offer.vitest.ts src/__tests__/nps.test.ts — note nps.test.ts is Jest, not vitest; run it via the package's Jest runner instead and record the command.

Standing instruction

Stay focused on the goal; control scope. Trivial-and-related fixes with a one-line note; drift halts and surfaces.

Operational metadata

  • Model tier: orchestrator-inherit (resumed persistent implementer).
  • Time-box: 45 minutes.
  • Halt conditions: the NPS helpers turn out not to be importable without dragging in survey side effects (surface, don't restructure NPS); out-of-scope surface required; any spec assumption observed false (I12).