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
12 changes: 12 additions & 0 deletions packages/agents-audit/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Changelog

## [0.4.3] - 2026-07-17

### Patch Changes

- Fix the `agents-audit` CLI entry-point guard so it fires when invoked through npm's `.bin` symlink (`npx agents-audit`, `npm exec agents-audit`). The guard previously compared `resolve(process.argv[1])` against the resolved module URL, which never matched through a symlink — every subcommand (`generate`, `scan`) silently no-op'd and exited 0 instead of running. It now compares real paths via `realpathSync`.

Also hardens `scripts/verify-package-tarball.mjs` for `agents-audit`: after packing and installing the tarball fresh, it now runs `npx agents-audit generate` and asserts `.agents/workspace.json` actually exists and parses, rather than trusting a clean exit code.

- Updated dependencies
- @workspacejson/rules@0.4.3
- @workspacejson/spec@0.4.3

## 0.4.2

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/agents-audit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "agents-audit",
"version": "0.4.2",
"version": "0.4.3",
"description": "Audit tool for AGENTS.md hygiene - reads .agents/workspace.json for richer findings",
"license": "Apache-2.0",
"author": "workspace-json contributors",
Expand Down
6 changes: 5 additions & 1 deletion packages/agents-audit/src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env node
import { resolve } from 'node:path';
import { realpathSync } from 'node:fs';
import { createRequire } from 'node:module';
import { fileURLToPath } from 'node:url';
import { Command } from 'commander';
Expand Down Expand Up @@ -147,7 +148,10 @@ export async function runCli(argv: string[] = process.argv): Promise<number> {
return exitCode;
}

if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
// npm exposes package bins through node_modules/.bin symlinks. Resolve both
// paths before comparing them so the executable runs whether invoked directly
// or through npx/npm exec.
if (process.argv[1] && realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url))) {
const exitCode = await runCli(process.argv);
process.exit(exitCode);
}
11 changes: 11 additions & 0 deletions packages/rules/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## [0.4.3] - 2026-07-17

### Patch Changes

- Fix the `agents-audit` CLI entry-point guard so it fires when invoked through npm's `.bin` symlink (`npx agents-audit`, `npm exec agents-audit`). The guard previously compared `resolve(process.argv[1])` against the resolved module URL, which never matched through a symlink — every subcommand (`generate`, `scan`) silently no-op'd and exited 0 instead of running. It now compares real paths via `realpathSync`.

Also hardens `scripts/verify-package-tarball.mjs` for `agents-audit`: after packing and installing the tarball fresh, it now runs `npx agents-audit generate` and asserts `.agents/workspace.json` actually exists and parses, rather than trusting a clean exit code.

- Updated dependencies
- @workspacejson/spec@0.4.3

## 0.4.2

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/rules/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@workspacejson/rules",
"version": "0.4.2",
"version": "0.4.3",
"description": "Rule engine for auditing AGENTS.md hygiene using .agents/workspace.json",
"license": "Apache-2.0",
"author": "workspace-json contributors",
Expand Down
8 changes: 8 additions & 0 deletions packages/spec/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## [0.4.3] - 2026-07-17

### Patch Changes

- Fix the `agents-audit` CLI entry-point guard so it fires when invoked through npm's `.bin` symlink (`npx agents-audit`, `npm exec agents-audit`). The guard previously compared `resolve(process.argv[1])` against the resolved module URL, which never matched through a symlink — every subcommand (`generate`, `scan`) silently no-op'd and exited 0 instead of running. It now compares real paths via `realpathSync`.

Also hardens `scripts/verify-package-tarball.mjs` for `agents-audit`: after packing and installing the tarball fresh, it now runs `npx agents-audit generate` and asserts `.agents/workspace.json` actually exists and parses, rather than trusting a clean exit code.

## [0.4.2] - 2026-07-16

### Added
Expand Down
2 changes: 1 addition & 1 deletion packages/spec/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@workspacejson/spec",
"version": "0.4.2",
"version": "0.4.3",
"description": "JSON Schema and TypeScript types for workspace.json",
"license": "Apache-2.0",
"author": "workspace-json contributors",
Expand Down
48 changes: 47 additions & 1 deletion scripts/verify-package-tarball.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env node

import { existsSync, readFileSync, rmSync } from "node:fs";
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { basename, join } from "node:path";
import { spawnSync } from "node:child_process";

Expand Down Expand Up @@ -40,6 +41,7 @@ try {
assertNoWorkspaceProtocol(manifest, "package");
assertFixedGroupDependencies(manifest);
assertRuntimeFiles(manifest, files);
if (packageName === "agents-audit") assertAgentsAuditBinGenerates(tarballPath);
console.log(`Verified ${basename(tarballPath)} with ${packer}: packed manifest and runtime files are release-safe.`);
} finally {
rmSync(tarballPath, { force: true });
Expand Down Expand Up @@ -93,3 +95,47 @@ function assertRuntimeFiles(manifest, files) {
function normalizeArchivePath(file) {
return file.replace(/^\.\//, "").replaceAll("\\", "/").replace(/\/{2,}/g, "/");
}

function assertAgentsAuditBinGenerates(tarballPath) {
const smokeDirectory = mkdtempSync(join(tmpdir(), "agents-audit-pack-"));
try {
writeFileSync(join(smokeDirectory, "package.json"), JSON.stringify({ private: true }));
// agents-audit's packed manifest depends on @workspacejson/rules and
// @workspacejson/spec at this same fixed-group version, which is not yet
// on the npm registry pre-publish. Pack and install those siblings from
// disk too, so the install resolves locally instead of hitting the registry.
const siblingTarballs = ["../rules", "../spec"].map((relative) =>
packSibling(join(packageDirectory, relative), smokeDirectory),
);
run("npm", ["install", "--ignore-scripts", "--no-package-lock", ...siblingTarballs, tarballPath], smokeDirectory);
run("npx", ["--no-install", "agents-audit", "generate"], smokeDirectory);

const artifact = join(smokeDirectory, ".agents", "workspace.json");
if (!existsSync(artifact)) {
throw new Error("Packed agents-audit bin exited without creating .agents/workspace.json.");
}
JSON.parse(readFileSync(artifact, "utf8"));
} finally {
rmSync(smokeDirectory, { recursive: true, force: true });
}
}

function packSibling(siblingDirectory, destinationDirectory) {
const siblingManifest = JSON.parse(readFileSync(join(siblingDirectory, "package.json"), "utf8"));
const siblingTarballName = `${siblingManifest.name.replace(/^@/, "").replaceAll("/", "-")}-${siblingManifest.version}.tgz`;
const packArgs = packer === "npm"
? ["pack", "--ignore-scripts", "--pack-destination", destinationDirectory]
: ["pack", "--pack-destination", destinationDirectory];
const packed = spawnSync(packer, packArgs, { cwd: siblingDirectory, encoding: "utf8" });
process.stdout.write(packed.stdout);
process.stderr.write(packed.stderr);
if (packed.status !== 0) throw new Error(`${packer} pack failed for ${siblingDirectory}.`);
return join(destinationDirectory, siblingTarballName);
}

function run(command, args, cwd) {
const result = spawnSync(command, args, { cwd, encoding: "utf8" });
process.stdout.write(result.stdout);
process.stderr.write(result.stderr);
if (result.status !== 0) throw new Error(`${command} ${args.join(" ")} failed with exit ${result.status ?? 1}.`);
}
Loading