docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies - #1229
Conversation
…timization strategies
ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9):
- HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0)
- HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s)
- MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files
vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them
- maxBuffer truncation, python -c port interpolation, version drift, duplicate skills,
guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding
claim-check on these very ADRs), zero CI
ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against
the published registry tarball:
- HIGH: exports.require -> dist/index.cjs which is never built nor published
- MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload
- stdio-only server described as dual-transport; mixed dot/underscore tool names;
double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training
job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates;
ruview bin-name collision
ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix
(test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only
with npm provenance, version single-sourcing from package.json, bin/namespace
ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs.
Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated.
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz
…, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz
stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz
…ckage doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net>
…fore 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net>
|
High-effort review completed: 26 verified findings → 16 distinct defects; the 10 most severe (all CONFIRMED) were fixed on this branch in d46eb8a — guardrails fail-open (code-span digits, F1 phrasing), tools/call serialization + stdin-close drain, negative which() caching, rvagent library-import stdio side effect, Origin allowlist bypass, unbounded session map, stale 'running' job reconciliation, cog binary arch ordering, and the full ADR-265 D1 gate ported into ruview-npm-release.yml. Also fixed the ruview-cli CI matrix failure (jest --passWithNoTests) in d26fb0b. Tests: harness 30→36, rvagent 99→112, all green across the node 20/22 matrix. Published and verified from the registry: @ruvnet/ruview@0.2.0 (21 files, 55.5 kB unpacked) and @ruvnet/rvagent@0.2.0 (46 files, no source maps, no phantom exports.require). Clean-install smoke: ruview claim-check fails closed (exit 2 on no input, flags 'F1: 0.91'), MCP stdio initialize/tools/list/ping OK on both bins, rvagent library import is side-effect free. @ruv/ruview-cli stays private per ADR-265 D4. Note: 0.2.0 was published locally (npm user ruvnet) because NPM_TOKEN isn't configured and ruview-npm-release.yml isn't on main yet — future releases can use the CI+provenance path once this merges. 🤖 Generated with claude-flow |
…R-263/264/265 optimization strategies (ruvnet#1229) * docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9): - HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0) - HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s) - MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them - maxBuffer truncation, python -c port interpolation, version drift, duplicate skills, guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding claim-check on these very ADRs), zero CI ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against the published registry tarball: - HIGH: exports.require -> dist/index.cjs which is never built nor published - MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload - stdio-only server described as dual-transport; mixed dot/underscore tool names; double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates; ruview bin-name collision ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix (test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only with npm provenance, version single-sourcing from package.json, bin/namespace ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs. Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * fix(npm): implement ADR-263/264/265 — harness fail-closed + async MCP, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * ci(ruview-cli): pass jest --passWithNoTests so the private no-test package doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net> * fix(npm): address 10 verified review findings in harness + rvagent before 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> e6f26e9
…R-263/264/265 optimization strategies (ruvnet#1229) * docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9): - HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0) - HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s) - MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them - maxBuffer truncation, python -c port interpolation, version drift, duplicate skills, guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding claim-check on these very ADRs), zero CI ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against the published registry tarball: - HIGH: exports.require -> dist/index.cjs which is never built nor published - MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload - stdio-only server described as dual-transport; mixed dot/underscore tool names; double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates; ruview bin-name collision ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix (test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only with npm provenance, version single-sourcing from package.json, bin/namespace ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs. Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * fix(npm): implement ADR-263/264/265 — harness fail-closed + async MCP, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * ci(ruview-cli): pass jest --passWithNoTests so the private no-test package doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net> * fix(npm): address 10 verified review findings in harness + rvagent before 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> e6f26e9
…R-263/264/265 optimization strategies (ruvnet#1229) * docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9): - HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0) - HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s) - MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them - maxBuffer truncation, python -c port interpolation, version drift, duplicate skills, guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding claim-check on these very ADRs), zero CI ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against the published registry tarball: - HIGH: exports.require -> dist/index.cjs which is never built nor published - MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload - stdio-only server described as dual-transport; mixed dot/underscore tool names; double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates; ruview bin-name collision ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix (test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only with npm provenance, version single-sourcing from package.json, bin/namespace ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs. Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * fix(npm): implement ADR-263/264/265 — harness fail-closed + async MCP, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * ci(ruview-cli): pass jest --passWithNoTests so the private no-test package doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net> * fix(npm): address 10 verified review findings in harness + rvagent before 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> e6f26e9
|
H |
…R-263/264/265 optimization strategies (ruvnet#1229) * docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9): - HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0) - HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s) - MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them - maxBuffer truncation, python -c port interpolation, version drift, duplicate skills, guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding claim-check on these very ADRs), zero CI ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against the published registry tarball: - HIGH: exports.require -> dist/index.cjs which is never built nor published - MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload - stdio-only server described as dual-transport; mixed dot/underscore tool names; double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates; ruview bin-name collision ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix (test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only with npm provenance, version single-sourcing from package.json, bin/namespace ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs. Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * fix(npm): implement ADR-263/264/265 — harness fail-closed + async MCP, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * ci(ruview-cli): pass jest --passWithNoTests so the private no-test package doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net> * fix(npm): address 10 verified review findings in harness + rvagent before 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> e6f26e9
…R-263/264/265 optimization strategies (ruvnet#1229) * docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9): - HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0) - HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s) - MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them - maxBuffer truncation, python -c port interpolation, version drift, duplicate skills, guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding claim-check on these very ADRs), zero CI ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against the published registry tarball: - HIGH: exports.require -> dist/index.cjs which is never built nor published - MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload - stdio-only server described as dual-transport; mixed dot/underscore tool names; double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates; ruview bin-name collision ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix (test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only with npm provenance, version single-sourcing from package.json, bin/namespace ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs. Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * fix(npm): implement ADR-263/264/265 — harness fail-closed + async MCP, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * ci(ruview-cli): pass jest --passWithNoTests so the private no-test package doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net> * fix(npm): address 10 verified review findings in harness + rvagent before 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> e6f26e9
…R-263/264/265 optimization strategies (ruvnet#1229) * docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9): - HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0) - HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s) - MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them - maxBuffer truncation, python -c port interpolation, version drift, duplicate skills, guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding claim-check on these very ADRs), zero CI ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against the published registry tarball: - HIGH: exports.require -> dist/index.cjs which is never built nor published - MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload - stdio-only server described as dual-transport; mixed dot/underscore tool names; double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates; ruview bin-name collision ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix (test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only with npm provenance, version single-sourcing from package.json, bin/namespace ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs. Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * fix(npm): implement ADR-263/264/265 — harness fail-closed + async MCP, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * ci(ruview-cli): pass jest --passWithNoTests so the private no-test package doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net> * fix(npm): address 10 verified review findings in harness + rvagent before 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> e6f26e9
…R-263/264/265 optimization strategies (ruvnet#1229) * docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9): - HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0) - HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s) - MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them - maxBuffer truncation, python -c port interpolation, version drift, duplicate skills, guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding claim-check on these very ADRs), zero CI ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against the published registry tarball: - HIGH: exports.require -> dist/index.cjs which is never built nor published - MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload - stdio-only server described as dual-transport; mixed dot/underscore tool names; double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates; ruview bin-name collision ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix (test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only with npm provenance, version single-sourcing from package.json, bin/namespace ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs. Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * fix(npm): implement ADR-263/264/265 — harness fail-closed + async MCP, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * ci(ruview-cli): pass jest --passWithNoTests so the private no-test package doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net> * fix(npm): address 10 verified review findings in harness + rvagent before 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> e6f26e9
…R-263/264/265 optimization strategies (ruvnet#1229) * docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9): - HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0) - HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s) - MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them - maxBuffer truncation, python -c port interpolation, version drift, duplicate skills, guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding claim-check on these very ADRs), zero CI ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against the published registry tarball: - HIGH: exports.require -> dist/index.cjs which is never built nor published - MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload - stdio-only server described as dual-transport; mixed dot/underscore tool names; double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates; ruview bin-name collision ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix (test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only with npm provenance, version single-sourcing from package.json, bin/namespace ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs. Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * fix(npm): implement ADR-263/264/265 — harness fail-closed + async MCP, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * ci(ruview-cli): pass jest --passWithNoTests so the private no-test package doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net> * fix(npm): address 10 verified review findings in harness + rvagent before 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> e6f26e9
…R-263/264/265 optimization strategies (ruvnet#1229) * docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9): - HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0) - HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s) - MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them - maxBuffer truncation, python -c port interpolation, version drift, duplicate skills, guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding claim-check on these very ADRs), zero CI ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against the published registry tarball: - HIGH: exports.require -> dist/index.cjs which is never built nor published - MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload - stdio-only server described as dual-transport; mixed dot/underscore tool names; double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates; ruview bin-name collision ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix (test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only with npm provenance, version single-sourcing from package.json, bin/namespace ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs. Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * fix(npm): implement ADR-263/264/265 — harness fail-closed + async MCP, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * ci(ruview-cli): pass jest --passWithNoTests so the private no-test package doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net> * fix(npm): address 10 verified review findings in harness + rvagent before 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> e6f26e9
…R-263/264/265 optimization strategies (ruvnet#1229) * docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9): - HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0) - HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s) - MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them - maxBuffer truncation, python -c port interpolation, version drift, duplicate skills, guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding claim-check on these very ADRs), zero CI ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against the published registry tarball: - HIGH: exports.require -> dist/index.cjs which is never built nor published - MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload - stdio-only server described as dual-transport; mixed dot/underscore tool names; double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates; ruview bin-name collision ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix (test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only with npm provenance, version single-sourcing from package.json, bin/namespace ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs. Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * fix(npm): implement ADR-263/264/265 — harness fail-closed + async MCP, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * ci(ruview-cli): pass jest --passWithNoTests so the private no-test package doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net> * fix(npm): address 10 verified review findings in harness + rvagent before 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> e6f26e9
…R-263/264/265 optimization strategies (ruvnet#1229) * docs(adr): deep review of the RuView npm surface — ADR-263/264/265 optimization strategies ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9): - HIGH: claim-check CLI fails open on empty input (no --text/--file -> PASS exit 0) - HIGH: MCP stdio server head-of-line blocking (spawnSync verify/calibrate up to 600s) - MEASURED: optionalDependencies triple the cold npx install (4 pkgs/620kB/71 files vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them - maxBuffer truncation, python -c port interpolation, version drift, duplicate skills, guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding claim-check on these very ADRs), zero CI ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against the published registry tarball: - HIGH: exports.require -> dist/index.cjs which is never built nor published - MEASURED: 44 dead source-map files = 62,698B of the 188kB unpacked payload - stdio-only server described as dual-transport; mixed dot/underscore tool names; double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates; ruview bin-name collision ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix (test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only with npm provenance, version single-sourcing from package.json, bin/namespace ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs. Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * fix(npm): implement ADR-263/264/265 — harness fail-closed + async MCP, rvagent packaging/transport/naming, npm CI+provenance gate ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz * ci(ruview-cli): pass jest --passWithNoTests so the private no-test package doesn't fail the npm-packages matrix Co-Authored-By: claude-flow <ruv@ruv.net> * fix(npm): address 10 verified review findings in harness + rvagent before 0.2.0 publish harness/ruview (@ruvnet/ruview): - guardrails: digit gate now sees numbers inside code spans; F1-style metric tokens followed by ':' or a nearby number are no longer scrubbed (fail-open regressions in the honesty gate) - mcp-server: tools/call requests serialize through a FIFO promise chain (hardware/mutating tools never overlap) while ping/tools/list stay immediate; stdin close drains in-flight responses before exit - tools: which() no longer memoizes negative lookups tools/ruview-mcp (@ruvnet/rvagent): - index: realpath invoked-directly guard — library import no longer connects a stdio transport to the consumer's process - http-transport: explicit allowedOrigins is exact-match only (localhost any-port convenience applies only with no configured allowlist); session map gains maxSessions=64 + 5min idle TTL sweep - train-count: job records persist the child pid and reconcile stale 'running' status after a server restart (exit-code marker or dead pid) - config: cog binary candidates ordered by process.arch .github/workflows/ruview-npm-release.yml: port the full ADR-265 D1 gate (version-literal check, unpacked-size budget, tarball-install smoke test) from npm-packages.yml so the publish path enforces what the header claims. Tests: harness 30→36, rvagent 99→112, all passing. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> e6f26e9
ADR-263 — @ruvnet/ruview@0.1.0 harness review (O1–O9):
vs 1 pkg/172kB/22 files with --omit=optional) for a path that never imports them
guardrail METRIC_TERMS substring false positives ('map'/'F1' — found by dogfooding
claim-check on these very ADRs), zero CI
ADR-264 — @ruvnet/rvagent@0.1.0 + @ruv/ruview-cli review (O1–O9), verified against
the published registry tarball:
double Zod validation + hand-duplicated advertised schemas; 2-fd leak per training
job; unbounded body in the unwired HTTP scaffold; dead detectCogBinary candidates;
ruview bin-name collision
ADR-265 — cross-cutting npm distribution strategy: npm-packages.yml CI matrix
(test + pack-content/size gate + tarball-install smoke test), publish-from-CI-only
with npm provenance, version single-sourcing from package.json, bin/namespace
ownership (ruview bin belongs to @ruvnet/ruview), claim-check on package READMEs.
Docs only — no runtime code changed. Index/CHANGELOG/CLAUDE.md/README counts updated.
Co-Authored-By: claude-flow ruv@ruv.net
Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz