Bug Description
Address rest of recommendations from Copilot analysis
To Reproduce
Got it — I'll review the script against your stated intention (compare --app-dir vs HEAD of --git-url/--branch and report binaries/affected files), list every behavior/bug that contradicts that intention (without changing code), explain why it's a problem, and propose a prioritized, actionable plan to fix and validate them.
Checklist (what I'll cover)
Verify the core comparison flow (clone branch, diff against --app-dir) — confirm or reject.
Find mismatches between CLI options, internal variable names and behavior.
Identify parsing/portability edge-cases that could produce wrong results.
Point out logging/debug/safety inconsistencies and uninitialized variables.
Recommend a prioritized remediation plan and tests to validate fixes.
Quick verdict up-front
Core comparison: The script does clone the requested branch into a temp repo and runs diff between that checkout and the provided APP_DIR; that behavior matches your high-level intention.
Major functional problem: the script accepts --report (sets REPORT_DIR) but internally checks and writes to REPORT_FILE (which is never initialized from REPORT_DIR). That mismatch breaks the common "write a report into the provided report directory" use case and causes many downstream branches (parsing, JSON, summary, artifact files) to behave as if no report was requested.
Several other bugs and portability issues should be fixed for robust, production behavior. Below I enumerate them with why they matter and how to address them.
Detailed findings (explicit, line-level where helpful)
REPORT_DIR vs REPORT_FILE mismatch — primary functional bug
What the script does:
CLI parsing maps --report to REPORT_DIR (REPORT_DIR="$2").
Early on, if REPORT_DIR is non-empty it creates the directory and prints its permissions.
Later, almost every decision about producing a saved diff uses REPORT_FILE (checks like [[ -n "REPORT_FILE" ]]) and then writes the report toREPORT_FILE.
Why this breaks your intention:
If a user runs the script with --report /tmp/reports (as help suggests), the script will create /tmp/reports but will NOT set REPORT_FILE to a file path within that directory. As a result:
The script goes down the "no REPORT_FILE" branch and either streams diff to stdout or uses a temp file in test mode, rather than saving a user-visible persistent report file in the requested directory.
JSON output and summary/artifact report generation reference REPORT_FILE, SUMMARY_FILE and ARTIFACT_FILE which remain unset (or null in JSON). So the files the user expects to appear in REPORT_DIR won't be created.
Where to look in the script:
CLI parsing: --report) REPORT_DIR="$2"
Report usages: many places check REPORT_FILE (for example: if [[ -n "$REPORT_FILE" ]]; then ... and show_tree_diff > "$REPORT_FILE").
Impact: High — this prevents the script from saving the human-readable diff report into a user-requested directory and breaks the JSON / summary artifact outputs.
Uninitialized SUMMARY_FILE and ARTIFACT_FILE (and inconsistent naming)
What: The script references SUMMARY_FILE and ARTIFACT_FILE when generating summary and artifact reports, but those variables are never set from the CLI or elsewhere.
Why it matters:
--summary is parsed (it sets SUMMARY=true) but there is no place that derives SUMMARY_FILE; when the script calls grep ... > "$SUMMARY_FILE" the target filename will be empty/unset and behavior will be wrong (or the redirection may fail under set -u).
Similar for ARTIFACT_FILE: the script checks if [[ -n "$ARTIFACT_FILE" ]] later, but no CLI flag sets it.
Impact: Medium — summary/artifact features will be unusable or silently fail.
Use of two debug variables (DEBUG vs DEBUG_MODE) — consistency issue
What: The script defines both DEBUG and DEBUG_MODE, sets both in --debug code-path but helper logging functions check DEBUG variable.
Why it matters:
Duplication is confusing and error-prone. Some branches check DEBUG_MODE, others DEBUG. Right now the script sets both on --debug, so it hides a runtime bug, but it's still fragile if future changes touch one name and not the other.
Impact: Low (but sticky for future maintenance).
--safe-mode option requires an argument (weird UX)
What: The CLI parsing uses --safe-mode) SAFE_MODE="$2"; shift 2 ;; which expects the user to pass --safe-mode false to disable safe mode.
Why it matters:
Many CLI conventions make flags boolean (presence toggles) or use explicit --no-safe-mode. Current behavior may surprise users and will break simple --safe-mode usage without an argument.
Impact: Low (UX), but could cause accidental temp-dir retention/deletion.
Parsing assumptions and portability (diff output format differences)
What:
The parser relies on matching exact textual forms of diff -q output:
Files ... and ... differ => it takes the 4th field (second path) via awk '{print $4}' and stores that.
Binary files ... and ... differ => it uses awk '{print $5}'.
Only in
: => it uses sed to make / and then checks whether the line contains $TMP_DIR/repo to turn it into Deleted vs Added.
Why it matters:
diff implementations differ between GNU and BSD (macOS) in edge cases; binary reporting vs "Files .. differ" might vary. Using awk by field number can break when paths contain spaces or if diff output format differs slightly.
The parser chooses only the second path in the "Files" or "Binary files" line (the APP_DIR path). That fits the use-case where we want affected deployed files, but it's worth calling out: currently the script always stores the second path — if we wanted canonical repo path also, we'd lose it. This may be intentional but must be explicit.
Impact: Medium — can mis-parse files with spaces or under some platform diff variants.
Test-output helper uses /app prefix while test mode sets APP_DIR="/test/app"
What:
test-output generator writes lines referencing /app/... (see lib/test-output.sh). In test mode in main script the APP_DIR is set to "/test/app", which is not /app.
The cleaner clean_file_path function strips /app/ explicitly, and also strips ${APP_DIR}/ and ${TMP_DIR}/repo/. This mismatch is minor and only affects test-mode reports, but it’s inconsistent.
Impact: Low (only for tests), but suggests test fixtures and real behavior may differ.
set -euo pipefail and unguarded variable expansions
What: The script is set -euo pipefail, and many places use ${VAR} without a default or check (though most use ${VAR:-}). If some variables are not defined, script can exit unexpectedly (e.g., if REPORT_FILE is referenced in a redirection but unset).
Why it matters:
Because REPORT_FILE is not initialized, some branches referencing it assume it’s empty; depending on how redirections are used, set -u may cause an immediate exit. The script appears careful, but it's brittle.
Impact: Medium — unexpected early exit in corner cases.
Cleanup logic (SAFE_MODE semantics)
What: Default SAFE_MODE=true and deletion happens only when SAFE_MODE == "false" and DRY_RUN == "false".
Why it matters:
The default keeps the temp repo, which might be intentional for debugging but surprising for normal runs. The name SAFE_MODE and its boolean logic should be documented or reversed to be intuitive.
Impact: Low to Medium (depends on intended default semantics).
JSON output: jq requirement and null fields
What:
JSON generation uses jq that must be present. If not present the script fails with an error — this is handled.
The JSON includes full_diff_report, summary_report, artifact_report pointing to ${REPORT_FILE:-null}, etc. Because REPORT_FILE/SUMMARY_FILE/ARTIFACT_FILE are often unset, JSON will show null or empty values.
Impact: Low to Medium (usability of JSON output).
Suggested prioritized plan of action (concrete, minimal changes, test plan)
Priority 1 — Fix REPORT_DIR/REPORT_FILE and summary/artifact variables (required)
Change behavior (one of these options):
Option A (recommended): If --report intentionally takes a directory, derive REPORT_FILE automatically:
When REPORT_DIR is set, create a default file path: REPORT_FILE="
{REPORT_DIR}/diff_{TIMESTAMP}.log".
Also derive SUMMARY_FILE="
{REPORT_DIR}/summary_{TIMESTAMP}.log" and ARTIFACT_FILE="
{REPORT_DIR}/artifacts_{TIMESTAMP}.txt".
Option B: Keep REPORT_DIR as the flag name, but add an explicit --report-file flag and treat --report as directory only (less user-friendly).
Why: This will make --report /path behave as expected (create file in that directory) and avoid the internal uninitialized variable usage.
Tests to run after change:
Run: ./diff-check.sh --test-output mixed --report /tmp/test-reports
Expect: /tmp/test-reports/diff_.log exists and contains the tree-style report and git-style log.
Run with --json to ensure JSON full_diff_report points to that report file.
Priority 2 — Add CLI options for SUMMARY_FILE and ARTIFACT_FILE (or derive them) and wire --summary flag
Either allow --summary-file and --artifact-file flags, or default to derived files under REPORT_DIR.
Ensure --summary uses an actual SUMMARY_FILE instead of trying to write to empty path.
Priority 3 — Harden parsing and portability
Replace naive awk-by-field parsing with robust regex extraction using bash regex groups so paths with spaces are handled:
For "Files (.+) and (.+) differ" use bash regex: if [[ $line =~ ^Files\ (.+)\ and\ (.+)\ differ$ ]]; then file="${BASH_REMATCH[2]}"; fi
For "Binary files (.+) and (.+) differ" similarly.
For "Only in (.+): (.+)" use [[ $line =~ ^Only\ in\ (.+):\ (.+)$ ]].
Rationale: This avoids breaking on spaces and is portable across diff variations assuming the main English wording is the same.
Tests:
Test with filenames that include spaces.
Test on macOS (BSD diff) and Linux (GNU diff) to confirm behavior.
Priority 4 — Improve variable initializations and unify debug flags
Initialize REPORT_FILE, SUMMARY_FILE, ARTIFACT_FILE at top to empty strings (defensive).
Pick a single debug variable (prefer DEBUG=true) and remove DEBUG_MODE or use it consistently.
Make --safe-mode a boolean flag (presence/absence) or provide --no-safe-mode.
Priority 5 — Improve tests and housekeeping
Add unit/integration test harness using --test-output modes that exercise:
empty, modified-only, mixed, large
files with spaces and binary files
Add a smoke test in CI that runs the script with --test-output and validates:
REPORT_FILE exists and contains the expected markers
JSON file created and contains non-null arrays
Add a README snippet showing CLI usage and examples, including the expected files written into REPORT_DIR.
Edge cases to cover in tests
Paths with spaces
Huge diffs (ensure temp file handling scales)
Missing jq (verify error message)
macOS vs Linux diff output formats
USER passes --report but no write permissions for that dir
SSH clone failures (key path quoting and messages)
Minimal validation steps you can run now (no code changes)
Run the script in test mode (already supported) to exercise parsing path:
Example: bash diff-check/diff-check.sh --test-output mixed --report /tmp/test-reports
Observe: because of the REPORT_DIR vs REPORT_FILE bug, the script will create the directory /tmp/test-reports but will not write a report file there. The script will instead write to a temp file (see the branch where REPORT_FILE gets set to $TMP_DIR/test_diff.tmp).
If you omit --report and run --test-output mixed, the script will produce a temp RAW_DIFF_FILE and will parse it, then print the tree-style output to stdout. This confirms parsing logic (but not report-writing).
Run with --json to see JSON nulls:
Example: bash diff-check/diff-check.sh --test-output mixed --json /tmp/out.json
Expect: out.json will be created but full_diff_report etc will be null unless REPORT_FILE was set.
Summary mapping to your requirements
Requirement: "Compare --app-dir with HEAD in --git-url at branch --branch" — PASS. The script clones the given branch into a temp repo and runs diff between the repo and APP_DIR.
Requirement: "Show binaries and affected files" — PARTIAL. The parser does attempt to detect "Binary files" and "Files ... differ" and populate ARTIFACTS and MODIFIED/ADDED/DELETED arrays. However, parsing is brittle and some fields (artifact report, JSON) will not be written due to missing REPORT_FILE/ARTIFACT_FILE wiring.
Requirement: "Produce saved reports in provided --report" — FAIL as-is. REPORT_DIR is created but REPORT_FILE is never set from REPORT_DIR, so no saved report appears there.
Next steps I recommend (concrete, minimal code changes)
Add a small block after the REPORT_DIR creation that sets:
REPORT_FILE="
{REPORT_DIR}/diff_{TIMESTAMP}.log"
SUMMARY_FILE="
{REPORT_DIR}/summary_{TIMESTAMP}.log"
ARTIFACT_FILE="
{REPORT_DIR}/artifacts_{TIMESTAMP}.txt" This single change will immediately make --report do what users expect.
Replace awk-based parsing with bash regex for the three diff-line patterns to handle spaces.
Provide CLI flags --report-file, --summary-file, --artifact-file for power users; default to derived files from REPORT_DIR.
Initialize REPORT_FILE/SUMMARY_FILE/ARTIFACT_FILE at top to empty strings to be explicit.
Add small tests that use --test-output mixed and verify files exist and JSON contains expected arrays.
If you want, I can:
implement the minimal fix (point 1) now, run the provided test-output smoke tests, and show the before/after behavior; or
implement the more robust parsing changes and tests next.
Which of the two actions would you like me to take next? (I won't change any code until you say go; I can also produce small patch suggestions if you prefer.)
Additional Context
Add any other context about the problem here.
Possible Solution
If you have ideas about what might be causing this or how to fix it, please share.
Checklist
Bug Description
Address rest of recommendations from Copilot analysis
To Reproduce
Got it — I'll review the script against your stated intention (compare --app-dir vs HEAD of --git-url/--branch and report binaries/affected files), list every behavior/bug that contradicts that intention (without changing code), explain why it's a problem, and propose a prioritized, actionable plan to fix and validate them.
Checklist (what I'll cover)
Verify the core comparison flow (clone branch, diff against --app-dir) — confirm or reject.
Find mismatches between CLI options, internal variable names and behavior.
Identify parsing/portability edge-cases that could produce wrong results.
Point out logging/debug/safety inconsistencies and uninitialized variables.
Recommend a prioritized remediation plan and tests to validate fixes.
Quick verdict up-front
Core comparison: The script does clone the requested branch into a temp repo and runs diff between that checkout and the provided APP_DIR; that behavior matches your high-level intention.
Major functional problem: the script accepts --report (sets REPORT_DIR) but internally checks and writes to REPORT_FILE (which is never initialized from REPORT_DIR). That mismatch breaks the common "write a report into the provided report directory" use case and causes many downstream branches (parsing, JSON, summary, artifact files) to behave as if no report was requested.
Several other bugs and portability issues should be fixed for robust, production behavior. Below I enumerate them with why they matter and how to address them.
Detailed findings (explicit, line-level where helpful)
REPORT_DIR vs REPORT_FILE mismatch — primary functional bug
What the script does:
CLI parsing maps --report to REPORT_DIR (REPORT_DIR="$2").
Early on, if REPORT_DIR is non-empty it creates the directory and prints its permissions.
Later, almost every decision about producing a saved diff uses REPORT_FILE (checks like [[ -n "REPORT_FILE" ]]) and then writes the report toREPORT_FILE.
Why this breaks your intention:
If a user runs the script with --report /tmp/reports (as help suggests), the script will create /tmp/reports but will NOT set REPORT_FILE to a file path within that directory. As a result:
The script goes down the "no REPORT_FILE" branch and either streams diff to stdout or uses a temp file in test mode, rather than saving a user-visible persistent report file in the requested directory.
JSON output and summary/artifact report generation reference REPORT_FILE, SUMMARY_FILE and ARTIFACT_FILE which remain unset (or null in JSON). So the files the user expects to appear in REPORT_DIR won't be created.
Where to look in the script:
CLI parsing: --report) REPORT_DIR="$2"
Report usages: many places check REPORT_FILE (for example: if [[ -n "$REPORT_FILE" ]]; then ... and show_tree_diff > "$REPORT_FILE").
Impact: High — this prevents the script from saving the human-readable diff report into a user-requested directory and breaks the JSON / summary artifact outputs.
Uninitialized SUMMARY_FILE and ARTIFACT_FILE (and inconsistent naming)
What: The script references SUMMARY_FILE and ARTIFACT_FILE when generating summary and artifact reports, but those variables are never set from the CLI or elsewhere.
Why it matters:
--summary is parsed (it sets SUMMARY=true) but there is no place that derives SUMMARY_FILE; when the script calls grep ... > "$SUMMARY_FILE" the target filename will be empty/unset and behavior will be wrong (or the redirection may fail under set -u).
Similar for ARTIFACT_FILE: the script checks if [[ -n "$ARTIFACT_FILE" ]] later, but no CLI flag sets it.
Impact: Medium — summary/artifact features will be unusable or silently fail.
Use of two debug variables (DEBUG vs DEBUG_MODE) — consistency issue
What: The script defines both DEBUG and DEBUG_MODE, sets both in --debug code-path but helper logging functions check DEBUG variable.
Why it matters:
Duplication is confusing and error-prone. Some branches check DEBUG_MODE, others DEBUG. Right now the script sets both on --debug, so it hides a runtime bug, but it's still fragile if future changes touch one name and not the other.
Impact: Low (but sticky for future maintenance).
--safe-mode option requires an argument (weird UX)
What: The CLI parsing uses --safe-mode) SAFE_MODE="$2"; shift 2 ;; which expects the user to pass --safe-mode false to disable safe mode.
Why it matters:
Many CLI conventions make flags boolean (presence toggles) or use explicit --no-safe-mode. Current behavior may surprise users and will break simple --safe-mode usage without an argument.
Impact: Low (UX), but could cause accidental temp-dir retention/deletion.
Parsing assumptions and portability (diff output format differences)
: => it uses sed to make / and then checks whether the line contains $TMP_DIR/repo to turn it into Deleted vs Added.What:
The parser relies on matching exact textual forms of diff -q output:
Files ... and ... differ => it takes the 4th field (second path) via awk '{print $4}' and stores that.
Binary files ... and ... differ => it uses awk '{print $5}'.
Only in
Why it matters:
diff implementations differ between GNU and BSD (macOS) in edge cases; binary reporting vs "Files .. differ" might vary. Using awk by field number can break when paths contain spaces or if diff output format differs slightly.
The parser chooses only the second path in the "Files" or "Binary files" line (the APP_DIR path). That fits the use-case where we want affected deployed files, but it's worth calling out: currently the script always stores the second path — if we wanted canonical repo path also, we'd lose it. This may be intentional but must be explicit.
Impact: Medium — can mis-parse files with spaces or under some platform diff variants.
Test-output helper uses /app prefix while test mode sets APP_DIR="/test/app"
What:
test-output generator writes lines referencing /app/... (see lib/test-output.sh). In test mode in main script the APP_DIR is set to "/test/app", which is not /app.
The cleaner clean_file_path function strips /app/ explicitly, and also strips ${APP_DIR}/ and ${TMP_DIR}/repo/. This mismatch is minor and only affects test-mode reports, but it’s inconsistent.
Impact: Low (only for tests), but suggests test fixtures and real behavior may differ.
set -euo pipefail and unguarded variable expansions
What: The script is set -euo pipefail, and many places use ${VAR} without a default or check (though most use ${VAR:-}). If some variables are not defined, script can exit unexpectedly (e.g., if REPORT_FILE is referenced in a redirection but unset).
Why it matters:
Because REPORT_FILE is not initialized, some branches referencing it assume it’s empty; depending on how redirections are used, set -u may cause an immediate exit. The script appears careful, but it's brittle.
Impact: Medium — unexpected early exit in corner cases.
Cleanup logic (SAFE_MODE semantics)
What: Default SAFE_MODE=true and deletion happens only when SAFE_MODE == "false" and DRY_RUN == "false".
Why it matters:
The default keeps the temp repo, which might be intentional for debugging but surprising for normal runs. The name SAFE_MODE and its boolean logic should be documented or reversed to be intuitive.
Impact: Low to Medium (depends on intended default semantics).
JSON output: jq requirement and null fields
What:
JSON generation uses jq that must be present. If not present the script fails with an error — this is handled.
The JSON includes full_diff_report, summary_report, artifact_report pointing to ${REPORT_FILE:-null}, etc. Because REPORT_FILE/SUMMARY_FILE/ARTIFACT_FILE are often unset, JSON will show null or empty values.
Impact: Low to Medium (usability of JSON output).
Suggested prioritized plan of action (concrete, minimal changes, test plan)
Priority 1 — Fix REPORT_DIR/REPORT_FILE and summary/artifact variables (required)
Change behavior (one of these options):
Option A (recommended): If --report intentionally takes a directory, derive REPORT_FILE automatically:
When REPORT_DIR is set, create a default file path: REPORT_FILE="{REPORT_DIR}/diff_{TIMESTAMP}.log".
Also derive SUMMARY_FILE="{REPORT_DIR}/summary_{TIMESTAMP}.log" and ARTIFACT_FILE="{REPORT_DIR}/artifacts_{TIMESTAMP}.txt".
Option B: Keep REPORT_DIR as the flag name, but add an explicit --report-file flag and treat --report as directory only (less user-friendly).
Why: This will make --report /path behave as expected (create file in that directory) and avoid the internal uninitialized variable usage.
Tests to run after change:
Run: ./diff-check.sh --test-output mixed --report /tmp/test-reports
Expect: /tmp/test-reports/diff_.log exists and contains the tree-style report and git-style log.
Run with --json to ensure JSON full_diff_report points to that report file.
Priority 2 — Add CLI options for SUMMARY_FILE and ARTIFACT_FILE (or derive them) and wire --summary flag
Either allow --summary-file and --artifact-file flags, or default to derived files under REPORT_DIR.
Ensure --summary uses an actual SUMMARY_FILE instead of trying to write to empty path.
Priority 3 — Harden parsing and portability
Replace naive awk-by-field parsing with robust regex extraction using bash regex groups so paths with spaces are handled:
For "Files (.+) and (.+) differ" use bash regex: if [[ $line =~ ^Files\ (.+)\ and\ (.+)\ differ$ ]]; then file="${BASH_REMATCH[2]}"; fi
For "Binary files (.+) and (.+) differ" similarly.
For "Only in (.+): (.+)" use [[ $line =~ ^Only\ in\ (.+):\ (.+)$ ]].
Rationale: This avoids breaking on spaces and is portable across diff variations assuming the main English wording is the same.
Tests:
Test with filenames that include spaces.
Test on macOS (BSD diff) and Linux (GNU diff) to confirm behavior.
Priority 4 — Improve variable initializations and unify debug flags
Initialize REPORT_FILE, SUMMARY_FILE, ARTIFACT_FILE at top to empty strings (defensive).
Pick a single debug variable (prefer DEBUG=true) and remove DEBUG_MODE or use it consistently.
Make --safe-mode a boolean flag (presence/absence) or provide --no-safe-mode.
Priority 5 — Improve tests and housekeeping
Add unit/integration test harness using --test-output modes that exercise:
empty, modified-only, mixed, large
files with spaces and binary files
Add a smoke test in CI that runs the script with --test-output and validates:
REPORT_FILE exists and contains the expected markers
JSON file created and contains non-null arrays
Add a README snippet showing CLI usage and examples, including the expected files written into REPORT_DIR.
Edge cases to cover in tests
Paths with spaces
Huge diffs (ensure temp file handling scales)
Missing jq (verify error message)
macOS vs Linux diff output formats
USER passes --report but no write permissions for that dir
SSH clone failures (key path quoting and messages)
Minimal validation steps you can run now (no code changes)
Run the script in test mode (already supported) to exercise parsing path:
Example: bash diff-check/diff-check.sh --test-output mixed --report /tmp/test-reports
Observe: because of the REPORT_DIR vs REPORT_FILE bug, the script will create the directory /tmp/test-reports but will not write a report file there. The script will instead write to a temp file (see the branch where REPORT_FILE gets set to $TMP_DIR/test_diff.tmp).
If you omit --report and run --test-output mixed, the script will produce a temp RAW_DIFF_FILE and will parse it, then print the tree-style output to stdout. This confirms parsing logic (but not report-writing).
Run with --json to see JSON nulls:
Example: bash diff-check/diff-check.sh --test-output mixed --json /tmp/out.json
Expect: out.json will be created but full_diff_report etc will be null unless REPORT_FILE was set.
Summary mapping to your requirements
Requirement: "Compare --app-dir with HEAD in --git-url at branch --branch" — PASS. The script clones the given branch into a temp repo and runs diff between the repo and APP_DIR.
Requirement: "Show binaries and affected files" — PARTIAL. The parser does attempt to detect "Binary files" and "Files ... differ" and populate ARTIFACTS and MODIFIED/ADDED/DELETED arrays. However, parsing is brittle and some fields (artifact report, JSON) will not be written due to missing REPORT_FILE/ARTIFACT_FILE wiring.
Requirement: "Produce saved reports in provided --report" — FAIL as-is. REPORT_DIR is created but REPORT_FILE is never set from REPORT_DIR, so no saved report appears there.
Next steps I recommend (concrete, minimal code changes)
Add a small block after the REPORT_DIR creation that sets:
REPORT_FILE="{REPORT_DIR}/diff_{TIMESTAMP}.log"
SUMMARY_FILE="{REPORT_DIR}/summary_{TIMESTAMP}.log"
ARTIFACT_FILE="{REPORT_DIR}/artifacts_{TIMESTAMP}.txt" This single change will immediately make --report do what users expect.
Replace awk-based parsing with bash regex for the three diff-line patterns to handle spaces.
Provide CLI flags --report-file, --summary-file, --artifact-file for power users; default to derived files from REPORT_DIR.
Initialize REPORT_FILE/SUMMARY_FILE/ARTIFACT_FILE at top to empty strings to be explicit.
Add small tests that use --test-output mixed and verify files exist and JSON contains expected arrays.
If you want, I can:
implement the minimal fix (point 1) now, run the provided test-output smoke tests, and show the before/after behavior; or
implement the more robust parsing changes and tests next.
Which of the two actions would you like me to take next? (I won't change any code until you say go; I can also produce small patch suggestions if you prefer.)
Additional Context
Add any other context about the problem here.
Possible Solution
If you have ideas about what might be causing this or how to fix it, please share.
Checklist