Skip to content

fix: zero-disk credential injection via PRAISONAI_AUTH_CONTENT - #3775

Open
praisonai-triage-agent[bot] wants to merge 2 commits into
mainfrom
claude/issue-3774-20260807-0850
Open

fix: zero-disk credential injection via PRAISONAI_AUTH_CONTENT#3775
praisonai-triage-agent[bot] wants to merge 2 commits into
mainfrom
claude/issue-3774-20260807-0850

Conversation

@praisonai-triage-agent

@praisonai-triage-agent praisonai-triage-agent Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #3774

Summary

Adds a zero-disk credential path for ephemeral/CI runs. When the
PRAISONAI_AUTH_CONTENT environment variable is set, CredentialStore loads
its JSON value as the entire credential store in memory and never reads or
writes ~/.praisonai/credentials.json. This lets a single CI/container secret
inject all provider auth β€” including OAuth/refresh tokens β€” with nothing
persisted to disk.

Changes

  • cli/configuration/credentials.py:
    • Parse PRAISONAI_AUTH_CONTENT on init into an in-memory store (invalid
      JSON / non-object payloads raise a clear ValueError).
    • _read_credentials returns the in-memory blob; _write_credentials
      updates it in memory only and skips all disk I/O (writes become no-ops).
    • New is_in_memory property. Env-blob content takes precedence over disk.
    • OAuth refresh still works and stays in memory (no disk writes).
  • cli/commands/auth.py: auth list / auth status report the source as
    env (in-memory) so the zero-disk mode is not silently invisible.

Notes on scope

Minimal, wrapper/CLI-tier change. No new Agent params, no new dependencies, no
new exports beyond a module-level env-var name constant. Per-provider env vars
continue to work unchanged.

Tests

  • tests/unit/test_credential_env_blob.py (6 tests): env-blob precedence over
    disk, writes never touch disk, OAuth token available in-memory, invalid
    JSON / non-object rejected, and no-env-blob still uses disk. All pass; the
    existing test_credential_onboarding.py suite (12) still passes.

Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for loading authentication credentials from a JSON environment variable.
    • Environment-provided credentials take precedence over stored credentials and remain in memory only.
    • Credential listings and status checks now identify in-memory credentials clearly.
  • Bug Fixes

    • Improved validation and error handling for invalid credential data.
  • Tests

    • Added coverage for loading, precedence, token access, validation, and non-persistent updates.

fixes #3774)

Load the whole credential store from a single env var (JSON) in memory when
PRAISONAI_AUTH_CONTENT is set; skip all disk reads and make writes in-memory
no-ops so nothing is persisted. Surface the in-memory source in auth list/status.

Co-authored-by: MervinPraison <MervinPraison@users.noreply.github.com>
@MervinPraison

Copy link
Copy Markdown
Owner

@coderabbitai review

@MervinPraison

Copy link
Copy Markdown
Owner

/review

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor
βœ… Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@MervinPraison MervinPraison added pipeline/blocked:ci Blocked: CI not green on HEAD pipeline/blocked:no-final Blocked: no FINAL @claude trigger yet pipeline/final-claude-pending Reviews done; waiting for FINAL @claude labels Aug 7, 2026
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more β†’

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account β†’

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us β†’

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3b2b23ea-e509-4dd6-82e4-bf463368ceaa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • πŸ” Trigger review
πŸ“ Walkthrough

Walkthrough

The credential store now accepts a complete JSON credential set from PRAISONAI_AUTH_CONTENT, keeps it in memory, and skips disk access. Authentication listing and status commands report the in-memory source.

Changes

Credential injection

Layer / File(s) Summary
Environment-backed credential store
src/praisonai-code/praisonai_code/cli/configuration/credentials.py, src/praisonai-code/tests/unit/test_credential_env_blob.py
CredentialStore parses PRAISONAI_AUTH_CONTENT, validates the JSON object, exposes is_in_memory, and bypasses disk reads and writes in this mode. Tests cover loading, precedence, updates, OAuth access, validation errors, and disk fallback.
Authentication source reporting
src/praisonai-code/praisonai_code/cli/commands/auth.py
Credential listings and auth status commands report env (in-memory) for environment-backed stored credentials while preserving per-provider environment-variable source reporting.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PRAISONAI_AUTH_CONTENT
  participant CredentialStore
  participant AuthStatus
  PRAISONAI_AUTH_CONTENT->>CredentialStore: Provide JSON credentials
  CredentialStore->>CredentialStore: Validate and retain credentials in memory
  AuthStatus->>CredentialStore: Read credentials and source mode
  CredentialStore-->>AuthStatus: Return credentials with env (in-memory) source
Loading
πŸš₯ Pre-merge checks | βœ… 5
βœ… Passed checks (5 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title clearly summarizes the main change: zero-disk credential injection through PRAISONAI_AUTH_CONTENT.
Linked Issues check βœ… Passed The implementation satisfies issue #3774 by adding in-memory JSON credentials, disk bypass, precedence, validation, OAuth support, and source reporting.
Out of Scope Changes check βœ… Passed The changes remain within issue #3774 and include only credential handling, authentication reporting, and related unit tests.
Docstring Coverage βœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
πŸ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/issue-3774-20260807-0850

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/praisonai-code/tests/unit/test_credential_env_blob.py (2)

56-73: πŸ“ Maintainability & Code Quality | πŸ”΅ Trivial | ⚑ Quick win

Cover OAuth refresh in zero-disk mode.

This test uses an unexpired token. It does not verify that a refresh updates only self._memory_store. Add an expired token, mock requests.post, and assert that the refreshed access token is available through get_credential while disk still does not exist.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai-code/tests/unit/test_credential_env_blob.py` around lines 56 -
73, Update test_env_blob_oauth_token_available_in_memory to use an expired OAuth
token, mock requests.post with a successful refresh response, and trigger the
refresh through the CredentialStore. Assert get_credential returns the refreshed
access token and confirm the credentials file at disk still does not exist.

23-37: πŸ“ Maintainability & Code Quality | πŸ”΅ Trivial | ⚑ Quick win

Test the no-read guarantee directly.

This test verifies precedence, but it can pass if an implementation reads the disk file before returning the environment value. Patch store._effective_read_path to fail after construction, then call get_credential. This makes any disk-read path fail the test.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai-code/tests/unit/test_credential_env_blob.py` around lines 23 -
37, Update test_env_blob_loads_in_memory_without_reading_disk to patch
store._effective_read_path after CredentialStore construction so any subsequent
disk access fails, then perform the existing get_credential and token
assertions. Preserve the precedence and in-memory checks while directly
enforcing that the environment blob is used without reading the disk file.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/praisonai-code/praisonai_code/cli/configuration/credentials.py`:
- Around line 94-108: Update the environment-variable handling in the
credentials initializer to distinguish an unset AUTH_CONTENT_ENV from a
set-but-empty value, parsing and rejecting the latter with ValueError before any
disk-backed store access. Add a regression test covering an empty
AUTH_CONTENT_ENV value and asserting ValueError.

---

Nitpick comments:
In `@src/praisonai-code/tests/unit/test_credential_env_blob.py`:
- Around line 56-73: Update test_env_blob_oauth_token_available_in_memory to use
an expired OAuth token, mock requests.post with a successful refresh response,
and trigger the refresh through the CredentialStore. Assert get_credential
returns the refreshed access token and confirm the credentials file at disk
still does not exist.
- Around line 23-37: Update test_env_blob_loads_in_memory_without_reading_disk
to patch store._effective_read_path after CredentialStore construction so any
subsequent disk access fails, then perform the existing get_credential and token
assertions. Preserve the precedence and in-memory checks while directly
enforcing that the environment blob is used without reading the disk file.
πŸͺ„ Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 50107777-cdde-4986-bc1b-c5cf0ec48a2c

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 2251822 and 2f73548.

πŸ“’ Files selected for processing (3)
  • src/praisonai-code/praisonai_code/cli/commands/auth.py
  • src/praisonai-code/praisonai_code/cli/configuration/credentials.py
  • src/praisonai-code/tests/unit/test_credential_env_blob.py

Comment on lines +94 to +108
self._memory_store: Optional[Dict[str, Dict[str, Any]]] = None
env_blob = os.environ.get(AUTH_CONTENT_ENV)
if env_blob:
try:
parsed = json.loads(env_blob)
except json.JSONDecodeError as exc:
raise ValueError(
f"{AUTH_CONTENT_ENV} is set but is not valid JSON: {exc}"
) from exc
if not isinstance(parsed, dict):
raise ValueError(
f"{AUTH_CONTENT_ENV} must be a JSON object mapping "
"provider -> credential"
)
self._memory_store = parsed

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.

πŸ”’ Security & Privacy | 🟠 Major | ⚑ Quick win

Treat an empty environment value as configured input.

Line 96 treats PRAISONAI_AUTH_CONTENT="" as absent. The store then reads and writes the disk-backed credential file instead of rejecting the invalid JSON value. This violates the zero-disk contract when the variable is set.

Proposed fix
-        if env_blob:
+        if env_blob is not None:

Add a regression test for an empty value that expects ValueError.

πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
self._memory_store: Optional[Dict[str, Dict[str, Any]]] = None
env_blob = os.environ.get(AUTH_CONTENT_ENV)
if env_blob:
try:
parsed = json.loads(env_blob)
except json.JSONDecodeError as exc:
raise ValueError(
f"{AUTH_CONTENT_ENV} is set but is not valid JSON: {exc}"
) from exc
if not isinstance(parsed, dict):
raise ValueError(
f"{AUTH_CONTENT_ENV} must be a JSON object mapping "
"provider -> credential"
)
self._memory_store = parsed
self._memory_store: Optional[Dict[str, Dict[str, Any]]] = None
env_blob = os.environ.get(AUTH_CONTENT_ENV)
if env_blob is not None:
try:
parsed = json.loads(env_blob)
except json.JSONDecodeError as exc:
raise ValueError(
f"{AUTH_CONTENT_ENV} is set but is not valid JSON: {exc}"
) from exc
if not isinstance(parsed, dict):
raise ValueError(
f"{AUTH_CONTENT_ENV} must be a JSON object mapping "
"provider -> credential"
)
self._memory_store = parsed
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai-code/praisonai_code/cli/configuration/credentials.py` around
lines 94 - 108, Update the environment-variable handling in the credentials
initializer to distinguish an unset AUTH_CONTENT_ENV from a set-but-empty value,
parsing and rejecting the latter with ValueError before any disk-backed store
access. Add a regression test covering an empty AUTH_CONTENT_ENV value and
asserting ValueError.

@greptile-apps

greptile-apps Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds an environment-backed, zero-disk credential store and identifies that source in authentication CLI output.

  • Rejects empty, invalid, non-object, and malformed provider payloads during initialization.
  • Keeps credential updates in memory and bypasses credential-file reads and writes.
  • Labels environment-blob credentials as env (in-memory) in authentication listing and status output.
  • Adds focused credential-store tests and updates an interactive-surface test double for the current call signature.

Confidence Score: 4/5

The PR is not yet safe to merge because refreshed OAuth state remains isolated to one CredentialStore instance, allowing later instances to retry with stale rotated credentials.

Each store reparses the original environment blob, while successful OAuth refreshes update only the current instance; a later store can therefore reload an invalidated refresh token and fail authentication.

Files Needing Attention: src/praisonai-code/praisonai_code/cli/configuration/credentials.py

Important Files Changed

Filename Overview
src/praisonai-code/praisonai_code/cli/configuration/credentials.py Adds validated environment-blob loading and zero-disk writes; the previously reported cross-instance OAuth refresh-state issue remains outstanding.
src/praisonai-code/praisonai_code/cli/commands/auth.py Labels credentials originating from the environment-backed store without exposing their values.
src/praisonai-code/tests/unit/test_credential_env_blob.py Covers environment precedence, zero-disk updates, payload validation, OAuth access, and disk fallback.
src/praisonai/tests/unit/cli/test_interactive_surfaces_parity.py Updates the test double to accept the newly expected read-only argument.

Reviews (2): Last reviewed commit: "fix: reject empty/malformed PRAISONAI_AU..." | Re-trigger Greptile

Comment thread src/praisonai-code/praisonai_code/cli/configuration/credentials.py Outdated
Comment thread src/praisonai-code/praisonai_code/cli/configuration/credentials.py
Comment thread src/praisonai-code/praisonai_code/cli/configuration/credentials.py
@MervinPraison

Copy link
Copy Markdown
Owner

@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAI (not a fork), you are able to make modifications to this branch and push directly. SCOPE: Focus ONLY on Python packages (praisonaiagents, praisonai). Do NOT modify praisonai-rust or praisonai-ts. Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding.

Phase 1: Review per AGENTS.md

  1. Protocol-driven: check heavy implementations vs core SDK
  2. Backward compatible: ensure zero feature regressions
  3. Performance: no hot-path regressions
  4. SDK value: review in depth whether the change genuinely adds value to the SDK β€” never add features for the sake of adding them. It must strengthen the SDK (simpler, more user-friendly, robust, world-class, secure). If it does not clearly add value, request changes or recommend rejecting/closing rather than merging scope creep
  5. Do not bloat the Agent class with additional params β€” only if absolutely required; we already support many params.
  6. Repo routing: agent-callable tools β†’ PraisonAI-Tools; lifecycle plugins β†’ PraisonAI-Plugins; optional sandbox backends β†’ PraisonAI-Plugins (praisonai.sandbox entry point) β€” request changes if wrongly added to praisonaiagents/

Phase 2: FIX Valid Issues
7. For any VALID bugs or architectural flaws found by Gemini, CodeRabbit, Qodo, Copilot, or any other reviewer: implement the fix
8. Also independently identify and fix any gaps or issues you find in the changed code β€” do not rely only on prior reviewer feedback
9. Push all code fixes directly to THIS branch (do NOT create a new PR)
10. Comment a summary of exact files modified and what you skipped

Phase 3: Final Verdict
11. If all issues are resolved, approve the PR / close the Issue
12. If blocking issues remain, request changes / leave clear action items

@MervinPraison MervinPraison added pipeline/awaiting-merge-gate FINAL done; waiting for merge gate / CI pipeline/blocked:cooldown Blocked: post-push or @claude cooldown claude-ci-fix-pending and removed pipeline/final-claude-pending Reviews done; waiting for FINAL @claude pipeline/blocked:no-final Blocked: no FINAL @claude trigger yet labels Aug 7, 2026
@MervinPraison

Copy link
Copy Markdown
Owner

@claude CI failed on HEAD 2f735488. Please fix the failures below and push to this branch.

Failed checks

Failures (extracted)

  1. tests/unit/cli/test_interactive_surfaces_parity.py::test_async_tui_expands_at_mentions β€” KeyError: 'prompt'
    • Job: test-core (cli)

Critical review first

Before changing code or tests, decide which side is wrong:

  1. Legitimate feature change β€” the PR intent is correct but implementation or tests need updating. Preserve SDK guarantees; update tests only when behaviour intentionally changed and document why.
  2. Regression / bug in this PR β€” the failure exposes a real breakage introduced here. Fix the implementation; do not weaken, skip, or delete tests just to go green.
  3. Pre-existing flake or unrelated failure β€” say so explicitly; prefer fixing the root cause over masking it.

SDK guardrails (AGENTS.md):

  • Agent-callable tools β†’ PraisonAI-Tools; lifecycle plugins β†’ PraisonAI-Plugins; sandbox backends β†’ PraisonAI-Plugins (praisonai.sandbox) β€” not praisonaiagents/.
  • Do not disturb core SDK contracts to accommodate a wrapper/feature change.
  • Tests must continue to guard backward compatibility and hot-path behaviour β€” passing CI by lowering test standards is not acceptable.
  • If the feature does not genuinely add SDK value, recommend reverting or narrowing scope instead of patching around failures.

What to do

  1. State your verdict: legitimate fix, regression fix, or needs human review β€” and why (1–3 sentences).
  2. Fix root cause with minimal changes; never bloat the Agent class with extra params.
  3. Run failing tests locally, e.g. pytest tests/unit/cli/test_interactive_surfaces_parity.py::test_async_tui_expands_at_mentions -q, plus any related SDK tests touched by the PR.
  4. Push to this branch and comment: files changed, review verdict, and why tests still protect SDK behaviour.

@praisonai-triage-agent

praisonai-triage-agent Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Claude finished @MervinPraison's task β€”β€” View job


Final Architecture Review β€” PR #3775 (zero-disk credential injection)

  • Read AGENTS.md + changed files
  • Investigate CI failure (test_async_tui_expands_at_mentions)
  • Fix: empty PRAISONAI_AUTH_CONTENT re-enabled disk (Major)
  • Fix: malformed provider entries escaped validation (P1)
  • Fix CI test stub (_fake_execute missing read_only kwarg)
  • Add regression tests
  • Run tests & push (52f33362)

Phase 1 β€” Architecture review (per AGENTS.md)

Check Verdict
Protocol vs heavy impl βœ… Correctly scoped to the praisonai-code wrapper CLI; core SDK untouched.
Backward compatible βœ… Env var opt-in only; disk path unchanged when unset; per-provider env vars still work.
Performance / hot path βœ… One-time parse at construction; reads/writes become in-memory dict ops. No hot-path regression.
SDK value βœ… Genuine, security-positive: single CI/container secret injects all provider auth (incl. OAuth) with nothing on disk.
Agent class bloat βœ… No new Agent params, no new deps, no new public exports beyond the env-var name constant.
Repo routing βœ… Credential store belongs in the wrapper CLI β€” correct location.

Not scope creep β€” narrow, minimal, and it strengthens security.

Phase 2 β€” Fixes applied

credentials.py β€” resolves the two valid P1/Major reviewer findings (CodeRabbit + Greptile):

  • Empty value bug: if env_blob: β†’ if env_blob is not None: plus an explicit empty/whitespace-only guard. A set-but-empty PRAISONAI_AUTH_CONTENT now raises ValueError instead of silently re-enabling disk reads/writes β€” the zero-disk contract can no longer be broken by an empty secret.
  • Malformed provider entries: non-object entries (e.g. {"openai": null}) are rejected up-front with a clear error, instead of crashing auth list/auth status and silently treating the credential as missing at runtime.

test_credential_env_blob.py β€” added test_env_blob_empty_raises (empty + whitespace) and test_env_blob_malformed_provider_entry_raises.

test_interactive_surfaces_parity.py (CI failure) β€” verdict: pre-existing test bug, not a regression from this PR. This PR only touches 3 praisonai-code credential files; the failing test is in the separate praisonai package. Commit e6eb0d099 added a read_only kwarg to _execute_prompt, but this test's _fake_execute(prompt) stub was never updated. The real call _execute_prompt(prompt, read_only=...) therefore raised a TypeError that execute_llm swallowed, leaving captured['prompt'] unset β†’ KeyError. Fixed the stub signature to _fake_execute(prompt, read_only=False), preserving the test's original intent (asserts single @file expansion) without weakening it.

Skipped (with reason):

  • Greptile: "OAuth refresh state isolated across store instances." Correct-by-design and out of scope. Zero-disk mode is for ephemeral CI/container runs seeded from an immutable env secret; there is intentionally no shared persistence. Sharing refreshed OAuth state across processes would require re-introducing disk (or another store), which defeats the feature's purpose. The existing docstring already documents refresh stays in-memory.
  • CodeRabbit nitpicks (expired-token refresh test, _effective_read_path patch). Non-blocking test-hardening suggestions; current tests already assert precedence, disk-avoidance, and OAuth in-memory availability. Left as-is to keep the change minimal.

Phase 3 β€” Verdict: βœ… Approve

All blocking issues resolved and CI root cause fixed. Tests: test_credential_env_blob (8), test_credential_onboarding (12), and test_interactive_surfaces_parity (4) all pass locally.

Files changed in 52f33362: credentials.py, test_credential_env_blob.py, test_interactive_surfaces_parity.py.
β€’ Branch: claude/issue-3774-20260807-0850

…t stub

- credentials: treat a set-but-empty PRAISONAI_AUTH_CONTENT as a
  misconfiguration (ValueError) instead of silently falling back to disk,
  preserving the zero-disk contract; validate that each provider entry is a
  JSON object so malformed entries fail fast with a clear error.
- tests: add regression coverage for empty value and non-object provider entry.
- fix pre-existing CI failure in test_async_tui_expands_at_mentions: the
  _fake_execute stub predated the read_only kwarg on _execute_prompt, so the
  real call raised a swallowed TypeError and left the prompt uncaptured.

Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
@MervinPraison MervinPraison added pipeline/blocked:stale-final Blocked: FINAL stale after new commits and removed pipeline/blocked:stale-final Blocked: FINAL stale after new commits labels Aug 7, 2026
@praisonai-triage-agent

praisonai-triage-agent Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Claude finished @MervinPraison's task β€”β€” View job


CI Failure Fix β€” PR #3775

  • Read failing test + check current state on branch
  • Determine verdict
  • Run failing test locally
  • Confirm no push needed (fix already present)

Verdict: Pre-existing test bug β€” already fixed on this branch

The failing test test_async_tui_expands_at_mentions is not in this PR's scope (this PR touches only the praisonai-code credential files). The _fake_execute stub was never updated when an earlier commit added the read_only kwarg to _execute_prompt, so the real call _execute_prompt(prompt, read_only=...) raised a TypeError that got swallowed β†’ captured['prompt'] unset β†’ KeyError.

The fix was already committed in 52f333620 (_fake_execute(prompt, read_only=False) at test_interactive_surfaces_parity.py:58). The stub's intent β€” asserting single @file expansion β€” is preserved, not weakened.

Local verification (HEAD 52f333620)

Test Result
test_async_tui_expands_at_mentions (CI failure) βœ… 1 passed
test_credential_env_blob.py (PR changes) βœ… 8 passed

Note: A separate run showed test_single_command_registry failing locally, but that's a local artifact β€” my editable install resolved praisonai_code from a stale site-packages copy rather than the source tree (.../site-packages/praisonai_code/...). It is unrelated to this PR and not part of the reported CI failure.

Files changed / pushed

None β€” the CI root cause (test_interactive_surfaces_parity.py:58) was already fixed in 52f333620 on this branch. Nothing further to push. The reported job ran against 2f735488 (before that fix landed); a re-run on current HEAD should pass.
β€’ Branch: claude/issue-3774-20260807-0850

@praisonai-triage-agent praisonai-triage-agent Bot removed the pipeline/blocked:cooldown Blocked: post-push or @claude cooldown label Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude-ci-fix-pending pipeline/awaiting-merge-gate FINAL done; waiting for merge gate / CI pipeline/blocked:ci Blocked: CI not green on HEAD

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support zero-disk credential injection via a single environment variable for ephemeral/CI runs

1 participant