Metadata-Version: 2.4
Name: herdr-office
Version: 0.1.0
Summary: A supervised engineering office for Herdr-managed OpenAI Codex workers.
Author: happy_ryo
License-Expression: MIT
Project-URL: Homepage, https://github.com/suisya-systems/herdr-office
Project-URL: Documentation, https://github.com/suisya-systems/herdr-office/tree/main/docs
Project-URL: Repository, https://github.com/suisya-systems/herdr-office
Project-URL: Issues, https://github.com/suisya-systems/herdr-office/issues
Keywords: codex,herdr,multi-agent,automation,orchestration
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Herdr Office

Herdr Office is your supervised engineering office, powered by Herdr. You talk
to one **Secretary**, who turns requests into clear, limited tasks, starts
isolated Codex Workers across multiple repositories, and brings their questions
and results back to the same conversation.

Herdr Office is an independent open-source integration and is not affiliated
with or endorsed by OpenAI.
It is developed by Suisya Systems and integrates with the separately maintained
[Herdr project](https://github.com/ogulcancelik/herdr).

For example, one organization can ask separate Workers to change `renga` and
`claude-org` at the same time, then ask another Worker to draft notes without
using a repository.

You do not operate the Workers directly. Your normal interaction is:

1. Start the organization.
2. Open Herdr and talk to Secretary.
3. Confirm tasks, answer questions, and review results there.
4. Stop the organization when no Worker is running.

## Before you start: understand the directories

Herdr Office uses several locations for different purposes. Keeping them
separate prevents the organization itself from being confused with a project it
is asked to edit.

| Location | Example | Purpose |
| --- | --- | --- |
| Installed command | Managed by `pipx` | Keeps the application and its Python dependencies isolated. |
| Control directory | `~/.local/state/herdr-office/organizations/default/control` | Created by `init`; fixed working directory for organization roles, never for Worker project edits. |
| Source repositories | `~/work/renga` | Existing projects that tasks may target. |
| Task workspaces | `.../workspaces/...` | One isolated working copy or empty scratch directory created for each delegated task. |

`init` creates the control directory below the named organization. Lifecycle
commands resolve it deterministically, so they can be run from any directory.
The shell's current directory is never adopted as control state or as a source
repository.

The control directory does **not** limit which projects can be edited. Project
selection happens later, for each task.

## Requirements

Install these before continuing:

- Linux or macOS
- Bubblewrap on Linux (`bwrap`) with either unprivileged user namespaces or a
  distribution-supported setuid installation; macOS uses the built-in
  `sandbox-exec`
- Python 3.10 or newer
- `pipx`
- Git
- [Herdr](https://herdr.dev/docs/install/) 0.7.3 or newer
- [Codex CLI](https://developers.openai.com/codex/cli/), authenticated with
  `codex login`

GitHub CLI and `gh auth login` are needed only if you want the organization to
create pull requests. You do not need to run a separate `herdr server` terminal.

## First-time installation

Install the application in an isolated environment, then initialize the default
organization:

```bash
pipx install herdr-office
herdr-office init
```

These commands do different jobs: `pipx install` installs the command in an
isolated environment, while `init` creates the named organization's separate
`control/`, `state/`, `workspaces/`, and `authority/` roots. The control
directory is for organization roles, not project work. `init` does not create a
project working copy; a separate task workspace is created later for every task
that Secretary delegates to a Worker.

`init` also installs the restricted Worker policy at
`$CODEX_HOME/codex-herdr-worker.config.toml` (`~/.codex` by default). It safely
updates a profile previously installed by Herdr Office when that file is still
unmodified, and refuses to overwrite a local customization. The policy prevents
a Worker from granting itself network access or permission to publish changes.
`init` also runs prerequisite diagnostics, including the same network-disabled,
read-only sandbox probe used for Worker verification.

The output includes the absolute `control_directory` and
`authority_requests_directory`. Use those exact values in later human-terminal
commands, for example:

```bash
CONTROL_DIRECTORY="/absolute/control_directory/printed/by/init"
AUTHORITY_REQUESTS="/absolute/authority_requests_directory/printed/by/init"
```

Resolve every `FAIL` before continuing. A `WARN` describes an optional feature
or a decision that still belongs to you. `init` is idempotent, so it is safe to
repeat after an upgrade or a repaired prerequisite.

Start the organization:

```bash
herdr-office start
```

> **Run it anywhere.** `herdr-office start` does not use the shell's current
> directory. You do not need to create an empty directory or change into the
> control directory first. Starting inside a source repository does not select
> that repository. Secretary selects a source for each task, and Herdr Office
> creates its isolated task workspace at delegation time. [See the full
> directory layout.](#where-organization-data-lives)

`start` starts or reuses the Herdr server and organization helper processes,
then connects the terminal to the named Herdr session. Running it again reuses a
healthy organization instead of creating duplicate panes. It rechecks the
installed Worker policy and host prerequisites before starting. For automation
that must return without opening the Herdr interface, use
`herdr-office start --detach`.

After Herdr opens, select the **Secretary** pane. Initialization is complete.

## Daily routine

You do not repeat installation or initialization every morning. Run `init`
again after an upgrade, and use `doctor` when startup or authentication fails.

### Start of the day

```bash
herdr-office start
```

Then use the Secretary pane. To resume from the previous day, say:

> Show me unfinished tasks, unanswered decisions, and results awaiting approval.

Secretary already receives this information automatically at startup. The
sentence above is useful as a human cross-check, not as the mechanism that
restores state.

If you close only the Herdr view, the organization continues running. Run
`herdr-office start` again to reuse it and reconnect.

### Give Secretary work

Describe the outcome and the project in ordinary language:

> In renga, fix the parser regression and run the focused tests.

For several independent tasks, give the complete request at once:

> Fix the parser in renga, update the matching guide in claude-org, and draft
> release notes without using a repository.

Secretary will:

1. identify the project for each task;
2. restate the expected result, allowed scope, and verification;
3. show the exact delegation command;
4. ask for confirmation before starting Workers;
5. return every question and result to the Secretary pane.

On the first use of a local path or Git URL, Secretary asks you to approve that
source. The organization remembers it, so later requests can use the project
name. Work that needs no repository uses a new empty **scratch workspace**.

### When a Worker asks a question

A Worker does not remain open waiting at an interactive prompt. If it needs a
product, design, or task-direction decision, it stops in the `blocked` state and
sends Secretary a question with concrete options.

Answer in the Secretary pane. Secretary records the answer and starts a new
Worker attempt in the same unchanged task workspace. The answer only tells the
Worker which direction to take; it cannot allow wider file changes, network
access, weaker safety restrictions, publishing, merging, or exporting results.

The corresponding diagnostic commands are:

```bash
herdr-office decisions
herdr-office answer <task_id> --choice <option-id> --answered-by "$USER"
```

### Review a result

When a Worker finishes, Secretary shows its changed files, verification, risks,
and available release actions. Worker changes remain isolated; they are not
silently copied into the original source repository.

For a Git task, you may explicitly approve a pull request or patch. For a
scratch or copied-directory task, you may explicitly export its output files
(called artifacts).
Workers cannot approve, push, create pull requests, export results, or merge by
themselves. The organization never merges automatically.

### End of the day

Ask Secretary:

> Summarize running or blocked work and anything still awaiting my approval.

Do not shut down while a Worker is still running. If needed, cross-check the
durable state:

```bash
herdr-office workers list
herdr-office decisions
herdr-office attention
```

These commands do not modify project files or release results. `attention` may
update its notification bookkeeping.

When no Worker is running:

```bash
herdr-office stop
```

`stop` refuses to shut down while any Worker is active. It does not accept,
discard, or delete task results. Unanswered decisions, unreleased changes, task
workspaces, and diagnostics remain on disk for the next `start`.

## Where organization data lives

The default organization stores durable state and task workspaces under:

```text
${XDG_STATE_HOME:-$HOME/.local/state}/herdr-office/
  organizations/default/
    control/                        # fixed role working directory
    state/                          # tasks, messages, approvals, and diagnostics
    authority/                      # human-issued capabilities and trusted catalog
    workspaces/
      cache/repositories/           # bare mirror for each remote Git project
      projects/<project>/<task>/    # isolated Git worktree for a task
      directories/<project>/<task>/ # isolated copy of a non-Git directory
      scratch/<task>/               # empty repository-free task workspace
```

Local source repositories stay in their existing locations. A remote repository
is fetched into the organization mirror cache. Every task still gets its own
isolated workspace. Completed workspaces remain available until you clean them
up.

## Who and what run behind Secretary

- **Secretary** is your conversation and approval point.
- **Dispatcher** records task status and helps diagnose failures.
- **Workers** are temporary Codex processes, one isolated workspace per task.
- **Broker** is a background process that validates host-side workspace and
  release operations. It does not occupy a normal operator pane.

Secretary and Dispatcher do not have to remember their entire operating method
from an earlier conversation. On every `start`, the runtime writes a versioned role
manual and reconstructs a handoff from durable task, decision, review, message,
and release records. The role's non-negotiable rules are also supplied as Codex
developer instructions. Before an important Secretary operation, the managed
CLI requires a fresh check bound to that exact command, such as
`role-context secretary --operation delegate`; Dispatcher performs the
equivalent read-only check before monitoring. A stale conversation therefore
cannot silently become authority to retry, widen, or release work.

Terminal text is useful for viewing progress. The saved files under the
organization's `state/` directory are authoritative if the display disagrees.

To inspect exactly what either role should currently know:

```bash
herdr-office role-context secretary
herdr-office role-context dispatcher
herdr-office role-manual verify
```

`role-context` is read-only with respect to tasks and approvals; it only
refreshes the role's handoff snapshot. `role-manual verify` detects an altered
audit copy or a manual that references a command the installed CLI does not
provide.

## Command-line reference

Most users should let Secretary construct these commands. They are documented
here for automation and diagnosis.

### Select a project directly

First use of a local repository or remote URL:

```bash
herdr-office authorize-source --source "$HOME/work/renga" \
  --approved-by "$USER"
herdr-office delegate \
  --task-id task-renga-parser-fix \
  --source "$HOME/work/renga" \
  --source-approval-id <source-approval-id> \
  --allowed-scope src/parser --allowed-scope tests/test_parser.py \
  --verify-command pytest -q tests/test_parser.py \
  --title "Fix parser regression" \
  --objective "Fix the regression and run the focused parser tests" \
  --work-manifest-id <work-manifest-id>
```

Later, use its learned name:

```bash
herdr-office projects
herdr-office delegate --project renga \
  --task-id task-renga-error-message \
  --allowed-scope src/parser --allowed-scope tests/test_parser.py \
  --verify-command pytest -q tests/test_parser.py \
  --title "Improve error message" \
  --objective "Clarify the parser error and update its focused test" \
  --work-manifest-id <work-manifest-id>
```

Repository-free work:

```bash
herdr-office delegate --workspace scratch \
  --task-id task-release-notes \
  --allowed-scope release-notes.md \
  --title "Draft release notes" \
  --objective "Write release-notes.md from the supplied requirements" \
  --work-manifest-id <work-manifest-id>
```

For several independent tasks, Secretary saves the task array under the
organization control directory, for example as `$CONTROL_DIRECTORY/tasks.json`:

```json
[
  {
    "task_id": "task-renga-parser-fix",
    "project": "renga",
    "title": "Parser fix",
    "objective": "Fix and test the parser",
    "allowed_scope": ["src/parser", "tests/test_parser.py"],
    "base_ref": "HEAD",
    "verification": "Run pytest -q tests/test_parser.py."
  },
  {
    "task_id": "task-claude-org-parser-guide",
    "project": "claude-org",
    "title": "Guide",
    "objective": "Update the parser guide",
    "allowed_scope": ["docs/parser-guide.md"],
    "base_ref": "HEAD",
    "verification": "Review the rendered guide and run its focused documentation checks."
  },
  {
    "task_id": "task-release-notes",
    "workspace": {"kind": "scratch"},
    "title": "Notes",
    "objective": "Draft release notes",
    "allowed_scope": ["release-notes.md"],
    "base_ref": "HEAD",
    "verification": "Review release-notes.md against the supplied requirements."
  }
]
```

```bash
python3 - "$CONTROL_DIRECTORY/tasks.json" \
  "$AUTHORITY_REQUESTS/work-requests.json" <<'PY'
import json, os, sys
with open(sys.argv[1], encoding="utf-8") as source:
    tasks = json.load(source)
flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC | getattr(os, "O_NOFOLLOW", 0)
descriptor = os.open(sys.argv[2], flags, 0o600)
os.fchmod(descriptor, 0o600)
with os.fdopen(descriptor, "w", encoding="utf-8") as destination:
    json.dump([{"kind":"schedule","tasks":tasks,"max_concurrent_workers":3}],
              destination, indent=2)
    destination.write("\n")
PY
herdr-office authorize-work \
  --requests-file "$AUTHORITY_REQUESTS/work-requests.json" \
  --approved-by "$USER"
herdr-office schedule --tasks-file "$CONTROL_DIRECTORY/tasks.json" \
  --max-concurrent-workers 3 \
  --work-manifest-id <work-manifest-id>
```

Every dispatch entry must include the final `task_id` and a non-empty
`allowed_scope`; the matching `delegate` command passes them with `--task-id`
and one or more `--allowed-scope` options. A schedule also spells out its
`base_ref`, `verification`, and `workspace` object so the tasks file exactly
matches the human-authorized request. Human authorization request files must be
private regular files below the host-only
`<organization-root>/authority/requests` inbox created by `init`. Each request
must use mode `0600`. Files in `/tmp`, the Agent-writable control directory,
state, or workspaces are refused.

`authorize-work` runs in the human terminal. One manifest may enumerate an
exact sequence of dispatch, schedule, or continuation requests. Each entry
expires and is consumed once; changing its project, objective, scope,
verification, answer, or concurrency invalidates it.

### Inspect or answer decisions directly

```bash
herdr-office decisions
herdr-office decisions --stale-after-seconds 86400
herdr-office answer <task_id> --choice <option-id> --answered-by "$USER" \
  --work-manifest-id <work-manifest-id>
herdr-office answer <task_id> --answer "<bounded direction>" \
  --answered-by "$USER" --work-manifest-id <work-manifest-id>
```

### Review and release

Secretary may prepare `release-requests.json` under the control directory. After
reviewing its exact contents, the human copies it into the authority inbox with
mode `0600` before issuing the manifest:

```bash
herdr-office review <task_id>
herdr-office request-review <task_id>
install -m 600 "$CONTROL_DIRECTORY/release-requests.json" \
  "$AUTHORITY_REQUESTS/release-requests.json"
herdr-office authorize-release \
  --requests-file "$AUTHORITY_REQUESTS/release-requests.json" \
  --approved-by "$USER"
herdr-office approve-pr <task_id> \
  --branch "worker/<task_id>" --title "..." --body "..." \
  --manifest-id <approval-id>
herdr-office export-patch <task_id> --manifest-id <approval-id>
```

For an explicitly reviewed group of pull requests:

```bash
herdr-office approve-prs --requests-file pull-requests.json \
  --manifest-id <approval-id>
```

`authorize-release` must be run by the human in an interactive terminal. One
manifest may contain several tasks, but each entry is bound to its task,
action, repository or destination, branch, base branch, reviewed workspace
identity, PR title, PR body, commit message, and expiry. A `pull_request` entry
in `release-requests.json` therefore requires `task_id`, `action`, `branch`,
`base_branch`, `title`, and `body`. Requests run in list order, so a provider failure may leave an
explicitly reported partial batch. Nothing is merged automatically.

For repository-free artifacts:

```bash
herdr-office artifacts <task_id>
herdr-office export-artifacts <task_id> --to ./accepted-output \
  --manifest-id <approval-id>
```

## Named organizations

Use a separate name when you intentionally need completely separate state,
control, workspaces, authority, and Herdr sessions:

```bash
herdr-office --organization product-team init
herdr-office --organization product-team start
```

Use `herdr-office --organization product-team stop` to stop it. Its complete
runtime layout lives below `organizations/product-team/` and is independent of
the default organization.

## Upgrade and migration

Upgrade the isolated installation, then rerun the idempotent initializer so a
new packaged Worker policy or prerequisite problem is reported before startup:

```bash
pipx upgrade herdr-office
herdr-office init
```

`init` automatically adopts a newer packaged policy only when its managed
profile is still unmodified. It never overwrites a local customization; inspect
and resolve a reported conflict deliberately before running `start`.

Older releases stored state inside a target repository. With the old
organization stopped, migrate its durable state once:

```bash
herdr-office migrate-state --from /path/to/project/.state
```

Project repositories remain separate from organization state. Select them per
task with `--source` on first use or a learned `--project` name later.

## More detail

- [Operator Guide](https://github.com/suisya-systems/herdr-office/blob/main/docs/runbooks/operator-guide.md)
- [Task Workspace Contract](https://github.com/suisya-systems/herdr-office/blob/main/docs/contracts/task-workspaces.md)
- [State Layout](https://github.com/suisya-systems/herdr-office/blob/main/docs/contracts/state-layout.md)
- [Safety Model](https://github.com/suisya-systems/herdr-office/blob/main/docs/design/safety-model.md)
