Skip to content

fix: surface silent YAML/timeout collapses and unblock nested skill paths#3176

Open
praisonai-triage-agent[bot] wants to merge 2 commits into
mainfrom
claude/issue-3175-20260719-0817
Open

fix: surface silent YAML/timeout collapses and unblock nested skill paths#3176
praisonai-triage-agent[bot] wants to merge 2 commits into
mainfrom
claude/issue-3175-20260719-0817

Conversation

@praisonai-triage-agent

@praisonai-triage-agent praisonai-triage-agent Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Fixes #3175

Summary

Wrapper-layer (src/praisonai/praisonai/) fixes for three silent behavioural gaps, kept minimal and backward-compatible.

1. Silent YAML duplicate collapse (agents_generator.py)

_normalize_yaml_config previously collapsed list-form agents/tasks with duplicate name keys silently — a 3-agent YAML could run as 1. Now duplicate agent/task names and unknown task→agent references raise under PRAISONAI_VALIDATE_STRICT=true or warn loudly and preserve both entries by suffixing (name__dup_i). Correct YAML is unaffected.

2. Per-agent tool_timeout collapsed to global max() (agents_generator.py)

_resolve_effective_tool_timeout used max(), forcing a fast agent (5s) to inherit a slow agent's budget (60s). Switched to the tightest (min) value β€” the safe-by-default choice β€” and warns on every agent whose declared value is overridden. Avoided a per-agent tools-dict restructure (no live adapter consumer β†’ scope creep).

3. Nested skill paths blocked (tools/skill_manage.py)

_is_safe_path deny-listed /, blocking every canonical nested skill file (references/, scripts/, assets/). Now allows nested relative paths while still rejecting absolute paths, ~, null bytes, and .. segments. Real containment remains enforced by the callers' resolve().relative_to() check.

Test plan

  • Issue reproducers pass (duplicates preserved+warned, timeout=5.0, nested files write while traversal rejected)
  • Updated test_effective_timeout_uses_tightest_declared_role (maxβ†’min semantics)
  • test_tool_timeout_enforcement.py β€” 10 passed
  • skill/normalize/yaml unit tests β€” 44 passed

Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Preserved duplicate agent, role, and task entries instead of silently overwriting them.
    • Added stricter validation for tasks referencing unknown agents, with optional strict failure handling.
    • Tool timeouts now use the tightest applicable limit, with warnings when overrides occur.
    • Improved file path safety checks to block traversal, absolute paths, null bytes, and invalid segments.
  • Tests

    • Updated timeout validation coverage to confirm the tightest declared timeout is applied.

…aths (fixes #3175)

- _normalize_yaml_config: detect duplicate agent/task names and unknown
  task agent refs; raise under PRAISONAI_VALIDATE_STRICT or warn loudly and
  preserve both entries by suffixing, instead of silently dropping.
- _resolve_effective_tool_timeout: apply the tightest (min) declared
  tool_timeout to the shared tool dict and warn on any overridden agent,
  so a fast agent is never silently forced to wait a slower agent's budget.
- BasicSkillMutator._is_safe_path: allow nested skill files (references/,
  scripts/, assets/) while still rejecting absolute paths and parent
  traversal; real containment stays enforced by the caller's resolve().

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

Copy link
Copy Markdown
Owner

@coderabbitai review

@MervinPraison

Copy link
Copy Markdown
Owner

/review

@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 Jul 19, 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.

@coderabbitai

coderabbitai Bot commented Jul 19, 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

Run ID: 1ad055b6-2d02-438b-a2dc-a21db7de90af

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

YAML normalization now preserves duplicate entries and validates task references. Tool timeout resolution selects the tightest configured value. Skill path filtering rejects unsafe syntax while allowing valid nested paths.

Changes

Configuration safety

Layer / File(s) Summary
YAML duplicate and reference handling
src/praisonai/praisonai/agents_generator.py
Agent, role, and task normalization now preserves duplicate names with suffixes or raises ValueError in strict mode; unknown task-agent references are skipped with structured warnings or rejected.
Tightest tool timeout resolution
src/praisonai/praisonai/agents_generator.py, src/praisonai/tests/unit/test_tool_timeout_enforcement.py
Shared tool timeout selection now uses the smallest declared role or agent value, retains CLI precedence, warns on overrides, and tests the tightest-timeout rule.

Skill path safety

Layer / File(s) Summary
Skill path prefilter
src/praisonai/praisonai/tools/skill_manage.py
Path validation rejects empty, absolute, null-byte, and ..-containing paths using normalized separators before containment checks.

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

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant AgentsGenerator
  participant RoleAgentConfig
  participant SharedToolDict
  CLI->>AgentsGenerator: provide optional tool_timeout
  AgentsGenerator->>RoleAgentConfig: read declared role and agent timeouts
  RoleAgentConfig-->>AgentsGenerator: return timeout values
  AgentsGenerator->>SharedToolDict: apply CLI timeout or tightest declared timeout
  AgentsGenerator-->>CLI: emit override warnings when values differ
Loading

Suggested reviewers: mervinpraison

πŸš₯ Pre-merge checks | βœ… 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR covers YAML, timeout, and nested-path fixes, but does not address the concurrency-safety requirements in #3175. Implement the TOCTOU and skill-log concurrency protections, or scope the issue to the changes actually delivered.
Docstring Coverage ⚠️ Warning Docstring coverage is 69.23% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (3 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title is concise and matches the main fixes: YAML/timeout handling plus nested skill-path support.
Out of Scope Changes check βœ… Passed The changes shown are all directly related to the stated YAML, timeout, and skill-path objectives.
✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/issue-3175-20260719-0817

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

πŸ€– 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/praisonai/agents_generator.py`:
- Line 814: Update the entities construction in the agent configuration flow to
use an empty-dictionary fallback when either config.get("roles", {}) or
config.get("agents", {}) returns None. Preserve the existing merge behavior for
populated mappings while preventing dictionary unpacking of null values.
πŸͺ„ Autofix (Beta)

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

Run ID: 46573732-e55d-46ba-b6dc-28dbab82eea1

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 882143d and 2d71956.

πŸ“’ Files selected for processing (3)
  • src/praisonai/praisonai/agents_generator.py
  • src/praisonai/praisonai/tools/skill_manage.py
  • src/praisonai/tests/unit/test_tool_timeout_enforcement.py

if isinstance(cli_timeout, (int, float)) and not isinstance(cli_timeout, bool):
return float(cli_timeout)

entities = {**config.get("roles", {}), **config.get("agents", {})}

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.

🩺 Stability & Availability | 🟑 Minor | ⚑ Quick win

Prevent TypeError when configuration keys are explicit nulls.

If roles or agents are explicitly defined as empty in the YAML (e.g., roles: null), config.get("roles", {}) returns None. Using the dictionary unpacking operator (**) on None raises a TypeError.

Consider adding an or {} fallback to safely handle None values.

πŸ› οΈ Proposed fix
-        entities = {**config.get("roles", {}), **config.get("agents", {})}
+        entities = {**(config.get("roles") or {}), **(config.get("agents") or {})}
πŸ“ 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
entities = {**config.get("roles", {}), **config.get("agents", {})}
entities = {**(config.get("roles") or {}), **(config.get("agents") or {})}
πŸ€– 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/praisonai/agents_generator.py` at line 814, Update the entities
construction in the agent configuration flow to use an empty-dictionary fallback
when either config.get("roles", {}) or config.get("agents", {}) returns None.
Preserve the existing merge behavior for populated mappings while preventing
dictionary unpacking of null values.

@greptile-apps

greptile-apps Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR addresses three silent failure modes in the wrapper layer: duplicate YAML entries no longer collapse silently (with __dup_N suffixing and optional strict-mode raising), _resolve_effective_tool_timeout switches from max() to min() across agent declarations, and _is_safe_path now permits nested relative skill-file paths while still blocking traversal and absolute paths.

  • Duplicate preservation (_list_to_dict): Keeps both entries under suffixed keys and warns loudly, but duplicate agents still receive no task assignments (the task loop resolves by original name only), and there is a minor edge case where an explicitly-named __dup_N entry can be silently overwritten when a collision at the same enumerate index generates the same suffix.
  • min() timeout semantics: Prevents a fast agent from inheriting a slow agent's budget, but imposes the tightest declared timeout on the entire shared tool dict β€” agents that legitimately declared a larger budget to accommodate long-running tools will time out prematurely.
  • _is_safe_path relaxation: Correctly removes the blanket / rejection, using segment-level .. and empty-string checks instead; the resolve().relative_to() containment check in all three callers remains the real security boundary.

Confidence Score: 4/5

Safe to merge only if the min() timeout behaviour and the orphaned duplicate-agent issue are accepted as known deferred work rather than resolved bugs β€” both are behavioural regressions for certain valid YAML configurations.

Two of the three fixes change observable runtime behaviour in ways that can break valid configurations: agents with larger declared timeouts will now always time out as early as the smallest peer, and agents with duplicate names end up in the config dict with empty task lists while the task-assignment loop silently ignores them. The _is_safe_path fix is clean, and the new minor edge case (silent clobber when an explicit __dup_N name coincides with a generated suffix) is low-probability but confirmed by code inspection.

src/praisonai/praisonai/agents_generator.py β€” both _list_to_dict (suffix collision and task-orphan behaviour) and _resolve_effective_tool_timeout (min vs max semantics) warrant a second look before merging.

Important Files Changed

Filename Overview
src/praisonai/praisonai/agents_generator.py Adds _list_to_dict for duplicate-preserving normalisation and switches _resolve_effective_tool_timeout from max() to min(); the __dup_N suffix scheme has a silent-clobber edge case when an explicitly-named entry coincides with an auto-generated collision key, and the min() semantics can break agents that legitimately need longer timeouts (flagged in prior review rounds).
src/praisonai/praisonai/tools/skill_manage.py Replaces the blanket /-blocker with a proper prefilter that allows nested relative paths while still rejecting .., absolute paths, ~, null bytes, and empty segments; the resolve().relative_to() containment check in all three callers remains intact as the real security boundary.
src/praisonai/tests/unit/test_tool_timeout_enforcement.py Renames and updates one assertion from max to min semantics to match the changed implementation; the rest of the test suite is unchanged and the harness logic is correct.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[YAML config loaded] --> B{agents/roles list?}
    B -- yes --> C[_list_to_dict\npreserve duplicates\nwith __dup_N suffix]
    B -- no --> D[use existing dict]
    C --> E{duplicate names?}
    E -- STRICT=true --> F[raise ValueError]
    E -- STRICT=false --> G[warn + suffix key\ne.g. researcher__dup_1]
    G --> H[tasks list processing]
    D --> H
    H --> I{task.agent in bucket?}
    I -- no --> J{STRICT=true?}
    J -- yes --> K[raise ValueError]
    J -- no --> L[warn + skip task]
    I -- yes --> M[assign task to\nfirst matching agent\noriginal key only]
    M --> N[__dup_N agents\norphaned β€” no tasks]
    N --> O[_resolve_effective_tool_timeout]
    O --> P{CLI tool_timeout?}
    P -- yes --> Q[use CLI value]
    P -- no --> R[min across all\nagent declarations]
    R --> S[warn agents overridden\nby tighter budget]
    Q --> T[build tools dict\nwith shared timeout]
    S --> T
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[YAML config loaded] --> B{agents/roles list?}
    B -- yes --> C[_list_to_dict\npreserve duplicates\nwith __dup_N suffix]
    B -- no --> D[use existing dict]
    C --> E{duplicate names?}
    E -- STRICT=true --> F[raise ValueError]
    E -- STRICT=false --> G[warn + suffix key\ne.g. researcher__dup_1]
    G --> H[tasks list processing]
    D --> H
    H --> I{task.agent in bucket?}
    I -- no --> J{STRICT=true?}
    J -- yes --> K[raise ValueError]
    J -- no --> L[warn + skip task]
    I -- yes --> M[assign task to\nfirst matching agent\noriginal key only]
    M --> N[__dup_N agents\norphaned β€” no tasks]
    N --> O[_resolve_effective_tool_timeout]
    O --> P{CLI tool_timeout?}
    P -- yes --> Q[use CLI value]
    P -- no --> R[min across all\nagent declarations]
    R --> S[warn agents overridden\nby tighter budget]
    Q --> T[build tools dict\nwith shared timeout]
    S --> T
Loading

Reviews (2): Last reviewed commit: "fix: guard None roles/agents in timeout+..." | Re-trigger Greptile

Comment on lines +826 to +835
tightest = float(min(timeouts))
for name, entity in entities.items():
v = _declared(entity)
if v is not None and float(v) != tightest:
self.logger.warning(
"Agent %r declared tool_timeout=%s but a shared tool dict "
"forces the tightest value %ss for the whole run.",
name, v, tightest,
)
return tightest

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.

P1 min() timeout silently breaks slow-tool agents

An agent that explicitly declares tool_timeout: 60 to accommodate long-running operations (slow APIs, large file reads, compilation) will now be forced to timeout after 5 seconds if any peer agent in the same YAML declares tool_timeout: 5. Since the shared tool dict has a single effective timeout, min() guarantees the slow agent's tools will always time out prematurely rather than that the fast agent will ever wait slightly longer. The warning is emitted, but the run still proceeds β€” meaning the slow agent's tools silently fail on every invocation.

The original max() had the mirror problem (a 5 s agent inherits a 60 s budget and can get stuck), but that only wastes time; min() actively breaks correct configurations. Neither value is universally right for a shared dict, which is exactly why the per-agent restructure is needed. Until that is done, the safer fallback is max() (tools can always complete), with a visible warning that the effective timeout may be larger than declared.

Comment on lines +43 to +65
def _list_to_dict(entries: list, prefix: str, kind: str) -> dict:
"""Convert a list of named entries to a dict, preserving duplicates.

Duplicate ``name`` keys would otherwise silently clobber each other. Instead
we raise under ``PRAISONAI_VALIDATE_STRICT`` or warn loudly and keep both by
suffixing the colliding key, so a multi-agent YAML never quietly shrinks.
"""
normalized: dict = {}
duplicates: list = []
for i, entry in enumerate(entries):
if not isinstance(entry, dict):
continue
key = entry.get("name") or f"{prefix}_{i}"
if key in normalized:
duplicates.append(key)
key = f"{key}__dup_{i}"
normalized[key] = entry
if duplicates:
msg = f"Duplicate {kind} name(s) in YAML: {sorted(set(duplicates))}"
if _strict_validation_enabled():
raise ValueError(msg)
logger.warning("%s β€” kept both by suffixing keys; rename to silence.", msg)
return normalized

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.

P1 Duplicate agent preserved with __dup_i suffix but receives no task assignments

_list_to_dict stores duplicate agents under a suffixed key (e.g. researcher__dup_1), but the task-assignment loop at line 97 looks up agents by the value of task.get("agent"), which still holds the original name "researcher". The bucket lookup therefore always hits the first entry, and researcher__dup_1 ends up in the config dict with an empty tasks sub-dict. Downstream adapters that require at least one task per agent (or that iterate the role dict expecting all agents to be runnable) will encounter an orphaned, task-less agent. The original code silently collapsed to the last entry; the new code changes the failure mode rather than resolving it, and the warning that is emitted does not prevent the partial config from being passed to the framework layer.

Comment thread src/praisonai/praisonai/agents_generator.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 and removed pipeline/final-claude-pending Reviews done; waiting for FINAL @claude pipeline/blocked:no-final Blocked: no FINAL @claude trigger yet labels Jul 19, 2026
@praisonai-triage-agent

praisonai-triage-agent Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

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


Final Architecture Review β€” PR #3176 βœ…

Reviewed against AGENTS.md (lightweight-and-powerful, protocol-driven, backward-compatible) and all prior reviewer feedback. Fixes pushed to deac48c83.

Verdict: APPROVE β€” scope-appropriate, backward-compatible, correctly routed (all changes in wrapper src/praisonai/, no praisonaiagents/ bloat, no new params).


Fixes I implemented (src/praisonai/praisonai/agents_generator.py)

# Source Finding Action
1 CodeRabbit {**config.get("roles", {}), ...} β†’ TypeError when YAML has roles: null Fixed β€” or {} fallback in _resolve_effective_tool_timeout (L813) and the same latent bug in _validate_cli_backend_compatibility (L859)
2 Greptile P2 redundant inner import os in _strict_validation_enabled Fixed β€” os already imported at module top; removed

Verified with a direct reproducer (roles: None β†’ returns 7.0/None, no crash).

Reviewer points I evaluated and deliberately skipped (not bugs)

  • Greptile P1 β€” revert min() β†’ max() timeout: Rejected. The issue author (repo owner, Wrapper gaps in src/praisonai/praisonai: silent YAML duplicate drops, global-max tool_timeout, and skill nested-path lockoutΒ #3175) explicitly endorsed min()+warn as the correct minimal fix and called max() "the worst choice of the three" β€” a fast agent inheriting a 60s budget can hang, which violates multi-agent safe by default. min() bounds every tool and warns loudly on override. Keeping. The proper long-term answer (per-agent tool dict) is intentionally deferred β€” no live adapter consumer, so building it now would be scope creep.
  • Greptile P1 β€” orphaned __dup_i agent gets no tasks: Rejected as "bug". This is the intended, endorsed behaviour β€” the issue asks to preserve both entries + warn loudly (raise under PRAISONAI_VALIDATE_STRICT) rather than silently collapse 3 agents β†’ 1. A visible, task-less duplicate that emits a warning is the "loud, actionable" outcome the issue requires; matches the author's fix sketch exactly.
  • CodeRabbit inline (L814): Same finding as Github actions fixΒ #1 above β€” resolved.

Testing

  • test_tool_timeout_enforcement.py β€” 10 passed
  • test_skills_cli.py + test_agents_yaml_validation.py + test_yaml_skills.py β€” 27 passed (37 total green)
  • Remaining collection errors in the broader suite are pre-existing env gaps (pydantic/typer/toml not installed), unrelated to this PR.

Files modified

  • src/praisonai/praisonai/agents_generator.py (+3/βˆ’4)

No changes to praisonai-rust / praisonai-ts / praisonaiagents/ (out of scope).

Job run Β· branch claude/issue-3175-20260719-0817

…edundant os import

- _resolve_effective_tool_timeout and _validate_cli_backend_compatibility now
  fall back to {} when roles/agents are explicit YAML nulls, preventing a
  TypeError on dict unpacking (CodeRabbit).
- Remove redundant inner `import os` in _strict_validation_enabled; os is
  already imported at module top (Greptile).

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

Labels

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.

Wrapper gaps in src/praisonai/praisonai: silent YAML duplicate drops, global-max tool_timeout, and skill nested-path lockout

1 participant