epic #250: Rewrite every component invocation to name a toolkit, behind a build-time gate - #328
Merged
Merged
Conversation
The invocation gate lands first, against the sites as they are. One scanner walks the same shipped bodies the payload-composition boundary walks, extracts every invocation written in a code span — fenced or inline — and classifies it against a closed set of addressing forms: the two named-toolkit forms and the legacy repository-bound ones (transpiler-against-script, interpreter-against- script, runtime-against-bundle, workspace script alias), plus a repository-bound artifact named with no command around it. Each toolkit's surface is read from the surface itself. The executable's dispatch names are derived from the registry that composes its own usage text, which now declares each subverb so the dispatcher and the gate read one list — the full dispatch name is what gets checked, because the commonest realistic typo lives in the second token. The Python toolkit gains a machine-readable capability listing beside its human diagnostic, so the gate never scrapes prose. Migration state is an explicit register of not-yet-migrated bodies. A body absent from it must be fully migrated: any legacy form found there fails the build by name. The register only shrinks; reaching empty is this epic's completion condition. Closes #301
Every shipped command and skill body now names `nexus` and a verb where it named a repository-relative script, a vendored bundle, or a workspace script alias. Each value crosses as its own argument; nothing is interpolated into a path or an executable name. The alternative-invocation passages go with the paths that motivated them. A body that told the reader to run the script here and the bundle there was offering one capability twice, and unified addressing leaves one command with no choice to make. The distill stage's single-repo/hub branches keep their shape for now — both sides name the same verb, and #304 collapses them while preserving the mode-conditional instructions the hub side carries. With no body naming them, the seven legacy skill scripts are deleted, which empties the payload-composition waiver register — the completion condition that register recorded — and retires the script-versus-verb parity axis that existed only to compare them. The specs that entered those capabilities through a script now enter through the maintainer's one from-source command shape, which is documented in the feature's own README and appears in no shipped body. Closes #302
Every shipped body that reached a Python capability through a script path now names `nexus-gh` and the capability. Twenty-three of those sites named a bare `python`, and nine wrote a working-directory-relative path that resolved only from inside the skill directory; both are gone, and the capability resolves the same way from any working directory because the entry point self-locates. That was the last body carrying a repository-bound form, so the pending register reached empty — the completion condition it recorded — and is deleted. Tolerance is not a parameter with nothing in it: the verdict now fails any legacy form wherever it sits, so a reintroduced script path, bundle path, workspace alias or bare `python` fails the build immediately. The acceptance harness, which drove the same two capabilities through paths that no longer exist, reaches them through the toolkit entry point in the checkout it was pointed at. Closes #303
The distill stage described three capabilities twice each — once for a single-repository drain, once for a hub — and the two copies could diverge with nothing to catch it. With addressing unified the two sides said the same thing, so they collapse to one command. Only the addressing branch goes. Everything the run mode still governs survives, restated as a condition on arguments rather than on which program to run: a hub still passes every page path and git ref as its own quoted token, its regenerated anchor sidecars are still validated alongside the pages, and a member repo still does not drain. The step that used to select a runner now states those rules and keeps its number, because eight passages elsewhere cite it by number. Two other bodies described one capability in two places — the worktree removal in analyze, and the epic filer's plain form repeated as its own first example. Each is stated once now. No new check ships with this: what made the branch possible was a second addressing form, and the build gate rejects that unconditionally. Closes #304
An unbalanced inner fence marker inverted codeSpans' fence state and silently un-gated every invocation after it in that body. Three component bodies already nest 3-backtick fences inside 4- and 5-backtick ones, so only their correct-by-accident balance held the gate up. Follow CommonMark instead: an opening fence records its backtick run length, and only a marker at least that long with nothing trailing it closes it. A shorter marker, or one carrying trailing text, is fence content. Latent in the live tree — invocation counts are unchanged — so this changes no verdict today, only what a future body can do to the gate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ga8zCem6NqbJ62BKrZURcB
Reconciles the invocation rewrite with #257 (vendored tools retired) and #252 (one published package), both of which landed on main after this branch was implemented. - nxs.distill: Phase 5.3 keeps this branch's mode-conditional bullets, with main's unconditional quoting rule lifted above them; the derive-entry-diff remediation drops the pointer to the retired hub-tooling-install document. - nxs.epic, nxs.setup, nxs-workspace-status: the "portable CLI instead" paragraph goes — one named invocation covers both toolchains. - parity.spec.ts: main's payload-manifest pin and per-verb parity helpers, plus this branch's component-invocation gate; the #274 verb-vs-standalone axis retires with the #272/#273 script axes, since #252 left no standalone artifact to compare against. - bundle-fingerprint.json and payload-manifest.json re-pinned; the manifest drops the seven deleted skill scripts. `pnpm nexus:release-gate` — #252's invariant-15 gate, red on main — is now green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011o2Jo7QZ59YpauqUMGmLPz
sameera
marked this pull request as ready for review
August 27, 2026 21:48
Owner
Author
Every acceptance criterion across the four stories is met, no decision-record invariant is broken, and all five success metrics are both moved and measurable through the parity gate. The two low findings are documentation-adjacent and outside every AC; neither blocks close. epic: "#250"
nexus_version: 0.1.0
pr: 328
date: 2026-08-27
head: 4aa418c6dc39163345ace569582fa581480f3e16
mode: full
record: "#325"
record_hash: b4c02eedcdc8089d7943145214dd9abc80feb6e2ff52a77245b4b4ed1b4fec2a
findings: { critical: 0, high: 0, medium: 0, low: 2 } |
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.
Implements the story sub-issues of #250, one commit per story in blocked_by order.
Each commit body carries its own
Closes #<story>line, so merging this PRinto
maincloses the stories it implements. The epic itself closes through/nxs.close, not by merge.Draft opened by
utils/implement-epic.sh;/nxs.analyzeruns against it next.