From harness-claude
Configures time-windowed product pulse in harness.config.json via first-run interview: seeds from STRATEGY.md, defines SMART metrics/events, wires analytics (PostHog/Amplitude), tracing (Sentry/Datadog), payments (Stripe). Defers runtime.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Single-page time-windowed product pulse. **Phase 3 ships the first-run interview only**: it converts vague intent into a concrete `pulse:` block in `harness.config.json`, refuses read-write DB credentials, and seeds from `STRATEGY.md` when present. The actual `harness pulse run` (Phases 2-4 of the runtime) is deferred to spec Phase 4.
Sets up PostHog metrics tracking plans for iOS/web projects with event funnels, KPI benchmarks, North Star metrics, and kill/iterate/scale decision rules.
Produces complete metrics specs for product areas: names, formulas, data sources, segmentation, SQL/event tracking, thresholds. Use for KPI definition or feature instrumentation.
Implements PostHog analytics for event tracking, user identification, feature flags, and dashboards in Next.js and React apps. Use when adding product analytics.
Share bugs, ideas, or general feedback.
Single-page time-windowed product pulse. Phase 3 ships the first-run interview only: it converts vague intent into a concrete
pulse:block inharness.config.json, refuses read-write DB credentials, and seeds fromSTRATEGY.mdwhen present. The actualharness pulse run(Phases 2-4 of the runtime) is deferred to spec Phase 4.
harness.config.json has no pulse: block and the user invokes /harness:pulseharness-strategy first to write STRATEGY.md; pulse seeds from it)No PII reaches harness.config.json and no read-write DB credential is accepted. Both are interview-time gates; both are hard refusals (no warnings, no overrides without an explicit user-typed escape).
harness.config.json.pulse.enabled is set (true OR false), skip directly to "Phase 2: RUN" — deferred to spec Phase 4. For now, surface "pulse already configured; the run path ships in Phase 4" and stop.Read references/interview.md for the SMART pushback rules and the READ-WRITE-DB rejection rule. Both are mandatory.
Seed from STRATEGY.md. Shell out to a Node one-liner that imports seedFromStrategy from @harness-engineering/core. Capture { name, keyMetrics, warnings }.
warnings to the user verbatim.name is non-null, confirm it as the product name; otherwise prompt.keyMetric, walk it through the SMART bar in step 4.Pick the lookback default. Use emit_interaction (type: question) when in MCP mode; otherwise present numbered options in chat: ["24h", "7d", "30d", "custom"]. Default 24h per spec.
Identify the primary engagement event (e.g. session_started). Apply the SMART bar. If the user can't name one, set null and add a pending entry. Record the event name in primaryEvent.
Identify the value-realization event (e.g. plan_completed). SMART bar applies. Record in valueEvent.
Identify completion events (zero or more). SMART bar per item. Record in completionEvents.
Quality scoring (optional). Ask whether the user wants quality sampling on a single dimension (e.g. "did the plan deliver value"). Default off. If enabled, set qualityScoring: true and record qualityDimension.
Wire data sources. Ask which providers are available:
analytics: posthog, amplitude, mixpanel, custom — or nulltracing: sentry, datadog, custom — or nullpayments: stripe, custom — or nulldb: opt-in only, with the READ-WRITE-DB rejection rule active
For each non-null choice, check getPulseAdapter(name). If absent, surface the "Phase 4 will ship the adapter" warning from references/interview.md.Walk every STRATEGY.md key metric through SMART. Map to an event when wired; otherwise append to pendingMetrics (or excludedMetrics if explicitly skipped). Cite STRATEGY.md when seeding so the user understands provenance.
Confirm the assembled config. Show the user the proposed pulse: block; ask for confirmation.
Write the config. Shell out to a Node one-liner that imports writePulseConfig from @harness-engineering/core. Pipe the JSON through stdin so user-supplied event names, qualityDimension, and pendingMetrics never cross the shell tokenizer (quotes, backticks, $(), $VAR in user input would otherwise break the command or allow injection):
echo '<json-blob>' | node -e "import('@harness-engineering/core').then(m => m.writePulseConfig(JSON.parse(require('fs').readFileSync(0, 'utf-8')), { configPath: 'harness.config.json' })).catch(err => { console.error(err.message); process.exit(1); })"
The writer preserves all other config keys and writes a .bak.
Offer to register the product-pulse maintenance task. Deferred: Phase 6 of the spec wires it. For now, surface "the daily 8am product-pulse task will be registered automatically once Phase 6 of the feedback-loops spec ships; you can also run pulse on demand with /harness:pulse [window] once Phase 4 ships."
Run harness validate to confirm the new pulse: block parses.
Stub: when pulse.enabled === true, this phase will dispatch analytics/tracing/payments queries in parallel, run the SanitizeFn for each provider's response, and stash sanitized results for Phase 3. NOT YET IMPLEMENTED. The skill exits early with a "deferred to Phase 4" message if it reaches this phase.
harness validate — Run after writePulseConfig; the existing pulse-schema validator catches malformed blocks.@harness-engineering/core primitives consumed by this skill:
writePulseConfig(config, { configPath }) — atomic config update with .bak.seedFromStrategy({ cwd }) — defensive STRATEGY.md reader.getPulseAdapter(name) / listPulseAdapters() — adapter discovery (Phase 4 populates).PulseConfigSchema / PII_FIELD_DENYLIST — schema and PII contracts (already shipped Phase 1).harness-strategy — Strategy writes STRATEGY.md; pulse reads it to seed. Pulse never writes to STRATEGY.md.harness-observability — Observability designs what to instrument; pulse is the read-side companion that surfaces what was instrumented.references/interview.md.SanitizeFn adapter. Phase 3 ships the registry; Phase 4 ships the adapters.pulse: block, the interview produces a valid pulse: block in harness.config.json with all non-pulse keys preserved.harness.config.json.bak is written before mutation.sources.db.enabled: false.STRATEGY.md exists, name and Key metrics seed the interview; missing/malformed STRATEGY.md soft-fails with warnings.harness validate passes after the interview completes.seedFromStrategy returns { name: null, keyMetrics: [], warnings: ['STRATEGY.md not found'] }.lookbackDefault: '24h', primaryEvent: 'session_started', valueEvent: 'plan_completed', sources.analytics: 'posthog' (with adapter-availability warning), sources.db.enabled: false.writePulseConfig writes the block; .bak saved.harness validate passes.{ name: 'Acme', keyMetrics: ['DAU', 'plans/week', 'p95 latency'] }.session_started count over 24h, accepted.plan_completed count over 7d, accepted (recorded as a future custom window).pendingMetrics.postgresql://admin:pwd@host/db.admin username against the rejection list; refuses; cites Decision 6.sources.db.enabled: false.writePulseConfig is the only sanctioned write path. Do not hand-edit harness.config.json. The writer is the layer that preserves non-pulse keys and writes the .bak.harness validate must pass before exit. A malformed pulse: block silently breaks the daily task once Phase 4 ships.sources.db.enabled: false. Stop.name and surface a warning. If neither is parseable, prompt the user.writePulseConfig throws: Report the validator error verbatim. Do not retry without user fix.