cool-workflow 0.1.96 → 0.1.98
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/apps/architecture-review/app.json +1 -1
- package/apps/architecture-review-fast/app.json +1 -1
- package/apps/end-to-end-golden-path/app.json +1 -1
- package/apps/pr-review-fix-ci/app.json +1 -1
- package/apps/release-cut/app.json +1 -1
- package/apps/research-synthesis/app.json +1 -1
- package/dist/candidate-scoring.js +3 -3
- package/dist/capability-core.js +9 -1
- package/dist/capability-registry.js +7 -1
- package/dist/cli/command-surface.js +4 -0
- package/dist/cli/handlers/ledger.js +169 -0
- package/dist/cli/handlers/scheduling.js +7 -1
- package/dist/drive.js +108 -61
- package/dist/execution-backend/agent.js +84 -24
- package/dist/execution-backend.js +25 -5
- package/dist/ledger.js +313 -0
- package/dist/mcp/tool-call.js +36 -0
- package/dist/mcp/tool-definitions.js +26 -0
- package/dist/mcp-server.js +4 -0
- package/dist/onramp.js +2 -0
- package/dist/orchestrator/app-operations.js +6 -0
- package/dist/orchestrator/cli-options.js +8 -2
- package/dist/orchestrator/lifecycle-operations.js +40 -13
- package/dist/orchestrator/migration-operations.js +1 -1
- package/dist/orchestrator.js +11 -3
- package/dist/remote-source.js +10 -3
- package/dist/run-export.js +45 -5
- package/dist/sandbox-profile.js +6 -1
- package/dist/triggers.js +7 -1
- package/dist/version.js +1 -1
- package/dist/workbench-host.js +18 -2
- package/docs/agent-delegation-drive.7.md +4 -0
- package/docs/cli-mcp-parity.7.md +16 -2
- package/docs/contract-migration-tooling.7.md +4 -0
- package/docs/control-plane-scheduling.7.md +4 -0
- package/docs/cross-agent-ledger.7.md +217 -0
- package/docs/demo.7.md +80 -0
- package/docs/designs/handoff-ledger.md +145 -0
- package/docs/doctor.7.md +97 -0
- package/docs/durable-state-and-locking.7.md +4 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
- package/docs/execution-backends.7.md +4 -0
- package/docs/fix.7.md +44 -0
- package/docs/handoff-setup.md +120 -0
- package/docs/init.7.md +62 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
- package/docs/multi-agent-eval-replay-harness.7.md +4 -0
- package/docs/multi-agent-operator-ux.7.md +4 -0
- package/docs/node-snapshot-diff-replay.7.md +4 -0
- package/docs/observability-cost-accounting.7.md +4 -0
- package/docs/pipeline-verbs.7.md +93 -0
- package/docs/project-index.md +28 -5
- package/docs/real-execution-backends.7.md +4 -0
- package/docs/release-and-migration.7.md +4 -0
- package/docs/release-tooling.7.md +4 -0
- package/docs/routine.7.md +73 -0
- package/docs/run-registry-control-plane.7.md +4 -0
- package/docs/run-retention-reclamation.7.md +4 -0
- package/docs/state-explosion-management.7.md +4 -0
- package/docs/team-collaboration.7.md +4 -0
- package/docs/web-desktop-workbench.7.md +4 -0
- package/manifest/README.md +16 -10
- package/manifest/plugin.manifest.json +1 -1
- package/package.json +1 -1
- package/scripts/agents/agent-adapter-core.js +4 -1
- package/scripts/agents/codex-agent.js +34 -4
- package/scripts/canonical-apps.js +4 -4
- package/scripts/children/batch-delegate-child.js +40 -13
- package/scripts/children/http-delegate-child.js +2 -1
- package/scripts/dogfood-release.js +1 -1
- package/scripts/golden-path.js +4 -4
- package/scripts/release-flow.js +31 -17
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Design — Cross-agent handoff ledger
|
|
2
|
+
|
|
3
|
+
Status: DRAFT / proposal. Nothing here is built yet. This file ships no
|
|
4
|
+
behavior, no new command, no man-page contract, and changes no existing
|
|
5
|
+
output. It exists so two people (the operator and the reviewer agent) can
|
|
6
|
+
agree on the shape before any code is written.
|
|
7
|
+
|
|
8
|
+
North Star track: **Track B** (portable, verifiable state — the same
|
|
9
|
+
`run export` → `run restore` recovery story, now used as the channel
|
|
10
|
+
between two agents).
|
|
11
|
+
|
|
12
|
+
## Goal
|
|
13
|
+
|
|
14
|
+
Two agents work on two repositories:
|
|
15
|
+
|
|
16
|
+
- one agent scoped to repo **A** (for example `cool-workflow`),
|
|
17
|
+
- one agent scoped to repo **B** (for example `chime`).
|
|
18
|
+
|
|
19
|
+
The operator wants them to "share data, review each other, and each be
|
|
20
|
+
able to raise a pull request to the other". In plain terms:
|
|
21
|
+
|
|
22
|
+
- each side can hand the other a **change proposal**, and
|
|
23
|
+
- each side can hand the other a **review verdict** on a diff or PR,
|
|
24
|
+
- with saved, inspectable, fail-closed state — never a fabricated hand-off.
|
|
25
|
+
|
|
26
|
+
## The hard constraint (why the obvious design does not work)
|
|
27
|
+
|
|
28
|
+
The first idea is a shared local folder (for example `~/.chime/handoff/`)
|
|
29
|
+
that both agents read and append to. That only works when both agents run
|
|
30
|
+
on **one machine** with **one filesystem**.
|
|
31
|
+
|
|
32
|
+
In the operator's setup the two agents run as **two separate cloud
|
|
33
|
+
sessions**. Each session is a fresh, throwaway VM. Two facts follow, and
|
|
34
|
+
the design must respect both:
|
|
35
|
+
|
|
36
|
+
1. **No shared filesystem.** A file the B-agent writes to `~/.chime/handoff/`
|
|
37
|
+
in its VM is invisible to the A-agent's VM, and is gone when the session
|
|
38
|
+
ends. A local folder cannot be the channel.
|
|
39
|
+
2. **Single-repo scope.** Each session's GitHub reach is scoped to one repo
|
|
40
|
+
at launch (A-agent → repo A, B-agent → repo B). The A-agent cannot read
|
|
41
|
+
repo B through its GitHub tools, and the reverse is also true. Scope is
|
|
42
|
+
fixed at launch and cannot be widened mid-session.
|
|
43
|
+
|
|
44
|
+
The only medium both sessions can durably reach is **git / GitHub**. So the
|
|
45
|
+
ledger is a set of committed files, not a local folder — and the scope wall
|
|
46
|
+
means the hand-off still needs either a shared repo or a human relay for the
|
|
47
|
+
cross-repo step. This document is honest about that; it does not pretend the
|
|
48
|
+
wall is not there.
|
|
49
|
+
|
|
50
|
+
## What we reuse (no new trust machinery)
|
|
51
|
+
|
|
52
|
+
CW already has the parts this needs. The design adds a thin verb layer over
|
|
53
|
+
them; it invents no new crypto and no new state format.
|
|
54
|
+
|
|
55
|
+
- `run export` produces a **verifiable bundle** (file digests, telemetry
|
|
56
|
+
ledger, trust-audit hash chains).
|
|
57
|
+
- `run restore` **imports fail-closed**: it inspects first, refuses a corrupt
|
|
58
|
+
or tampered bundle without writing anything, and exits non-zero when the
|
|
59
|
+
chain does not verify. (`run import` is the exit-0 sibling; the hand-off
|
|
60
|
+
path must use the fail-closed `restore` contract.)
|
|
61
|
+
- `report verify` checks a run's evidence and citations.
|
|
62
|
+
|
|
63
|
+
A hand-off entry is therefore just a CW bundle. The receiving side trusts it
|
|
64
|
+
the same way it trusts any restored run: by verification, not by good faith.
|
|
65
|
+
|
|
66
|
+
## Two verbs
|
|
67
|
+
|
|
68
|
+
Both live under a single new `cw ledger` verb, so the existing surface is
|
|
69
|
+
untouched and the new behavior is opt-in (POLA). (The name `handoff` was already
|
|
70
|
+
taken by an unrelated collaboration primitive — ownership transfer of a run/task
|
|
71
|
+
— so the cross-agent verb is `ledger`, not `handoff`.) Stage 1 ships as
|
|
72
|
+
`cw ledger propose|review|verify`; see
|
|
73
|
+
[cross-agent-ledger](../cross-agent-ledger.7.md) for the contract.
|
|
74
|
+
|
|
75
|
+
- **`propose`** — the read-only side writes a structured *change proposal*
|
|
76
|
+
(title, rationale, target files, suggested diff) as a ledger entry. It does
|
|
77
|
+
**not** mutate the other repo. The write-capable side picks the entry up,
|
|
78
|
+
verifies it, and turns it into a **real GitHub pull request**.
|
|
79
|
+
- **`review`** — the reviewing side writes a structured *review verdict*
|
|
80
|
+
(`APPROVED` / `REJECTED`, findings, the diff or PR it judged) as a ledger
|
|
81
|
+
entry. The other side surfaces it and can act on it.
|
|
82
|
+
|
|
83
|
+
This keeps a read-only agent honest: it emits proposals and verdicts as
|
|
84
|
+
**data**, and the write-capable side is the only one that opens PRs. Neither
|
|
85
|
+
side has to be trusted to have mutated the other's code.
|
|
86
|
+
|
|
87
|
+
## Transports (how an entry actually crosses)
|
|
88
|
+
|
|
89
|
+
The verbs above produce and consume entries; the transport is how an entry
|
|
90
|
+
moves from one VM to the other. Two are in scope, smallest first.
|
|
91
|
+
|
|
92
|
+
- **T1 — Human relay (MVP, works today, zero infra).** The producing side
|
|
93
|
+
prints the entry (a verifiable bundle, or its safe text form) to stdout;
|
|
94
|
+
the operator carries it to the other session; the consuming side verifies
|
|
95
|
+
it fail-closed and acts (opens the PR, or records the verdict). This is
|
|
96
|
+
exactly the loop the operator is already running by hand. It needs no new
|
|
97
|
+
code beyond a stable print/parse shape.
|
|
98
|
+
- **T2 — Git-as-ledger.** Each entry is committed to a repo under a known
|
|
99
|
+
path (for example `handoff/<from>-<to>/<id>.bundle`). Because scope is
|
|
100
|
+
single-repo, this needs one of:
|
|
101
|
+
- **T2a — a shared handoff repo** both agents are scoped to (cleanest, but
|
|
102
|
+
the operator must create it and launch both sessions against it), or
|
|
103
|
+
- **T2b — each side writes to its own repo** and a bridge (the operator, or
|
|
104
|
+
a scheduled job that *is* scoped to both) moves entries across. The
|
|
105
|
+
cross-repo read cannot be automatic inside a single scoped session — this
|
|
106
|
+
is the scope wall, stated plainly, not a gap to be quietly filled.
|
|
107
|
+
|
|
108
|
+
## Fail-closed rules (non-negotiable)
|
|
109
|
+
|
|
110
|
+
- An entry that does not verify is **refused**, never acted on. No PR is
|
|
111
|
+
opened, no verdict is recorded, and the refusal is explicit on stderr with
|
|
112
|
+
a non-zero exit — the same contract as `run restore`.
|
|
113
|
+
- A proposal is a **suggestion only**. It never edits the target repo by
|
|
114
|
+
itself; a human-or-agent on the write side always makes the real PR, so the
|
|
115
|
+
read-only vow of the proposing side holds.
|
|
116
|
+
- stdout stays data (the entry / the machine result); stderr stays
|
|
117
|
+
diagnostics; a piped run is silent on success. `--json` is stable and
|
|
118
|
+
decoration-free.
|
|
119
|
+
|
|
120
|
+
## Non-goals / POLA
|
|
121
|
+
|
|
122
|
+
- No existing command, output byte, exit code, or file layout changes.
|
|
123
|
+
- No new runtime dependency (zero-dependency red line holds).
|
|
124
|
+
- No vendor-specific logic in core; the verbs move opaque bundles.
|
|
125
|
+
- Nothing ships until its own cycle lands with a test that fails before and
|
|
126
|
+
passes after, and a `docs/*.7.md` contract page — this design file is not
|
|
127
|
+
that contract and claims no shipped behavior.
|
|
128
|
+
|
|
129
|
+
## Suggested rollout (each stage its own reviewed cycle)
|
|
130
|
+
|
|
131
|
+
0. **This design doc** (no behavior). ← you are here.
|
|
132
|
+
1. **T1 human-relay shape** — a stable, documented print/parse form for a
|
|
133
|
+
proposal and a verdict, plus a smoke that round-trips one of each and
|
|
134
|
+
proves a tampered entry is refused.
|
|
135
|
+
2. **`cw ledger propose` / `review`** over `run export` / `restore`, with the
|
|
136
|
+
fail-closed refusal test.
|
|
137
|
+
3. **T2 git-ledger** (shared-repo first), then optionally a scoped bridge job
|
|
138
|
+
for T2b.
|
|
139
|
+
|
|
140
|
+
## Open decisions for the operator
|
|
141
|
+
|
|
142
|
+
- T2a (shared handoff repo) or T2b (own repos + bridge)? T2a is simpler and
|
|
143
|
+
should be the default unless a shared repo is not acceptable.
|
|
144
|
+
- Should a verdict be able to **block** a PR merge on the other side, or only
|
|
145
|
+
advise? Advise-only is the safer default and matches "review as data".
|
package/docs/doctor.7.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# DOCTOR(7)
|
|
2
|
+
|
|
3
|
+
## NAME
|
|
4
|
+
|
|
5
|
+
`cw doctor` — check the setup and name all problems with their fixes
|
|
6
|
+
|
|
7
|
+
## SYNOPSIS
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
node dist/cli.js doctor
|
|
11
|
+
node dist/cli.js doctor --json
|
|
12
|
+
node dist/cli.js doctor --fix
|
|
13
|
+
node dist/cli.js doctor --onramp
|
|
14
|
+
node dist/cli.js doctor --onramp --changed-from origin/main
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## DESCRIPTION
|
|
18
|
+
|
|
19
|
+
`cw doctor` is a read-only check of your CW setup, based on `brew doctor`. It
|
|
20
|
+
probes your machine and says what is wrong and what to do about it — before a
|
|
21
|
+
run fails with a strange error.
|
|
22
|
+
|
|
23
|
+
The command never makes any file; it only reads. Running it changes nothing on
|
|
24
|
+
disk.
|
|
25
|
+
|
|
26
|
+
It gives back a report with one line for every check. Each check has a status
|
|
27
|
+
(`ok`, `warn`, or `fail`) and a clear note. Checks that are not `ok` carry a
|
|
28
|
+
`fix` line with the right command or step to put things right.
|
|
29
|
+
|
|
30
|
+
If any check has status `fail`, the command exits with code 1 (non-zero). A
|
|
31
|
+
`warn` (for example, no agent yet — demos and previews still work) does not
|
|
32
|
+
make the exit fail.
|
|
33
|
+
|
|
34
|
+
## CHECKS
|
|
35
|
+
|
|
36
|
+
The command runs six checks in order:
|
|
37
|
+
|
|
38
|
+
**node**
|
|
39
|
+
: The Node.js version. CW needs v18 or higher. A `fail` here stops everything.
|
|
40
|
+
|
|
41
|
+
**agent**
|
|
42
|
+
: The AI agent backend. CW can auto-detect agents (Claude, Codex, Gemini,
|
|
43
|
+
OpenCode) or take one from `CW_AGENT_COMMAND` / `--agent-command`. Without one,
|
|
44
|
+
real runs report `status: blocked`, but `demo` and `--preview` still work.
|
|
45
|
+
|
|
46
|
+
**agent-binary**
|
|
47
|
+
: When the agent is set by a command name (not auto or HTTP), this check sees if
|
|
48
|
+
the binary is on `$PATH`. Missing here gives a `warn` — the run will get a clear
|
|
49
|
+
error later, but CW will not guess at a different agent.
|
|
50
|
+
|
|
51
|
+
**git**
|
|
52
|
+
: The `git` command. CW uses it for commit place of origin. A `warn` here means
|
|
53
|
+
commit roots will be recorded as absent; no other part of a run needs git.
|
|
54
|
+
|
|
55
|
+
**home-registry**
|
|
56
|
+
: The cross-repo run index at `$CW_HOME` (default `$HOME/.local/state/cool-workflow`).
|
|
57
|
+
This location must be writable. A `fail` here blocks discovery across repos.
|
|
58
|
+
|
|
59
|
+
**repo-state**
|
|
60
|
+
: The per-repo run store under `<cwd>/.cw`. Must be writable. A `warn` here
|
|
61
|
+
means runs stay in-memory only — you can use `--cwd PATH` to point at another
|
|
62
|
+
writable root.
|
|
63
|
+
|
|
64
|
+
## OPTIONS
|
|
65
|
+
|
|
66
|
+
`--json`
|
|
67
|
+
: Give back the full report as a stable JSON object. Good for scripts.
|
|
68
|
+
|
|
69
|
+
`--fix`
|
|
70
|
+
: Give back only the fix commands for every non-ok check. Same as running `cw fix`
|
|
71
|
+
by itself.
|
|
72
|
+
|
|
73
|
+
`--onramp`
|
|
74
|
+
: Add a quick-start guide to the human output, with recommended checks and a
|
|
75
|
+
three-step path to your first report.
|
|
76
|
+
|
|
77
|
+
`--changed-from <ref>`
|
|
78
|
+
: When used with `--onramp`, make the quick-start checks cover only files changed
|
|
79
|
+
since `<ref>` (a Git branch, tag, or commit). Good for CI and code reading.
|
|
80
|
+
|
|
81
|
+
## FILES
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
src/doctor.ts
|
|
85
|
+
dist/doctor.js
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## EXIT CODES
|
|
89
|
+
|
|
90
|
+
| Exit | Meaning |
|
|
91
|
+
| --- | --- |
|
|
92
|
+
| 0 | All checks ok (may have warnings) |
|
|
93
|
+
| 1 | One or more checks have status `fail` |
|
|
94
|
+
|
|
95
|
+
## SEE ALSO
|
|
96
|
+
|
|
97
|
+
cw fix — the same checks, but gives back only the fix commands
|
package/docs/fix.7.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# FIX(7)
|
|
2
|
+
|
|
3
|
+
## NAME
|
|
4
|
+
|
|
5
|
+
`cw fix` — give back the fix commands for all setup problems
|
|
6
|
+
|
|
7
|
+
## SYNOPSIS
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
node dist/cli.js fix
|
|
11
|
+
node dist/cli.js fix --json
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## DESCRIPTION
|
|
15
|
+
|
|
16
|
+
`cw fix` runs the same setup checks as `cw doctor`, but gives back only the
|
|
17
|
+
fix commands — one numbered step for every check that has a problem. No
|
|
18
|
+
running check detail, no status glyphs; just the directions you need to put
|
|
19
|
+
things right.
|
|
20
|
+
|
|
21
|
+
When the output is empty ("No fixes needed."), the setup is clean and nothing
|
|
22
|
+
needs doing.
|
|
23
|
+
|
|
24
|
+
Like `cw doctor`, the command only reads — it never makes a file or does a
|
|
25
|
+
fix on its own. You are meant to run the fix commands yourself.
|
|
26
|
+
|
|
27
|
+
If any check has status `fail`, the command exits with code 1.
|
|
28
|
+
|
|
29
|
+
## OPTIONS
|
|
30
|
+
|
|
31
|
+
`--json`
|
|
32
|
+
: Give back the full doctor report as a stable JSON object, with the same shape
|
|
33
|
+
as `cw doctor --json`. The `checks` array carries every fix string.
|
|
34
|
+
|
|
35
|
+
## EXIT CODES
|
|
36
|
+
|
|
37
|
+
| Exit | Meaning |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| 0 | No fixes needed — all checks ok or only warnings |
|
|
40
|
+
| 1 | One or more checks have status `fail` |
|
|
41
|
+
|
|
42
|
+
## SEE ALSO
|
|
43
|
+
|
|
44
|
+
cw doctor — the full setup check with detail for every check
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Handoff ledger — shared-repo setup (T2a)
|
|
2
|
+
|
|
3
|
+
How to stand up the shared repo that carries `cw ledger` entries between two
|
|
4
|
+
agents scoped to two separate repos (e.g. `cool-workflow` and `chime`), each
|
|
5
|
+
running in its own cloud session. The verbs are documented in
|
|
6
|
+
[cross-agent-ledger](cross-agent-ledger.7.md); this is the operator runbook.
|
|
7
|
+
|
|
8
|
+
Examples are portable — replace `<owner>`, `<src-repo>`, and the paths with your
|
|
9
|
+
own, and keep tokens in environment variables, never in files or commit text.
|
|
10
|
+
|
|
11
|
+
## What only the operator can do
|
|
12
|
+
|
|
13
|
+
- A cool-workflow-scoped web session cannot create the shared repo — the GitHub
|
|
14
|
+
integration returns `403 Resource not accessible by integration` for any repo
|
|
15
|
+
outside its scope. Create it yourself.
|
|
16
|
+
- Scoping the two agent environments (or granting them git credentials) is a
|
|
17
|
+
Claude Code web-UI step; it cannot be done from inside a session.
|
|
18
|
+
|
|
19
|
+
## Choosing a host: GitHub vs self-hosted (Gitea)
|
|
20
|
+
|
|
21
|
+
The transport is git-host-agnostic — the kernel has no git logic, so any git
|
|
22
|
+
remote works. The choice is about reachability and operations, not code.
|
|
23
|
+
|
|
24
|
+
| | GitHub (private repo) | Self-hosted Gitea (your VPS) |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| Reachability from cloud sessions | github.com is in the default **Trusted** allowlist — works with no network-policy change | Your VPS host is **not** in the default allowlist — the environment's network access must be configured to permit it |
|
|
27
|
+
| Scope wall | The GitHub MCP scope is per-repo; the ledger uses plain git (not MCP) so it works, but it runs against the grain of the scoping model | Not a GitHub repo at all, so the GitHub scope wall does not apply |
|
|
28
|
+
| Limits / quota | Disable Actions on this repo (it needs no CI) so it burns no minutes; git push/pull is not API-rate-limited; ledger traffic is tiny | Fully self-controlled, unlimited |
|
|
29
|
+
| Operations | Managed, backed up, zero maintenance | You run it: uptime, backups, TLS cert, patching |
|
|
30
|
+
| Data location | GitHub's servers (private) | Your own hardware |
|
|
31
|
+
|
|
32
|
+
**Recommendation.** Start on **GitHub private** — it is reachable out of the box
|
|
33
|
+
and the quota worry is practically moot for tiny ledger traffic. Move to **Gitea**
|
|
34
|
+
if you want full self-hosting AND have confirmed the cloud environment can reach
|
|
35
|
+
your VPS through its network policy (the deciding prerequisite). Migrating later
|
|
36
|
+
is only a change of git remote — no code change.
|
|
37
|
+
|
|
38
|
+
## GitHub private — setup
|
|
39
|
+
|
|
40
|
+
1. **Token.** GitHub → Settings → Developer settings → Personal access tokens →
|
|
41
|
+
Fine-grained. Repository access: only `<owner>/handoff`. Permissions:
|
|
42
|
+
Contents = Read and write. Copy the token.
|
|
43
|
+
2. **Repo.** Create `<owner>/handoff`, private, initialized with a README. In
|
|
44
|
+
Settings → Actions → General, disable Actions (no CI needed → no minutes).
|
|
45
|
+
3. **Environments.** In each agent environment (both the `cool-workflow` and the
|
|
46
|
+
`chime` environment), add an environment variable `GH_TOKEN=<token>` (`.env`
|
|
47
|
+
format, no quotes). A new session is required for it to take effect.
|
|
48
|
+
4. **Optional** — put the clone in each environment's setup script so the ledger
|
|
49
|
+
is present at session start:
|
|
50
|
+
```bash
|
|
51
|
+
#!/bin/bash
|
|
52
|
+
git clone https://oauth2:${GH_TOKEN}@github.com/<owner>/handoff.git /home/user/handoff || true
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Gitea (self-hosted) — setup
|
|
56
|
+
|
|
57
|
+
Same shape, two extra prerequisites:
|
|
58
|
+
|
|
59
|
+
1. Serve Gitea over HTTPS with a valid certificate (e.g. Let's Encrypt) so the
|
|
60
|
+
cloud VM's git can verify it.
|
|
61
|
+
2. Configure the agent environment's **network access** to permit your VPS host —
|
|
62
|
+
the default Trusted allowlist does not include it. If the loop cannot reach
|
|
63
|
+
the VPS, it cannot run.
|
|
64
|
+
3. Create a Gitea access token, store it as an environment variable, and clone
|
|
65
|
+
with an authenticated remote (`https://<user>:${GIT_TOKEN}@<vps-host>/<owner>/handoff.git`).
|
|
66
|
+
|
|
67
|
+
## Directory convention
|
|
68
|
+
|
|
69
|
+
Entries live under `ledger/` in the shared repo, one file per entry named by its
|
|
70
|
+
id:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
handoff/
|
|
74
|
+
ledger/
|
|
75
|
+
ldg-1de7c92172af1871.json
|
|
76
|
+
ldg-2315e4b33b9a812f.json
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## The loop
|
|
80
|
+
|
|
81
|
+
Producing side (propose a change, hand it over):
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
entry=$(cw ledger propose --from cool-workflow --to chime \
|
|
85
|
+
--title "Add retry" --rationale "flaky net" \
|
|
86
|
+
--files src/net.ts --diff "$(git -C <src-repo> diff)")
|
|
87
|
+
id=$(printf '%s' "$entry" | jq -r .id)
|
|
88
|
+
printf '%s\n' "$entry" > /home/user/handoff/ledger/$id.json
|
|
89
|
+
git -C /home/user/handoff add ledger/$id.json
|
|
90
|
+
git -C /home/user/handoff commit -m "propose $id"
|
|
91
|
+
git -C /home/user/handoff push
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Note the single `cw ledger propose` call captured into `$entry` — calling it
|
|
95
|
+
twice would mint two different entries (each carries a fresh `createdAt`).
|
|
96
|
+
|
|
97
|
+
Consuming side (verify the inbox, then act or review back):
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git -C /home/user/handoff pull
|
|
101
|
+
cw ledger list --dir /home/user/handoff/ledger && echo "inbox verified — safe to act"
|
|
102
|
+
|
|
103
|
+
# hand a verdict back:
|
|
104
|
+
entry=$(cw ledger review --from chime --to cool-workflow \
|
|
105
|
+
--target ldg-1de7c92172af1871 --verdict approved --findings "tests pass,scope ok")
|
|
106
|
+
id=$(printf '%s' "$entry" | jq -r .id)
|
|
107
|
+
printf '%s\n' "$entry" > /home/user/handoff/ledger/$id.json
|
|
108
|
+
git -C /home/user/handoff add ledger/$id.json
|
|
109
|
+
git -C /home/user/handoff commit -m "review $id"
|
|
110
|
+
git -C /home/user/handoff push
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Notes
|
|
114
|
+
|
|
115
|
+
- Keep private code out of a **public** handoff repo: omit `--diff` and reference
|
|
116
|
+
a commit/branch in the private source repo instead, so only metadata + a
|
|
117
|
+
pointer is exposed. On a private handoff repo, full diffs are fine.
|
|
118
|
+
- The other side may build entries without `cw` as long as they match the
|
|
119
|
+
digest/id rules in [cross-agent-ledger](cross-agent-ledger.7.md); otherwise
|
|
120
|
+
`cw ledger verify` refuses them with `ledger-digest-mismatch`.
|
package/docs/init.7.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# INIT(7)
|
|
2
|
+
|
|
3
|
+
## NAME
|
|
4
|
+
|
|
5
|
+
`cw init` — scaffold a new workflow definition from nothing
|
|
6
|
+
|
|
7
|
+
## SYNOPSIS
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
node dist/cli.js init <workflow-id> [--title TITLE] [--output PATH] [--force]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## DESCRIPTION
|
|
14
|
+
|
|
15
|
+
`cw init` makes a new workflow definition file — a `.workflow.js` file filled
|
|
16
|
+
with a simple template. The template has a basic run shape: one step with a
|
|
17
|
+
sandbox profile, one evidence gate, and the hooks you need to add your own
|
|
18
|
+
steps.
|
|
19
|
+
|
|
20
|
+
This is how you start a new workflow app from zero. After `init`, you have a
|
|
21
|
+
real file you can edit to make your own run shape.
|
|
22
|
+
|
|
23
|
+
The workflow id you give is turned into a safe file name (spaces become dashes,
|
|
24
|
+
special signs are taken out). By default, the file is written to the current
|
|
25
|
+
working directory, but you can point it somewhere else with `--output`.
|
|
26
|
+
|
|
27
|
+
If a file of that name is already there, the command refuses to overwrite it
|
|
28
|
+
unless you pass `--force`.
|
|
29
|
+
|
|
30
|
+
## OPTIONS
|
|
31
|
+
|
|
32
|
+
`--title TITLE`
|
|
33
|
+
: A human name for the workflow. If not given, a title is made from the id.
|
|
34
|
+
|
|
35
|
+
`--output PATH`
|
|
36
|
+
: Where to write the workflow file. Default is `<id>.workflow.js` in the
|
|
37
|
+
current directory.
|
|
38
|
+
|
|
39
|
+
`--force`
|
|
40
|
+
: Overwrite an existing file. Without this flag, the command fails if the
|
|
41
|
+
file already exists.
|
|
42
|
+
|
|
43
|
+
## EXIT CODES
|
|
44
|
+
|
|
45
|
+
| Exit | Meaning |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| 0 | Workflow file written |
|
|
48
|
+
| 1 | Missing workflow id, invalid id, or file exists without `--force` |
|
|
49
|
+
|
|
50
|
+
## FILES
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
src/orchestrator.ts (init method)
|
|
54
|
+
src/workflow-app-framework.ts (template renderer)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## SEE ALSO
|
|
58
|
+
|
|
59
|
+
cw list — see all workflow apps you have
|
|
60
|
+
cw info <id> — read the shape of a workflow app
|
|
61
|
+
workflow-app-framework.7.md — the full framework for writing workflow apps
|
|
62
|
+
pipeline-verbs.7.md — plan, dispatch, result (the pipeline engine)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# PIPELINE-VERBS(7)
|
|
2
|
+
|
|
3
|
+
## NAME
|
|
4
|
+
|
|
5
|
+
`cw plan`, `cw dispatch`, `cw result` — the three core pipeline engine verbs
|
|
6
|
+
|
|
7
|
+
## SYNOPSIS
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
node dist/cli.js plan <workflow-id> [--question Q] [--repo PATH] [--sandbox PROFILE]
|
|
11
|
+
node dist/cli.js dispatch <run-id> [--sandbox PROFILE]
|
|
12
|
+
node dist/cli.js result <run-id> <task-id> <result-file>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## DESCRIPTION
|
|
16
|
+
|
|
17
|
+
These three verbs are the engine that drives every CW run. A run goes through
|
|
18
|
+
three stages: plan (get ready), dispatch (hand out work), and result (take work
|
|
19
|
+
back). Together they make the CW pipeline loop — a worker gets a task, does it,
|
|
20
|
+
and hands in a result file; CW checks the result and moves the run forward.
|
|
21
|
+
|
|
22
|
+
None of these verbs starts or stops the agent host. They give the control-plane
|
|
23
|
+
data that the host reads and acts on. The host keeps its own loop: call
|
|
24
|
+
`dispatch`, give the task to an agent, get back a result file, call `result`.
|
|
25
|
+
|
|
26
|
+
## PLAN
|
|
27
|
+
|
|
28
|
+
`cw plan <workflow-id>` makes a new run and gives back its canonical plan
|
|
29
|
+
summary in JSON. The plan has the run id, the first task (or tasks) to do,
|
|
30
|
+
the sandbox profile, and the state of the run.
|
|
31
|
+
|
|
32
|
+
The workflow id names a workflow app that gives the run its shape: inputs,
|
|
33
|
+
steps, evidence gates, and sandbox policy. Use `cw list` to see the workflow
|
|
34
|
+
apps you have.
|
|
35
|
+
|
|
36
|
+
The plan output is stable JSON, good for scripts and the agent host.
|
|
37
|
+
|
|
38
|
+
Options:
|
|
39
|
+
: `--question`, `--repo`, `--sandbox` — the same inputs the workflow app
|
|
40
|
+
expects. Different apps take different inputs; see `cw info <workflow-id>`
|
|
41
|
+
for the list.
|
|
42
|
+
|
|
43
|
+
## DISPATCH
|
|
44
|
+
|
|
45
|
+
`cw dispatch <run-id>` makes the next task ready for a worker. It gives back
|
|
46
|
+
a dispatch manifest in JSON: the task id, the prompt, the sandbox profile, and
|
|
47
|
+
the input and output paths the worker should use.
|
|
48
|
+
|
|
49
|
+
The dispatch picks the next runnable task in the pipeline. If no task is ready
|
|
50
|
+
— for example, all tasks are done or waiting on evidence — the dispatch payload
|
|
51
|
+
says so, and the host should wait or check the run status.
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
: `--sandbox PROFILE` — pick a sandbox profile for the worker. The default is
|
|
55
|
+
the one the workflow app asked for.
|
|
56
|
+
|
|
57
|
+
## RESULT
|
|
58
|
+
|
|
59
|
+
`cw result <run-id> <task-id> <result-file>` records a worker's result against
|
|
60
|
+
a task. The result file is a Markdown file the agent wrote — it must have a
|
|
61
|
+
`cw:result` JSON fence with the agent's `findings` and `evidence`.
|
|
62
|
+
|
|
63
|
+
CW accepts the result, checks it, and advances the run pipeline. If the result
|
|
64
|
+
is bad (missing, broken, or the evidence does not check out), CW rejects it and
|
|
65
|
+
gives back an error feedback record. The host can then try again or give the
|
|
66
|
+
task a different agent.
|
|
67
|
+
|
|
68
|
+
After `result`, the run may be done or have more tasks waiting. Check with
|
|
69
|
+
`cw status <run-id>` or `cw next <run-id>`.
|
|
70
|
+
|
|
71
|
+
## FILES
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
.cw/runs/<run-id>/state.json
|
|
75
|
+
.cw/runs/<run-id>/dispatches/<dispatch-id>.json
|
|
76
|
+
.cw/runs/<run-id>/tasks/<task-id>.json
|
|
77
|
+
.cw/runs/<run-id>/results/<task-id>.md
|
|
78
|
+
.cw/runs/<run-id>/workers/<worker-id>/worker.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## PIPELINE FLOW
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
plan -> dispatch -> [agent does work] -> result -> [dispatch...] -> done
|
|
85
|
+
└─ rejected -> feedback -> retry
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## SEE ALSO
|
|
89
|
+
|
|
90
|
+
cw init — make a new workflow definition from nothing
|
|
91
|
+
cw status — see the current state of a run
|
|
92
|
+
cw next — find the next action for a run
|
|
93
|
+
pipeline-runner.7.md — the full pipeline engine detail
|