文件历史

15 次代码提交

作者 SHA1 备注 提交日期
SABUJ123472 4c3bf5bbc9 fix(platform): harden Windows lock detection
Recognize win32 as a Windows platform alias and wrap missing platform lock modules in SwarmLockUnavailableError instead of leaking raw ImportError.

Based-on: #34
2026-05-24 09:07:19 +00:00
Siaochuan 63ac368975 fix(auth): prefer scoped provider env keys
Prefer OPENHARNESS_<PROVIDER>_API_KEY variables over provider-native globals while resolving API-key auth. Keep provider-native variables as fallback and avoid applying unrelated native keys across active profiles.

Forward the OpenHarness-scoped auth/provider environment variables to spawned teammates.

Based-on: #93
2026-05-24 09:05:44 +00:00
tjb-tech c281d34c4a fix(swarm): inherit OpenHarness permission config
Forward OpenHarness config/data env vars to spawned teammates and apply CLI permission_mode overrides to Settings.permission.mode so full_auto survives sub-agent startup paths.

Fixes #274
2026-05-24 08:18:20 +00:00
tjb-tech 57a9134997 test(swarm): accept versioned Python executables 2026-05-06 10:05:11 +00:00
David Whatley 5f97b2416e fix(swarm,tasks): direct-exec teammate spawn, bypass shell on Windows (#230)
Teammate spawn (`agent` tool, `task_create`) failed on Windows with exit
127 and "command not found" against a backslash-mangled Python path,
even though the same `bash -lc "..."` command worked interactively.

Root cause: `subprocess_backend.spawn` built a single shell command
string with a `KEY='val' python ...` env-prefix, then routed through
`bash -lc` via `asyncio.create_subprocess_exec`. Two failures stacked:

  1. The env-prefix string used Python `repr()` for values, and Git
     Bash's `-lc` argument parser consumed backslashes inside the
     quoted segments as escape sequences (`\U` -> `U`).
  2. Even with proper `shlex.quote` of every command part — keeping
     backslashes intact — Git Bash launched via
     `asyncio.create_subprocess_exec` could not exec a Windows-pathed
     Python interpreter, returning `command not found` for the same
     argv that interactive bash exec'd fine.

Fix: don't use a shell at all for teammate spawn.

  * Add `argv: list[str] | None` to `TaskRecord` plus matching kwargs
    on `BackgroundTaskManager.create_shell_task` /
    `create_agent_task`. Either `command` (shell) or `argv` (direct
    exec) must be supplied; both is rejected.
  * `_start_process` runs the argv path via
    `asyncio.create_subprocess_exec(*argv, env=...)` directly, with no
    bash wrapper.
  * `subprocess_backend.spawn` builds an argv list (via
    `get_teammate_command()` plus inherited CLI flags) and hands it to
    `create_agent_task(argv=..., env=...)`. Inherited env vars now
    flow through `env=` rather than being embedded in the command
    string.
  * The legacy shell-evaluated `command=` path is preserved verbatim
    for callers (e.g. `BashTool`) that legitimately want shell
    semantics — only teammate spawn migrates to direct exec.

Tests: 5 new unit tests in `tests/test_swarm/test_subprocess_backend.py`
and 3 in `tests/test_tasks/test_manager.py` lock in the contract — env
plumbed via `env=` kwarg, argv list preserves Windows backslashed
paths, command/argv mutual exclusion, direct-exec round-trip.

Validated end-to-end on Windows 11 against a real CEO/Lead workflow:
CEO successfully calls `agent` tool, Lead spawns at depth=1 and
issues 29 tool calls. Same path was producing exit-127 task logs
before this change.
2026-05-04 16:21:40 -05:00
tjb-tech ee97f8e78d test(swarm): stabilize subprocess backend prompt coverage 2026-04-20 08:10:05 +00:00
tjb-tech 1158027082 fix(swarm): forward worker system prompts to subprocesses 2026-04-20 08:05:41 +00:00
yulin c881c7deed fix(agent): Explore and claude-code-guide no longer hard-code model=haiku (#154)
Both built-in agents previously set model="haiku", which caused
subprocess spawning to fail for users running any non-Anthropic provider
(OpenAI, Bedrock, custom base URLs, etc.) because the literal string
"haiku" is not a valid model on those APIs.

Changes:
- Explore and claude-code-guide now use model="inherit", consistent
  with the existing Plan and verification built-in agents.
- build_inherited_cli_flags now skips the --model flag when the value
  is "inherit", so the subprocess inherits the parent model via the
  OPENHARNESS_MODEL env var that build_inherited_env_vars already
  forwards. Previously "inherit" was passed verbatim as a model name,
  which would have also broken Plan and verification agents.

Tests added:
- build_inherited_cli_flags: model="inherit" and model=None produce no
  --model flag; a real model name is included as expected.
- Builtin agent definitions: Explore and claude-code-guide must not
  reference Anthropic-only model aliases; Plan, verification, Explore,
  and claude-code-guide must all use None or "inherit".

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 17:05:25 +08:00
José Maia 4857439e50 fix(persistence): atomic writes and locks for shared state (#128)
Files under ~/.openharness/ — credentials, settings, session snapshots,
cron registry, memory index — were written with `Path.write_text()` in
truncating mode. A crash, SIGKILL, power loss, or out-of-disk error
during the write leaves a truncated file on disk; concurrent writers
clobber each other's updates; and the credentials file spent a brief
window at the default umask mode (commonly 0o644) before chmod-to-0600
ran.

Introduce `openharness.utils.fs.atomic_write_text` / `atomic_write_bytes`
which write to a same-directory temp file, fsync, apply the target mode
while the file is still private, and `os.replace` into place. Thread
them through all persistence writers. For read-modify-write on shared
files (credentials, settings, cron, memory index), pair atomic writes
with the existing `exclusive_file_lock` primitive so two `oh` processes
no longer race.

The generic lock helper moves from `openharness.swarm.lockfile` to
`openharness.utils.file_lock`. `swarm.lockfile` is retained as a thin
re-export so existing callers keep working.

Co-authored-by: José Maia <glitch-ux@users.noreply.github.com>
2026-04-13 12:40:24 +08:00
tjb-tech 76d91fdfa1 fix(swarm): run subprocess teammates in headless worker mode 2026-04-10 09:50:07 +00:00
José Maia 642f4ec240 Fix _READ_ONLY_TOOLS using wrong tool names in swarm permission sync
The _READ_ONLY_TOOLS frozenset used PascalCase names (e.g. "Read",
"Glob", "WebFetch") carried over from the TypeScript original, but the
Python tool registry registers tools with snake_case names (e.g.
"read_file", "glob", "web_fetch"). This meant _is_read_only() never
matched any tool, so handle_permission_request() never auto-approved
read-only operations — every tool call required explicit permission
evaluation from the leader, including safe read-only tools.

Update _READ_ONLY_TOOLS to use the actual registered tool names and
align the test parametrizations accordingly.
2026-04-05 12:53:40 +01:00
tjb-tech 34c8186605 fix(tests): patch swarm lockfile module correctly 2026-04-05 09:48:23 +00:00
tjb-tech 49dfaeacd7 refactor(swarm): extract mailbox lock layer
Also align real eval scripts with the product default max_turns instead of hardcoded small limits.
2026-04-05 09:32:40 +00:00
tjb-tech d26c626111 refactor: move maintainer skills (harness-eval, pr-merge) to .claude/skills/
These are developer/maintainer workflow skills, not user-facing bundled
skills. They belong in .claude/skills/ (project-local, not packaged).
2026-04-05 06:51:24 +00:00
tjb-tech a2514101af test: add comprehensive unit tests for swarm and coordinator components
Adds 156 tests across 9 new test files covering:
- coordinator_mode: TaskNotification XML, is_coordinator_mode, WorkerConfig
- agent_definitions: AgentDefinition model, built-ins, load_agents_dir
- swarm/types: TeammateIdentity, SpawnResult, TeammateExecutor protocol
- swarm/registry: BackendRegistry register/detect/get_executor
- swarm/mailbox: TeammateMailbox write/read/mark_read/clear + factories
- swarm/in_process: InProcessBackend spawn/shutdown/send_message, contextvars
- swarm/permission_sync: create/send/poll/handle permission flow
- swarm/team_lifecycle: TeamLifecycleManager CRUD with tmp_path fixtures
- swarm/worktree: validate_worktree_slug edge cases, flatten/branch helpers
2026-04-04 09:42:19 +00:00