Skip to content

v0.19.1#131

Merged
runkids merged 2 commits intomainfrom
v0.19.1
Apr 13, 2026
Merged

v0.19.1#131
runkids merged 2 commits intomainfrom
v0.19.1

Conversation

@runkids
Copy link
Copy Markdown
Owner

@runkids runkids commented Apr 13, 2026

Bug Fixes

runkids added 2 commits April 12, 2026 22:18
UpdateNotification() wrote to stdout via fmt.Printf, corrupting JSON
output when --json was passed to commands like search.  Machine
consumers got invalid JSON with trailing human-readable text.

Three-layer fix:
1. Move UpdateNotification output to os.Stderr (safety net for any
   caller that bypasses the main.go guard).
2. Add isStructuredOutput() that detects all machine-readable modes:
   --json, -j, and --format json/sarif/markdown.
3. Skip the update check and trailing newline entirely in main()
   when structured output is requested, honouring the contract that
   stdout = pure structured data and stderr = empty.

Tests:
- Unit: isStructuredOutput table test (9 cases)
- Unit: UpdateNotification writes only to stderr
- Integration: versioned binary (1.0.0) with seeded cache (9.9.9)
  exercises the real update path for search --json, list -j, and
  audit --format json — asserts valid JSON stdout + empty stderr.

Closes #129
Restructure contribution guidelines to clarify expectations:
- Issues are the primary entry point for all contributions
- PRs are for small fixes; features require issue + proposal first
- Implementation is handled by maintainer after proposal approval
- All development must use devcontainer (make devc)

Add PR template to surface checklist when contributors open PRs.
Add proposals/ directory with TEMPLATE.md for feature proposals.
@runkids runkids merged commit 121b54b into main Apr 13, 2026
8 checks passed
@runkids runkids deleted the v0.19.1 branch April 13, 2026 08:00
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses an issue where structured output (JSON, SARIF, Markdown) was being corrupted by human-readable update notifications and trailing newlines. Key changes include the introduction of an isStructuredOutput helper to detect machine-readable modes, redirecting update notifications to stderr, and updating the project's contribution guidelines and templates. Feedback was provided regarding the isStructuredOutput function, which currently fails to account for the --flag=value syntax common in Go CLIs, potentially leading to missed detections.

Comment on lines +124 to +137
func isStructuredOutput(args []string) bool {
if hasFlag(args, "--json") || hasFlag(args, "-j") {
return true
}
for i, arg := range args {
if arg == "--format" && i+1 < len(args) {
switch args[i+1] {
case "json", "sarif", "markdown":
return true
}
}
}
return false
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The isStructuredOutput function fails to detect structured output modes when flags use the --flag=value syntax (e.g., --format=json or --json=true). This is a common syntax in Go CLIs. When detection fails, main() will print a trailing newline to stdout and execute the update check, which contradicts the PR's goal of ensuring a clean payload for machine consumers.

Additionally, the current implementation of hasFlag (used for --json and -j) only performs an exact match, missing cases like --json=true.

func isStructuredOutput(args []string) bool {
	for i, arg := range args {
		if arg == "--json" || arg == "-j" || arg == "--json=true" || arg == "-j=true" {
			return true
		}
		if arg == "--format" && i+1 < len(args) {
			switch args[i+1] {
			case "json", "sarif", "markdown":
				return true
			}
		}
		switch arg {
		case "--format=json", "--format=sarif", "--format=markdown":
			return true
		}
	}
	return false
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

search --json prints update notice after JSON on stdout in non-current versions, breaking machine consumers

1 participant