chore: update meta-audits + add opencode coupling grep gate
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { readdir, readFile } from "node:fs/promises"
|
||||
import { readdir, readFile, stat } from "node:fs/promises"
|
||||
import path from "node:path"
|
||||
import ts from "typescript"
|
||||
|
||||
const SOURCE_ROOT = path.resolve(import.meta.dir, "..")
|
||||
const WORKSPACE_ROOT = path.resolve(SOURCE_ROOT, "..")
|
||||
const MOCK_MODULE_TOKEN = "mock.module"
|
||||
const MOCK_MODULE_LIFECYCLE_ALLOWLIST = new Map<string, string>([
|
||||
// TODO(MOCK-MODULE-AUDIT): add cleanup for team mailbox inbox module mocks.
|
||||
@@ -79,6 +80,31 @@ async function listTestFiles(directory: string): Promise<string[]> {
|
||||
return nestedFiles.flat()
|
||||
}
|
||||
|
||||
async function listPackageTestFiles(): Promise<string[]> {
|
||||
const packagesDir = path.join(WORKSPACE_ROOT, "packages")
|
||||
let packageNames: string[] = []
|
||||
try {
|
||||
packageNames = await readdir(packagesDir)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
|
||||
const nestedFiles = await Promise.all(packageNames.map(async (name) => {
|
||||
const packageSrc = path.join(packagesDir, name, "src")
|
||||
try {
|
||||
const s = await stat(packageSrc)
|
||||
if (!s.isDirectory()) {
|
||||
return []
|
||||
}
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
return listTestFiles(packageSrc)
|
||||
}))
|
||||
|
||||
return nestedFiles.flat()
|
||||
}
|
||||
|
||||
function relativeSourcePath(filePath: string): string {
|
||||
return path.relative(SOURCE_ROOT, filePath)
|
||||
}
|
||||
@@ -177,7 +203,7 @@ function hasCleanupPattern(sourceFile: ts.SourceFile): boolean {
|
||||
describe("mock.module lifecycle hygiene", () => {
|
||||
test("#given test files using mock.module #when audited #then each must pair with cleanup", async () => {
|
||||
// given
|
||||
const files = await listTestFiles(SOURCE_ROOT)
|
||||
const files = [...await listTestFiles(SOURCE_ROOT), ...await listPackageTestFiles()]
|
||||
const offenders: string[] = []
|
||||
|
||||
// when
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { readdir, readFile } from "node:fs/promises"
|
||||
import path from "node:path"
|
||||
|
||||
const WORKSPACE_ROOT = path.resolve(import.meta.dir, "../..")
|
||||
const PACKAGES_DIR = path.join(WORKSPACE_ROOT, "packages")
|
||||
const SKIP_PACKAGES = new Set(["ast-grep-mcp", "lsp-tools-mcp"])
|
||||
|
||||
const OPENCODE_IMPORT_RE = /from\s+['"](@opencode-ai\/[^'"]+|opencode\/[^'"]+)['"]/
|
||||
const BUN_API_RE = /\bBun\.(spawn|file|write|which|hash)\b/
|
||||
|
||||
async function listPackageSourceFiles(): Promise<string[]> {
|
||||
let packageNames: string[] = []
|
||||
try {
|
||||
packageNames = await readdir(PACKAGES_DIR)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
|
||||
const nestedFiles = await Promise.all(packageNames.map(async (name) => {
|
||||
if (SKIP_PACKAGES.has(name)) {
|
||||
return []
|
||||
}
|
||||
|
||||
const packageSrc = path.join(PACKAGES_DIR, name, "src")
|
||||
const entries = await listSourceFilesRecursive(packageSrc)
|
||||
return entries
|
||||
}))
|
||||
|
||||
return nestedFiles.flat()
|
||||
}
|
||||
|
||||
async function listSourceFilesRecursive(directory: string): Promise<string[]> {
|
||||
let entries: { name: string; isDirectory(): boolean; isFile(): boolean }[] = []
|
||||
try {
|
||||
entries = await readdir(directory, { withFileTypes: true })
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
|
||||
const nestedFiles = await Promise.all(entries.map(async (entry) => {
|
||||
const entryPath = path.join(directory, entry.name)
|
||||
if (entry.isDirectory()) {
|
||||
return listSourceFilesRecursive(entryPath)
|
||||
}
|
||||
if (
|
||||
entry.isFile()
|
||||
&& entry.name.endsWith(".ts")
|
||||
&& !entry.name.endsWith(".test.ts")
|
||||
&& !entry.name.endsWith(".d.ts")
|
||||
) {
|
||||
return [entryPath]
|
||||
}
|
||||
return []
|
||||
}))
|
||||
|
||||
return nestedFiles.flat()
|
||||
}
|
||||
|
||||
function relativeWorkspacePath(filePath: string): string {
|
||||
return path.relative(WORKSPACE_ROOT, filePath)
|
||||
}
|
||||
|
||||
describe("package opencode coupling grep gate", () => {
|
||||
test("#given package source files #when audited #then no file imports from @opencode-ai/* or opencode/", async () => {
|
||||
// given
|
||||
const files = await listPackageSourceFiles()
|
||||
const offenders: string[] = []
|
||||
|
||||
// when
|
||||
for (const filePath of files) {
|
||||
const contents = await readFile(filePath, "utf8")
|
||||
const lines = contents.split("\n")
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i]
|
||||
const match = OPENCODE_IMPORT_RE.exec(line)
|
||||
if (match) {
|
||||
offenders.push(`${relativeWorkspacePath(filePath)}:${i + 1} imports ${match[1]}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// then
|
||||
expect(offenders.sort()).toEqual([])
|
||||
}, 20_000)
|
||||
|
||||
test("#given package source files #when audited #then no file uses Bun.spawn, Bun.file, Bun.write, Bun.which, or Bun.hash", async () => {
|
||||
// given
|
||||
const files = await listPackageSourceFiles()
|
||||
const offenders: string[] = []
|
||||
|
||||
// when
|
||||
for (const filePath of files) {
|
||||
const contents = await readFile(filePath, "utf8")
|
||||
const lines = contents.split("\n")
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i]
|
||||
const match = BUN_API_RE.exec(line)
|
||||
if (match) {
|
||||
offenders.push(`${relativeWorkspacePath(filePath)}:${i + 1} uses ${match[0]}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// then
|
||||
expect(offenders.sort()).toEqual([])
|
||||
}, 20_000)
|
||||
})
|
||||
@@ -1,9 +1,10 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { readdir, readFile } from "node:fs/promises"
|
||||
import { readdir, readFile, stat } from "node:fs/promises"
|
||||
import path from "node:path"
|
||||
import ts from "typescript"
|
||||
|
||||
const SOURCE_ROOT = path.resolve(import.meta.dir, "..")
|
||||
const WORKSPACE_ROOT = path.resolve(SOURCE_ROOT, "..")
|
||||
const PROMPT_GATE_FILE = path.join(SOURCE_ROOT, "shared", "prompt-async-gate.ts")
|
||||
const RAW_PROMPT_ALLOWLIST = new Map<string, string>([
|
||||
[
|
||||
@@ -45,6 +46,31 @@ async function listSourceFiles(directory: string): Promise<string[]> {
|
||||
return nestedFiles.flat()
|
||||
}
|
||||
|
||||
async function listPackageSourceFiles(): Promise<string[]> {
|
||||
const packagesDir = path.join(WORKSPACE_ROOT, "packages")
|
||||
let packageNames: string[] = []
|
||||
try {
|
||||
packageNames = await readdir(packagesDir)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
|
||||
const nestedFiles = await Promise.all(packageNames.map(async (name) => {
|
||||
const packageSrc = path.join(packagesDir, name, "src")
|
||||
try {
|
||||
const s = await stat(packageSrc)
|
||||
if (!s.isDirectory()) {
|
||||
return []
|
||||
}
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
return listSourceFiles(packageSrc)
|
||||
}))
|
||||
|
||||
return nestedFiles.flat()
|
||||
}
|
||||
|
||||
function relativeSourcePath(filePath: string): string {
|
||||
return path.relative(SOURCE_ROOT, filePath)
|
||||
}
|
||||
@@ -334,7 +360,7 @@ await dispatchInternalPrompt(options)
|
||||
|
||||
test("#given production TypeScript sources #when prompt routes are audited #then only the shared gate may call raw OpenCode prompt APIs", async () => {
|
||||
// given
|
||||
const files = await listSourceFiles(SOURCE_ROOT)
|
||||
const files = [...await listSourceFiles(SOURCE_ROOT), ...await listPackageSourceFiles()]
|
||||
const offenders: string[] = []
|
||||
|
||||
// when
|
||||
@@ -358,7 +384,7 @@ await dispatchInternalPrompt(options)
|
||||
|
||||
test("#given production TypeScript sources #when prompt gate callers are audited #then callers cannot disable the post-dispatch reservation hold", async () => {
|
||||
// given
|
||||
const files = await listSourceFiles(SOURCE_ROOT)
|
||||
const files = [...await listSourceFiles(SOURCE_ROOT), ...await listPackageSourceFiles()]
|
||||
const offenders: string[] = []
|
||||
|
||||
// when
|
||||
@@ -375,7 +401,7 @@ await dispatchInternalPrompt(options)
|
||||
|
||||
test("#given production TypeScript sources #when prompt gate callers are audited #then callers cannot bypass the central prompt queue", async () => {
|
||||
// given
|
||||
const files = await listSourceFiles(SOURCE_ROOT)
|
||||
const files = [...await listSourceFiles(SOURCE_ROOT), ...await listPackageSourceFiles()]
|
||||
const offenders: string[] = []
|
||||
|
||||
// when
|
||||
@@ -392,7 +418,7 @@ await dispatchInternalPrompt(options)
|
||||
|
||||
test("#given production TypeScript sources #when prompt gate callers are audited #then every route declares queue behavior explicitly", async () => {
|
||||
// given
|
||||
const files = await listSourceFiles(SOURCE_ROOT)
|
||||
const files = [...await listSourceFiles(SOURCE_ROOT), ...await listPackageSourceFiles()]
|
||||
const offenders: string[] = []
|
||||
|
||||
// when
|
||||
@@ -413,7 +439,7 @@ await dispatchInternalPrompt(options)
|
||||
|
||||
test("#given production TypeScript sources #when model-suggestion prompt wrappers are audited #then every retry caller declares queue behavior explicitly", async () => {
|
||||
// given
|
||||
const files = await listSourceFiles(SOURCE_ROOT)
|
||||
const files = [...await listSourceFiles(SOURCE_ROOT), ...await listPackageSourceFiles()]
|
||||
const offenders: string[] = []
|
||||
|
||||
// when
|
||||
|
||||
Reference in New Issue
Block a user