> 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.
Scanned 9/11/2026
Install to Claude Code
npx -y skills add Intense-Visions/harness-engineering --skill harness-pulse --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Harness Pulse?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/intense-visions-harness-pulse-7d0a85d5)More formats (shields.io, HTML) on the badges page.
# Harness Pulse
> 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.
## When to Use
- Manually, when a project wants to start receiving daily pulse reports
- When `harness.config.json` has no `pulse:` block and the user invokes `/harness:pulse`
- NOT for ad-hoc one-off metric queries (that's the analytics tool's job)
- NOT for replacing dashboards (pulse is a single-page summary, not a metrics platform)
- NOT for projects that have not yet decided what their key metrics are (run `harness-strategy` first to write `STRATEGY.md`; pulse seeds from it)
## Process
### Iron Law
**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).
---
### Phase 0: ROUTE BY CONFIG STATE
1. Read `harness.config.json`.
2. If `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.
3. Otherwise enter Phase 1.
---
### Phase 1: FIRST-RUN INTERVIEW
Read `references/interview.md` for the SMART pushback rules and the READ-WRITE-DB rejection rule. Both are mandatory.
1. **Seed from STRATEGY.md.** Call `seed_pulse_from_strategy({ path: process.cwd() })` on the harness MCP server. Capture `{ name, keyMetrics, warnings }` — the server does the file read and bullet extraction internally. Fallback when the MCP server is unavailable: `node -e "import('@harness-engineering/core').then(m => console.log(JSON.stringify(m.seedFromStrategy({}))))"` — only works when `@harness-engineering/core` is resolvable from the project.
- Surface `warnings` to the user verbatim.
- If `name` is non-null, confirm it as the product name; otherwise prompt.
- For each `keyMetric`, walk it through the SMART bar in step 4.
2. **Pick the lookback default.** Ask in plain text — present numbered options `["24h", "7d", "30d", "custom"]` and wait (do NOT use `emit_interaction`/`AskUserQuestion`; the human won't see it — it renders only to the model and the client collapses the call to "Called harness"). Default `24h` per spec.
3. **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`.
4. **Identify the value-realization event** (e.g. `plan_completed`). SMART bar applies. Record in `valueEvent`.
5. **Identify completion events** (zero or more). SMART bar per item. Record in `completionEvents`.
6. **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`.
7. **Wire data sources.** Ask which providers are available:
- `analytics`: posthog, amplitude, mixpanel, custom — or null
- `tracing`: sentry, datadog, custom — or null
- `payments`: stripe, custom — or null
- `db`: 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`.
8. **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.
9. **Confirm the assembled config.** Show the user the proposed `pulse:` block; ask for confirmation.
10. **Write the config.** Call `write_pulse_config({ path: process.cwd(), config })` on the harness MCP server. The `config` argument is the assembled `PulseConfig` JSON. The MCP tool validates against `PulseConfigSchema` and refuses to touch disk on schema failure; passing the config as a JSON parameter (not through a shell) means user-supplied prose never crosses the shell tokenizer — no quoting, backtick, or `$VAR` hazard. The writer preserves all other config keys and writes `harness.config.json.bak` on first call.
Fallback for environments without the MCP server (only works when `@harness-engineering/core` is resolvable from the project): `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' }))"`.
11. **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."
12. **Run `harness validate`** to confirm the new `pulse:` block parses.
---
### Phase 2: RUN — deferred to spec Phase 4
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.
### Phase 3: ASSEMBLE — deferred
### Phase 4: SAVE — deferred
---
### Question-File Mode (opt-in)
The default is the interactive first-run interview above. **Question-file mode** is an opt-in variant for **async, team-reviewable** pulse configuration — useful when the metric/event decisions need review from data owners before the `pulse:` block is written. The skill writes its questions to a durable file, the human fills them in over time, and the skill reads them back. Enter it only when the human asks; never automatically. The full convention — file location, the `[Answer]:` tag, the read-back ritual, context hygiene — lives in `references/question-file-mode.md`; this section states only how it maps onto the pulse interview.
1. **WRITE.** Assemble the same questions Phase 1 would ask (lookback window; primary engagement event; value-realization event; completion events; quality-scoring opt-in; data-source wiring; and one question per `STRATEGY.md` Key metric when seeded) into `docs/pulse/interviews/pulse-questions.md` — a pulse-scoped home next to the pulse config it produces (no per-change slug) (or `.harness/sessions/<slug>/interviews/pulse-questions.md` when a session slug is known), each with an empty `[Answer]:`. **Never write a DB connection string into the file** — collect any `db` credential interactively so the READ-WRITE-DB rejection rule runs on a value that is not persisted to a committable file. Report the path and stop.
2. **READ-BACK.** On the next run, re-read the file from disk and treat each filled `[Answer]:` as that question's answer. Apply the SMART bar to every proposed metric/event exactly as in interactive mode, flagging failures **in the file** under the question. Unanswered questions route to `pendingMetrics`/`null` per the normal skip handling.
3. **CONTRADICTION PASS.** Run the cross-answer contradiction pass (see `references/interview.md` and `references/question-file-mode.md`) over the filled answers — most importantly the **metric ⇄ approach** category: a Key metric whose data source was never wired (e.g. "p95 latency" with no tracing source) is a contradiction, not merely a pending metric. Surface it; never auto-resolve.
4. **PROCEED.** Continue to the unchanged Phase 1.9 confirm → `write_pulse_config` path. File mode changes only how answers are gathered — the PII gate, the READ-WRITE-DB rejection, schema validation, and `.bak` behavior are identical.
## Harness Integration
- **`harness validate`** — Run after `write_pulse_config`; the existing pulse-schema validator catches malformed blocks.
- **Harness MCP tools consumed by this skill** (canonical execution path — no project-local `@harness-engineering/core` required):
- `seed_pulse_from_strategy({ path })` — defensive STRATEGY.md reader; returns `{ name, keyMetrics, warnings }`.
- `write_pulse_config({ path, config })` — atomic config update with .bak. Validates against `PulseConfigSchema`.
- **`@harness-engineering/core`** primitives the MCP tools wrap (only directly relevant when developing inside the monorepo or when the MCP server is unavailable):
- `writePulseConfig(config, { configPath })`, `seedFromStrategy({ cwd })`, `getPulseAdapter(name)` / `listPulseAdapters()` (Phase 4 populates), `PulseConfigSchema` / `PII_FIELD_DENYLIST`.
- **Boundary with `harness-strategy`** — Strategy writes `STRATEGY.md`; pulse reads it to seed. Pulse never writes to `STRATEGY.md`.
- **Boundary with `harness-observability`** — Observability designs _what_ to instrument; pulse is the read-side companion that surfaces what was instrumented.
- **Decision 6 (read-only)** — Pulse refuses read-write DB credentials. Documented in `references/interview.md`.
- **Decision 7 (PII contract)** — Every provider source must have a registered `SanitizeFn` adapter. Phase 3 ships the registry; Phase 4 ships the adapters.
## Success Criteria
- On a project with no `pulse:` block, the interview produces a valid `pulse:` block in `harness.config.json` with all non-pulse keys preserved.
- A `harness.config.json.bak` is written before mutation.
- A read-write DB credential is refused; the interview either accepts a read-only credential or sets `sources.db.enabled: false`.
- When `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.
## Rationalizations to Reject
These are common rationalizations that sound reasonable but lead to incorrect results. When you catch yourself thinking any of these, stop and follow the documented process instead.
| Rationalization | Why It Is Wrong |
| ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| "The user pasted an admin DB connection string, but they clearly know their setup — I'll accept it." | The READ-WRITE-DB rejection is non-negotiable: no flag, no override, no "I know what I'm doing" path. Refuse, cite Decision 6, and set `sources.db.enabled: false`. A pulse report never needs write access. |
| "'Engagement' is a bit vague, but I know what they mean — I'll record it without SMART pushback." | SMART pushback is mandatory on every proposed metric/event. Silently accepting a vague name pollutes the config and produces an unmeasurable pulse. Push back until the metric names a concrete, measurable event. |
| "It's just one field — I'll hand-edit the `pulse:` block into `harness.config.json` directly." | `write_pulse_config` is the only sanctioned write path: it preserves all non-pulse keys, validates against `PulseConfigSchema`, and writes the `.bak`. A hand-edit bypasses the schema gate and can clobber sibling config. |
| "STRATEGY.md already lists the key metrics — I'll copy them into the config as-is." | Every seeded key metric must still clear the SMART bar and be mapped to a wired event. Metrics with no data source belong in `pendingMetrics`, not the live block — copying them wholesale ships a config that silently can't be computed. |
| "The config assembled cleanly — I'll skip `harness validate`." | A malformed `pulse:` block silently breaks the daily `product-pulse` task once the run path ships. Validation is a gate that must pass before exit, not an optional final touch. |
## Examples
### Example: greenfield (no STRATEGY.md, no existing pulse block)
- Phase 0: route to Phase 1.
- Phase 1.1: `seedFromStrategy` returns `{ name: null, keyMetrics: [], warnings: ['STRATEGY.md not found'] }`.
- Phase 1.2-7: prompt user; collect `lookbackDefault: '24h'`, `primaryEvent: 'session_started'`, `valueEvent: 'plan_completed'`, `sources.analytics: 'posthog'` (with adapter-availability warning), `sources.db.enabled: false`.
- Phase 1.10: `write_pulse_config` writes the block; `.bak` saved.
- Phase 1.12: `harness validate` passes.
### Example: STRATEGY.md present with 3 Key metrics
- Phase 1.1: seed returns `{ name: 'Acme', keyMetrics: ['DAU', 'plans/week', 'p95 latency'] }`.
- Phase 1.8: walk each metric through SMART.
- "DAU" → mapped to `session_started` count over 24h, accepted.
- "plans/week" → mapped to `plan_completed` count over 7d, accepted (recorded as a future custom window).
- "p95 latency" → no tracing source wired yet; lands in `pendingMetrics`.
### Example: user offers an admin DB credential
- Phase 1.7: user pastes `postgresql://admin:pwd@host/db`.
- Skill matches `admin` username against the rejection list; refuses; cites Decision 6.
- User declines to provide a read-only credential; skill writes `sources.db.enabled: false`.
## Gates
- **READ-WRITE-DB rejection is non-negotiable.** No flag, no override, no "I know what I'm doing" path. Refuse and document.
- **SMART pushback is mandatory on every proposed metric/event.** Silently accepting a vague name pollutes the corpus.
- **`write_pulse_config` (or `writePulseConfig` when invoked directly) 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.
## Escalation
- **User insists on read-write DB credentials:** Refuse. Set `sources.db.enabled: false`. Stop.
- **Adapter not registered for a chosen provider:** Warn, record the choice, continue. The runtime gate (Phase 4) refuses to run until the adapter ships.
- **STRATEGY.md frontmatter is malformed but H1 is present:** Use H1 as `name` and surface a warning. If neither is parseable, prompt the user.
- **`write_pulse_config` returns `{ written: false, error }` (or `writePulseConfig` throws directly):** Report the validator error verbatim. Do not retry without user fix.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!