mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-08 17:58:13 +01:00
The redact resolver test, the #2679 mktemp guard test, the /spec invariant and the spec secret-sink harness pinned the heredoc transport. They now pin the agent-written file: the harness runs the draft-file block, writes the draft the way the file-write tool would, then runs the real scan fence, with every HIGH/MEDIUM/scanner-failure assertion unchanged. Co-authored-by: dgrant <dgrant@users.noreply.github.com>
73 lines
2.9 KiB
TypeScript
73 lines
2.9 KiB
TypeScript
/**
|
|
* redact-doc resolver tests (T3/T16). The taxonomy table is generated from
|
|
* lib/redact-patterns (single source of truth) and must contain every pattern
|
|
* id + the recognizable credential prefixes. The invocation block must encode
|
|
* the scan-at-sink contract (temp file → scan → same file), the exit-code
|
|
* branches, the which-bun probe, and the guardrail framing.
|
|
*/
|
|
import { describe, test, expect } from "bun:test";
|
|
import {
|
|
generateRedactInvocationBlock,
|
|
} from "../scripts/resolvers/redact-doc";
|
|
import { HOST_PATHS } from "../scripts/resolvers/types";
|
|
import { PATTERNS } from "../lib/redact-patterns";
|
|
|
|
const ctx = {
|
|
skillName: "spec",
|
|
tmplPath: "",
|
|
host: "claude" as const,
|
|
paths: HOST_PATHS["claude"],
|
|
};
|
|
|
|
|
|
describe("REDACT_INVOCATION_BLOCK", () => {
|
|
test("scan-at-sink: agent-written private file → scan that file → exact bytes", () => {
|
|
const block = generateRedactInvocationBlock(ctx, ["pre-issue"]);
|
|
// CEO-12: the bytes come from the file the agent wrote (created by the
|
|
// shared mktemp free-text block), never from a heredoc.
|
|
expect(block).toContain('/.gstack/tmp/<redact-file-name>"');
|
|
expect(block).not.toContain("<<");
|
|
expect(block).toContain("--from-file");
|
|
expect(block).toMatch(/exact bytes/i);
|
|
});
|
|
|
|
test("encodes exit-code branches 3/2/0", () => {
|
|
const block = generateRedactInvocationBlock(ctx, ["pre-codex"]);
|
|
expect(block).toContain("Exit 3 (HIGH)");
|
|
expect(block).toContain("Exit 2 (MEDIUM)");
|
|
expect(block).toContain("Exit 0 (clean)");
|
|
});
|
|
|
|
test("resolves visibility config → gh → glab → unknown", () => {
|
|
const block = generateRedactInvocationBlock(ctx, ["pre-issue"]);
|
|
expect(block).toContain("redact_repo_visibility");
|
|
expect(block).toContain("gh repo view --json visibility");
|
|
expect(block).toContain("glab repo view");
|
|
});
|
|
|
|
test("includes a which-bun probe", () => {
|
|
expect(generateRedactInvocationBlock(ctx, ["pre-issue"])).toContain("command -v bun");
|
|
});
|
|
|
|
test("HIGH has no skip flag; framed as guardrail not enforcement", () => {
|
|
const block = generateRedactInvocationBlock(ctx, ["pre-issue"]);
|
|
expect(block).toMatch(/no skip flag for HIGH/i);
|
|
expect(block).toMatch(/guardrail, not airtight enforcement/i);
|
|
});
|
|
|
|
test("PII subset offers auto-redact; non-PII MEDIUM does not", () => {
|
|
const block = generateRedactInvocationBlock(ctx, ["pre-pr-body"]);
|
|
expect(block).toContain("--auto-redact");
|
|
expect(block).toContain("Proceed (acknowledged)");
|
|
});
|
|
|
|
test("sink label drives the prose noun/verb", () => {
|
|
expect(generateRedactInvocationBlock(ctx, ["pre-commit"])).toContain("commit");
|
|
expect(generateRedactInvocationBlock(ctx, ["pre-pr-title"])).toContain("PR title");
|
|
});
|
|
|
|
test("unknown sink label falls back without throwing", () => {
|
|
expect(() => generateRedactInvocationBlock(ctx, ["bogus-sink"])).not.toThrow();
|
|
});
|
|
});
|