Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ running package installs.
## Workflow Skills

DevNexus TypeScript ships baseline workflow skills for TypeScript diagnosis,
bounded refactoring, project topology, test hygiene, API boundary review, and
dry-run codemod planning. The plugin config declares them as `projected_skill`
capabilities, and the package also exports DevNexus skill definitions for
projects that materialize package-owned skills:
bounded refactoring, project topology, quality feedback, test hygiene, API
boundary review, and dry-run codemod planning. The plugin config declares them
as `projected_skill` capabilities, and the package also exports DevNexus skill
definitions for projects that materialize package-owned skills:

```ts
import {
Expand Down Expand Up @@ -162,6 +162,9 @@ attention to new bugs, vulnerabilities, security hotspots, and critical or
blocker findings. Rule playbooks cover `typescript:S3776`, `typescript:S5852`,
and `typescript:S4036`; their references point to SonarSource guidance on
cognitive complexity, regex backtracking, quality gates, and PATH trust review.
The plugin advertises these operations through its MCP capability list and
projects the `typescript-quality-feedback` skill so agents know when to use the
snapshot, delta, and rule playbook workflow.

## Boundaries

Expand Down
87 changes: 87 additions & 0 deletions skills/typescript-quality-feedback/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
name: typescript-quality-feedback
description: TypeScript quality feedback workflow for using diagnostics, import graphs, Sonar JSON snapshots, touched-file deltas, and rule playbooks before and after source changes. Use when Codex must audit or improve TypeScript quality, triage Sonar findings, or avoid introducing new quality regressions.
---

# TypeScript Quality Feedback

Use this skill when working on TypeScript or JavaScript source quality.

1. Start with setup facts. Confirm the project has local dependency context,
TypeScript, a selected `tsconfig`, and usable package scripts. Report setup
blockers instead of installing packages or fetching tools automatically.
2. Take a read-only baseline before editing when quality tools are available:
TypeScript diagnostics, import graph cycles, and any local Sonar JSON exports.
3. Scope the work to touched files unless the work item explicitly asks for a
broad cleanup. Avoid hiding old debt behind unrelated edits.
4. After editing, compare before/after quality snapshots for touched files.
Call out new bugs, vulnerabilities, security hotspots, critical/blocker
findings, failed quality-gate conditions, diagnostics, and import cycles.
5. Treat new bugs, vulnerabilities, security hotspots, and critical/blocker
findings as stop-and-fix issues unless the user or project policy explicitly
accepts the risk.
6. Use focused verification first, then the nearest package check. Keep Sonar or
Docker-backed scans local unless the project has an explicit CI policy.
7. In the handoff, report the touched-file quality delta, serious remaining
findings, verification commands, and any deferred debt.

## Rule Playbooks

### `typescript:S3776` Cognitive Complexity

Preferred fixes:

- Extract helpers around cohesive decisions or output construction.
- Replace deep nesting with guards, early returns, or named predicate helpers.
- Move repeated condition matrices into data-driven policy tables when that
matches the domain.
- Keep behavior tests around the original path before splitting a large
function.

Defer when the code is generated, adapter glue, or safer to split after a
broader boundary change. Do not create single-use helpers that make names worse
than the original branches.

References:

- https://www.sonarsource.com/resources/cognitive-complexity/
- https://www.sonarsource.com/blog/5-clean-code-tips-for-reducing-cognitive-complexity/

### `typescript:S5852` Regex Backtracking Risk

Preferred fixes:

- Remove nested or overlapping quantifiers on attacker-controlled or unbounded
input.
- Constrain repetition with explicit character classes, anchors, and length
bounds.
- Replace the regex with a parser or linear scan when the accepted language is
not simple.
- Add worst-case tests for long non-matching inputs when the path stays regex
based.

Defer only when the input is trusted, tightly bounded, and that bound is
enforced nearby, or when a proper parser needs separate design work.

References:

- https://www.sonarsource.com/blog/crafting-regexes-to-avoid-stack-overflows/
- https://community.sonarsource.com/t/write-efficient-error-free-and-safe-regular-expressions-in-javascript-and-typescript/47720

### `typescript:S4036` PATH Trust Boundary

Preferred fixes:

- Resolve executable paths from trusted configuration or an allowlist instead of
ambient `PATH`.
- Sanitize `PATH` before process launch when ambient lookup is required.
- Keep process launch policy behind one helper so callers cannot bypass it.
- Test that untrusted path entries are rejected or ignored.

Defer when the command is deliberately interactive developer tooling and the
trust model is documented, or when a proper fix depends on a broader credential,
runner, or host-policy boundary.

Reference:

- https://community.sonarsource.com/t/false-positive-for-rule-typescript-s4036/142908
4 changes: 4 additions & 0 deletions skills/typescript-quality-feedback/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "TypeScript Quality Feedback"
short_description: "Use TypeScript and Sonar quality feedback."
default_prompt: "Use TypeScript Quality Feedback to audit touched-file quality and apply the relevant rule playbooks."
14 changes: 14 additions & 0 deletions skills/typescript-quality-feedback/dev-nexus.skill.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "typescript-quality-feedback",
"name": "typescript-quality-feedback",
"description": "TypeScript quality feedback workflow for using diagnostics, import graphs, Sonar JSON snapshots, touched-file deltas, and rule playbooks before and after source changes. Use when Codex must audit or improve TypeScript quality, triage Sonar findings, or avoid introducing new quality regressions.",
"version": "0.1.0",
"license": "Apache-2.0",
"source": {
"type": "local",
"uri": "@evref-bl/dev-nexus-typescript/skills/typescript-quality-feedback"
},
"supportedAgents": ["codex", "claude"],
"materialization": "copy",
"sourceControl": "support"
}
60 changes: 59 additions & 1 deletion src/devNexusTypeScriptPlugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,14 @@ describe("DevNexus TypeScript plugin", () => {
"skill-typescript-diagnose",
"skill-typescript-refactor",
"skill-typescript-project-topology",
"skill-typescript-quality-feedback",
"skill-typescript-test-hygiene",
"skill-typescript-api-boundaries",
"skill-typescript-codemod-planning",
"mcp-typescript-diagnostics-tracer",
"mcp-typescript-import-graph-analysis",
"mcp-typescript-bulk-rewrite-planning",
"mcp-typescript-quality-feedback",
"context-typescript-toolchain-boundary",
"briefing-typescript-worktree-setup",
]);
Expand Down Expand Up @@ -200,6 +202,14 @@ describe("DevNexus TypeScript plugin", () => {
skillId: "typescript-project-topology",
targetAgents: ["codex", "claude"],
},
{
kind: "projected_skill",
id: "skill-typescript-quality-feedback",
description:
"Project the TypeScript quality feedback and Sonar rule playbook skill.",
skillId: "typescript-quality-feedback",
targetAgents: ["codex", "claude"],
},
{
kind: "projected_skill",
id: "skill-typescript-test-hygiene",
Expand Down Expand Up @@ -236,6 +246,7 @@ describe("DevNexus TypeScript plugin", () => {
"typescript-diagnose",
"typescript-refactor",
"typescript-project-topology",
"typescript-quality-feedback",
"typescript-test-hygiene",
"typescript-api-boundaries",
"typescript-codemod-planning",
Expand Down Expand Up @@ -297,6 +308,27 @@ describe("DevNexus TypeScript plugin", () => {
},
],
},
{
kind: "mcp_server",
id: "mcp-typescript-quality-feedback",
description:
"Advertise read-only TypeScript quality snapshot and delta operations.",
serverName: "dev-nexus-typescript",
command: devNexusTypeScriptMcpCommand,
args: [...devNexusTypeScriptMcpArgs],
tools: [
{
name: "typescript.qualitySnapshot",
description:
"Read TypeScript diagnostics, import cycles, and Sonar JSON into one quality snapshot.",
},
{
name: "typescript.qualityDelta",
description:
"Compare two TypeScript quality snapshots and highlight touched-file regressions.",
},
],
},
]);

const projected = projectPluginCapabilityProjections({
Expand Down Expand Up @@ -353,6 +385,26 @@ describe("DevNexus TypeScript plugin", () => {
},
],
});
expect(
projected[0]!.capabilities.find(
(capability) => capability.id === "mcp-typescript-quality-feedback",
),
).toMatchObject({
kind: "mcp_server",
serverName: "dev-nexus-typescript",
tools: [
{
name: "typescript.qualitySnapshot",
description:
"Read TypeScript diagnostics, import cycles, and Sonar JSON into one quality snapshot.",
},
{
name: "typescript.qualityDelta",
description:
"Compare two TypeScript quality snapshots and highlight touched-file regressions.",
},
],
});
});

it("provides worker guidance without package-manager mutation", () => {
Expand All @@ -366,6 +418,7 @@ describe("DevNexus TypeScript plugin", () => {
expect(contextFragment.body).toContain("does not choose or supervise");
expect(contextFragment.body).toContain("report missing dependency context");
expect(contextFragment.body).toContain("instead of silently fetching packages");
expect(contextFragment.body).toContain("quality snapshot");

expect(briefingFragment).toMatchObject({
id: "briefing-typescript-worktree-setup",
Expand All @@ -374,6 +427,7 @@ describe("DevNexus TypeScript plugin", () => {
expect(briefingFragment.body).toContain("Prefer existing package scripts");
expect(briefingFragment.body).toContain("Do not run npm, pnpm, yarn, or bun install");
expect(briefingFragment.body).toContain("instead of using npx package fetches");
expect(briefingFragment.body).toContain("critical/blocker findings");
});

it("exposes plugin capabilities through DevNexus projection helpers", () => {
Expand All @@ -386,7 +440,7 @@ describe("DevNexus TypeScript plugin", () => {
pluginId: "dev-nexus-typescript",
pluginName: "DevNexus TypeScript",
version: devNexusTypeScriptPluginVersion,
capabilityCount: 12,
capabilityCount: 14,
},
]);
expect(projected[0]!.capabilities.map((capability) => capability.kind)).toEqual([
Expand All @@ -397,6 +451,8 @@ describe("DevNexus TypeScript plugin", () => {
"projected_skill",
"projected_skill",
"projected_skill",
"projected_skill",
"mcp_server",
"mcp_server",
"mcp_server",
"mcp_server",
Expand All @@ -416,12 +472,14 @@ describe("DevNexus TypeScript plugin", () => {
"skill-typescript-diagnose",
"skill-typescript-refactor",
"skill-typescript-project-topology",
"skill-typescript-quality-feedback",
"skill-typescript-test-hygiene",
"skill-typescript-api-boundaries",
"skill-typescript-codemod-planning",
"mcp-typescript-diagnostics-tracer",
"mcp-typescript-import-graph-analysis",
"mcp-typescript-bulk-rewrite-planning",
"mcp-typescript-quality-feedback",
"context-typescript-toolchain-boundary",
"briefing-typescript-worktree-setup",
"context-typescript-setup-inventory",
Expand Down
4 changes: 4 additions & 0 deletions src/devNexusTypeScriptPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { TypeScriptProjectSetupInventory } from "./typeScriptProjectSetupIn
import { devNexusTypeScriptBulkRewritePlanningCapability } from "./typeScriptBulkRewritePlanning.js";
import { devNexusTypeScriptImportGraphAnalysisCapability } from "./typeScriptImportGraphAnalysis.js";
import { devNexusTypeScriptMcpDiagnosticsTracerCapability } from "./typeScriptMcpDiagnosticsTracer.js";
import { devNexusTypeScriptQualityFeedbackCapability } from "./typeScriptQualityFeedback.js";
import { typeScriptProjectSetupWorkerFragmentCapabilities } from "./typeScriptWorkerGuidance.js";
import { devNexusTypeScriptProjectedSkillCapabilities } from "./typeScriptWorkflowSkills.js";

Expand Down Expand Up @@ -44,6 +45,7 @@ export function devNexusTypeScriptDevNexusPluginConfig(
devNexusTypeScriptMcpDiagnosticsTracerCapability(),
devNexusTypeScriptImportGraphAnalysisCapability(),
devNexusTypeScriptBulkRewritePlanningCapability(),
devNexusTypeScriptQualityFeedbackCapability(),
{
kind: "worker_context_fragment",
id: "context-typescript-toolchain-boundary",
Expand All @@ -52,6 +54,7 @@ export function devNexusTypeScriptDevNexusPluginConfig(
"DevNexus TypeScript composes with DevNexus and does not choose or supervise implementation work.",
"It contributes TypeScript and JavaScript setup policy through DevNexus plugin capabilities.",
"Use projected dependencies when available, and report missing dependency context as a setup blocker instead of silently fetching packages.",
"For quality work, use read-only TypeScript diagnostics, import graph, quality snapshot, and quality delta tools before changing source.",
].join(" "),
targetAgents: ["codex", "claude"],
...targetComponents,
Expand All @@ -66,6 +69,7 @@ export function devNexusTypeScriptDevNexusPluginConfig(
"Prefer existing package scripts such as test, check, typecheck, lint, or build.",
"Do not run npm, pnpm, yarn, or bun install commands unless the project policy or user explicitly allows dependency installation.",
"If package binaries are unavailable, report the setup blocker instead of using npx package fetches as a substitute.",
"When touching quality findings, compare before/after quality snapshots for touched files and call out new bugs, vulnerabilities, security hotspots, and critical/blocker findings.",
].join(" "),
targetAgents: ["codex", "claude"],
...targetComponents,
Expand Down
22 changes: 22 additions & 0 deletions src/typeScriptQualityFeedback.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import fs from "node:fs";
import path from "node:path";
import type { NexusPluginMcpServerCapability } from "dev-nexus";
import { analyzeTypeScriptImportGraph } from "./typeScriptImportGraphAnalysis.js";
import {
traceTypeScriptDiagnostics,
type TypeScriptMcpTraceInput,
} from "./typeScriptMcpDiagnosticsTracer.js";
import {
devNexusTypeScriptMcpArgs,
devNexusTypeScriptMcpCommand,
devNexusTypeScriptMcpServerName,
} from "./typeScriptMcpServerConfig.js";
import type { TypeScriptImportGraphInput } from "./typeScriptImportGraphAnalysis.js";
import type { TypeScriptSetupFinding } from "./typeScriptProjectSetupInventory.js";

Expand Down Expand Up @@ -275,6 +281,22 @@ export function createTypeScriptQualityAnalyzer(): TypeScriptQualityAnalyzer {
};
}

export function devNexusTypeScriptQualityFeedbackCapability(): NexusPluginMcpServerCapability {
return {
kind: "mcp_server",
id: "mcp-typescript-quality-feedback",
description:
"Advertise read-only TypeScript quality snapshot and delta operations.",
serverName: devNexusTypeScriptMcpServerName,
command: devNexusTypeScriptMcpCommand,
args: [...devNexusTypeScriptMcpArgs],
tools: typeScriptQualityFeedbackToolDescriptors.map((tool) => ({
name: tool.name,
description: tool.description,
})),
} as NexusPluginMcpServerCapability;
}

export function readTypeScriptQualitySnapshot(
input: TypeScriptQualitySnapshotInput,
): TypeScriptQualitySnapshot {
Expand Down
7 changes: 7 additions & 0 deletions src/typeScriptWorkflowSkills.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ describe("DevNexus TypeScript workflow skills", () => {
"typescript-diagnose",
"typescript-refactor",
"typescript-project-topology",
"typescript-quality-feedback",
"typescript-test-hygiene",
"typescript-api-boundaries",
"typescript-codemod-planning",
Expand All @@ -21,6 +22,7 @@ describe("DevNexus TypeScript workflow skills", () => {
"typescript-diagnose",
"typescript-refactor",
"typescript-project-topology",
"typescript-quality-feedback",
"typescript-test-hygiene",
"typescript-api-boundaries",
"typescript-codemod-planning",
Expand Down Expand Up @@ -59,5 +61,10 @@ describe("DevNexus TypeScript workflow skills", () => {
(definition) => definition.manifest.id === "typescript-project-topology",
)!.files["REFERENCES.md"],
).toContain("https://www.typescriptlang.org/tsconfig/rootDir.html");
expect(
definitions.find(
(definition) => definition.manifest.id === "typescript-quality-feedback",
)!.files["SKILL.md"],
).toContain("typescript:S3776");
});
});
3 changes: 3 additions & 0 deletions src/typeScriptWorkflowSkills.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const devNexusTypeScriptWorkflowSkillIds = [
"typescript-diagnose",
"typescript-refactor",
"typescript-project-topology",
"typescript-quality-feedback",
"typescript-test-hygiene",
"typescript-api-boundaries",
"typescript-codemod-planning",
Expand All @@ -29,6 +30,8 @@ const projectedSkillDescriptions: Record<
"Project the bounded TypeScript refactoring workflow skill.",
"typescript-project-topology":
"Project the TypeScript project directory topology workflow skill.",
"typescript-quality-feedback":
"Project the TypeScript quality feedback and Sonar rule playbook skill.",
"typescript-test-hygiene": "Project the TypeScript test hygiene workflow skill.",
"typescript-api-boundaries":
"Project the TypeScript API boundary review workflow skill.",
Expand Down
Loading