Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,12 @@
"category": "verification",
"tags": ["verification", "outcome", "baseline", "measure", "verify", "skill"]
},
{
"name": "performance",
"source": "./plugins/performance",
"category": "verification",
"tags": ["performance", "benchmarking", "baseline", "measurement", "optimization", "noise-characterization", "drift-immune-counter", "interleaved-ab", "skill"]
},
{
"name": "kindle-dedrm",
"displayName": "Kindle DeDRM",
Expand Down
1 change: 1 addition & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"mutation-testing@melodic-software": true,
"naming@melodic-software": true,
"overengineering@melodic-software": true,
"performance@melodic-software": true,
"planning@melodic-software": true,
"playbooks@melodic-software": true,
"playgrounds@melodic-software": false,
Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,26 @@ jobs:
BASE_REF: ${{ github.base_ref }}
run: scripts/sync-state-key.sh --check-bump "origin/$BASE_REF"

spawn-noise-sync:
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- name: Check out
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Fetch base
uses: ./.github/actions/checkout-with-base
- name: Verify spawn-noise cluster matches canonical
run: scripts/sync-spawn-noise.sh --check
- name: Run spawn-noise tests
run: bash plugins/claude-ops/lib/spawn_noise.test.sh
- name: Verify carrying plugins bumped when canonical changed
if: github.event_name == 'pull_request'
env:
BASE_REF: ${{ github.base_ref }}
run: scripts/sync-spawn-noise.sh --check-bump "origin/$BASE_REF"

resolve-convention-pattern-sync:
runs-on: ubuntu-24.04
timeout-minutes: 15
Expand Down Expand Up @@ -1729,6 +1749,7 @@ jobs:
- parse-concern-value-sync
- managed-scope-sync
- state-key-sync
- spawn-noise-sync
- resolve-convention-pattern-sync
- index-regen-sync
- standards-contract-sync
Expand Down
1 change: 1 addition & 0 deletions docs/CATALOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ plugin manifests and kept in sync by CI — never hand-edit it; the category voc
## Verification

- [`verification`](../plugins/verification) — Outcome-verification stage: prove a change achieved its intended outcome (`/verification:confirm` — a mechanical build/test/lint prerequisite gate, then intent-match + evidence + verdict with the criterion auto-detected by change type), and verify measurable-improvement claims against a planning-time baseline (`/verification:measure`), never fabricating numbers.
- [`performance`](../plugins/performance) — Measurement-first optimization workflow for an arbitrary target, built around refusing to report what the data does not support. Four skills: target (identify and rank optimization candidates by evidence quality rather than suspicion, so an unmeasured target makes "instrument this first" the recommendation instead of a guess), goal (human-gated goal construction that holds a realistic target and an ideal target separately and computes the irreducible floor BEFORE any work, so a target below the floor is surfaced as unreachable-by-any-code-change up front rather than discovered as a failed goal at the end), snapshot (baseline and post capture with the host qualified first: repeated no-op spawns characterize the machine's own noise, a drift-immune counter is reported alongside and ranked above any duration, before/after arms are interleaved within one run rather than compared across two passes, and a wall-clock claim is REFUSED outright from a host whose spread carries the bimodal contention signature, naming the counter it can still report instead), and verify (fresh-context adversarial re-derivation that does not inherit the implementer's numbers, plus a report that states a target as met or not met and never rounds a miss into a win). Gates hard-block, with a named override recorded in the report. Every gate ships with a discrimination check proving it fails when its condition is unmet, because a check that passes whether or not the condition holds is worse than no check: it reports success. Normative claims carry a source tier, and the ones the benchmarking literature does not ground (sample counts, the p95 convention, counts-over-time for anything but instruction counts) are labelled as house rules rather than dressed as consensus.

## Quality

Expand Down
4 changes: 4 additions & 0 deletions docs/SKILL-CHEAT-SHEET.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ owned by [docs/CATALOG-TAXONOMY.md](CATALOG-TAXONOMY.md).
| [`/discovery:blindspot`](../plugins/discovery/skills/blindspot/SKILL.md) | `discovery` | Surface your unknown-unknowns and sharpen the prompt before unfamiliar work |
| [`/discovery:explore`](../plugins/discovery/skills/explore/SKILL.md) | `discovery` | Explore code, history, tests, and config before changing anything |
| [`/discovery:trace-intent`](../plugins/discovery/skills/trace-intent/SKILL.md) | `discovery` | Reconstruct why a thing was built this way, from evidence outside the code |
| [`/performance:target`](../plugins/performance/skills/target/SKILL.md) | `performance` | Rank optimization candidates by evidence quality, not suspicion |

## 2. Research

Expand All @@ -63,6 +64,7 @@ owned by [docs/CATALOG-TAXONOMY.md](CATALOG-TAXONOMY.md).
| [`/event-storming:methodology`](../plugins/event-storming/skills/methodology/SKILL.md) | `event-storming` | EventStorming facilitation reference across all three formats |
| [`/event-storming:simulation`](../plugins/event-storming/skills/simulation/SKILL.md) | `event-storming` | Multi-persona agentic EventStorming workshop on Miro |
| [`/naming:name-it-better`](../plugins/naming/skills/name-it-better/SKILL.md) | `naming` | Generate and evaluate name candidates from blind fresh-context lenses |
| [`/performance:goal`](../plugins/performance/skills/goal/SKILL.md) | `performance` | Build a goal with realistic and ideal targets plus a computed floor |
| [`/planning:design`](../plugins/planning/skills/design/SKILL.md) | `planning` | Resolve types, contracts, and module boundaries before planning |
| [`/planning:design-handoff`](../plugins/planning/skills/design-handoff/SKILL.md) | `planning` | Gate a finished design and package it for planning |
| [`/planning:devils-advocate`](../plugins/planning/skills/devils-advocate/SKILL.md) | `planning` | Stress-test a plan or the incumbent approach adversarially |
Expand Down Expand Up @@ -118,6 +120,8 @@ owned by [docs/CATALOG-TAXONOMY.md](CATALOG-TAXONOMY.md).

| Skill | Plugin | What it does |
| --- | --- | --- |
| [`/performance:snapshot`](../plugins/performance/skills/snapshot/SKILL.md) | `performance` | Capture a snapshot only from a host proven measurable |
| [`/performance:verify`](../plugins/performance/skills/verify/SKILL.md) | `performance` | Re-derive the result in fresh context and report it honestly |
| [`/toolchain:check`](../plugins/toolchain/skills/check/SKILL.md) | `toolchain` | Build, test, and lint changed files across detected ecosystems |
| [`/toolchain:lint`](../plugins/toolchain/skills/lint/SKILL.md) | `toolchain` | Polyglot lint and format checks without a full build |
| [`/verification:confirm`](../plugins/verification/skills/confirm/SKILL.md) | `verification` | Prove the change achieved its intended outcome with evidence |
Expand Down
2 changes: 1 addition & 1 deletion plugins/claude-ops/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "claude-ops",
"version": "0.41.0",
"version": "0.41.1",
"description": "Claude Code operations toolkit. Twelve skills: audit-skill-visibility (audit whether each installed skill is actually VISIBLE to the model, and diagnose why most of a fleet never gets used \u2014 a skill is invisible when its description is dropped by Claude Code's skill-listing context budget, which sheds descriptions lowest-score-first so an unused skill loses the keywords that would let it be matched, from skills genuinely not wanted, from skills the run cannot observe at all; computes whether the listing overflows from documented settings, and withholds every cold verdict the data cannot support rather than reporting absence of data as absence of use), inventory (read-only enumeration of the complete invocable surface \u2014 every built-in CLI command with aliases and hidden/gated status, every bundled skill, and every component of every installed plugin across all marketplaces; reads the shipped binary because upstream publishes no built-in command list, and carries an integrity verdict so a drifted build reports counts as floors rather than silently short totals), audit-install-state (read-only audit of the machine-scope ~/.claude installation directory and ~/.claude.json \u2014 full inventory split into an authored surface and rolled-up bulk trees, product-managed retention vs genuinely unmanaged state, filename-scheme resolution before any process-liveness check, and deliberate/mid-experiment detection; reports, never deletes), audit-performance (read-only slowness-diagnostic capture run at the moment the machine or a session feels slow: CLI version, retention-sweep health including the silent unparsable-settings pause, a timed census walk of the install tree as a sweep-cost proxy, active-session and plugin-fleet counts, a process census, and the fan-out layer, which covers a load-labelled no-op spawn baseline, every hook that will fire bucketed per-tool-call versus per-turn with its invocation shape, the configured statusline, subagent concurrency and spawn-depth ceilings against documented defaults, whether running sessions predate the settings file they are judged by, and orphan attribution by parent liveness rather than age; read against a bundled known-performance-issues reference that also records the causes tested and cleared; separates the four documented suspects of accumulated state, version regression, component bloat, and per-spawn fan-out cost, and routes remediation out; reports, never mutates, and never executes a discovered hook or statusline command), audit-native-overlap (map native Claude Code surfaces \u2014 built-in CLI commands, bundled skills, plugin-backed built-ins, session-provided skills \u2014 against the current repo's plugin skills and agents, so a custom component never silently duplicates what Claude Code itself ships; bare invocation is a read-only overlap report carrying the extraction's integrity floors and a shared-listing-budget exposure section, verdicts are human-gated in a committed store rendered into a generated registry whose every row carries an observable recheck trigger, and only an explicit apply step bakes presence-gated native references into descriptions and Boundary sections), observability (read locally captured telemetry \u2014 OTEL store, collector, hook-event JSONL, ccusage \u2014 with trend reports and store pruning), known-issues (search known Claude product GitHub bugs, check service health, maintain a persistent tracked-issue registry), changelog (ingest Claude Code changelog entries and integrate them into the current repo), plugins (bring a machine's plugin fleet current on demand \u2014 marketplace refresh, effective-scope updates including in-repo project/local installs, new-plugin install per policy, scope-divergence detection and explicit convergence), morning-brief (read-only gh-based operator morning view \u2014 queue-label counts, merge-ready PRs, parked decisions with their RECOMMENDED lines, and loop-lane telemetry freshness), lanes (start/restart/stop/status loop lanes as named background Claude Code sessions seeded from canonical prompt files, with per-lane model/effort, a repo-pull + marketplace-refresh launch step, and a consume-restarts action \u2014 an OS-schedulable reader that relaunches stopped lanes whose telemetry carries a restart_request), and a re-runnable setup action that settles where the known-issues registry lives. Plus a family of eight advisory *-audit hooks (API errors, config changes, instruction loads, permission denials, pre-compaction, skill usage, tool failures, and unsurfaced hook failures \u2014 the last also warns the user via systemMessage, since a hook that fails to launch enforces nothing and Claude Code surfaces the failure to nobody) that emit the shared hook-telemetry envelope, and a reference sink that maps envelopes into the hook-events.jsonl the observability skill reads.",
"author": {
"name": "Melodic Software",
Expand Down
17 changes: 17 additions & 0 deletions plugins/claude-ops/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,23 @@
All notable changes to the `claude-ops` plugin are documented here. Format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning.

## [0.41.1]

### Added

- **`lib/spawn_noise.py` gains `is_measurable()` and `percentile_floor()`.** `is_measurable()` turns
a spawn-noise summary into a verdict on whether a WALL-CLOCK claim may be reported from this host,
reading the `findings` list rather than `spread_ratio` alone so the two-part bimodal predicate is
preserved. `percentile_floor()` returns `1/(1-p)`, the only sample-count constraint the
benchmarking literature actually grounds. `claude-ops` calls neither; both exist for the
`performance` plugin, which now carries this file as a registered cross-plugin cluster
(`scripts/sync-spawn-noise.sh`, CI lane `spawn-noise-sync`) so the bimodal threshold keeps exactly
one home. Adding them here rather than only in the consumer is what byte-identical cluster copies
require.
- **Lib tests for both.** The measurability test asserts the quiet-host and contended-host arms
produce DIFFERENT verdicts as a first-class check, not merely that each produced its expected
value: a refusal that fires on every host refuses nothing.

## [0.41.0]

### Added
Expand Down
74 changes: 74 additions & 0 deletions plugins/claude-ops/lib/spawn_noise.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

from __future__ import annotations

import math
import statistics
import subprocess
import sys
Expand Down Expand Up @@ -118,3 +119,76 @@ def spawn_probe(samples: int = SPAWN_SAMPLES, timeout_s: float = SPAWN_TIMEOUT_S
summary = summarize_spawn_samples(durations, timeouts, load)
summary["command"] = " ".join(command)
return summary


def is_measurable(summary: dict) -> tuple[bool, str]:
"""Decide whether a WALL-CLOCK claim may be reported from this host.

Returns `(measurable, reason)`. This function states a verdict and its basis;
it never suppresses anything itself, and the caller decides what a False means.
`performance` treats it as a hard refusal; `claude-ops` does not call it.

The verdict rides on the `findings` list rather than on `spread_ratio`,
because `bimodal-spawn-latency` is the two-part predicate documented at module
level. A bare ratio comparison would fire on a healthy cold-then-warm host.

A False is never the end of the road: a drift-immune counter (process spawns,
syscalls, queries) is still reportable from a host too noisy for a duration,
and that is what the source run of this workflow ultimately shipped -- a
deterministic 4 -> 1 spawn count, not a millisecond figure that no independent
verifier could reproduce an hour later on the same machine.

Refusing above a variance threshold is stricter than the benchmarking field:
pyperf, Criterion, JMH and benchstat all WARN and print the number anyway. This
is a deliberate house rule, not a consensus practice, and callers must present
it as one.
"""
findings = summary.get("findings", [])
if "no-spawn-samples-captured" in findings:
return False, "no spawn samples were captured, so the host was never characterized"
# A timeout outranks the bimodal signature, and the order is load-bearing.
# A timed-out sample is recorded as the timeout ceiling, not as a measurement,
# so `max_ms` is a censored value. Reporting the bimodal reason first would
# hand the reader a spread computed from that ceiling and explain it as an
# observed slow mode, which reads as a finite measurement of a tail that is
# actually unbounded.
if "spawn-probe-timed-out" in findings:
return False, (
f"{summary.get('timeouts')} of {summary.get('samples')} no-op spawns hit the probe "
f"timeout, so the tail is unbounded and max_ms is a censored ceiling rather than a "
f"measurement"
)
if "bimodal-spawn-latency" in findings:
return False, (
f"spawn cost spread {summary.get('spread_ratio')}x across identical no-op spawns "
f"(min {summary.get('min_ms')} ms, max {summary.get('max_ms')} ms), with the slow mode "
f"above the {SLOW_SPAWN_FLOOR_MS} ms floor: the bimodal contention signature"
)
if "slow-spawn-floor" in findings:
return False, (
f"even the fastest no-op spawn cost {summary.get('min_ms')} ms, above the "
f"{SLOW_SPAWN_FLOOR_MS} ms floor: the host is contended before any work starts"
)
return True, (
f"spawn cost spread {summary.get('spread_ratio')}x with a {summary.get('min_ms')} ms "
"floor: within the measurable band"
)


def percentile_floor(percentile: float) -> int:
"""Minimum samples for a percentile to be arithmetically expressible: `1/(1-p)`.

This is the ONLY grounded constraint on sample count that this codebase is
aware of, and it is grounded because it is derivable, not because a source
states it. The research pass behind #3530 found no benchmarking-community
consensus figure for "enough samples to make a percentile meaningful": the
familiar folklore numbers appear in no first-party or peer-reviewed source.

So `performance` enforces this floor and labels its p50/p95-over-20 default as
a house convention. p95 needs 20 samples; p99 needs 100. Below the floor the
percentile is not merely imprecise, it cannot be computed from the data at all
-- the requested tail does not exist in the sample.
"""
if not 0.0 < percentile < 1.0:
raise ValueError(f"percentile must be in (0, 1), got {percentile!r}")
return math.ceil(1.0 / (1.0 - percentile))
Loading
Loading