Skip to content

[jsweep] Clean ai_credits_context.cjs#42008

Merged
pelikhan merged 2 commits into
mainfrom
signed/jsweep/ai-credits-context-5df6a8a73adbb3c8
Jun 28, 2026
Merged

[jsweep] Clean ai_credits_context.cjs#42008
pelikhan merged 2 commits into
mainfrom
signed/jsweep/ai-credits-context-5df6a8a73adbb3c8

Conversation

@github-actions

@github-actions github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Refactors ai_credits_context.cjs to reduce duplication in provenance logging and simplifies a boolean return expression. Adds comprehensive Vitest test coverage for three previously untested exported functions.

Changes

actions/setup/js/ai_credits_context.cjs

  • Extract logAICreditSource helper: Moves the repeated 4-branch provenance-logging pattern (audit_logagent_stdioenv(VAR)none) into a single reusable function. Callers in resolveAICreditsFailureState are reduced from 16 lines to 2 calls. No behaviour change.
  • Simplify parseMaxAICreditsExceededFromAuditEntry: Replaces if (...) { return true; } return false; with a direct return <condition>. No behaviour change.

actions/setup/js/ai_credits_context.test.cjs

Adds 232 lines covering three new describe blocks:

Suite Cases Coverage focus
parseMaxAICreditsFromAuditLog 9 Missing log, snake_case/camelCase/nested fields, last-wins, decimal, non-positive
parseAICreditsErrorInfoFromAuditLog 9 Missing/empty defaults, snake_case/camelCase credits and rate-limit flags, message/code pattern detection, multi-entry accumulation
resolveFirewallAuditLogPath 7 Override passthrough, GH_AW_AGENT_OUTPUT-derived paths, log.jsonl/audit.jsonl precedence, logs/ subdir fallback, default fallback

Risk

Low. All changes are mechanical refactors (no logic changes) plus additive tests. The extracted helper preserves the exact conditional order and log format of the original inline blocks.

Generated by PR Description Updater for #42008 · 36.7 AIC · ⌖ 6.73 AIC · ⊞ 4.6K ·

- Extract logAICreditSource() helper to deduplicate the verbose
  provenance logging in resolveAICreditsFailureState, reducing it
  from ~30 lines to 3 calls
- Simplify parseMaxAICreditsExceededFromAuditEntry: convert the final
  if/return-true/return-false into a direct boolean return expression
- Add 24 new tests covering three previously untested exported functions:
  parseMaxAICreditsFromAuditLog, parseAICreditsErrorInfoFromAuditLog,
  and resolveFirewallAuditLogPath (49 tests total, up from 25)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor Author

👋 Automated jsweep sweep for ai_credits_context.cjs — this one looks solid.

The extraction of logAICreditSource cleanly eliminates the two duplicated 4-branch logging chains in resolveAICreditsFailureState, and the return (condition) simplification in parseMaxAICreditsExceededFromAuditEntry is a textbook unbloat. Both changes are behaviour-preserving by construction.

The test suite expansion is particularly thorough: 24 new cases covering parseMaxAICreditsFromAuditLog, parseAICreditsErrorInfoFromAuditLog, and resolveFirewallAuditLogPath — three previously untested exports — with good edge-case coverage (missing log, empty log, snake_case/camelCase variants, multi-entry accumulation, non-positive values, fallback path resolution). Validation (format, lint, typecheck, tests) all passed per the PR body.

This PR is focused, well-described, adds no new dependencies, and is generated by an internal agentic workflow in line with how this project operates. Looks ready for merge. 🟢

Generated by ✅ Contribution Check · 113.9 AIC · ⌖ 19.9 AIC · ⊞ 6K ·

@pelikhan pelikhan marked this pull request as ready for review June 28, 2026 09:00
Copilot AI review requested due to automatic review settings June 28, 2026 09:00
@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #42008 does not have the 'implementation' label and has 0 new lines of code in business logic directories (threshold: 100).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors and tidies the Node.js AI credits parsing/provenance logic in actions/setup/js/ai_credits_context.cjs, reducing duplicated logging code while expanding automated test coverage for previously untested exported helpers.

Changes:

  • Introduces a logAICreditSource(...) helper to de-duplicate provenance logging in resolveAICreditsFailureState.
  • Simplifies parseMaxAICreditsExceededFromAuditEntry by returning the boolean condition directly.
  • Adds comprehensive tests for parseMaxAICreditsFromAuditLog, parseAICreditsErrorInfoFromAuditLog, and resolveFirewallAuditLogPath.
Show a summary per file
File Description
actions/setup/js/ai_credits_context.cjs Refactors provenance logging via a helper and simplifies a boolean-return path while preserving behavior.
actions/setup/js/ai_credits_context.test.cjs Adds new unit tests covering additional exported audit-log parsing and path resolution helpers.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Low

@github-actions github-actions Bot mentioned this pull request Jun 28, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /improve-codebase-architecture, /zoom-out, and /tdd — leaving as COMMENT; no blocking issues, four non-critical suggestions.

📋 Key Themes & Highlights

Key Themes

  • logAICreditSource API fragility: 5 positional params with similar types; destructured options would make call sites order-safe and self-documenting
  • Mixed dependency model: the helper's else branch reads process.env directly while every other branch uses pre-computed values — worth a clarifying comment at minimum
  • Duplicate writeAuditLog helper: identical copy in two describe blocks; a top-level factory would keep isolation while removing the duplication
  • Weak fallback test: the resolveFirewallAuditLogPath fallback assertion (toMatch(/\.jsonl$/)) always passes and tests nothing about actual path resolution

Positive Highlights

  • ✅ Extracting logAICreditSource cleanly removes ~30 lines of duplicated if/else chains
  • ✅ Simplifying parseMaxAICreditsExceededFromAuditEntry to a direct return (condition) is a clear improvement
  • ✅ 24 new tests for three previously untested exported functions are a genuine coverage win, with solid edge-case thinking (snake_case/camelCase, nested fields, accumulation, decimal values, path fallback chain)
  • ✅ All formatting, linting, type-checking, and tests pass per the PR description

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 58.9 AIC · ⌖ 8.07 AIC · ⊞ 6.6K

Comment thread actions/setup/js/ai_credits_context.cjs
Comment thread actions/setup/js/ai_credits_context.cjs
delete process.env.GH_AW_AGENT_OUTPUT;
});

function writeAuditLog(lines) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[/improve-codebase-architecture] writeAuditLog is defined identically in both the parseMaxAICreditsFromAuditLog and parseAICreditsErrorInfoFromAuditLog describe blocks — a small DRY miss in the new test code.

💡 Suggestion

Extract to a top-level factory that takes a getTmpDir getter so each describe block's isolation is preserved:

function makeWriteAuditLog(getTmpDir) {
  return (lines) => {
    const auditDir = path.join(getTmpDir(), "sandbox", "firewall", "audit");
    fs.mkdirSync(auditDir, { recursive: true });
    const logPath = path.join(auditDir, "log.jsonl");
    fs.writeFileSync(logPath, lines.map(l => JSON.stringify(l)).join("\n") + "\n", "utf8");
    process.env.GH_AW_AGENT_OUTPUT = path.join(getTmpDir(), "output.json");
    return logPath;
  };
}

Then in each beforeEach: const writeAuditLog = makeWriteAuditLog(() => tmpDir);

@copilot please address this.

// but the default /tmp/gh-aw paths might — so just assert the returned path
// is a string ending in .jsonl (the function always returns some valid path).
const result = resolveFirewallAuditLogPath();
expect(result).toMatch(/\.jsonl$/);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[/tdd] The assertion toMatch(/\.jsonl$/) is essentially a no-op — the test comment explicitly acknowledges it can't reliably assert the actual path, so this provides false confidence rather than real coverage of the fallback behaviour.

💡 Suggestion

Strengthen by spying on fs.existsSync (or fs.accessSync) to simulate a filesystem with no candidates, then assert the exact expected default path:

it("returns default fallback path when no file exists", () => {
  const fakeTmpOutput = path.join(tmpDir, "nested", "output.json");
  process.env.GH_AW_AGENT_OUTPUT = fakeTmpOutput;
  vi.spyOn(fs, "existsSync").mockReturnValue(false);
  // Now assert the exact default path the function should emit:
  expect(resolveFirewallAuditLogPath()).toBe("/tmp/gh-aw/agent/sandbox/firewall/audit/log.jsonl");
});

If mocking fs is too invasive in this module, consider marking it it.todo("needs fs mock to test default fallback") rather than leaving an always-passing assertion.

@copilot please address this.

@github-actions

Copy link
Copy Markdown
Contributor Author

🧪 Test Quality Sentinel Report

Test Quality Score: 80/100 — Excellent

Analyzed 24 new test(s) across 3 previously-untested functions: 24 design, 0 implementation, 0 guideline violations.

📊 Metrics & Test Classification (24 tests analyzed)
Metric Value
New/modified tests analyzed 24
✅ Design tests (behavioral contracts) 24 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 16 (67%)
Duplicate test clusters 0
Test inflation detected YES — 229 test additions / 20 prod additions = 11.45:1 (justified: tests add coverage for 3 previously-untested functions)
🚨 Coding-guideline violations 0
Test File Classification Issues Detected
returns empty string for missing audit log ai_credits_context.test.cjs ✅ Design
returns empty string when no max_ai_credits field is present ai_credits_context.test.cjs ✅ Design
parses snake_case max_ai_credits ai_credits_context.test.cjs ✅ Design
parses camelCase maxAiCredits ai_credits_context.test.cjs ✅ Design
parses nested max_ai_credits field ai_credits_context.test.cjs ✅ Design
returns the last non-empty value across multiple entries ai_credits_context.test.cjs ✅ Design
returns empty string for empty audit log ai_credits_context.test.cjs ✅ Design
parses decimal max_ai_credits value ai_credits_context.test.cjs ✅ Design
ignores non-positive max_ai_credits values ai_credits_context.test.cjs ✅ Design
returns empty defaults for missing log ai_credits_context.test.cjs ✅ Design
returns empty defaults for empty log ai_credits_context.test.cjs ✅ Design
parses ai_credits value from snake_case field ai_credits_context.test.cjs ✅ Design
parses aiCredits value from camelCase field ai_credits_context.test.cjs ✅ Design
detects ai_credits_rate_limit_error: true (snake_case) ai_credits_context.test.cjs ✅ Design
detects aiCreditsRateLimitError: true (camelCase) ai_credits_context.test.cjs ✅ Design
detects rate limit from message field text pattern ai_credits_context.test.cjs ✅ Design
detects rate limit from code field with ai_credits_limit_exceeded ai_credits_context.test.cjs ✅ Design
accumulates aiCredits and rateLimitError across multiple entries ai_credits_context.test.cjs ✅ Design
returns the override path directly without checking existence ai_credits_context.test.cjs ✅ Design
returns derived audit path when GH_AW_AGENT_OUTPUT is set and log.jsonl exists ai_credits_context.test.cjs ✅ Design
prefers log.jsonl over audit.jsonl when both exist ai_credits_context.test.cjs ✅ Design
falls back to audit.jsonl when log.jsonl does not exist in derived path ai_credits_context.test.cjs ✅ Design
checks the logs subdir when audit subdir has no match ai_credits_context.test.cjs ✅ Design
returns default fallback path when GH_AW_AGENT_OUTPUT is set but no file exists ai_credits_context.test.cjs ✅ Design Weak assertion (.toMatch only checks extension; intentional per inline comment)

Go: 0; JavaScript: 24 (*.test.cjs). No other languages detected.

Score breakdown: Behavioral coverage 40/40 · Edge cases 20/30 (16/24 tests cover error/edge cases) · Duplication 20/20 · Growth 0/10 (11.45:1 inflation ratio, binary penalty)

Verdict

Check passed. 0% implementation tests (threshold: 30%). All 24 new tests verify observable behavioral contracts — input/output correctness, missing-file handling, format variants (snake_case/camelCase), fallback/priority logic, and error-state detection. The 10-point growth deduction is a mechanical artifact of the 2:1 rule applied to a PR that adds first-time coverage for three previously-untested functions rather than inflating existing tests.

🧪 Test quality analysis by Test Quality Sentinel · 72.1 AIC · ⌖ 17.1 AIC · ⊞ 8.2K ·

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 80/100. Test quality is Excellent — 0% of new tests are implementation tests (threshold: 30%).

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Non-blocking observations

The production changes are correct: the if/else-ifreturn (condition) simplification in parseMaxAICreditsExceededFromAuditEntry is semantically identical, and the logAICreditSource extraction faithfully preserves the original branch ordering and log format. The 24 new tests add real value.

Issues noted (both non-blocking)
  1. Weak fallback-path test (test file, line 476) — expect(result).toMatch(/\.jsonl$/) asserts nothing about the actual fallback constant. A spy-based approach can fix this.

  2. logAICreditSource envVarName contract (source file, line 329) — process.env[envVarName] in the else branch is a live lookup that silently misreports if the caller passes a mismatched name. No current bug; worth documenting the invariant.

🔎 Code quality review by PR Code Quality Reviewer · 84.7 AIC · ⌖ 7.23 AIC · ⊞ 5.2K

// but the default /tmp/gh-aw paths might — so just assert the returned path
// is a string ending in .jsonl (the function always returns some valid path).
const result = resolveFirewallAuditLogPath();
expect(result).toMatch(/\.jsonl$/);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Weak assertion cannot detect real fallback regressions: expect(result).toMatch(/\.jsonl$/) only checks the file extension — any path ending in .jsonl passes, so a broken default-path selection (wrong directory, wrong constant) would go completely undetected.

💡 Suggested fix

Spy on fs.existsSync so no candidate path resolves, then assert the actual default:

vi.spyOn(fs, 'existsSync').mockReturnValue(false);
const result = resolveFirewallAuditLogPath();
// Assert the known fallback path rather than just the extension:
expect(result).toContain('gh-aw'); // or compare to the DEFAULT_FIREWALL_AUDIT_LOG constant

The test comment acknowledges the limitation but the fix is tractable; leaving it as-is provides false coverage confidence without protecting the actual fallback logic.

Comment thread actions/setup/js/ai_credits_context.cjs
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address any unresolved review feedback, refresh this branch if needed, and rerun checks once it is up to date.

Generated by 👨‍🍳 PR Sous Chef · 70.2 AIC · ⌖ 1.04 AIC · ⊞ 17.1K ·

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot review all pr review comments

@pelikhan

Copy link
Copy Markdown
Collaborator

/q update pr sous chef to list pr reviews that need to be addressed explicitely

@github-actions

Copy link
Copy Markdown
Contributor Author

🚀 Agentic Commands has started processing this issue comment

@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

🎩 Mission equipment ready! Q has optimized your workflow. Use wisely, 007! 🔫

Copilot AI requested a review from pelikhan June 28, 2026 09:41
@pelikhan pelikhan merged commit 9eeb121 into main Jun 28, 2026
22 checks passed
@github-actions

Copy link
Copy Markdown
Contributor Author

🎉 This pull request is included in a new release.

Release: v0.82.0

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants