---
name: acahti
description: Use Acahti git, pull requests, pipelines, commit checks, packages, teams, and built-in Work, Chat and Argos. Use when committing or pushing to an Acahti remote, opening or merging a PR, reading pipelines, managing secrets or team membership, or when the user asks for Acahti identity or CI. Connect MCP at <instance>/mcp with OAuth or a personal Access Token; Benchyard and shell agents use the acahti CLI.
---

# Use Acahti

This is the product skill, published at https://acahti.benchyard.com/skill.md. If you are reading a cached copy, fetch that URL now and follow it. Everything instance-specific comes from the instance itself, through `whoami`.

## Find the instance

An Acahti instance is one deployment, such as `https://acahti.example.com`. Take its URL from the first of these that exists:

1. The user names it.
2. An MCP server already connected to `<instance>/mcp`.
3. `ACAHTI_ROOT_URL`, or the host stored by `acahti auth login`.
4. The HTTPS URL of the git remote named `acahti`.

Do not guess it. Once connected, call `whoami`. It returns `login`, `root_url`, `org`, `clone_url_template`, `skill_url`, `git_name`, `git_email`, `setup_local`, `apply_when_remote_host`, `org_admin`, `work_manager`, `can_create_team`, `can_create_repo`, and `plugins`. Below, `<instance>` is `whoami.root_url` and `<org>` is `whoami.org`.

## Transports

One catalog, two clients. Keep both surfaces; do not require both on every machine.

| Client | Use when |
|---|---|
| Native MCP at `<instance>/mcp` | Codex, Cursor, Claude Code, ChatGPT plugins, or any MCP client |
| `acahti` CLI against `/acahti/v1` | Benchyard shells, scripts, and pipeline jobs without MCP tools |

Codex and other IDE agents need the skill plus an authenticated MCP connection. They do not install or use the CLI. The CLI is a thin REST client of the same catalog; named commands cover the delivery loop, and `acahti mcp call` reaches any tool when a shell has no native MCP.

## Instance configuration

Reuse the intended instance's existing connection. Otherwise take `ACAHTI_ROOT_URL` or the CLI's stored instance; ask for the URL only when neither is available. Never guess the instance from the publisher. If multiple instances are plausible, clarify before sending credentials. Keep Git remotes unchanged.

MCP accepts `Authorization: Bearer` from OAuth or a personal Access Token. Codex/ChatGPT native plugins use the client's OAuth flow (or a bearer token from an environment variable). Benchyard shells use a personal Access Token from the instance's avatar menu → Access tokens, without OAuth login or localhost callbacks. A skill cannot run an installation hook: begin onboarding on its first invocation, or when the user asks to connect.

## First use and connection troubleshooting

1. Discover available MCP tools. If the intended connection works, call `whoami` and continue. Do not install the CLI for Codex, Cursor, or any client that already exposes MCP tools.
2. **Codex (and other native MCP clients):** install the skill, then connect MCP and authenticate. OAuth:

   ```bash
   codex mcp add acahti --url https://acahti.example.com/mcp
   codex mcp login acahti
   ```

   Or a personal Access Token via an environment variable (never paste the value into chat or into `config.toml`):

   ```bash
   export ACAHTI_TOKEN=…   # avatar menu → Access tokens
   codex mcp add acahti --url https://acahti.example.com/mcp --bearer-token-env-var ACAHTI_TOKEN
   ```

   Complete the client's auth, then verify with MCP `whoami`. Do not require Benchyard Secrets for desktop OAuth. Do not fall back to the CLI when MCP is available.
3. **Benchyard / shell without MCP:** check `command -v acahti` and the presence (never values) of `ACAHTI_ROOT_URL` and `ACAHTI_TOKEN`; also try `acahti auth status` for a stored login. Do not read credentials files or extract tokens from Git. If configuration is missing, give this concrete guidance in the user's language: “在你的 Acahti 实例打开头像菜单 → Access tokens，创建个人 Token；在 Benchyard 的 Secrets 中设置 ACAHTI_ROOT_URL（实例地址）和 ACAHTI_TOKEN（Token），将 Token 的目标主机限定为该实例。让新变量在当前终端/任务生效后，告诉我继续。” Supply the known instance link. Ask only for missing configuration, never for secret values in chat. Each member uses their own token; workspace packages contain no credentials. Account signup uses an admin invite at `<instance>/join`.
4. If the CLI is missing **in a shell path that needs it**, install the private package from GitHub Packages (it is not on registry.npmjs.org):

   ```bash
   # GitHub PAT with read:packages for the acahti-ai org
   echo '@acahti-ai:registry=https://npm.pkg.github.com' >> ~/.npmrc
   echo '//npm.pkg.github.com/:_authToken=GITHUB_TOKEN' >> ~/.npmrc
   npm install -g @acahti-ai/acahti
   ```

   An installed skill does not install the CLI. Pipeline jobs already receive host and token.
5. Environment credentials are used directly. Benchyard may supply host-bound placeholders: never print, copy, persist, or pass them as literal CLI arguments. For a person outside Benchyard who explicitly wants local storage, `acahti auth login --hostname <instance> --with-token` reads the token on stdin and stores it privately. Bare `acahti auth login` prints setup guidance and exits; it does not open a browser.
6. Verify native MCP `whoami` (or `acahti whoami` in a shell), report `login` and `root_url`, then run the requested read operation or `inbox` / `acahti inbox`. To exercise MCP from a shell that has the CLI, use `acahti mcp tools` and `acahti mcp call whoami`. Successful website login or merely installing the skill is not connection success.

Prefer native MCP when available; the CLI is the supported path in Benchyard. Named CLI commands cover common operations. `acahti mcp tools` discovers the full live catalog; `acahti mcp call TOOL '{"argument":"value"}'` invokes it, and `acahti mcp call TOOL -` accepts a JSON object on stdin for sensitive arguments. Respect the user's authorization for mutations regardless of transport.

Reuse existing server identifiers; do not create duplicate connections. Do not embed tokens in a shared package or URL. Reload a task only when its tool inventory or environment is stale.

- **401:** check the token's presence, target host and revocation; guide the user to replace it in Secrets. For OAuth connections, allow token refresh and reconnect once if refresh fails. Do not send Benchyard shell users through OAuth or repeatedly retry invalid credentials.
- **403 / permission denied:** authentication may be valid; inspect account/repository permission. Do not request a new login without evidence.
- **Timeout / DNS / TLS / transport error:** report the actual connection failure and endpoint; diagnose reachability separately from credentials.
- **Wrong account or instance:** stop before mutations and resolve the intended configuration. Never send a stored token to another instance.
- **CLI install 404 from registry.npmjs.org:** expected. The package is private on `npm.pkg.github.com`. Codex does not need it; use MCP. For shells, authenticate to GitHub Packages as above.

## Git

HTTPS only: `<instance>/<org>/<repo>.git` (`whoami.clone_url_template`). Username is the Acahti login. Password is the account password or an access token; agents use the system credential helper with the token. `ssh://` URLs, custom SSH ports, and bare IP addresses are not Acahti git.

A team grants access; it is not a clone path. Clone is always `<org>/<repo>`.

If another host is `origin`, keep it. Add Acahti as the remote named `acahti`, and fetch and push it by name. Do not `git fetch --all`.

### Commit identity

This applies only to commits intended for Acahti and pushes to Acahti. Another remote pointing at Acahti does not change a commit bound elsewhere.

1. Resolve the actual push destination from the user's request, an explicit remote or URL, or Git's configured push destination (including push URLs). Never infer it from the directory name, remote name, or whichever remote is listed first. If more than one destination is plausible, ask before changing identity.
2. For an Acahti destination, call a fresh `whoami` before each commit-producing operation (commit, merge, amend, rebase, cherry-pick, revert, and their `--continue`). Compare the destination HTTPS host with `apply_when_remote_host`.
3. Run `setup_local` in that repository (local config only). Author is `git_name`, email is `git_email`; `login` is the account, not a name. If `whoami` fails, stop and diagnose before committing.
4. Verify `git var GIT_AUTHOR_IDENT` and `git var GIT_COMMITTER_IDENT`, accounting for `git -c`, `--author`, and `GIT_AUTHOR_*` / `GIT_COMMITTER_*`. New commits, merges, and reverts match the verified identity on both. Amend, rebase, and cherry-pick keep the original author and use the verified identity as committer. Inspect outgoing commits before pushing.
5. For any other destination, change nothing. If you set `setup_local` temporarily in a mixed-remote repository, restore the previous local identity afterwards.

### Branches

Protection is per repository. Before pushing, `repo_get` and `branch_list`. Push directly to branches with `protected: false`. For a protected branch, push a topic branch and open a PR (`pr_create`; `base` defaults to `repo_get.default_branch`). If the remote declines a push, open a PR to the default branch. Do not assume branch names. Operators set protection on the repository's Branches page.

## After push

Call each verb as an MCP tool or the CLI command in parentheses.

1. `git rev-parse HEAD`.
2. `checks_wait` `{owner, name, sha}` (`acahti checks OWNER/REPO SHA --wait`, which polls for you and exits 1 unless green). The MCP tool returns a snapshot of the latest pipeline round; poll until `done` is true. Do not pass `timeout_sec`.
3. Failed: `pipeline_list` `{repo, sha}` (`acahti pipeline list OWNER/REPO --sha SHA`), then `pipeline_get` (`acahti pipeline view OWNER/REPO N`), then `pipeline_log` without `step` for the failed steps (`acahti pipeline log OWNER/REPO N`).
4. Fix and push, or `pipeline_rerun`. Use `pipeline_cancel` only for a stuck run.
5. Green (`ok` and `done`): `pr_merge` (`acahti pr merge OWNER/REPO N`). It succeeds only when the newest pipeline on the head SHA is green. `blocked`: a person approves with `deploy_approve`.
6. Triage across repositories: `inbox` (`acahti inbox --section pipes` for the latest failed or blocked run per repo, `--section prs` for open PRs ready to merge).

Close leftover heads with `pr_close`, then `ref_delete`.

Rename a repository with `repo_rename` `{owner, name, new_name}`; repo admins only. Access, collaborators, pipeline history, and secrets follow it. Then `git remote set-url` in every clone.

If a pipeline stays queued with no runner, stop and report it with the `pipeline_get` wait state. Do not claim a green result.

## Pipelines

YAML lives in `.acahti/pipelines/`. Call official pipes with `pipe: <name>@v1` and `with:`; one-off steps use `commands:`. The pipe catalog: https://acahti.benchyard.com/docs/pipelines.md.

Trigger CI with `git push`, a tag, or opening a PR. `pipeline_trigger` is a manual run, not a release.

Git tags are `vX.Y.Z`. Image tags never carry the `v`: use `${CI_COMMIT_TAG#v}`, not `${CI_COMMIT_TAG}`.

In `commands:`, write `$VAR` for step environment. `${VAR}` is interpolated before the shell runs and is empty unless it is job context such as `${CI_COMMIT_SHA}`.

## Secrets

Pipeline secrets hold credentials for systems outside Acahti: registries, kubeconfigs, object storage. YAML names them (`DOCKER_PASSWORD: registry_password`). Values never go in git, chat, or `with:`.

Acahti's own npm and PyPI registries use the run's identity: the head commit author's account, falling back to the account that started the run. Do not create an `NPM_TOKEN` or publish token for them.

With `repo_get.can_manage_secrets` or `whoami.org_admin`: `secret_list` (names only; repo scope is the effective set), then `secret_put`. Never print a value; there is no `secret_get`. Without admin rights, do not call `secret_*`: tell the operator which secret is missing and where to add it (repository → Secrets, or Admin → Org secrets).

## Packages

Same credentials as git.

- npm: `<instance>/api/packages/<org>/npm/`
- PyPI: `<instance>/api/packages/<org>/pypi/simple/`

On a laptop, authenticate with `~/.npmrc` (`username`, `_password` as base64 of the password or token, `always-auth=true`), or `UV_INDEX_<NAME>_USERNAME` / `UV_INDEX_<NAME>_PASSWORD`, or `~/.netrc`. In CI the `docker-build` pipe passes these as BuildKit secrets `npmrc` and `netrc`; Dockerfiles mount them at `/root/.npmrc` and `/root/.netrc`.

Publish with the `npm-publish-acahti` or `pypi-publish-acahti` pipes, or `pkg_publish`. Org admins remove versions with `pkg_delete`.

## Teams

`user_list` `{q}` (`acahti user list [--q TEXT]`) matches login or display name. Org admins create people with `user_create` / `acahti user create LOGIN --author NAME` (`author` is the git display name; response includes a one-time `password`—hand it to the person, never put it in skill.md or chat). `user_update` / `acahti user update LOGIN --author NAME` changes author or email.

`team_list`, then `team_get` `{team}` for members (`read`, `write`, `admin`) and repositories. A membership covers every repository in the team.

Team admins or org admins: `team_member_set` `{team, login, permission}` (omit `permission` for `write`), `team_member_remove` `{team, login}`, and `team_delete` `{team}` / `acahti team delete NAME`. Do not add the same person as a collaborator on each repository in a team.

One repository: `repo_access` `{owner, name}`, then `collaborator_set` `{owner, name, login, permission}` (omit `permission` for `write`) and `collaborator_remove` `{owner, name, login}`. Repo admin or org admin. This does not change team membership. Do not add someone to a team to open a single repository.

## Creation permissions

`whoami` includes `can_create_team` and `can_create_repo`. Org admins have both. Other users need an explicit grant for each operation.

Org admins grant or revoke both with `user_permissions_set` `{login, can_create_team, can_create_repo}` or `acahti user permissions LOGIN --create-team true --create-repo true`. `user_permissions` / `acahti user permissions LOGIN` reads the effective permissions (self or org admin). These grants are scoped to the current organization.

`team_create` `{team}` / `acahti team create NAME` makes the caller a team admin. `repo_create` `{name, team?}` / `acahti repo create NAME [--team TEAM]` makes the caller a repository admin. Assigning a new repository to a team also requires team admin or org admin. Org admins move an existing repository to another team with `repo_team_set` `{owner, name, team}` / `acahti repo move OWNER/REPO TEAM`; the new team's members get access if the old team's grant was on. Org admins archive a repository with `repo_archive` `{owner, name, archived}` / `acahti repo archive|unarchive OWNER/REPO`: it becomes read-only, members and CI stop seeing it, and admins still list it marked `archived`.

## Built-in features and plugins

Work, Chat, Aidy and Argos are built in. Phaevo is the one plugin; it appears in `whoami.plugins` only when installed and granted, and plugin operations join MCP the same way. Do not invent tabs that are not there.

| Feature | Web app | Notes |
|---|---|---|
| Work | `<instance>/projects`, `/tickets`, `/docs`, `/track` | Projects, tickets, todos, documents and uploaded files, and Track flows from report to release |
| Chat | header sidecar (Acahti mark) → Messages tab, `<instance>/chat` on mobile | Direct messages; `chat_search` finds messages in the caller's conversations, `chat_share_document` sends a knowledge document as a card |
| Aidy | header sidecar → Aidy tab | Agent on the host model over the caller's MCP catalog; conversations kept per person (`acahti aidy`, `aidy_*`) |
| Argos | `<instance>/argos` | Cases (`/argos/cases?case=<id>` shows a case with its Track flow), runs, sources and plans. `argos run <selector> --env <name> --dash` streams a run as the runner's own identity from `ACAHTI_ROOT_URL` and `ACAHTI_TOKEN` (pipelines inject both); its page is `<instance>/argos/runs/<sid>` |

Use the Work MCP tools, REST `/acahti/v1/work/*`, or CLI. Work is instance-wide shared collaboration; personal list views are filters, and restricted documents carry their own view and edit grants. All web, REST and MCP operations use the same service and rules.

```bash
acahti ticket view 267
acahti ticket view https://your-instance.example/tickets/267
acahti ticket list --view mine --page 1 --page-size 20
acahti ticket create --body-file ticket.json
acahti ticket comment 267 --body-file comment.txt --file evidence.png
acahti ticket archive 267
acahti todo list
acahti document list
acahti search --q TurboMesh
acahti search --type ticket --scope mine --state open
acahti iteration list --project web --state open
acahti mcp call project_context '{"id":"web"}'
acahti aidy ask --question "Which of my tickets are still open?"
acahti attachment download 123 --output evidence.png
acahti mcp call ticket_get '{"id":267}'
```

Ticket detail includes the description, reproduction, expected/actual result, comments and attachment metadata. Page URLs must belong to the selected instance. Create/update JSON comes from `--body-file` (or stdin with `-`); comments use text files. Attachment metadata provides an authenticated content URL; downloads require the same identity and never embed a token in the URL. Binary uploads use HTTP multipart; ticket files accompany a comment. CLI supports `attachment upload todo|document ID --file PATH`.

Benchyard shell tasks use the configured personal Token directly: no browser Cookie, OAuth callback or localhost listener is needed. Native clients can continue using OAuth. Discover actual tools before choosing the command.

The browser surfaces under `/ui/*`, plugin pages included, use the browser session. Agents reach Work, Chat, Argos, Git, PRs, CI and secrets through MCP or the CLI.

## Tools

Work: `project_list` `project_reorder` `project_get` `project_create` `project_update` `project_members_set` `project_repos_set` `project_context` `agent_run_list` `agent_run_get` `agent_run_create` `agent_run_update` `agent_run_event` `decision_list` `decision_create` `decision_update` `planning_move_todos` `planning_todo_links` `planning_todo_time` `planning_progress` `planning_brief` `delivery_submit` `delivery_draft` `delivery_list` `delivery_get` `delivery_retry` `planning_run_step` `planning_run_steps` `iteration_list` `iteration_get` `iteration_create` `iteration_update` `iteration_close` `iteration_delete` `search` `knowledge_backlinks` `knowledge_history` `knowledge_restore` `knowledge_save_chat_file` `knowledge_share_links` `knowledge_share_link_create` `knowledge_share_link_revoke` `knowledge_sharing` `knowledge_sharing_configure` `aidy_settings` `aidy_configure` `aidy_ask` `aidy_confirm` `aidy_conversation_list` `aidy_conversation_get` `aidy_conversation_update` `aidy_conversation_delete` `track_get` `track_list` `track_template_list` `track_template_update` `track_template_reset` `track_flow_update` `track_activity` `work_overview` `work_manager_list` `work_manager_set` `work_manager_remove` `time_entry_list` `time_entry_save` `time_entry_delete` `time_entry_suggest` `notification_nav` `notification_list` `notification_mark_read` `notification_mark_all_read` `ticket_nav` `ticket_list` `ticket_get` `ticket_create` `ticket_update` `ticket_comment` `ticket_archive` `todo_nav` `todo_list` `todo_get` `todo_create` `todo_update` `todo_delete` `todo_comment` `todo_link_ticket` `document_nav` `document_list` `document_get` `document_create` `document_update` `document_delete` `document_grants` `document_grant_set` `document_grant_delete` `document_folder_update` `document_folder_delete` `document_folder_create` `attachment_get`

Chat and Argos: `chat_search` `chat_share_document` `argos_overview` `argos_catalog` `argos_case_history` `argos_run_list` `argos_run_get` `argos_run_interrupt` `argos_run_comment` `argos_test_list` `argos_test_get` `argos_test_save` `argos_test_source` `argos_plan_list` `argos_plan_save` `argos_search`

Git, CI, packages, people and plugins: `whoami` `repo_list` `repo_get` `repo_create` `repo_rename` `repo_team_set` `repo_archive` `repo_delete` `branch_list` `ref_delete` `pr_create` `pr_list` `pr_get` `pr_comment` `pr_comments` `pr_merge` `pr_close` `checks_wait` `pipeline_list` `pipeline_get` `pipeline_log` `pipeline_rerun` `pipeline_trigger` `pipeline_cancel` `pipeline_delete` `inbox` `pkg_publish` `pkg_list` `pkg_delete` `agent_status` `deploy_approve` `secret_list` `secret_put` `secret_delete` `user_list` `user_create` `user_update` `user_permissions` `user_permissions_set` `team_create` `team_list` `team_get` `team_delete` `team_member_set` `team_member_remove` `repo_access` `collaborator_set` `collaborator_remove` `plugin_document` `plugin_list` `plugin_get` `plugin_operate` `plugin_retry`

Arguments and descriptions: https://acahti.benchyard.com/docs/mcp.md.

## Answering Work questions and Aidy

For questions such as open tickets, planned iterations, or knowledge lookup, do
not invent answers from memory:

1. **Search first** — `search` / `acahti search` with keyword `q` and optional
   filters `type`, `assignee` (`me` or login), `state` (`open` or exact status),
   `scope` (`mine`/`created`/`assigned`/`all`). `q` may be empty when filters
   alone list Work.
2. **Read records** when search is thin — `ticket_list`, `todo_list`,
   `iteration_list`/`iteration_get`, `document_get`, `knowledge_history`. Prefer
   named CLI (`acahti ticket list`, `acahti iteration view`, …) or the matching
   MCP tools.
3. **Cite sources** with their URLs (`/tickets/…`, `/docs/…`, `/projects/…/iterations/…`).
   If evidence is empty, say so and ask for a sharper product, version or title.

For an action the user asked for, call the write operation directly
(`project_create`, `todo_create`, `ticket_update`, …); look up only the ids or
logins you lack.

Planning rules every transport enforces:

- Status updates, risks and capacity come from `planning_brief` (a project and
  its current iteration, or `iteration_id`). Report health with its evidence.
- Due and start dates are days (`YYYY-MM-DD`, Asia/Shanghai). Pushing a due day
  later needs `due_change_reason`; `estimate_minutes` is planned effort (480 a day).
- An active iteration keeps the baseline it started with; todos added later are
  out of plan, with `iteration_reason`. Release or cancel only through
  `iteration_close`, carrying every unfinished todo (move, unplan, or keep with a reason).
- A delivery names the todos it delivers: draft with `delivery_draft`, submit
  with `todo_ids`. Work done without a todo gets one first.
- Tickets run todo → in_progress → verifying → closed; the reporter (or a Work
  manager) closes or rejects with `status_reason`.
- Log time from `time_entry_suggest` (the day's evidence), one `time_entry_save` each.

Aidy (sidecar Aidy tab, `aidy_ask`, `acahti aidy ask`) is the same loop on the
host model, acting as the caller over the caller's MCP catalog. Reads run at
once; writes come back under `pending` and run only after `aidy_confirm`
(`acahti aidy confirm ID --call CALL_ID`, `--cancel` to drop). Never confirm a
write the user did not ask for. Pass `conversation_id` / `--conversation` to
continue a conversation; `aidy_conversation_list|get|update|delete` /
`acahti aidy list|view|rename|delete` manage history. Aidy withholds its own
settings, `secret_put`, `user_create` and `pkg_publish`. Missing model
configuration is explicit via `aidy_settings`.

## Product planning, knowledge and Aidy

Use `iteration_list`, `iteration_get`, `iteration_create`, and `iteration_update`
(or `acahti iteration …`) for releases on projects whose `kind` is `product` or
`ops`. Pass `project_id` (not a separate product enum). New iterations use an immutable X.Y series; deliveries allocate project-wide X.Y.Z versions. Every iteration has an owner. Read before updating and
pass the current `revision`; a conflict requires a fresh read. Move todos with planning_move_todos (current revisions and request_key required). Link tickets, documents, Argos runs, pipelines and PRs as evidence. Marking an
iteration released does not deploy it.

`knowledge_history` reads immutable article revisions; `knowledge_restore`
creates a new revision from a retained one. Documents default to instance-shared; restricted documents use view/edit grants.
Only org admins may call `aidy_configure` / `acahti aidy configure --body-file -`;
pass keys on stdin and never print them. `aidy_settings` / `acahti aidy settings`
redacts keys.

Process `notification_list` to discover work changes, inspect the referenced
object and evidence, then use `notification_mark_read`. Notifications are not
approval to merge, deploy or change permissions.

Argos is built in and every member reads it: `argos_test_list/get/save/source`,
`argos_plan_list/save`, `argos_run_list/get/comment/interrupt`,
`argos_case_history`, `argos_catalog`, `argos_overview`, and `argos_search`.
Register the full source with repository, revision and path; retain its checksum
with execution evidence. After creation only the owner, creator or an org admin
changes a case or plan; updating a case requires `expected_sha256` from a fresh
read, a plan its current `revision`. Shared plans require registered cases and an owner;
run them with Argos/CI and attach the actual results. Never claim that saving a
plan or registering source executed a test.

Guides: https://acahti.benchyard.com/docs/iterations/,
https://acahti.benchyard.com/docs/knowledge/,
https://acahti.benchyard.com/docs/aidy/,
https://acahti.benchyard.com/docs/track/,
https://acahti.benchyard.com/docs/testing/.

Knowledge articles support `tags` on create/update; tags participate in search.
`knowledge_backlinks` returns related articles referencing a document URL.

## Agent-driven planning and delivery

Todo updates require revision. Requirement is a todo status; closed_at is separate.
Use planning_todo_links for incremental ticket, document, pull request
(`to_key` owner/repo#n), pipeline (owner/repo#n) and Argos run (run id) links,
planning_todo_time for all authors/dates, planning_progress for exact aggregates,
and planning_move_todos for atomic same-project iteration moves.

Use delivery_submit (acahti delivery submit --body-file FILE) with a stable
request_key, iteration_id, summary, changelog and a complete project repository
manifest. Each repository has name, branch, full sha and changed; unchanged
repositories retain a verified tag. Changed repositories receive the shared
vX.Y.Z. delivery_retry (acahti delivery retry ID) resumes the same version.
Inspect delivery_get for dispatch events and actual pipeline evidence.

Name the todo in the branch, pull request or commit message (`todo#123`,
`todo-123`, `T-123`; `ticket#45` for a ticket) so Acahti links the pull request
and its pipelines automatically. `track_get` `{type, id}` (ticket, todo,
iteration, delivery or argos_case; `id` is a string) reports where that work
stands across the stages its type's template expects (bug, feature, todo, ops,
argos_case, iteration), from reported through review, build, Argos and
delivered to released; `track_template_update` (Work managers) changes a type's
stages and `track_flow_update` adjusts one flow (`template`, `add`, `skip`); `track_activity` `{login, days}` answers what a person did (Work, commits, pull requests, reviews, pipelines); `track_list` lists open flows by `view` (`work`,
`tickets`, or `argos` for failing and recently fixed cases), with `stuck_days`
for those without activity (`acahti track list|view`).

planning_run_step publishes revisioned structured steps, dependencies, parent,
attempt and evidence; planning_run_steps reads them for Trace and DAG views.
Only the run's agent, creator or Work manager may publish steps.
