docs(humanizer): v5.1.0 release notes across plugin + marketplace docs
- Plugin README: add "What's New in v5.1.0" section with humanizer overview, before/after example, plain-language vocabulary table, --raw flag docs. Bump version badge 5.0.0 → 5.1.0. Add Version History row. - Plugin CLAUDE.md: add humanizer.mjs + humanizer-data.mjs to Scanner Lib table. Add "Plain-Language Output (v5.1.0)" section documenting output modes, vocabularies, and Wave 5 lessons. Bump test count 635 → 792 across 52 test files. - Marketplace root README: bump config-audit entry 5.0.0 → 5.1.0, update one-line description to mention plain-language UX, add bullet for the v5.1.0 humanizer, bump test count 635+ → 792+. Test-normalizer hardening (consequence of growing CLAUDE.md): walkClaudeMdCascade walks upward from the marketplace-medium fixture into this plugin's own CLAUDE.md, so any docs edit ripples into `scanners[*].activeConfig.claudeMdEstimatedTokens`. The v5.0.0 byte-stability contract is about scanner internals being unchanged, not ancestor input content being frozen. Normalizers in json-backcompat, raw-backcompat, posture-humanizer, scan-orchestrator-humanizer, and snapshot-default-output now strip claudeMdEstimatedTokens to <ANCESTOR_DERIVED>. The default-output snapshot for scan-orchestrator was re-seeded via UPDATE_SNAPSHOT=1 (intent: Wave 6 docs additions; humanizer prose unchanged). Verify: - grep -E "5\.1\.0|v5\.1\.0" README.md CLAUDE.md ../../README.md | wc -l = 12 - node --test 'tests/**/*.test.mjs' = 792/792 pass - self-audit configGrade A (97), pluginGrade A (100), readmeCheck.passed true
This commit is contained in:
parent
819fd47ce0
commit
fc8808d6e4
9 changed files with 170 additions and 10 deletions
|
|
@ -67,9 +67,24 @@ async function ensureDriftBaseline() {
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Normalizers — strip time / path fields that vary between runs.
|
||||
// Normalizers — strip time / path / ancestor-derived fields that vary
|
||||
// independently of scanner internals. `claudeMdEstimatedTokens` is computed
|
||||
// by walking the FS cascade upward from the fixture; any edit to this
|
||||
// plugin's own CLAUDE.md ripples into it, even though scanner behavior is
|
||||
// unchanged. The byte-stability contract covers scanner output shape, not
|
||||
// the size of ancestor input docs.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function stripAncestorDerived(envOrEnvelope) {
|
||||
if (Array.isArray(envOrEnvelope?.scanners)) {
|
||||
for (const s of envOrEnvelope.scanners) {
|
||||
if (s?.activeConfig && 'claudeMdEstimatedTokens' in s.activeConfig) {
|
||||
s.activeConfig.claudeMdEstimatedTokens = '<ANCESTOR_DERIVED>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeScanOrchestrator(env) {
|
||||
const out = JSON.parse(JSON.stringify(env));
|
||||
if (out.meta) {
|
||||
|
|
@ -81,6 +96,7 @@ function normalizeScanOrchestrator(env) {
|
|||
s.duration_ms = 0;
|
||||
}
|
||||
}
|
||||
stripAncestorDerived(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
@ -96,6 +112,7 @@ function normalizePosture(p) {
|
|||
s.duration_ms = 0;
|
||||
}
|
||||
}
|
||||
stripAncestorDerived(out.scannerEnvelope);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,8 +66,21 @@ async function ensureDriftBaseline() {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Normalizers — same as json-backcompat to keep the contracts aligned.
|
||||
// `claudeMdEstimatedTokens` is stripped because walkClaudeMdCascade walks
|
||||
// upward from the fixture into this plugin's own CLAUDE.md; any docs edit
|
||||
// here ripples into it even when scanner internals are unchanged.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function stripAncestorDerived(envOrEnvelope) {
|
||||
if (Array.isArray(envOrEnvelope?.scanners)) {
|
||||
for (const s of envOrEnvelope.scanners) {
|
||||
if (s?.activeConfig && 'claudeMdEstimatedTokens' in s.activeConfig) {
|
||||
s.activeConfig.claudeMdEstimatedTokens = '<ANCESTOR_DERIVED>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeScanOrchestrator(env) {
|
||||
const out = JSON.parse(JSON.stringify(env));
|
||||
if (out.meta) {
|
||||
|
|
@ -79,6 +92,7 @@ function normalizeScanOrchestrator(env) {
|
|||
s.duration_ms = 0;
|
||||
}
|
||||
}
|
||||
stripAncestorDerived(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
@ -94,6 +108,7 @@ function normalizePosture(p) {
|
|||
s.duration_ms = 0;
|
||||
}
|
||||
}
|
||||
stripAncestorDerived(out.scannerEnvelope);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ const POSTURE_STDERR_SNAPSHOT = resolve(REPO, 'tests/snapshots/v5.0.0-stderr/pos
|
|||
|
||||
/**
|
||||
* Normalize a runPosture result for snapshot comparison by zeroing out
|
||||
* time-varying fields and machine-specific paths.
|
||||
* time-varying fields, machine-specific paths, and ancestor-cascade-derived
|
||||
* counts. `claudeMdEstimatedTokens` reflects walkClaudeMdCascade walking
|
||||
* upward from the fixture; any docs edit to this plugin's own CLAUDE.md
|
||||
* ripples into it even though scanner behavior is unchanged.
|
||||
*/
|
||||
function normalizePosture(p) {
|
||||
const out = JSON.parse(JSON.stringify(p));
|
||||
|
|
@ -28,6 +31,9 @@ function normalizePosture(p) {
|
|||
if (Array.isArray(out.scannerEnvelope.scanners)) {
|
||||
for (const s of out.scannerEnvelope.scanners) {
|
||||
s.duration_ms = 0;
|
||||
if (s.activeConfig && 'claudeMdEstimatedTokens' in s.activeConfig) {
|
||||
s.activeConfig.claudeMdEstimatedTokens = '<ANCESTOR_DERIVED>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,11 @@ const SNAPSHOT_PATH = resolve(REPO, 'tests/snapshots/v5.0.0/scan-orchestrator.js
|
|||
|
||||
/**
|
||||
* Normalize a scan-orchestrator envelope for snapshot comparison by
|
||||
* blanking out time-varying fields (timestamp, durations, target path).
|
||||
* Returns a NEW object — does not mutate input.
|
||||
* blanking out time-varying fields (timestamp, durations, target path)
|
||||
* and ancestor-cascade-derived counts. `claudeMdEstimatedTokens` reflects
|
||||
* walkClaudeMdCascade walking upward from the fixture; any docs edit to
|
||||
* this plugin's own CLAUDE.md ripples into it even when scanner behavior
|
||||
* is unchanged. Returns a NEW object — does not mutate input.
|
||||
*/
|
||||
function normalizeEnvelope(env) {
|
||||
const out = JSON.parse(JSON.stringify(env));
|
||||
|
|
@ -27,6 +30,9 @@ function normalizeEnvelope(env) {
|
|||
if (Array.isArray(out.scanners)) {
|
||||
for (const s of out.scanners) {
|
||||
s.duration_ms = 0;
|
||||
if (s.activeConfig && 'claudeMdEstimatedTokens' in s.activeConfig) {
|
||||
s.activeConfig.claudeMdEstimatedTokens = '<ANCESTOR_DERIVED>';
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,13 @@ function normalizeScanOrchestrator(env) {
|
|||
if (Array.isArray(out.scanners)) {
|
||||
for (const s of out.scanners) {
|
||||
s.duration_ms = 0;
|
||||
// claudeMdEstimatedTokens reflects walkClaudeMdCascade walking up from
|
||||
// the fixture into this plugin's own CLAUDE.md; any docs edit ripples
|
||||
// into it independently of scanner internals. Strip to keep the
|
||||
// default-output snapshot focused on humanizer prose stability.
|
||||
if (s.activeConfig && 'claudeMdEstimatedTokens' in s.activeConfig) {
|
||||
s.activeConfig.claudeMdEstimatedTokens = '<ANCESTOR_DERIVED>';
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
|
|
|||
|
|
@ -491,7 +491,7 @@
|
|||
],
|
||||
"total_estimated_tokens": 1809,
|
||||
"activeConfig": {
|
||||
"claudeMdEstimatedTokens": 5716,
|
||||
"claudeMdEstimatedTokens": "<ANCESTOR_DERIVED>",
|
||||
"mcpServerCount": 3,
|
||||
"pluginCount": 41,
|
||||
"skillCount": 65
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue