Skip to content

Scaffold lepenseur as a full CLI/PyPI AgentCulture sibling (#1) - #3

Merged
OriNachum merged 17 commits into
mainfrom
scaffold-cli-sibling
May 22, 2026
Merged

Scaffold lepenseur as a full CLI/PyPI AgentCulture sibling (#1)#3
OriNachum merged 17 commits into
mainfrom
scaffold-cli-sibling

Conversation

@OriNachum

Copy link
Copy Markdown
Contributor

Closes #1.

Scaffolds lepenseur to the AgentCulture sibling pattern by copying the lecodeur twin and adapting it to the thinker role.

Summary

  • Top-level lepenseur package; read-only verbs whoami/learn/explain/overview + a cli noun (cli overview). All read-only — consistent with "thinker, not actor".
  • doctor ships as a rubric-shaped stub — self-diagnosis semantics for a "non-doer" thinker are an open question, deferred to a follow-up (candidates: vLLM endpoint health, culture.yaml/AGENTS.md coherence). The stub honors the full JSON contract so the gate passes today.
  • Runtime: AGENTS.md + culture.yaml (acp backend, vllm-local/nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4).
  • CI: tests.yml (test + lint + afi cli doctor . --strict gate + version-check) and publish.yml (Trusted Publishing).
  • Six vendored skills (cicd, communicate, version-bump, run-tests, sonarclaude, doc-test-alignment), provenance: steward.

Intentional deviation from the issue

  • Package name is bare lepenseur (not lepenseur-cli), matching the lecodeur twin. CLAUDE.md is updated to match in this PR.

Test plan

  • uv sync && uv run pytest -n auto -v — 20/20 pass
  • black --check, isort --check-only, flake8, bandit -r lepenseur — clean
  • uv run afi cli doctor . --strict — 26/26, exit 0 (all seven agent-first rubric bundles)
  • All acceptance-criteria CLI invocations exit 0 (--version, whoami[/--json], learn, explain backend, overview[/--json], cli overview, doctor[/--json])
  • markdownlint-cli2 clean; both workflow YAMLs valid

Follow-ups (not in this PR)

  • steward PR adding lepenseur to docs/skill-sources.md downstream column.
  • Define doctor semantics for a thinking agent.
  • PyPI/TestPyPI Trusted Publishing registration for the lepenseur project.

Design spec and implementation plan are committed under docs/superpowers/.

🤖 Generated with Claude Code

  • lepenseur (Claude)

OriNachum and others added 14 commits May 22, 2026 17:22
Design for scaffolding lepenseur as a full CLI/PyPI AgentCulture sibling:
copy the lecodeur twin as base, add the agent-first quartet
(whoami/learn/explain/overview/doctor), wire the afi doctor --strict rubric
gate, and rewrite identity content for the thinker role.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Align packaging with the lecodeur twin: dist == package == script == lepenseur.
Note the deviation from CLAUDE.md/issue #1 (which say lepenseur-cli) and that
CLAUDE.md must be updated as part of the scaffold work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…implementation plan

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The _build_parser description mistakenly called lepenseur the "local
coding agent" — it is the "local thinking agent". Aligns CLI help text
with CLAUDE.md, AGENTS.md, and the project's stated identity.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-json)

- Run black + isort to resolve CI lint blockers (overview.py, doctor.py, test file)
- Rename _report() -> report() in whoami.py; update overview.py import and call site
- Add --json argument to bare `cli` parser so `lepenseur cli --json` no longer errors
- Add 'cli overview' self-description to cli_sections() Verbs list
- Extend test_doctor_json_shape to assert 'remediation' key (full documented contract)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Scaffold lepenseur as a full CLI/PyPI AgentCulture sibling

✨ Enhancement 🧪 Tests 📝 Documentation

Grey Divider

Walkthroughs

Description
• Scaffolds lepenseur as a full CLI/PyPI sibling to lecodeur by copying and adapting the twin
  pattern
• Implements read-only verbs (whoami, learn, explain, overview, doctor) and cli noun,
  consistent with "thinker, not actor" philosophy
• Provides doctor as a rubric-shaped stub with full JSON contract compliance; real self-diagnosis
  semantics deferred to follow-up
• Establishes package structure with zero runtime dependencies, Python >=3.12 requirement, and
  console script entry point
• Includes comprehensive test suite (20/20 passing) covering CLI commands, introspection verbs, and
  error handling
• Configures CI/CD pipelines: tests.yml (pytest, lint, afi rubric gate, version-check) and
  publish.yml (Trusted Publishing to PyPI/TestPyPI)
• Vendors six skills from steward with provenance: cicd, communicate, version-bump,
  run-tests, sonarclaude, doc-test-alignment
• Defines runtime identity via AGENTS.md (system prompt, thinker role) and culture.yaml (acp
  backend, vLLM Nemotron-3-Super-120B model)
• Includes design spec and implementation plan under docs/superpowers/ for reproducible execution
• Updates CLAUDE.md to reflect bare lepenseur package name (not lepenseur-cli)
Diagram
flowchart LR
  lecodeur["lecodeur<br/>(actor twin)"]
  lepenseur["lepenseur<br/>(thinker twin)"]
  verbs["Read-only verbs<br/>whoami/learn/explain<br/>overview/doctor"]
  cli["CLI noun<br/>cli overview"]
  runtime["Runtime<br/>AGENTS.md<br/>culture.yaml"]
  cicd["CI/CD<br/>tests.yml<br/>publish.yml"]
  skills["Vendored skills<br/>cicd/communicate<br/>version-bump/run-tests<br/>sonarclaude/doc-test-alignment"]
  tests["Test suite<br/>20/20 passing<br/>CLI + introspection"]
  
  lecodeur -- "copy & adapt" --> lepenseur
  lepenseur --> verbs
  lepenseur --> cli
  lepenseur --> runtime
  lepenseur --> cicd
  lepenseur --> skills
  lepenseur --> tests

Loading

File Changes

1. docs/superpowers/plans/2026-05-22-scaffold-cli-sibling.md 📝 Documentation +1413/-0

Comprehensive implementation plan for lepenseur CLI/PyPI scaffold

• Comprehensive 10-task implementation plan for scaffolding lepenseur as a full CLI/PyPI sibling
 by copying and adapting the lecodeur twin
• Detailed step-by-step instructions covering package setup, identity rewriting, verb implementation
 (overview, cli, doctor), CI integration, and skill reframing
• Includes file structure mapping, acceptance criteria verification, and self-review checklist
• Provides exact bash commands, code snippets, and commit messages for reproducible execution

docs/superpowers/plans/2026-05-22-scaffold-cli-sibling.md


2. docs/superpowers/specs/2026-05-22-scaffold-cli-sibling-design.md 📝 Documentation +275/-0

Design specification for lepenseur CLI/PyPI sibling scaffold

• Design specification for scaffolding lepenseur as an AgentCulture sibling with copy-then-adapt
 approach from lecodeur
• Defines target tree structure, CLI verbs (whoami, learn, explain, overview, cli overview, doctor),
 runtime files (AGENTS.md, culture.yaml), and packaging contract
• Specifies seven-bundle rubric requirements, CI pipelines, vendored skills with provenance, and
 testing strategy
• Documents intentional deviations (bare lepenseur package name) and follow-up work (doctor
 semantics, PyPI setup)

docs/superpowers/specs/2026-05-22-scaffold-cli-sibling-design.md


3. .claude/skills/communicate/SKILL.md 📝 Documentation +337/-0

Vendored communicate skill with steward provenance

• Vendored skill documentation for cross-repo and mesh communication (GitHub issues, comments,
 fetching, and Culture mesh messages)
• Describes when to use each communication mode (issue, broadcast, mesh, comment, fetch) with
 concrete examples and red flags
• Includes script inventory and conventions for briefs, signatures, and issue title formatting
• Reframed from steward upstream with provenance note crediting steward as canonical source

.claude/skills/communicate/SKILL.md


View more (50)
4. .claude/skills/sonarclaude/scripts/sonar.sh ✨ Enhancement +263/-0

SonarCloud API client script for quality gate automation

• Bash script for SonarCloud API client supporting status, issues, metrics, hotspots, and issue
 acceptance workflows
• Provides command-line interface with filtering by severity/type, raw JSON output, and rationale
 comment attachment
• Handles authentication via SONAR_TOKEN environment variable and project key resolution
• Includes help text and error handling for missing credentials or invalid commands

.claude/skills/sonarclaude/scripts/sonar.sh


5. .claude/skills/cicd/scripts/pr-status.sh ✨ Enhancement +163/-0

PR status aggregation script for CI/review pipeline visibility

• Bash script providing one-shot PR status overview combining CI checks, review-bot pipeline,
 SonarCloud quality gate, and inline-thread tallies
• Integrates with GitHub API, SonarCloud API, and Cloudflare Pages to surface deployment previews
 and code quality metrics
• Auto-detects repository and SonarCloud project key with fallback to environment variables
• Displays symbolic indicators (✅, ❌, ⚠️, …) for quick visual scanning of PR health

.claude/skills/cicd/scripts/pr-status.sh


6. lepenseur/cli/_commands/whoami.py ✨ Enhancement +103/-0

Identity probe verb reading culture.yaml without dependencies

• Implements lepenseur whoami verb to report agent identity (nick, version, backend, model) from
 culture.yaml
• Walks up from module location to find repo-local culture.yaml without external YAML dependencies
• Supports both text and --json output modes with fallback defaults for wheel installs
• Exports report() helper used by overview verb for shared identity data

lepenseur/cli/_commands/whoami.py


7. lepenseur/__init__.py ✨ Enhancement +11/-0

Package initialization with version metadata

• Establishes the top-level lepenseur package with version metadata
• Reads __version__ from package metadata via importlib.metadata
• Provides the module entry point for the CLI and package imports

lepenseur/init.py


8. lepenseur/__main__.py ✨ Enhancement +8/-0

Python module execution support

• Enables python -m lepenseur invocation
• Routes to the CLI main entry point

lepenseur/main.py


9. lepenseur/cli/__init__.py ✨ Enhancement +130/-0

CLI framework with command registration and error handling

• Implements unified CLI entry point with argparse-based command routing
• Defines _LepenseurArgumentParser to route errors through structured output
• Registers all global verbs (whoami, learn, explain, overview, doctor) and the cli noun
• Implements error handling contract with LepenseurError propagation

lepenseur/cli/init.py


10. lepenseur/cli/_errors.py Error handling +42/-0

Structured error handling and exit-code policy

• Defines LepenseurError exception with structured error contract (code, message,
 remediation)
• Establishes exit-code policy (0=success, 1=user error, 2=environment error)
• Provides to_dict() for JSON serialization

lepenseur/cli/_errors.py


11. lepenseur/cli/_output.py ✨ Enhancement +56/-0

Output formatting with strict stream separation

• Implements strict stdout/stderr separation for results and diagnostics
• Provides emit_result() for command output (text or JSON)
• Provides emit_error() for error output with optional remediation hints
• Provides emit_diagnostic() for progress messages

lepenseur/cli/_output.py


12. lepenseur/cli/_commands/whoami.py ✨ Enhancement +103/-0

Identity probe command implementation

• Implements lepenseur whoami verb for identity probing
• Reads culture.yaml to report nick, version, backend, and model
• Supports both text and JSON output modes
• Falls back to sensible defaults when culture.yaml is absent

lepenseur/cli/_commands/whoami.py


13. lepenseur/cli/_commands/learn.py ✨ Enhancement +107/-0

Self-teaching prompt command

• Implements lepenseur learn verb for self-teaching prompts
• Provides structured guidance on purpose, commands, exit codes, and sibling relationships
• Supports both text and JSON output with agent-friendly structure

lepenseur/cli/_commands/learn.py


14. lepenseur/cli/_commands/explain.py ✨ Enhancement +38/-0

Markdown documentation lookup command

• Implements lepenseur explain  verb for markdown catalog lookup
• Routes path resolution to lepenseur.explain module
• Supports both text and JSON output modes
• Raises LepenseurError with helpful remediation for unknown paths

lepenseur/cli/_commands/explain.py


15. lepenseur/cli/_commands/overview.py ✨ Enhancement +107/-0

Agent overview and CLI surface description

• Implements lepenseur overview verb describing the agent (identity, verbs, act surface)
• Provides shared section/render helpers reused by cli overview
• Supports both text and JSON output modes
• Gracefully handles optional target path argument (accepted but ignored)

lepenseur/cli/_commands/overview.py


16. lepenseur/cli/_commands/doctor.py ✨ Enhancement +60/-0

Self-diagnosis stub command

• Implements lepenseur doctor verb as a rubric-shaped stub
• Returns a single trivially-passing check to satisfy JSON contract
• Defers real self-diagnosis semantics for thinking agents to follow-up work
• Supports both text and JSON output modes

lepenseur/cli/_commands/doctor.py


17. lepenseur/cli/_commands/cli.py ✨ Enhancement +36/-0

CLI noun with overview subcommand

• Implements lepenseur cli noun grouping for CLI-surface introspection
• Provides cli overview subcommand describing the CLI surface
• Bare lepenseur cli invocation prints the noun's overview
• Satisfies agent-first rubric requirement for noun overview

lepenseur/cli/_commands/cli.py


18. lepenseur/explain/__init__.py ✨ Enhancement +27/-0

Explain catalog resolution interface

• Provides resolve() function for catalog path lookup with error handling
• Provides known_paths() for test enumeration
• Raises LepenseurError with remediation hints for unknown paths

lepenseur/explain/init.py


19. lepenseur/explain/catalog.py 📝 Documentation +149/-0

Markdown documentation catalog

• Defines markdown catalog entries keyed by topic-path tuples
• Includes root overview, backend, whoami, learn, explain, overview, and doctor topics
• Self-contained entries so agents can read single topics without chaining
• Aliases empty tuple and ("lepenseur",) to root entry

lepenseur/explain/catalog.py


20. tests/test_cli.py 🧪 Tests +124/-0

CLI command smoke tests

• Smoke tests for CLI entry point and inherited verbs
• Tests --version, no-args help, unknown command error handling
• Tests whoami, learn, explain in both text and JSON modes
• Tests catalog path resolution and error cases

tests/test_cli.py


21. tests/test_cli_introspection.py 🧪 Tests +78/-0

Introspection verb tests

• Tests introspection verbs: overview, cli overview, doctor
• Tests both text and JSON output shapes
• Tests graceful handling of bad paths (descriptive verbs never hard-fail)
• Tests JSON contract compliance for all introspection commands

tests/test_cli_introspection.py


22. pyproject.toml ⚙️ Configuration changes +72/-0

Project configuration and build metadata

• Defines project metadata for lepenseur package (name, version 0.1.0, description)
• Specifies Python >=3.12 requirement with no runtime dependencies
• Configures lepenseur console script entry point
• Sets up dev dependencies (pytest, coverage, linters, afi-cli)
• Configures coverage, isort, black, bandit, and pytest tools

pyproject.toml


23. CHANGELOG.md 📝 Documentation +22/-0

Initial changelog entry

• Initial changelog entry for version 0.1.0 (2026-05-22)
• Documents initial CLI/PyPI sibling scaffold with read-only verbs
• Lists doctor stub, runtime identity files, CI workflows, and vendored skills

CHANGELOG.md


24. README.md 📝 Documentation +28/-1

Project README with usage guide

• Describes lepenseur as the local thinking agent of Culture mesh
• Documents installation via uv tool install lepenseur
• Lists all CLI commands with brief descriptions
• Notes runtime: vLLM reasoning model over acp backend

README.md


25. CLAUDE.md 📝 Documentation +4/-4

Package naming correction in developer guide

• Updates package name from lepenseur-cli to lepenseur throughout
• Corrects PyPI distribution name and __version__ metadata reference
• Updates publish workflow description to reflect bare package name
• Maintains all development workflow and skills convention documentation

CLAUDE.md


26. AGENTS.md 📝 Documentation +40/-0

System prompt and agent identity definition

• Establishes lepenseur's system prompt and identity as the thinking agent
• Defines thinker-not-actor philosophy and act surface (chat, files only)
• Documents matched pair relationships (lecodeur, daria) and division of labor
• Specifies runtime: vLLM reasoning model (Nemotron-3-Super-120B) over acp backend

AGENTS.md


27. culture.yaml ⚙️ Configuration changes +22/-0

Culture mesh agent configuration

• Defines lepenseur agent configuration for Culture mesh
• Specifies acp backend with vLLM Nemotron-3-Super-120B model
• Includes inline system prompt matching AGENTS.md
• Configures acp_command for opencode integration

culture.yaml


28. .github/workflows/tests.yml ⚙️ Configuration changes +131/-0

CI/CD test and lint workflows

• Implements test job with pytest, coverage, and SonarCloud integration
• Implements lint job with black, isort, flake8, bandit, markdownlint
• Implements afi rubric gate (afi cli doctor . --strict)
• Implements version-check job enforcing per-PR version bumps

.github/workflows/tests.yml


29. .github/workflows/publish.yml ⚙️ Configuration changes +88/-0

PyPI publishing workflow

• Implements PyPI and TestPyPI publishing via Trusted Publishing
• Test job runs pytest before publishing
• Test-publish job publishes .dev to TestPyPI on PRs
• Publish job publishes to PyPI on push to main; skips fork PRs

.github/workflows/publish.yml


30. .flake8 ⚙️ Configuration changes +7/-0

Flake8 linter configuration

• Configures flake8 with 100-character line length (matching black)
• Ignores E203 (whitespace before ':') and W503 (line break before binary operator)

.flake8


31. .claude/skills/cicd/SKILL.md 📝 Documentation +169/-0

CI/CD skill documentation (vendored from steward)

• Documents steward's CI/CD skill layered on agex pr
• Describes core verbs (lint, open, read, reply, delta) delegated to agex
• Documents steward extensions (status, await) for SonarCloud gating
• Includes triage rules, greenfield-aware steps, and reply etiquette

.claude/skills/cicd/SKILL.md


32. .claude/skills/cicd/scripts/workflow.sh ✨ Enhancement +157/-0

CI/CD workflow orchestration script

• Implements thin wrapper over agex pr with steward extensions
• Provides subcommands: lint, open, read, reply, delta, status, await, help
• Implements status and await extensions for SonarCloud quality gate
• Handles legacy STEWARD_PR_AWAIT_SECONDS escape hatch

.claude/skills/cicd/scripts/workflow.sh


33. .claude/skills/cicd/scripts/portability-lint.sh ✨ Enhancement +57/-0

Portability lint for path leaks

• Checks for hard-coded /home// paths in committed files
• Checks for per-user ~/. config references in docs/configs
• Allows carve-outs for ~/.claude/skills/ and ~/.culture/
• Exits 0 if clean, 1 if leaks found

.claude/skills/cicd/scripts/portability-lint.sh


34. .claude/skills/cicd/scripts/pr-reply.sh ✨ Enhancement +77/-0

PR review comment reply script

• Replies to PR review comments with optional thread resolution
• Auto-signs with agent nick resolved from culture.yaml or repo basename
• Supports --repo, --resolve, --print-body flags
• Uses gh CLI for posting replies and resolving threads

.claude/skills/cicd/scripts/pr-reply.sh


35. .claude/skills/cicd/scripts/_resolve-nick.sh ✨ Enhancement +43/-0

Agent nick resolution helper

• Resolves agent nick from first agent's suffix in culture.yaml
• Falls back to git repo basename if manifest absent or unparseable
• Emits stderr warning if manifest exists but suffix cannot be extracted
• Always exits 0 to provide fallback nick

.claude/skills/cicd/scripts/_resolve-nick.sh


36. .claude/skills/version-bump/SKILL.md 📝 Documentation +68/-0

Version bump skill documentation

• Documents semver version bumping in pyproject.toml and CHANGELOG.md
• Describes bump types (major, minor, patch) with examples
• Specifies changelog JSON format for stdin input
• Notes single source of truth in pyproject.toml

.claude/skills/version-bump/SKILL.md


37. .claude/skills/version-bump/scripts/bump.py ✨ Enhancement +178/-0

Version bump automation script

• Bumps semver version in pyproject.toml (major, minor, patch)
• Updates __version__ literal in __init__.py if present
• Prepends changelog entry to CHANGELOG.md from JSON stdin
• Provides show command to read current version without bumping

.claude/skills/version-bump/scripts/bump.py


38. .claude/skills/run-tests/SKILL.md 📝 Documentation +52/-0

Test execution skill documentation

• Documents pytest execution with optional parallelism and coverage
• Describes modes: parallel, coverage, CI, quick
• Notes coverage targets read from pyproject.toml for portability
• Provides usage examples for different test scenarios

.claude/skills/run-tests/SKILL.md


39. .claude/skills/run-tests/scripts/test.sh ✨ Enhancement +52/-0

Test execution orchestration script

• Runs pytest with optional parallelism (-n auto), coverage, and CI mode
• Supports flags: --parallel, --coverage, --ci, --quick
• Resolves coverage config from pyproject.toml for sibling portability
• Passes extra arguments through to pytest

.claude/skills/run-tests/scripts/test.sh


40. .claude/skills/sonarclaude/SKILL.md 📝 Documentation +86/-0

SonarCloud integration skill documentation

• Documents SonarCloud API querying for code quality data
• Describes commands: status, issues, metrics, hotspots, accept
• Specifies environment variables and CLI options
• Explains when to use accept for won't-fix issues with rationale

.claude/skills/sonarclaude/SKILL.md


41. .claude/skills/communicate/scripts/post-issue.sh ✨ Enhancement +71/-0

Cross-repo issue posting script

• Posts cross-repo issues via agtag issue post
• Supports --repo, --title, --body-file flags
• Handles stdin body input by spooling to tempfile
• Auto-signs with agent nick from culture.yaml

.claude/skills/communicate/scripts/post-issue.sh


42. .claude/skills/communicate/scripts/post-comment.sh ✨ Enhancement +65/-0

Cross-repo issue comment script

• Comments on existing cross-repo issues via agtag issue reply
• Supports --repo, --number, --body-file flags
• Handles stdin body input by spooling to tempfile
• Auto-signs with agent nick from culture.yaml

.claude/skills/communicate/scripts/post-comment.sh


43. .claude/skills/communicate/scripts/mesh-message.sh ✨ Enhancement +74/-0

Culture mesh messaging script

• Sends messages to Culture mesh channels via culture channel message
• Supports --channel, --body, --body-file flags
• Handles stdin body input
• Forwards exit code from culture CLI

.claude/skills/communicate/scripts/mesh-message.sh


44. .claude/skills/communicate/scripts/templates/skill-update-brief.md 📝 Documentation +101/-0

Skill update announcement template

• Template for announcing vendored skill updates to sibling repos
• Provides step-by-step resync instructions with git commands
• Documents acceptance criteria for skill updates
• Includes references to upstream sources and AgentCulture conventions

.claude/skills/communicate/scripts/templates/skill-update-brief.md


45. .claude/skills/doc-test-alignment/SKILL.md 📝 Documentation +57/-0

Doc-test alignment skill stub documentation

• Documents doc-test-alignment skill as a stub
• Specifies contract for four alignment checks (README, CLAUDE.md, SKILL.md, tests)
• Explains why stub is shipped (partial implementation would false-positive)
• References roadmap in CLAUDE.md and sibling-pattern.md

.claude/skills/doc-test-alignment/SKILL.md


46. .claude/skills/doc-test-alignment/scripts/check.sh ✨ Enhancement +24/-0

Doc-test alignment stub entry point

• Entry-point script for doc-test-alignment skill
• Prints not-yet-implemented notice and exits 2
• Satisfies steward skills convention (executable entry-point)
• Defers real implementation to follow-up work

.claude/skills/doc-test-alignment/scripts/check.sh


47. .markdownlint-cli2.yaml ⚙️ Configuration changes +22/-0

Markdown linting configuration for workspace consistency

• Adds markdownlint-cli2 configuration file for lepenseur project
• Disables line length (MD013) and table pipe spacing (MD060) rules
• Allows duplicate headings under different parents (MD024) for changelog compatibility
• Excludes node_modules, .local, and docs/superpowers/** from linting

.markdownlint-cli2.yaml


48. .claude/skills.local.yaml.example ⚙️ Configuration changes +14/-0

Skills configuration example for local machine setup

• Creates example configuration file for lepenseur's local skills settings
• Defines workspace_root parameter for sibling Culture project references
• Defines nick parameter for agent identity in culture mesh
• Provides defaults and fallback behavior documentation

.claude/skills.local.yaml.example


49. lepenseur/__init__.py ✨ Enhancement +11/-0

Package initialization with dynamic version detection

• Initializes lepenseur package with version metadata
• Dynamically retrieves package version from installed metadata
• Falls back to 0.0.0+local for editable installs without metadata
• Exports __version__ in __all__

lepenseur/init.py


50. lepenseur/__main__.py ✨ Enhancement +8/-0

Module entry point for command-line execution

• Enables running lepenseur as a module via python -m lepenseur
• Imports and delegates to lepenseur.cli.main() entry point
• Properly exits with return code from CLI main function

lepenseur/main.py


51. .claude/skills/communicate/scripts/fetch-issues.sh Additional files +59/-0

...

.claude/skills/communicate/scripts/fetch-issues.sh


52. lepenseur/cli/_commands/__init__.py Additional files +0/-0

...

lepenseur/cli/_commands/init.py


53. tests/__init__.py Additional files +0/-0

...

tests/init.py


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented May 22, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (2)

Grey Divider


Action required

1. Wrong distribution name lepenseur 📎 Requirement gap § Compliance
Description
pyproject.toml sets the distribution name to lepenseur, but compliance requires the distribution
name to be lepenseur-cli. This breaks the required dist/package/script naming contract used by
tooling and publishing workflows.
Code

pyproject.toml[R1-3]

Evidence
PR Compliance ID 731625 requires [project].name to be exactly lepenseur-cli. The diff sets it to
lepenseur, violating the naming requirement.

Project scaffolding matches AgentCulture sibling pattern (pyproject + package + entrypoint)
Rule 731625: Enforce consistent distribution, package, and console script names for the CLI
pyproject.toml[1-4]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Python distribution name in `pyproject.toml` must be `lepenseur-cli`, but it is currently `lepenseur`.

## Issue Context
The compliance checklist requires consistent naming: distribution `lepenseur-cli`, import package `lepenseur`, and console script `lepenseur`.

## Fix Focus Areas
- pyproject.toml[1-31]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. __version__ uses wrong dist 📎 Requirement gap ⚙ Maintainability
Description
lepenseur.__version__ is derived from distribution metadata for lepenseur, but compliance
requires reading from importlib.metadata.version("lepenseur-cli") with no direct hardcoded
assignment. This will report the wrong version once the distribution name is corrected.
Code

lepenseur/init.py[R3-9]

Evidence
PR Compliance ID 731609 requires __version__ to be defined via importlib.metadata.version for
distribution name lepenseur-cli and forbids hardcoded assignment to __version__. The new code
calls _v("lepenseur") and also assigns __version__ = "0.0.0+local" in the exception path.

Project scaffolding matches AgentCulture sibling pattern (pyproject + package + entrypoint)
Rule 731609: Define version via importlib.metadata in package init
lepenseur/init.py[3-10]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`lepenseur/__init__.py` must define `__version__` via `importlib.metadata.version("lepenseur-cli")` (distribution name), and avoid assigning a hardcoded version literal to `__version__`.

## Issue Context
The compliance rule explicitly specifies the distribution name to query and prohibits hardcoded version literals for `__version__`.

## Fix Focus Areas
- lepenseur/__init__.py[3-11]
- pyproject.toml[1-5]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. culture.yaml prompt mismatched ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The culture.yaml system_prompt text does not exactly mirror the runtime prompt content in
AGENTS.md, so the agent runtime prompt source of truth is inconsistent. This can cause drift
between what developers edit and what the runtime uses.
Code

culture.yaml[R5-19]

Evidence
PR Compliance ID 731605 requires AGENTS.md and culture.yaml.system_prompt to match exactly after
normalization. The new AGENTS.md content (e.g., mentions run tools, additional
sections/headings) differs from the new culture.yaml prompt wording and structure, so they do not
match exactly.

Rule 731605: Ensure culture.yaml system_prompt mirrors AGENTS.md content
AGENTS.md[1-40]
culture.yaml[5-19]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`culture.yaml`'s `system_prompt` must exactly match the normalized content in `AGENTS.md`, but the wording/formatting differs.

## Issue Context
Compliance requires `AGENTS.md` and `culture.yaml.system_prompt` to match exactly after normalization (whitespace/line endings/heading markers), otherwise the runtime prompt and documented prompt diverge.

## Fix Focus Areas
- AGENTS.md[1-40]
- culture.yaml[5-19]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. Unstructured cli overview errors ✓ Resolved 🐞 Bug ≡ Correctness
Description
lepenseur cli overview is registered via a nested subparser created without the custom
_LepenseurArgumentParser, so parse-time errors (e.g., unknown flags) will use default argparse
behavior (unstructured stderr + exit code 2) instead of Lepenseur’s structured error contract.
Code

lepenseur/cli/_commands/cli.py[R33-36]

Evidence
The CLI contract states argparse errors are routed through _LepenseurArgumentParser.error() to
avoid default argparse stderr format/exit code 2, but the nested cli noun creates its own
subparsers without parser_class, so cli overview can fall back to default argparse error
handling.

lepenseur/cli/init.py[14-18]
lepenseur/cli/init.py[31-53]
lepenseur/cli/init.py[78-80]
lepenseur/cli/_commands/cli.py[26-36]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`lepenseur cli overview` is created from a nested `add_subparsers()` call that does not specify `parser_class`. As a result, `cli overview` parse errors (unknown flags, missing args in the future) bypass `_LepenseurArgumentParser.error()`, emitting default argparse output and exiting with code 2.

## Issue Context
The top-level CLI explicitly promises structured errors and JSON-aware parsing by using `_LepenseurArgumentParser` for subparsers. The nested `cli` noun’s subparsers should use the same parser class.

## Fix Focus Areas
- lepenseur/cli/_commands/cli.py[26-36]
 - Create nested subparsers with `parser_class=type(p)` (since `p` is already a `_LepenseurArgumentParser` instance).
 - This ensures `cli overview` errors route through the same structured error handler.
- tests/test_cli_introspection.py[45-66]
 - Add a regression test like `main(["cli","overview","--bogus"])` asserting exit code 1 and `error:`/`hint:` formatting (and optionally JSON mode).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

5. publish.yml uses uv publish 📘 Rule violation ⛨ Security
Description
The PyPI publish workflow does not use the official pypa/gh-action-pypi-publish Trusted Publishing
action as required. This deviates from the prescribed Trusted Publishing implementation in the
compliance checklist.
Code

.github/workflows/publish.yml[R85-88]

Evidence
PR Compliance ID 731614 requires Trusted Publishing via the official PyPI publish action. The
workflow publishes with uv publish instead of pypa/gh-action-pypi-publish.

Rule 731614: Use OIDC Trusted Publishing for PyPI in publish.yml
.github/workflows/publish.yml[85-88]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Publishing uses `uv publish` rather than the required official PyPI Trusted Publishing GitHub Action.

## Issue Context
The compliance checklist mandates using `pypa/gh-action-pypi-publish` (OIDC Trusted Publishing) and avoiding API tokens.

## Fix Focus Areas
- .github/workflows/publish.yml[68-88]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread culture.yaml Outdated
Comment thread pyproject.toml
Comment thread lepenseur/__init__.py
Comment thread lepenseur/cli/_commands/cli.py Outdated
…AGENTS.md

- Add sonar-project.properties (agentculture_lepenseur) — the missing file
  caused the tests.yml SonarCloud step to fail (no projectKey/organization).
- cli noun: propagate parser_class to nested subparsers so 'cli overview'
  parse errors route through the structured error contract (Qodo bug).
- culture.yaml system_prompt now mirrors AGENTS.md verbatim (Qodo rule).
- Add regression test for structured cli overview parse errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Single literal instead of adjacent-string concatenation; tightened wording
('not yet defined' -> 'undefined') so it fits the 100-char line limit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@OriNachum
OriNachum merged commit 8a00192 into main May 22, 2026
8 checks passed
@OriNachum
OriNachum deleted the scaffold-cli-sibling branch May 22, 2026 17:41
OriNachum added a commit that referenced this pull request May 31, 2026
…st-remote-code guidance

- Qodo #4 (bug): `model switch --apply` to a non-MTP model now writes .env but
  does NOT recreate the container (the template ships the MTP primary's
  incompatible flags); prints the lines to remove. New --force overrides. Guards
  against taking a healthy deployment down. Tests added.
- Qodo #5 (maintainability): MTP compose flags centralized in
  catalog.mtp_compose_command_items() — one source of truth for the templates and
  switch's removal notice; new drift test asserts the packaged templates contain them.
- Qodo #1 (security): added --trust-remote-code + HF_TOKEN safety guidance to both
  compose templates and env.example (leave HF_TOKEN empty for public defaults / use
  a minimal-scope read-only token; pin trusted revisions).
- Qodo #3 (doc): documented the ticket's unsloth baseline serve command and why we
  deliberately deviate (the baseline export drops the MTP head) + that the decode
  comparison is against the load-tested mmangkad baseline.

Qodo #2 (test unsloth not sakamakismile): pushback in the PR thread — the unsloth
baseline NVFP4 export drops the MTP head (~0% acceptance), so it cannot exercise
MTP; sakamakismile is the grafted re-export that makes MTP work (issue #26).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OriNachum added a commit that referenced this pull request May 31, 2026
* Promote the MTP 27B to fleet default primary; archive mmangkad

Promote sakamakismile/Qwen3.6-27B-Text-NVFP4-MTP from candidate to the
fleet's default primary, replacing mmangkad/Qwen3.6-27B-NVFP4. The
tool-calling gate that kept it a candidate is now closed: served through the
production compose it emits a valid qwen3_coder tool call, completes a full
tool round-trip, keeps its reasoning trace, and runs MTP spec-decode at
78.6% draft acceptance with tool calling on (~2.4x decode, 8 -> ~19 tok/s,
~71 GB; both `model assess` probes finish=stop).

- catalog: role_hint primary <-> candidate swap (sakamakismile <-> mmangkad)
- gateway _DEFAULT_PRIMARY, whoami _DEFAULT_MODEL
- both env.example + docker-compose templates (single + fleet vllm-primary):
  bake the MTP serve flags (--speculative-config / --trust-remote-code /
  --language-model-only / --tokenizer override / --max-num-seqs=2, quant
  modelopt) so a fresh `model init && model serve` of the default just works
- switch: invert _serve_notices (non-MTP target -> "remove these 4 lines";
  was "add" for the candidate); force the MTP seq cap to 2
- culture.yaml model field; docs reframed (candidate -> primary, baseline ->
  archived former primary)
- tests updated; mmangkad retained as the MTP tokenizer source + only
  vision-capable 27B

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Address Qodo review on #28: switch --apply safety, DRY MTP flags, trust-remote-code guidance

- Qodo #4 (bug): `model switch --apply` to a non-MTP model now writes .env but
  does NOT recreate the container (the template ships the MTP primary's
  incompatible flags); prints the lines to remove. New --force overrides. Guards
  against taking a healthy deployment down. Tests added.
- Qodo #5 (maintainability): MTP compose flags centralized in
  catalog.mtp_compose_command_items() — one source of truth for the templates and
  switch's removal notice; new drift test asserts the packaged templates contain them.
- Qodo #1 (security): added --trust-remote-code + HF_TOKEN safety guidance to both
  compose templates and env.example (leave HF_TOKEN empty for public defaults / use
  a minimal-scope read-only token; pin trusted revisions).
- Qodo #3 (doc): documented the ticket's unsloth baseline serve command and why we
  deliberately deviate (the baseline export drops the MTP head) + that the decode
  comparison is against the load-tested mmangkad baseline.

Qodo #2 (test unsloth not sakamakismile): pushback in the PR thread — the unsloth
baseline NVFP4 export drops the MTP head (~0% acceptance), so it cannot exercise
MTP; sakamakismile is the grafted re-export that makes MTP work (issue #26).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* switch: drop the unused 'messages' param from _apply_env_only

It writes .env + emits the blocked-on-compose-edits result; it never used the
parser/quant messages (those are only for the restart path in _apply_switch).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OriNachum added a commit that referenced this pull request Jun 9, 2026
Triage of Qodo findings on #37:

- #1 (rule 796119): CHANGELOG `~/.model-gear` → `$HOME/.model-gear`. (The .py
  --help/docstring keep `~/.model-gear` to match the repo-wide CLI help text;
  Qodo's docs/config rule only flags the markdown.)
- #2 (unreadable/dir .env crash): main() preflights that .env is a regular file
  and wraps the read/update/write in try/except OSError -> EXIT_ENV_ERROR,
  matching _read_key()'s graceful degradation.
- #3 (under-scoped bump): a new documented capability is a minor, not a patch —
  0.18.1 -> 0.19.0.
- #4 (unhandled chmod): os.chmod is now best-effort (try/except OSError with a
  note), so a chmod-unsupported FS doesn't crash after a successful write.
- #5 (unvalidated --bytes): reject `< 16` (128-bit floor) with a user error
  before generating, so no weak key or token_urlsafe stack trace.

New tests: too-few-bytes and non-regular-file .env.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OriNachum added a commit that referenced this pull request Jun 9, 2026
…ey (#37)

* Add scripts/gen-api-key.py to generate/rotate the served-API bearer key

`CULTURE_VLLM_API_KEY` gates the vLLM API (and is mandatory before exposing it
via `model tunnel`), but there was no first-class way to mint it. This adds a
small, stdlib-only generator that:

- creates the key with `secrets.token_urlsafe` and NEVER hardcodes a secret, so
  the script is safe in the open-source repo; the key only lands in the
  gitignored deployment `.env` (written 0o600);
- hides the key by default (no echo into logs/scrollback); `--show` prints it,
  `--force` rotates an existing key;
- resolves the deployment dir like the `model` CLI (`--dir` > $MODEL_GEAR_DIR >
  ~/.model-gear), and runs from a wheel install (no model_gear import).

Tests cover set/rotate/refuse-overwrite/missing-dir/show/no-leak/0o600. README
"Expose the API" section now points at it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Address PR #37 review: harden gen-api-key.py + correct semver bump

Triage of Qodo findings on #37:

- #1 (rule 796119): CHANGELOG `~/.model-gear` → `$HOME/.model-gear`. (The .py
  --help/docstring keep `~/.model-gear` to match the repo-wide CLI help text;
  Qodo's docs/config rule only flags the markdown.)
- #2 (unreadable/dir .env crash): main() preflights that .env is a regular file
  and wraps the read/update/write in try/except OSError -> EXIT_ENV_ERROR,
  matching _read_key()'s graceful degradation.
- #3 (under-scoped bump): a new documented capability is a minor, not a patch —
  0.18.1 -> 0.19.0.
- #4 (unhandled chmod): os.chmod is now best-effort (try/except OSError with a
  note), so a chmod-unsupported FS doesn't crash after a successful write.
- #5 (unvalidated --bytes): reject `< 16` (128-bit floor) with a user error
  before generating, so no weak key or token_urlsafe stack trace.

New tests: too-few-bytes and non-regular-file .env.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OriNachum added a commit that referenced this pull request Jun 12, 2026
- Scaffold _readiness.py via AUDIO_TEMPLATES so `model init --fleet --audio`
  writes it (Dockerfile.parakeet COPYs it — clean init would otherwise fail
  `docker compose build stt`). [Qodo #2, comment 3402397497]
- Remove the inline fallback copy of the readiness decision from
  listen_server.py and add a drift test asserting the vendored twin matches
  the canonical model_gear/realtime/_readiness.py. [Qodo #4]
- Log CUDA readiness-probe failures (type + message) before returning 503 so
  operators can tell driver-down / OOM / stale-context apart. [Qodo #3]
- audio-smoke.py now exercises /v1/audio/speech and wires --stt-url to a
  direct-Parakeet check (was claimed-but-untested). [Qodo #5]
- docs/realtime-pipeline.md uses $HOME/.model-gear, not ~/.model-gear
  (portability rule). [Qodo #1, comment 3402397490]

275 tests pass; black/isort/flake8 + markdownlint clean. Bump 0.20.0 -> 0.20.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OriNachum added a commit that referenced this pull request Jun 12, 2026
… + smoke (closes #39, #40) (#41)

* spec: model-gear owns the audio I/O surface (devague /think)

Work issues #39 (Parakeet STT 500s, CUDA-unknown) and #40 (deployed
:8080 facade missing /v1/audio/transcriptions) backwards into one
converged spec: model-gear takes ownership of the audio stack, wiring
Parakeet STT + Magpie TTS + the vendored realtime facade into its
compose template and `model fleet up`.

Decisions captured: full-stack ownership (both /v1/audio/* routes),
cheap model-ready Parakeet healthcheck, restart-clears-stale-CUDA-context
runbook. Unblocks reachy-mini-cli's "hey reachy" wake-word.

Includes the converged spec + the .devague frame state (evidence trail).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* plan: model-gear audio surface — 6 tasks, 5 waves (devague /spec-to-plan)

Forward leg from the converged audio-ownership spec. Six file-disjoint,
TDD-gated tasks covering all 24 coverage targets:
  t1 vendor Parakeet server + cheap model-ready probe
  t2 build Dockerfiles (facade + parakeet)
  t3 wire the audio stack into the compose template (sole compose owner)
  t4 bring it up via `model fleet up`
  t5 docs/realtime-pipeline.md + README Audio I/O + CUDA restart runbook
  t6 smoke/acceptance harness (openapi, WAV 200, healthcheck flip)

Waves: [t1,t5] -> t2 -> t3 -> t4 -> t6 (serial after wave 0 by the
compose chokepoint). Risks carried: CUDA root-cause unconfirmed, fleet
gating on the GB10 budget, cheap-probe wording reconciliation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(audio): real Parakeet readiness probe + realtime-pipeline docs + smoke

Implements the three real gaps found after reconnaissance (t2/t3/t4 — the
audio overlay, Dockerfiles, fleet wiring — already existed in
templates/fleet/):

- t1: Parakeet /v1/health/ready now reflects REAL readiness (model loaded +
  a trivial CUDA op) instead of returning {"status":"ready"}
  unconditionally — the misleading-health bug behind #39. The pure decision
  lives in stdlib-only model_gear/realtime/_readiness.py (CI-unit-tested,
  8 cases), vendored into the Parakeet build context and COPY'd into the
  image so the container imports it without the wheel. (decision c16: a
  cheap probe, not a full transcription each interval.)
- t5: docs/realtime-pipeline.md — ownership of the live :8080 facade, fleet
  bring-up, the prior drift (#39/#40), health/readiness, and the stale-CUDA
  restart runbook.
- t6: scripts/audio-smoke.py — stdlib-only live smoke (openapi lists both
  routes; WAV POST -> 200 {text}); reproduces #39's repro. Live run is
  GPU-box-bound, not CI.

271 tests pass; black/isort/flake8 + markdownlint clean.

Refs #39 #40

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump version 0.19.0 -> 0.20.0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: sync uv.lock to 0.20.0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* style: black-format listen_server.py (fix lint)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci: markdownlint ignores docs/specs + docs/plans (devague artifacts)

The devague-exported spec/plan H1 is the verbatim announcement sentence,
which ends in a period (MD026/no-trailing-punctuation). These are generated
planning artifacts like docs/superpowers/** — ignore them in lint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(audio): address Qodo review of #41

- Scaffold _readiness.py via AUDIO_TEMPLATES so `model init --fleet --audio`
  writes it (Dockerfile.parakeet COPYs it — clean init would otherwise fail
  `docker compose build stt`). [Qodo #2, comment 3402397497]
- Remove the inline fallback copy of the readiness decision from
  listen_server.py and add a drift test asserting the vendored twin matches
  the canonical model_gear/realtime/_readiness.py. [Qodo #4]
- Log CUDA readiness-probe failures (type + message) before returning 503 so
  operators can tell driver-down / OOM / stale-context apart. [Qodo #3]
- audio-smoke.py now exercises /v1/audio/speech and wires --stt-url to a
  direct-Parakeet check (was claimed-but-untested). [Qodo #5]
- docs/realtime-pipeline.md uses $HOME/.model-gear, not ~/.model-gear
  (portability rule). [Qodo #1, comment 3402397490]

275 tests pass; black/isort/flake8 + markdownlint clean. Bump 0.20.0 -> 0.20.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OriNachum added a commit that referenced this pull request Jun 20, 2026
- _metrics.parse_metrics: skip non-finite (NaN/inf) values — int() would raise
  and break the best-effort contract (Qodo #1).
- _metrics.http_get_text: cap the body at 5 MiB (read max_bytes+1, treat overflow
  as unavailable) so a misbehaving backend can't stress memory (Qodo #2).
- gateway /status: drop base_url from the payload — it's internal-only routing
  detail and /status may be reached over a public tunnel; matches the documented
  schema (Qodo #3).
- gateway fleet_status_payload: probe backends in parallel (ThreadPoolExecutor)
  with a bounded 3s timeout, so /status can't hang for timeout × N on a slow
  backend (Qodo #4); and probe_backend short-circuits /metrics when /health fails
  (colleague review). Order preserved.

Tests for each; 345 pass; black/isort/flake8/bandit clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NnDfFkZkXz8C68hr3AA9Qa
OriNachum added a commit that referenced this pull request Jul 13, 2026
…les (Qodo #2, #3)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TJc5yvfweHP2AEccKNeaVd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scaffold lepenseur as a full CLI/PyPI AgentCulture sibling (acp/vLLM agent)

1 participant