fix(#2911): audit-open emits raw human report and parseable JSON

Two bugs in the audit-open dispatch case in bin/gsd-tools.cjs:

  1. Bare output(...) calls (only core.output is in scope) threw
     ReferenceError: output is not defined on every invocation,
     blocking the first step of /gsd-complete-milestone.
  2. Even after switching to core.output(formattedReport, raw), the
     human-readable branch JSON-stringified the formatted text because
     core.output only bypasses JSON encoding when called as
     core.output(null, true, rawValue).

Fix:
  - --json path:  core.output(result, raw)   — pass the object,
    let core.output JSON-stringify (don't pre-stringify).
  - text path:    core.output(null, true, formatAuditReport(result))
    — use the rawValue form to emit verbatim section dividers and
    item lists.

Adds tests/bug-2911-audit-open-output-shape.test.cjs which parses
both modes structurally — line-by-line for text mode (asserting the
report headers exist as standalone lines, not as escaped \n inside a
JSON quoted string), and JSON.parse + key-by-key shape assertions for
--json mode (matching the contract returned by auditOpenArtifacts).
This commit is contained in:
Tom Boucher
2026-04-30 17:30:19 -04:00
parent 006cdafe8f
commit 9a13d2fc0b
2 changed files with 126 additions and 3 deletions

View File

@@ -703,12 +703,15 @@ async function runCommand(command, args, cwd, raw, defaultValue) {
case 'audit-open': {
const { auditOpenArtifacts, formatAuditReport } = require('./lib/audit.cjs');
const includeRaw = args.includes('--json');
const wantJson = args.includes('--json');
const result = auditOpenArtifacts(cwd);
if (includeRaw) {
if (wantJson) {
// core.output JSON-stringifies its first arg; pass the object directly.
core.output(result, raw);
} else {
core.output(formatAuditReport(result), raw);
// Human-readable report must bypass JSON encoding — use the rawValue
// form (third arg) which core.output emits verbatim.
core.output(null, true, formatAuditReport(result));
}
break;
}