chore(release): version packages#3939
Open
github-actions[bot] wants to merge 1 commit into
Open
Conversation
d8502aa to
fd45c54
Compare
fd45c54 to
eed75d5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
nexus-agents@2.133.0
Minor Changes
#3958
6139fe7Thanks @williamzujkowski! - feat(governance): convert the authentic vote-record ledger from a linear hashchain to a tamper-evident record SET + monotonic sequence (#3927 PR-1).
The
governance/vote-records.jsonlledger is a multi-branch committableartifact, so the chain model (each record's hash folding in the prior record's
hash) could not survive a concurrent-branch git merge. The revised model
(design vote 7-0, Option B) treats the ledger as an unordered SET of self-hashed
records plus a monotonic
sequence:sequencefield (integer ≥ 0); recordversionbumped1.0→1.1.previousHashis now advisory/optional and NOT verified.sequencebut EXCLUDESpreviousHash, so hashes areposition-independent and stable across merges and file reorders.
verifyVoteRecordChain→verifyVoteRecordSet. New verification reasons:sequence_gap(omission) added;previous_hash_mismatchremoved. Duplicatesequences are a benign concurrent-fork signal (surfaced as
forks), not afailure.
.gitattributes:governance/vote-records.jsonl merge=unionfor conflict-freeappend merges.
The separate audit-event/tier-transition chain is unchanged (single-writer
runtime — still a real chain). Fail-closed enforcement is deferred to PR-2; this
seam remains warn-only/unenforced.
Patch Changes
#3955
2301cafThanks @williamzujkowski! - test(ci): collect repo-root script tests in the CI run (#3952)The package vitest config only globs
packages/nexus-agents/src/**, so thescripts/**/*.test.tsfiles (the doc generators and drift gates shipped in#3688/#3949 and others) were never collected by CI — they passed locally but
gave zero CI protection. This adds a root
vitest.config.tsthat collects them(excluding stale
.claude/worktree copies), atest:scriptsnpm script, and aScript TestsCI job that buildsnexus-memoryfirst then runs the suite.Collecting these tests immediately surfaced a real bug masked by the missing
coverage:
scripts/check-mcp-description-drift.test.tspassed the rawTOOL_MANIFESTobjects tobuildDriftReport(which expects tool names, asthe CLI gate does), so every lookup missed; fixed to
.map((t) => t.name).scripts/inject-governance.test.tsis scoped out for now: it spawns ~30npx tsxsubprocesses that mutate shared repo files in place, takes ~400s solo, andis flaky under the forks pool. The governance
checkit exercises is alreadygated in CI via
docs-check.yml, so its protection is not lost. Tracked for aparallel-safe/fast rework in #3954.
#3957
2f17822Thanks @williamzujkowski! - test(cli): command-metadata parity gate to prevent dispatch/catalog drift (#3212)Add
command-parity.test.tsasserting the real invariant between the threeparallel command-name structures — the dispatch tables (
cli-commands.ts),COMMAND_CATALOG(cli-command-catalog.ts), andVALID_COMMANDS(
cli-types.ts) — so drift (e.g. #3713'sauto-remediatesilentMCP-server fallthrough) fails CI with the offending command named.
The gate asserts: dispatch ⊆ catalog, catalog ⊆ dispatch, and
VALID_COMMANDS== dispatchable, with a small documentedALLOWED_ASYMMETRYallowlist (
(default)catalog pseudo-entry; special-casedhelp/version).Adds a minimal
listDispatchableCommands()export tocli-commands.tsandexports the existing
VALID_COMMANDSconst so the test derives sets from thereal dispatch tables rather than re-listing names. No dispatch refactor, no
unified registry, no new CLI command or MCP tool.
#3941
89b048eThanks @williamzujkowski! - refactor(cli): unify exit handling under CommandResult (#3210)CLI command handlers in
cli-commands-handlers.tsandcli-commands-handlers-complex.tsnow RETURN aCliExitResult(aCommandResultcarrying anexitCode) instead of callingprocess.exitinline. The single
process.exitboundary lives in the dispatcher(
dispatchCommand→exitWith). Exit codes are identical to before forevery path — this is a behavior-preserving structural refactor, not a
behavior change. Handlers that own the process lifecycle (the MCP stdio
server, the
sessionvalid-subcommand path) intentionally returnundefinedso the dispatcher does not force an exit, preserving priorevent-loop-drain behavior.
#3944
95b9bfdThanks @williamzujkowski! - docs: add "Configuration for Reusable Pipelines" section to CONFIGURATION.md (#3253)Documents configuration composition and the project-level vs user-level split:
how billing mode, data dir / repo-preferred, and model tiers / sandbox affect a
composed pipeline; which settings belong in a committed project config vs
per-user environment overrides; and how the loader resolves them (single-file
selection, first match wins, with env vars overlaying per-setting). Claims
verified against
config-loader.ts,nexus-data-dir.ts, anddecision-cost-recording.ts.#3938
b627cb3Thanks @williamzujkowski! - feat(cli): suggest closest command on unknown subcommand (#3211)An unrecognized top-level subcommand (e.g.
nexus-agents reviw) previouslyfell through silently to the MCP stdio server. It now prints
Unknown command 'reviw'. Did you mean: review?plus the usage hint and exitsINVALID_ARGS. Suggestions are typo-tolerant via Levenshtein distance (capped at
distance 2 and ~40% of the input length), ranked nearest-first, up to 3. When
nothing is close, only the usage hint is shown — behavior is otherwise
unchanged. The shared Levenshtein helper is extracted to
string-distance.tsand reused by the env-var typo detector.
#3943
190e671Thanks @williamzujkowski! - refactor(cli): finish CommandResult migration + explicit lifecycle sentinel (#3942, completes #3210)Completes the #3210 migration started in #3941. Every CLI command handler
dispatched from
cli-commands.tsnow RETURNS its exit code instead of callingprocess.exitinline; the singleprocess.exitlives at the dispatcherboundary in
exitWith(). Migrated behavior-preservingly (exit codesbyte-identical): auth, login, usage, release-notes/validate/announce, scaffold,
visualize, capabilities, mode, scenario, validate, migrate, memory-benchmark,
status, health, improvement-review, auto-remediate, remediation-review.
Adds an explicit
LIFECYCLE_DELEGATEDsentinel (+LifecycleDelegatedtype andisLifecycleDelegatedguard) tocli-types.ts. Lifecycle-owning handlers (theMCP stdio server, the session valid-subcommand path) now RETURN the sentinel
instead of a bare
undefined/void. Every handler is typedCliExitResult | LifecycleDelegated(CliHandlerResult) with noundefined/voidmember, so a dropped return is a compile error (TS2366) rather than asilently-swallowed exit code.
exitWithhandles the union exhaustively. The twoeslint-disable @typescript-eslint/no-invalid-void-typesuppressions areremoved.
#3940
c0d3c3fThanks @williamzujkowski! - feat(cli): expose mode detection for inspection (#3214)Add a
nexus-agents modesubcommand that prints the detected invocation mode(server vs orchestrator), the signals that fed the decision (MCP client, stdin/
stdout TTY, CI platform, container) with their observed values, and the one-line
reasoning. Previously the detection in
mode-detector.tswas only reachableinternally, so users had no way to see why a given mode was chosen when
debugging CI/container issues. Supports
--format=jsonfor scripting and--mode=<m>to report what an explicit override would resolve to.#3946
7f1fa54Thanks @williamzujkowski! - docs: correct the Configuration Precedence section to match the loader (#3945)The section claimed a 4-level merge (env → project → user → default) with a user
config at
~/.config/nexus-agents/config.yaml. The loader (config-loader.ts)actually selects ONE file (first match wins:
NEXUS_CONFIG_PATH→ project./.nexus-agents/nexus-agents.yaml/./nexus-agents.yaml→ user~/.nexus-agents/nexus-agents.yaml), layered over defaults, with env varsoverlaying per-setting at consumption time — not a multi-file merge, and not the
~/.config/...path. Corrected to the real behavior; consistent with the"Configuration for Reusable Pipelines" section (#3253).
#3947
943e21fThanks @williamzujkowski! - fix(remediation): isolate soak/shadow tests from the production data dir (#3932)The auto-remediation cycle's default durable soak sink resolves under
NEXUS_DATA_DIR(falling back to~/.nexus-agents/learning/remediation-soak.jsonl).Audit-mode cases in
auto-remediation-cycle.test.tsranrunAutoRemediationCyclewithout injecting a
soakSink, so synthetic fixture records (signalKeysa/b)were written into the operator's real home-dir soak file — inflating the
enforce-readiness
volumecriterion with non-real data.The cycle test now pins
NEXUS_DATA_DIRto a throwaway temp dir for the wholesuite (with singleton reset + cleanup), a regression guard asserts the soak file
resolves under the temp data dir and never the home dir, and the readiness read
path now drops structurally-implausible soak records (signalKeys lacking the real
category:detailshape) as defense-in-depth so junk can't inflate the volume count.#3956
18a4185Thanks @williamzujkowski! - refactor(mcp): table-driven MCP tool registration seeded fromTOOL_MANIFEST(#3266)Collapse the per-tool registration wiring in
cli-server-tools.ts(the partialSTANDALONE_TOOLStable + five grouped helper functions + the category-dispatchregisterToolCategories) into a single declarativeHANDLER_TABLEkeyed byRegisteredToolNameand driven off the canonicalTOOL_MANIFEST. Adding a toolnow needs one manifest entry plus one handler row.
TOOL_MANIFESTstays thesingle source of truth; the registry derives from it, and
assertHandlerManifestParityfails loudly at registration if the table and themanifest disagree (a manifest entry with no handler, or a handler with no
manifest entry). No module-load self-registration, no dynamic-extension export —
tools remain statically declared. Behaviour-preserving: same 46 tools, same
order, same shared-instance wiring (expert registry, workflow engine), same
annotations/side-effects/tiers. MCP_TOOL_COUNT guard unchanged at 46.
#3951
fd4aa06Thanks @williamzujkowski! - docs(reference): single-source per-tool MCP schemas from Zod; slim ENTRYPOINTS (#3688)The hand-maintained ~590-line "Tool Schemas" JSON block in
docs/ENTRYPOINTS.mdduplicated the runtime Zod input schemas and silently drifted. Per the
vote-decided Option C, that detail is now single-sourced.
scripts/generate-tool-reference.ts(the existing #3687 generator) isre-sourced from static regex parsing to Zod v4's native
z.toJSONSchema(InputSchema, { io: 'input' }). The generated per-tool pagesin
docs/reference/tools/gain a Constraints column carrying the fullinput contract — enum members (previously only an opaque
*Schemaref name),minLength/maxLength, min/max (incl. exclusive), pattern, format, and
.default()values. No new generator: the existing CI drift gate(
pnpm docs:tools:check, the "Tool Reference Drift" job) covers it unchanged.docs/ENTRYPOINTS.md: the### Tool Schemasblock is removed (~590 lines)and replaced with a link to the generated MCP Tool Reference. The curated
index (Overview, Quick Reference, CLI Commands, the auto-injected MCP tool
list, Usage Examples, Workflow Templates) is unchanged.
scripts/generate-tool-reference.test.tsasserting the constraintextraction and the committed-vs-fresh drift contract.
Docs-only; no CLI command or MCP tool added or changed.
#3950
c5a73deThanks @williamzujkowski! - docs: expand the generated TypeDoc API reference (/api/) from the singlesrc/core/result.tsentry point to the full curated public surface — the 19 non-test barrels undersrc/exports/(core, config, adapters, agents, agents-skills, agents-ictm, workflows, mcp, cli-adapters, context, learning, audit, security, consensus, observability, orchestration, benchmarks, pipeline, scm). The website renders the committeddocs/api/markdown via the existing/api/[...slug]route (no prebuild re-added). Generation stays decoupled viapnpm -C packages/nexus-agents docs:api:md.#3948
5c12a37Thanks @williamzujkowski! - docs(site): render generated TypeDoc markdown as the website API reference (#3763)Wires the generated TypeDoc markdown (JSDoc -> typedoc + typedoc-plugin-markdown,
spike #3686) into the website as a dedicated, rendered API-reference section.
apiAstro content collection (website/src/content.config.ts) loading thecommitted generated markdown from
docs/api, sharing the docs frontmatter schema.website/src/pages/api/[...slug].astrorendering the collection (with thegenerated
indexpage mapped to the/api/section root).api/**from thedocscollection so the API reference renders only under/api/instead of being lumped into/docs/api/.docs:api:mdas the websiteprebuildso the markdown is regenerated beforeastro build.Frontmatter compatibility was already solved at generation time: the existing
typedoc-plugin-frontmatter + scripts/typedoc-astro-title.mjs inject the
title/description/tierfrontmatter the Astro collection schema expects.Scope: the API surface stays scoped to the spike's single canonical entry point
(
src/core/result.ts); expanding entry points across the 8740-export surface is afollow-up.
#3959
3a9c133Thanks @williamzujkowski! - fix(governance): surface + override vote-record persistence skip so authentic votes aren't silently lost (#3927)When the MCP server runs with a
process.cwd()outside the repo,resolveVoteRecordsPath()returnedundefinedandpersistVoteRecord()skipped the write at DEBUG level — real consensus votes were lost with no visible signal. The skip is now an actionable WARN, and aNEXUS_VOTE_RECORDS_PATHenv var lets you force the write to an explicit absolute path. Precedence:opts.filePath>NEXUS_VOTE_RECORDS_PATH>findRepoRoot(process.cwd()). Caller-commits (the proposer commits the returned record bytes intogovernance/vote-records.jsonlin the promotion PR) remains the authoritative population path per the 7-0 design vote; this is observability + an escape hatch, not enforcement.