Repository navigation
refactor: remove duplicated catalogs, tests and guardrails, drop operate from VS Code - #492
Merged
Merged
Conversation
The three per-engine catalogs were byte-identical (the engine patches were all empty), so the npm bundle and the standalone executable carried the same 1.6 MB catalog three times. Every adapter now reads src/generated/catalog.json; the empty spec/engines patch files, the per-engine generator loop and the dependency rule that tied an adapter to its own catalog file go. A diverging engine gets a catalog of its own again when it needs one. npm bundle dist/pulse-cli.js: 5,563,120 -> 2,311,498 bytes; standalone build/standalone/pulse-cli.cjs: 5,665,866 -> 2,414,244 bytes.
`pulse-cli guide <topic>` printed six hand-written topic pages that restated docs/cli (configuration, authentication, commands, output and errors, workflow commands, recipes). The topics now are those docs pages, bundled as text (tsdown's .md text loader for the npm bundle and the standalone build, a small vitest transform for the tests), so the command still works offline and the docs are the single source. The few agent-only facts the topics carried move into the pages (agents never run auth login, non-JSON responses and --out-file, the notable workflow options). The topic pages' own content and size tests go; the docs pages keep their budgets and run every command line already, and a test pins each topic to its docs page. docs/cli now also triggers the CLI's build scope in CI and the turbo cache of its build.
The bearer resolution rules (token sources and precedence, normalization, conflicts, expiry, their error texts) are asserted by the unit tests of src/config/ and src/auth/. The run() tests keep one case per wiring path; the Testcontainers suite keeps only what needs the gateway or Keycloak (17 of 27 cases dropped, including the TOKEN_EXPIRED wait on a 5 s token).
…s through one helper each registerDataFeed (data-feeds.ts), registerShowTool (widget-tools/shared.ts) and adapterStep (steps/shared.ts) write the registration frame once; the call sites hand the builders their arguments by rest destructuring instead of copying them field by field. The tools/list goldens are unchanged.
registerSettingsSection (@miragon/pulse-widget-shell/server) registers a module's show tool, app-only feed and gated save tool, derives canSave and the optional readOnlyReason from the one save decision, refuses a keyless save and stamps the OAuth caller as owner. The shell, camunda7 and analytics sections use it; one contract test replaces the per-module duplicates. Tool names, schemas, annotations and payloads are unchanged (tools/list goldens untouched).
nothing-imports-the-cli and nothing-imports-the-extension tripped only together with packages-never-import-the-app or apps-never-import-apps: every planted case of theirs already carried one of the two. extension-is-not-an-mcp-host repeated what the extension's closed-world config (apps/vscode/.dependency-cruiser.cjs) refuses anyway: a planted widget-shell, client, React, zod, mcp-use, toolkit or TanStack import in the host or the webview fails there as not-in-allowed and not-to-unresolvable. RESERVED_APP_NAMES guarded apps that do not exist (the list was empty); the declaration check for the real apps stays. Ratchet-Exception: removes the depcruise rules nothing-imports-the-cli, nothing-imports-the-extension (covered by packages-never-import-the-app + apps-never-import-apps) and extension-is-not-an-mcp-host (covered by the closed-world apps/vscode/.dependency-cruiser.cjs), plus the empty RESERVED_APP_NAMES list of check-package-naming (guarded no existing app)
No workspace package is a -domain package, yet three dependency rules (connectors-own-their-domain, domains-are-leaves, domains-are-pure), the -domain carve-out of cli-is-headless, a no-restricted-globals block in eslint.config.mjs and a third role suffix in the naming gate guarded it, each with its planted cases. The CLI now imports no workspace package at all, and a connector-family package is a -connector or a -client. A package two interfaces share is extracted on its second consumer, with the rules it needs then. Ratchet-Exception: removes the depcruise rules connectors-own-their-domain, domains-are-leaves and domains-are-pure, the no-restricted-globals block for packages/connectors/*/*-domain and the -domain naming role; no -domain package exists, so they guarded nothing
…rom source check-ratchets read eslint.config.mjs twice: an AST pass over the debt maps, every complexity/max-lines/no-restricted-syntax setting and every shape it could not see into, and the effective config ESLint itself computes per file (eslint-effective-config.mjs), which already fails a raised or dropped budget, a gate rule switched off or to warn and a file newly ignored. The AST pass now keeps only what the effective check cannot see: an ignores entry in a block of any other rule, and a local or dynamic import (the base config is evaluated next to today's files). The debt maps complexityRatchet and maxLinesRatchet were empty; they go with their spreads and the fitness report's debt line. Ratchet-Exception: drops the AST budget/debt-map/opaque-shape half of the eslint.config.mjs ratchet and the empty complexityRatchet/maxLinesRatchet maps; scripts/eslint-effective-config.mjs still fails every loosened complexity, max-lines or no-restricted-syntax setting and every newly ignored file, and the AST keeps ignores and local imports
lint:github keeps what protects the release credentials and the published set: the npm publish job's id-token and action pins, the publish matrix against the workspace with each package's repository, the release-please extra-files and plugin versions, the release gate, the CLI publish workflows' token shape, the VS Code publish path (one job in vscode-marketplace, the store tokens by name, never secrets: inherit, an install with --ignore-scripts and no build next to them) and the CI scope wiring, which keeps a failed changes job from passing as a row of skipped checks. Its test still runs the npm publish workflow's bash steps. Gone: the Dependabot group pins, the mirror of the ruleset's required checks, the Playwright pin sync, the report-artifact, nightly-mutation and Stryker incremental shape pins, the plain-release/dry-run/version and --skip-duplicate pins of the extension workflow, and the bash runs of the CLI release, tap update, extension Resolve and nightly steps. Ratchet-Exception: drops the lint:github checks checkDependabot, checkRequiredChecks, checkPlaywrightPins, checkArtifactGlobs, checkNightlyMutation, checkStrykerIncremental and the non-credential VS Code release pins; they pinned workflow shape, not credentials, and a broken shape shows up as a failed or missing run
check-package-naming parsed every @types/vscode range against
engines.vscode to refuse a types floor above the oldest VS Code the
extension admits. vsce refuses exactly that package ("@types/vscode ...
greater than engines.vscode"), and CI's "VS Code package (vsce dry run)"
job runs vsce package on every pull request in the extension's scope.
The naming gate keeps the extension's name and a non-empty
engines.vscode.
Ratchet-Exception: drops the @types/vscode floor check (versionFloor, compareVersions, checkVsCodeTypes) from lint:naming; vsce package, run by the CI "VS Code package (vsce dry run)" job, refuses the same package
APP_SCAN in source-scan.ts already named the three apps and their kind; on every scan it also walked apps/ to fail on an unclassified app, an entry naming no app, an app without src/ and an extension classified as an MCP server, each with its fixture test. The scan now reads the apps APP_SCAN lists; a new app adds its entry in the PR that brings it. Ratchet-Exception: drops the APP_SCAN classification checks (unclassified app, stale entry, app without src/, extension as mcp-host) and their self-tests; three apps exist and are listed, a new one adds its entry
The rename to Pulse is long done: old-names.test.ts no longer reads for the old npm scope, repo, docs URL, image, starter, slug, product name and Fly app names, nor for a capital in a GHCR path, and their allowances go. It keeps what still fails silently: the retired operate CLI's technical names, the unscoped npm package pulse-cli and an image off GHCR (the server's and the CLI's, now one rule). The pnpm filter checks (a --filter naming no workspace package, a pnpm filter without --fail-if-no-match on a gate path) move to scripts/check-package-scripts.mjs with their cases, so lint:package-scripts owns everything about how the workspace's packages are addressed. The Lint + Format job runs it next to docs-refs and old-names, so a docs-only pull request is still checked. Ratchet-Exception: drops the pre-Pulse name rules of old-names.test.ts (old scope, repo, docs URL, image, starter, slug, product name, Fly app names, image not lowercase); the rename shipped in 0.21.0 and nothing reintroduces those names; the filter checks moved unchanged to lint:package-scripts
pnpm test:mutation (scripts/mutation-diff.mjs) mapped a branch's changed files onto each package's mutate list, capped the run at 25 files behind a Mutation-Cap-Exception trailer and called each package's test:mutation script, which lint:package-scripts held to the plain `stryker run`. It is a local, on-demand helper no gate runs. The developer docs now give the command per package instead, `pnpm --fail-if-no-match --filter <package> exec stryker run` (`--mutate <file>` narrows it), and the nightly workflow calls `exec stryker run` the same way. The stryker.config.json files and the nightly run stay as they are. Ratchet-Exception: drops the root and package test:mutation scripts (gate commands pinned by check-ratchets) and scripts/mutation-diff.mjs with its tests; no CI job ran the diff runner, the nightly run now calls stryker run directly, and lint:package-scripts still holds every stryker.config.json
The C7 adapter no longer bundles and spawns the retired operate CLI. A small REST client inside the adapter (apps/vscode/src/adapters/c7/engine-rest) sends every call with fetch: no redirects, a 60 s deadline, at most 64 MiB of an answer, basic auth from the target, lossless JSON, every page of a list, and a read connection that refuses writes. The instance inspection operate's `inspect` did (called instances, wait states, root incidents with their stack traces, the history of activities, scope variables) and its incident retry are ported into the adapter; the error classification and redaction read HTTP statuses instead of exit codes. Gone: the engine-cli wrapper, its build step and dist/engine-cli.js, the @miragon/operate dependency, the engine-cli tests and fixtures, the engine-cli-wrapper-is-self-contained rule and the operate allowances of old-names. The conformance kit passes all 61 laws on operaton 2.1.5, cibseven run-2.2.0 and camunda run-7.24.0. Refs #470
Each of the 23 mapper classes had one implementation and one user. Their translations are now private methods of the reader that uses them; the Mapper interface and the wiring in C7ProcessRuntime.create are gone. What several readers share (definition refs, instance states, timestamps, root incidents) stays a static utility in mapping/. Rule 4 of code-structure.md no longer asks for mapper classes: a translation with one user is a private method of that class.
Every rule an agent follows stays. A rule a gate enforces is now one sentence plus the gate's name; the mechanics the gate already carries (and its failure message explains) go. Rules no gate enforces keep their reason. Invariant numbering, the section headings and the German Design-System section with its owner decisions stay. Fixes drifts: SANCTIONED_TOKEN_MANIFESTS lists the docs kit and the VS Code webview theme, not only the kit; the extension's npm name is pulse-cockpit; the CLI has one command catalog; the releases section points at the trimmed lint:github instead of restating its removed pins.
✅ Deploy Preview for spectacular-cobbler-f6c85b ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
emaarco
marked this pull request as ready for review
October 28, 2026 07:12
emaarco
enabled auto-merge (squash)
October 28, 2026 07:12
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.
Why
A dependency analysis found code, tests and guardrails that exist two or three times, or guard things that do not exist. This PR removes them, one commit per step, so each can be kept or dropped on its own. Net −102,600 lines, about −6,400 without the two duplicate generated catalogs.
What
CLI
pulse-cli guide <topic>prints the bundleddocs/clipage instead of a copy kept in code.MCP
registerDataFeed,registerShowTool,adapterStep).registerSettingsSectionfor shell, camunda7 and analytics.VS Code
.vsixshrinks from about 710 to 390 KB.Guardrails (each commit carries a
Ratchet-Exception:trailer with its reason)-domainrole no package has.check-ratchets: drops the AST half thateslint-effective-configcovers.check-github-config: trimmed to the publish security core.@types/vscodefloor check (vsce refuses the same thing) and the pre-Pulse name rules. The--filterchecks move tocheck-package-scripts.APP_SCANis now a fixed list, andmutation-diffis replaced by a documentedstryker run.Docs
CLAUDE.md: goes from 1,180 to 589 lines. A gated rule is one sentence plus its gate; ungated rules keep their reason.Verification
pnpm build && pnpm typecheck && pnpm test && pnpm lint && pnpm format:checkpassed per commit and on the combined branch.lint:ratchetsreports no loosened floor, debt list,mutatelist or knip ignore.test:engines: 61/61 on Operaton 2.1.5, CIB seven 2.2.0 and Camunda 7.24.ENVOY_UID: "0", whichmainneeds too; that change is not part of this PR.Breaking changes
NODE_EXTRA_CA_CERTSno longer applies.HTTP <status>: <message>.pulse-cli guide <topic>: it prints the docs page.Out of scope / Follow-ups
APP_SCANandAPP_PACKAGESby hand.Refs #470