agents-handoff 2.0.2 → 2.0.3
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/CHANGELOG.md +48 -6
- package/README.md +53 -13
- package/SKILL.md +12 -12
- package/capability-registry.json +1 -1
- package/docs/ARCHITECTURE.md +28 -5
- package/docs/CHANGELOG.md +62 -17
- package/docs/CLI.md +115 -12
- package/docs/CONTRIBUTING.md +2 -2
- package/docs/FORMAT.md +28 -0
- package/docs/INSTALL.md +239 -24
- package/docs/INTEGRATION.md +4 -4
- package/docs/LEVEL4.md +10 -10
- package/docs/LEVEL5.md +1 -1
- package/docs/PERMISSIONS.md +2 -2
- package/docs/PROVENANCE.md +27 -0
- package/docs/SECURITY.md +1 -1
- package/docs/SESSIONS.md +31 -0
- package/docs/UNINSTALL.md +47 -21
- package/docs/UPGRADE.md +59 -21
- package/docs/_config.yml +3 -1
- package/docs/index.md +15 -6
- package/docs/sessions.json +34 -0
- package/install/CHANGELOG.md +1 -1
- package/install/README.md +7 -7
- package/install/install.mjs +746 -147
- package/install/package.json +2 -2
- package/package.json +2 -2
- package/permission-policy.json +1 -1
- package/refs/protocol.md +1 -1
- package/schemas/handoff.schema.json +1 -1
- package/skill.json +11 -11
- package/tests/acceptance/acceptance.yaml +2 -2
- package/tools/agent-handoff.mjs +16 -404
- package/tools/agents-handoff.mjs +410 -0
- package/tools/capability-registry.mjs +2 -2
- package/tools/handoff.test.mjs +203 -0
- package/tools/lib/handoff-root.mjs +1 -1
- package/tools/runtime-engine.mjs +2 -2
package/docs/LEVEL4.md
CHANGED
|
@@ -5,7 +5,7 @@ title: Level 4 — the dynamic runtime layer
|
|
|
5
5
|
# Level 4 — the dynamic runtime layer
|
|
6
6
|
|
|
7
7
|
The engine ([handoff.mjs](https://github.com/Alot1z/agent-handoff/blob/main/tools/handoff.mjs)) is passive: something has to invoke it. The
|
|
8
|
-
runtime layer is [tools/
|
|
8
|
+
runtime layer is [tools/agents-handoff.mjs](https://github.com/Alot1z/agent-handoff/blob/main/tools/agents-handoff.mjs), which acts on the
|
|
9
9
|
state of the store — it probes for staleness, checks a handoff against a contract, composes
|
|
10
10
|
sessions, imports other stores and maintains the index.
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@ Every mutating command takes a lock, so two runs cannot capture or merge the sam
|
|
|
13
13
|
once. Locks live in `<root>/.locks/` and are named after a hash of the operation target.
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
node tools/
|
|
16
|
+
node tools/agents-handoff.mjs <command> [args]
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
| Command | Purpose |
|
|
@@ -32,7 +32,7 @@ An unknown command prints that list and exits 2.
|
|
|
32
32
|
## `auto` — self-triggering capture
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
node tools/
|
|
35
|
+
node tools/agents-handoff.mjs auto --source transcript.jsonl \
|
|
36
36
|
[--session <id>] [--harness <name>] [--project <name>] [--min-fresh-ms <n>]
|
|
37
37
|
```
|
|
38
38
|
|
|
@@ -49,7 +49,7 @@ file exits 2.
|
|
|
49
49
|
## `verify-gate` — the evidence gate
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
|
-
node tools/
|
|
52
|
+
node tools/agents-handoff.mjs verify-gate <id-prefix>
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
| Check | Passes when |
|
|
@@ -71,7 +71,7 @@ manifest is visible as a nonzero status.
|
|
|
71
71
|
## `promote` — stamping verified work
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
|
-
node tools/
|
|
74
|
+
node tools/agents-handoff.mjs promote <id-prefix>
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
The manifest is backed up to `manifest.json.bak`, the gate above is run and its verdict is
|
|
@@ -88,7 +88,7 @@ Two honest caveats:
|
|
|
88
88
|
## `merge` — composing two sessions
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
|
-
node tools/
|
|
91
|
+
node tools/agents-handoff.mjs merge <id-prefix-a> <id-prefix-b>
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
Timelines are concatenated and sorted by `ts`, and written to a new session directory named
|
|
@@ -103,7 +103,7 @@ on `contract` and `payload` until a brief is written for it, and `index` reports
|
|
|
103
103
|
## `federated-merge` — importing another store root
|
|
104
104
|
|
|
105
105
|
```bash
|
|
106
|
-
node tools/
|
|
106
|
+
node tools/agents-handoff.mjs federated-merge --from <remote-root> [--from <root> ...] [--dry-run]
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
Each remote root is expected to have the same `projects/<project>/<session>/` layout. A
|
|
@@ -121,7 +121,7 @@ recorded as failed, and a missing `--from` exits 2.
|
|
|
121
121
|
## `self-improve` — brief shortfalls
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
|
-
node tools/
|
|
124
|
+
node tools/agents-handoff.mjs self-improve
|
|
125
125
|
```
|
|
126
126
|
|
|
127
127
|
Every session is scanned, and a session with 40 or more USER+AGENT turns whose `HANDOFF.md`
|
|
@@ -132,7 +132,7 @@ so a configured store never collects rule candidates. The file lists counts, not
|
|
|
132
132
|
## `index` — the store index
|
|
133
133
|
|
|
134
134
|
```bash
|
|
135
|
-
node tools/
|
|
135
|
+
node tools/agents-handoff.mjs index
|
|
136
136
|
```
|
|
137
137
|
|
|
138
138
|
Rebuilds `<root>/INDEX.json` from the manifests, with one entry per session (`id`, `uuid`,
|
|
@@ -178,7 +178,7 @@ is rewritten with a sha256 seal, and the step is appended to `<state>/jobs/<sess
|
|
|
178
178
|
Each step is permission-gated at `R1`. `--fail-at <k>` simulates an abrupt kill before step
|
|
179
179
|
`k` executes, leaving the durable state at `k-1`.
|
|
180
180
|
|
|
181
|
-
The state directory is `<repo>/.
|
|
181
|
+
The state directory is `<repo>/.agents-handoff`, or `AGENT_HANDOFF_STATE_DIR` when set.
|
|
182
182
|
|
|
183
183
|
| Code | Meaning |
|
|
184
184
|
|---|---|
|
package/docs/LEVEL5.md
CHANGED
|
@@ -9,7 +9,7 @@ lets a handoff whose own record is complete hand its continuation to a worker th
|
|
|
9
9
|
broker, instead of waiting for a reader.
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
node tools/
|
|
12
|
+
node tools/agents-handoff.mjs dispatch <id-prefix> --task "<objective>" \
|
|
13
13
|
[--role <role>] [--parent <parentTaskId>] [--broker <broker-root>] [--live]
|
|
14
14
|
```
|
|
15
15
|
|
package/docs/PERMISSIONS.md
CHANGED
|
@@ -22,7 +22,7 @@ Every operation is evaluated first and executed only on an `ALLOWED` verdict. A
|
|
|
22
22
|
|
|
23
23
|
| Key | Shipped value |
|
|
24
24
|
|---|---|
|
|
25
|
-
| `approved_workspaces` | `.` (the skill root), `repo-upstream`, `.
|
|
25
|
+
| `approved_workspaces` | `.` (the skill root), `repo-upstream`, `.agents-handoff`, `.context` |
|
|
26
26
|
| `system_read_only_roots` | `C:\Windows`, `C:\Program Files`, `C:\Program Files (x86)` |
|
|
27
27
|
| `personal_data_roots` | `C:\Users` |
|
|
28
28
|
| `denied_roots` | empty |
|
|
@@ -103,7 +103,7 @@ are allowed only inside an approved workspace.
|
|
|
103
103
|
|
|
104
104
|
Every decision, allowed or denied, is written to
|
|
105
105
|
`<state dir>/executions/<timestamp>-<pid>-<random>.json`. The state directory is
|
|
106
|
-
`AGENT_HANDOFF_STATE_DIR` when set, and `<skill>/.
|
|
106
|
+
`AGENT_HANDOFF_STATE_DIR` when set, and `<skill>/.agents-handoff` otherwise; it is treated as
|
|
107
107
|
an approved workspace wherever it points.
|
|
108
108
|
|
|
109
109
|
## Declared but not enforced
|
package/docs/PROVENANCE.md
CHANGED
|
@@ -60,6 +60,33 @@ It prints one `PASS` line, or `FAIL` with the reason.
|
|
|
60
60
|
|
|
61
61
|
Treat the chain as damage detection, not as authentication.
|
|
62
62
|
|
|
63
|
+
## Install provenance
|
|
64
|
+
|
|
65
|
+
An installation carries its own record, `.agents-handoff-install.json`, written by the
|
|
66
|
+
installer into the copy it made. It is separate from every handoff folder: it says what was
|
|
67
|
+
installed and where the bytes came from, not what a session contains. `verify` run from the
|
|
68
|
+
installer re-hashes the installed file set and compares it with the record.
|
|
69
|
+
|
|
70
|
+
| Field group | What it records |
|
|
71
|
+
|---|---|
|
|
72
|
+
| `product`, `version`, `installer_version`, `installed_at` | Which version landed, and which installer wrote the record. |
|
|
73
|
+
| `harness`, `target` | Where the copy went (`claude`, `codex`, `agents`, or `null` for a direct path). |
|
|
74
|
+
| `source` | The tree beside the installer (`kind: 'tree'`), or the tagged archive it was fetched from (`kind: 'archive'`) with that archive's sha256. |
|
|
75
|
+
| `file_count`, `files_sha256`, `files` | That the files present are the files that were installed — one hash over the set, and one per path. |
|
|
76
|
+
|
|
77
|
+
What it detects: a file edited, replaced or removed after the install, because the per-file
|
|
78
|
+
values and the set hash no longer match. `verify` exits non-zero and names the differing
|
|
79
|
+
files, and `doctor` reports the same state for every harness installation it finds.
|
|
80
|
+
|
|
81
|
+
What it cannot detect:
|
|
82
|
+
|
|
83
|
+
- **A compromised source.** The record is written from whatever tree the installer ran in, so a
|
|
84
|
+
copy made from a tampered tree carries a record that matches that tree.
|
|
85
|
+
- **Files outside the manifest.** The hash covers the manifest files, not anything added beside
|
|
86
|
+
them.
|
|
87
|
+
- **A rewritten record.** Anyone who edits an installed copy can recompute the hashes, exactly
|
|
88
|
+
as a manifest can be re-hashed. There is no signature and no external trust anchor.
|
|
89
|
+
|
|
63
90
|
## Update instead of recreate
|
|
64
91
|
|
|
65
92
|
Re-running `build` on the same session id merges rather than duplicates: turns with a sequence above
|
package/docs/SECURITY.md
CHANGED
|
@@ -6,7 +6,7 @@ title: Security
|
|
|
6
6
|
|
|
7
7
|
## Scope
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
agents-handoff reads session transcripts you point it at and writes a handoff folder to disk. It has
|
|
10
10
|
no network code, no third-party dependencies, and no privileged operations. This document states
|
|
11
11
|
what the tool does with data, what it refuses to do, and which guarantees it does not make.
|
|
12
12
|
|
package/docs/SESSIONS.md
CHANGED
|
@@ -59,6 +59,37 @@ node .github/scripts/build-sessions-index.mjs --check # exit 1 when the page
|
|
|
59
59
|
`--check` is wired into CI, so a store that changes without the page changing fails the build
|
|
60
60
|
instead of publishing a table that no longer matches what the engine can read.
|
|
61
61
|
|
|
62
|
+
The store is also published as JSON, for anything that would rather read data than
|
|
63
|
+
markdown: [`sessions.json`](sessions.json) (`1.0-session-feed`) — the same rows, with an
|
|
64
|
+
`integrity` verdict per session. The filter below runs in the browser against the table you
|
|
65
|
+
are looking at; nothing is fetched.
|
|
66
|
+
|
|
67
|
+
<p class="session-filter">
|
|
68
|
+
<label for="session-filter">Filter sessions</label>
|
|
69
|
+
<input id="session-filter" type="search" placeholder="project, session, harness, integrity…" size="34" />
|
|
70
|
+
<span id="session-filter-count" class="session-filter-count"></span>
|
|
71
|
+
</p>
|
|
72
|
+
|
|
73
|
+
<script>
|
|
74
|
+
(function () {
|
|
75
|
+
var input = document.getElementById('session-filter');
|
|
76
|
+
if (!input) return;
|
|
77
|
+
var rows = Array.prototype.slice.call(document.querySelectorAll('table tbody tr'));
|
|
78
|
+
var count = document.getElementById('session-filter-count');
|
|
79
|
+
function apply() {
|
|
80
|
+
var q = input.value.trim().toLowerCase(), shown = 0;
|
|
81
|
+
rows.forEach(function (tr) {
|
|
82
|
+
var hit = !q || tr.textContent.toLowerCase().indexOf(q) > -1;
|
|
83
|
+
tr.style.display = hit ? '' : 'none';
|
|
84
|
+
if (hit) shown += 1;
|
|
85
|
+
});
|
|
86
|
+
if (count) count.textContent = shown + ' of ' + rows.length + ' shown';
|
|
87
|
+
}
|
|
88
|
+
input.addEventListener('input', apply);
|
|
89
|
+
apply();
|
|
90
|
+
})();
|
|
91
|
+
</script>
|
|
92
|
+
|
|
62
93
|
## Next
|
|
63
94
|
|
|
64
95
|
- The file-by-file contract for a session folder is in [FORMAT.md](FORMAT.md).
|
package/docs/UNINSTALL.md
CHANGED
|
@@ -15,10 +15,10 @@ npx agents-handoff --remove
|
|
|
15
15
|
Removal asks for confirmation first:
|
|
16
16
|
|
|
17
17
|
```
|
|
18
|
-
This will remove
|
|
18
|
+
This will remove agents-handoff from:
|
|
19
19
|
<install-path>
|
|
20
20
|
|
|
21
|
-
Your handoffs
|
|
21
|
+
Your handoffs and anything else you put in this directory will NOT be deleted.
|
|
22
22
|
Configuration (handoff.config.json) will NOT be deleted.
|
|
23
23
|
|
|
24
24
|
Continue? (y/N)
|
|
@@ -36,36 +36,56 @@ npx agents-handoff --remove --force
|
|
|
36
36
|
| Option | Effect |
|
|
37
37
|
|---|---|
|
|
38
38
|
| `--remove` | Remove the installation (interactive confirmation). |
|
|
39
|
-
| `--force`, `-f` | Skip the confirmation
|
|
39
|
+
| `--force`, `-f` | Skip the confirmation. |
|
|
40
40
|
| `--location <global\|local\|project>` | Which installation to remove. Global is the default and is resolved the same way as for install. |
|
|
41
41
|
| `--path <dir>` | Remove the installation at exactly this directory. |
|
|
42
|
+
| `--claude`, `--codex`, `--agents` | Remove that harness's installation. Repeatable, and combinable. |
|
|
43
|
+
| `--harness <a,b>` | Named harness(es), comma separated. Repeatable. |
|
|
44
|
+
| `--all` | Every harness whose configuration directory exists on this machine. |
|
|
45
|
+
| `--skills-dir <dir>` | Remove the installation under exactly this directory. Repeatable. |
|
|
46
|
+
| `--project` | With a harness flag: the per-repository installation. |
|
|
47
|
+
|
|
48
|
+
Removing several harnesses at once is the same one run as installing them, and each target is
|
|
49
|
+
reported on its own:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx agents-handoff --remove --claude --force
|
|
53
|
+
npx agents-handoff --remove --all --force
|
|
54
|
+
```
|
|
42
55
|
|
|
43
56
|
Flag form and bare verb are equivalent: `--remove` and `remove`, `--force` and `-f`.
|
|
44
57
|
|
|
45
58
|
## What is removed
|
|
46
59
|
|
|
47
|
-
|
|
60
|
+
**Only what the installation owns — the manifest.** The rule is a removal set, not a keep
|
|
61
|
+
list, so a directory nobody thought to name is kept rather than deleted:
|
|
48
62
|
|
|
49
63
|
- the engine and runtime: `tools/`, `tools/lib/`
|
|
50
|
-
- metadata: `SKILL.md`, `
|
|
64
|
+
- metadata: `SKILL.md`, `README.md`, `LICENSE`, `skill.json`, the manifest JSON files
|
|
65
|
+
- the install record: `.agents-handoff-install.json`
|
|
51
66
|
- `schemas/`, `refs/`, `templates/`, `docs/`, `tests/`
|
|
52
|
-
- `
|
|
67
|
+
- the `package.json` stub the installer wrote, and only that stub — a `package.json` you have
|
|
68
|
+
edited is kept
|
|
53
69
|
|
|
54
70
|
Each removed entry is printed as `Removed file: <name>` or `Removed directory: <name>/`.
|
|
55
71
|
|
|
56
72
|
## What is kept
|
|
57
73
|
|
|
58
|
-
|
|
59
|
-
|---|---|
|
|
60
|
-
| `handoffs/`, `projects/`, `links/` | Your session data. |
|
|
61
|
-
| `handoff.config.json` | Your configuration. |
|
|
62
|
-
| `.env.example` | Your environment template. |
|
|
63
|
-
| Anything you added elsewhere in the directory | The installer only removes entries it walks past; it never deletes a directory it keeps. |
|
|
74
|
+
Everything else in the directory — the installer prints the list at the end:
|
|
64
75
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
```
|
|
77
|
+
Kept — not the installer's to delete:
|
|
78
|
+
.agent-handoff/
|
|
79
|
+
handoff-session.md
|
|
80
|
+
handoff.config.json
|
|
81
|
+
handoffs/
|
|
82
|
+
projects/
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
That includes a store under any name (`.agent-handoff/`, `projects/`, `handoffs/`, or one of
|
|
86
|
+
your own), `links/`, notes, your `handoff.config.json`, and anything else you added. Nothing is
|
|
87
|
+
deleted for being empty, and nothing outside those paths is touched; if data remains, the
|
|
88
|
+
installation directory remains with it.
|
|
69
89
|
|
|
70
90
|
## Manual uninstall
|
|
71
91
|
|
|
@@ -74,13 +94,18 @@ Remove the skill files and leave the data behind:
|
|
|
74
94
|
```bash
|
|
75
95
|
cd "<install-path>"
|
|
76
96
|
|
|
77
|
-
#
|
|
78
|
-
|
|
79
|
-
rm -
|
|
97
|
+
# Exactly the manifest this same release installs. Your store, notes and
|
|
98
|
+
# handoff.config.json are not listed, so they stay.
|
|
99
|
+
rm -rf tools docs refs templates schemas tests
|
|
100
|
+
rm -f SKILL.md README.md LICENSE skill.json \
|
|
80
101
|
capability-registry.json permission-policy.json \
|
|
81
|
-
handoff.config.schema.json handoff.config.example.json
|
|
102
|
+
handoff.config.schema.json handoff.config.example.json \
|
|
103
|
+
.agents-handoff-install.json
|
|
82
104
|
```
|
|
83
105
|
|
|
106
|
+
A `package.json` the installer wrote (`"private": true`, `"name": "agents-handoff"`) can go
|
|
107
|
+
too; one you edited is yours to keep. `--remove` makes that distinction itself.
|
|
108
|
+
|
|
84
109
|
If you never store handoffs inside the installation — for example when `HANDOFFS_ROOT` points
|
|
85
110
|
somewhere else — and you do not need anything else in it, the whole directory can go:
|
|
86
111
|
|
|
@@ -113,7 +138,8 @@ and can be read by a later installation, or by any tool that reads a handoff fol
|
|
|
113
138
|
| Nothing was removed | The confirmation was skipped. Pass `--force`. |
|
|
114
139
|
| `EPERM` or `EBUSY` on Windows | A process is holding the files. Close it and retry, or check file attributes. |
|
|
115
140
|
| Permission denied | The installation is outside your user directory. Remove it with the privileges that created it, or use `--force` from a shell that can write there. |
|
|
116
|
-
|
|
|
141
|
+
| The directory is still there after `--remove` | It is not empty: the entries printed under `Kept — not the installer's to delete:` are still inside. Remove them yourself if you no longer want them. |
|
|
142
|
+
| Handoff data seems to be missing | `HANDOFFS_ROOT` points elsewhere. Check the root printed by `handoff.mjs config`; `--remove` never deletes a store inside the install directory. |
|
|
117
143
|
|
|
118
144
|
## See also
|
|
119
145
|
|
package/docs/UPGRADE.md
CHANGED
|
@@ -35,43 +35,71 @@ leaves that file alone.
|
|
|
35
35
|
npx agents-handoff --update
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
`--update`
|
|
39
|
-
|
|
38
|
+
With no target flag, `--update` updates **every installation found on this machine**. That is
|
|
39
|
+
the whole answer to "keep my install current": a machine can hold the same skill in
|
|
40
|
+
`~/.claude/skills` and in `~/.agents/skills`, and updating only one of them is how the other
|
|
41
|
+
keeps running an old engine. Each installation is updated and reported on its own, and the run
|
|
42
|
+
ends with a summary naming the version it moved from and to:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Update summary
|
|
46
|
+
✓ updated <dir>/agents-handoff — 2.0.2 → v2.0.3
|
|
47
|
+
✓ updated <dir>/agents-handoff — 2.0.2 → v2.0.3
|
|
48
|
+
✓ 2 of 2 installation(s) updated
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
When nothing is installed anywhere the installer can see, it says so and exits non-zero:
|
|
52
|
+
`Nothing to update: no agents-handoff installation found.`
|
|
40
53
|
|
|
41
54
|
The update then reinstalls: the skill files are copied over the existing installation and
|
|
42
55
|
overwrite the files of the same name. Files that are not part of the installation manifest —
|
|
43
|
-
`handoffs/`, `projects/`, `links/`, `handoff.config.json`, `.env.example`, and
|
|
44
|
-
— are left in place.
|
|
56
|
+
`handoffs/`, `projects/`, `links/`, `.agent-handoff/`, `handoff.config.json`, `.env.example`, and
|
|
57
|
+
anything you added — are left in place. Nothing outside the manifest is read or rewritten.
|
|
45
58
|
|
|
46
|
-
|
|
59
|
+
Scope the update to one harness, or several, with the same flags install uses:
|
|
47
60
|
|
|
48
61
|
```bash
|
|
62
|
+
npx agents-handoff --update --claude # just Claude Code
|
|
63
|
+
npx agents-handoff --update --codex # just Codex CLI
|
|
64
|
+
npx agents-handoff --update --all # every harness found on this machine
|
|
49
65
|
npx agents-handoff --update --location project
|
|
50
66
|
npx agents-handoff --update --version 2.0.0
|
|
51
67
|
```
|
|
52
68
|
|
|
53
|
-
`--
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
`--
|
|
57
|
-
|
|
69
|
+
`--all` covers the harnesses whose configuration directory exists here; a named harness is
|
|
70
|
+
updated whether or not that directory exists.
|
|
71
|
+
|
|
72
|
+
`--version` asks for a version, and the installer resolves it honestly: the tree beside the
|
|
73
|
+
installer is used when it **is** that version (or when nothing was requested), and when it is a
|
|
74
|
+
different version the requested tag's archive is fetched instead, with its sha256 recorded in
|
|
75
|
+
the install record's `source`. To switch versions, ask npm for the one you want
|
|
76
|
+
(`npx agents-handoff@<version>`), pass `--version <x>`, or install manually from that version's
|
|
77
|
+
tag archive. Confirm what is actually installed with `--verify`, which prints the version read
|
|
78
|
+
back from the installed `SKILL.md`, rather than trusting the request.
|
|
79
|
+
|
|
80
|
+
An update rewrites the install record as well, so `--verify --provenance` describes the new
|
|
81
|
+
state afterwards and reports the archive (with its sha256) when the files came from a download
|
|
82
|
+
rather than from a tree. The record's `package` block names the npm package and version the
|
|
83
|
+
installation should match; `npx agents-handoff --verify-package --record` fills in that
|
|
84
|
+
package's tarball hashes.
|
|
58
85
|
|
|
59
86
|
## Manual upgrade
|
|
60
87
|
|
|
61
88
|
Replace the skill files and keep the data:
|
|
62
89
|
|
|
63
|
-
1. Extract the release archive (`
|
|
64
|
-
|
|
90
|
+
1. Extract the release archive (`agents-handoff-v<version>.zip` from the
|
|
91
|
+
[releases page](https://github.com/Alot1z/agent-handoff/releases); the newest release carries
|
|
92
|
+
its own version in the file name) into a temporary directory.
|
|
65
93
|
2. Copy the skill files over the installation: `SKILL.md`, `skill.json`, the manifest JSON
|
|
66
94
|
files, `tools/`, `tools/lib/`, `schemas/`, `refs/`, `templates/`, `docs/`, `tests/`.
|
|
67
95
|
3. Do not delete `handoffs/`, `projects/`, `links/`, or `handoff.config.json`.
|
|
68
96
|
|
|
69
97
|
```bash
|
|
70
|
-
unzip
|
|
71
|
-
cp -r /tmp/
|
|
72
|
-
/tmp/
|
|
73
|
-
/tmp/
|
|
74
|
-
cp /tmp/
|
|
98
|
+
unzip agents-handoff-v<version>.zip -d /tmp/agents-handoff-new
|
|
99
|
+
cp -r /tmp/agents-handoff-new/tools/ /tmp/agents-handoff-new/refs/ \
|
|
100
|
+
/tmp/agents-handoff-new/templates/ /tmp/agents-handoff-new/schemas/ \
|
|
101
|
+
/tmp/agents-handoff-new/docs/ "<install-path>/"
|
|
102
|
+
cp /tmp/agents-handoff-new/SKILL.md /tmp/agents-handoff-new/skill.json "<install-path>/"
|
|
75
103
|
```
|
|
76
104
|
|
|
77
105
|
## What an upgrade changes
|
|
@@ -82,6 +110,8 @@ cp /tmp/agent-handoff-new/SKILL.md /tmp/agent-handoff-new/skill.json "<install-p
|
|
|
82
110
|
| `refs/`, `templates/`, `schemas/`, `docs/` | `projects/`, `links/` |
|
|
83
111
|
| `SKILL.md`, `skill.json`, manifest JSON files | `handoff.config.json` and your edits |
|
|
84
112
|
| `install/` — the installer itself | `HANDOFFS_ROOT`, if you use it |
|
|
113
|
+
| `.agents-handoff-install.json` — the install record, rewritten for the new version, including its `package` block | — |
|
|
114
|
+
| `.agent-handoff/` and any other store directory, whatever it is called | — |
|
|
85
115
|
|
|
86
116
|
Handoff folders are read from the handoff root in place, so an upgrade does not move or rewrite
|
|
87
117
|
them.
|
|
@@ -89,13 +119,18 @@ them.
|
|
|
89
119
|
## After upgrading
|
|
90
120
|
|
|
91
121
|
```bash
|
|
92
|
-
npx agents-handoff --verify
|
|
122
|
+
npx agents-handoff --verify # every installation found
|
|
123
|
+
npx agents-handoff --verify --provenance
|
|
124
|
+
npx agents-handoff --verify-package --record # and prove it matches the published tarball
|
|
125
|
+
npx agents-handoff doctor
|
|
93
126
|
node "<install-path>/tools/handoff.mjs" config
|
|
94
127
|
node "<install-path>/tools/handoff.mjs" list
|
|
95
128
|
```
|
|
96
129
|
|
|
97
130
|
`config` proves the engine starts and prints the handoff root it resolved. `list` proves the
|
|
98
|
-
engine still finds the handoff folders that were already there.
|
|
131
|
+
engine still finds the handoff folders that were already there. `--verify --provenance` prints
|
|
132
|
+
the install record the verification was checked against — version, source, harness and the
|
|
133
|
+
file-set hash — which is the shortest way to prove an upgrade landed and left nothing behind.
|
|
99
134
|
|
|
100
135
|
The shipped test suite is a stronger check and does not touch existing handoffs when you point
|
|
101
136
|
it at a scratch root:
|
|
@@ -126,10 +161,13 @@ upgrade damaged the folder.
|
|
|
126
161
|
|
|
127
162
|
| Symptom | Cause and fix |
|
|
128
163
|
|---|---|
|
|
129
|
-
| `Not installed at <dir>` |
|
|
130
|
-
|
|
|
164
|
+
| `Not installed at <dir>` | `--path`, `--location` or a harness flag named a directory that holds no installation. Drop the flag to update every installation found, or check `--list`. |
|
|
165
|
+
| `Nothing to update: no agents-handoff installation found.` | Nothing to update anywhere the installer looks. Run `npx agents-handoff --all`, or name the directory with `--path`. |
|
|
166
|
+
| Reported version did not change | The installer uses the tree beside it when that tree **is** the requested version (or nothing was requested), so running it from a checkout installs that checkout. Use the published package, pass `--version <x>` to fetch that tag's archive, or check `--verify --provenance` to see which source the record names. |
|
|
167
|
+
| `verify-package` fails with `does NOT match … as published` | A file changed after the update. The check names it; reinstall with `--force`. |
|
|
131
168
|
| Verification fails after an upgrade | A file is missing or the engine cannot start. Reinstall with `--force` and read the failing check. |
|
|
132
169
|
| Handoffs no longer listed | The engine is reading a different root. Run `config` and compare it with where your handoffs live; set `HANDOFFS_ROOT` if needed. |
|
|
170
|
+
| `no provenance record` after upgrading | The record is written by installs from 2.0.3 on. Reinstall with `--force` to write one for this target. |
|
|
133
171
|
| Configuration was overwritten | `handoff.config.json` is preserved, but a manual copy step can still overwrite it. Restore your backup. |
|
|
134
172
|
|
|
135
173
|
## See also
|
package/docs/_config.yml
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
title:
|
|
1
|
+
title: agents-handoff
|
|
2
2
|
description: Cross-harness capture and verified continuation for AI working sessions.
|
|
3
3
|
url: https://alot1z.github.io
|
|
4
|
+
# The site is served from the repository's Pages path, which follows the REPOSITORY name
|
|
5
|
+
# (agent-handoff), not the product name (agents-handoff).
|
|
4
6
|
baseurl: /agent-handoff
|
|
5
7
|
plugins:
|
|
6
8
|
- jekyll-relative-links
|
package/docs/index.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
2
|
+
title: agents-handoff
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
#
|
|
5
|
+
# agents-handoff documentation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
agents-handoff turns an AI working session — chat turns, tool calls, reasoning, however the
|
|
8
8
|
client stored it — into a folder of plain files that a different agent, a different harness,
|
|
9
9
|
or a colleague can read and continue from without the original chat. It builds from a
|
|
10
10
|
transcript or an adapter export, keeps a hash chain so a handoff can be re-verified, and
|
|
@@ -13,8 +13,8 @@ merges later turns into the same session instead of duplicating it.
|
|
|
13
13
|
## Quick start
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
# 1. Install the skill
|
|
17
|
-
npx agents-handoff
|
|
16
|
+
# 1. Install the skill into every harness found on this machine
|
|
17
|
+
npx agents-handoff --all
|
|
18
18
|
|
|
19
19
|
# 2. Build a handoff from a transcript
|
|
20
20
|
node tools/handoff.mjs build --source transcript.jsonl --project my-project
|
|
@@ -28,11 +28,20 @@ node tools/handoff.mjs verify <id-prefix>
|
|
|
28
28
|
`build` also accepts `--session`, `--harness`, `--model` and `--objective`. Run
|
|
29
29
|
`node tools/handoff.mjs config` to see which store root the engine resolved and why.
|
|
30
30
|
|
|
31
|
+
`--all` installs into every harness present on the machine; `--claude`, `--codex`, `--agents`
|
|
32
|
+
and `--skills-dir <dir>` pick one or several instead, and `npx agents-handoff --update` brings
|
|
33
|
+
every copy on the machine up to date in one run. `npx agents-handoff --verify-package` then
|
|
34
|
+
proves the copy on disk is identical to the tarball npm is serving for its version, while
|
|
35
|
+
`npx agents-handoff --doctor` reports what is installed where and whether each copy still
|
|
36
|
+
matches the record written when it was installed. The installer's full surface is in
|
|
37
|
+
[CLI.md](CLI.md) and [INSTALL.md](INSTALL.md).
|
|
38
|
+
|
|
31
39
|
## Where to start
|
|
32
40
|
|
|
33
41
|
| If you want to… | Read |
|
|
34
42
|
|---|---|
|
|
35
43
|
| install it | [INSTALL.md](INSTALL.md) |
|
|
44
|
+
| prove an install matches the published package | [INSTALL.md](INSTALL.md) and [CLI.md](CLI.md) |
|
|
36
45
|
| understand how the pieces fit | [ARCHITECTURE.md](ARCHITECTURE.md) |
|
|
37
46
|
| look up a command, flag or exit code | [CLI.md](CLI.md) |
|
|
38
47
|
| know exactly what a handoff folder holds | [FORMAT.md](FORMAT.md) |
|
|
@@ -51,7 +60,7 @@ node tools/handoff.mjs verify <id-prefix>
|
|
|
51
60
|
| [ARCHITECTURE.md](ARCHITECTURE.md) | The layers, the data flow, the store root, the write-safety discipline, the boundaries |
|
|
52
61
|
| [CLI.md](CLI.md) | Every executable, verb, flag, exit code, environment variable and file written |
|
|
53
62
|
| [FORMAT.md](FORMAT.md) | Handoff folder layout, every file in it, the manifest and the schemas |
|
|
54
|
-
| [SESSIONS.md](SESSIONS.md) | Session index: a sample store, its captured sessions, and how to verify and re-render them |
|
|
63
|
+
| [SESSIONS.md](SESSIONS.md) | Session index: a sample store, its captured sessions, and how to verify and re-render them. The same rows are published as [sessions.json](sessions.json) (schema `1.0-session-feed`) for anything that would rather read data than markdown, and the page filters in the browser |
|
|
55
64
|
| [INTEGRATION.md](INTEGRATION.md) | Embedding the engine, configuration and environment, CI and pipeline use |
|
|
56
65
|
| [LEVEL4.md](LEVEL4.md) | Dynamic runtime layer: runtime verbs, gates and promotion |
|
|
57
66
|
| [LEVEL5.md](LEVEL5.md) | Collaborative dispatch: routing a handoff to another agent |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "1.0-session-feed",
|
|
3
|
+
"generated_by": ".github/scripts/build-sessions-index.mjs",
|
|
4
|
+
"store": "examples/sessions",
|
|
5
|
+
"index_source": "INDEX.json",
|
|
6
|
+
"as_of": "2026-10-08T22:53:03.964Z",
|
|
7
|
+
"count": 2,
|
|
8
|
+
"projects": 2,
|
|
9
|
+
"failed": 0,
|
|
10
|
+
"sessions": [
|
|
11
|
+
{
|
|
12
|
+
"id": "typescript-project-setup",
|
|
13
|
+
"project": "demo",
|
|
14
|
+
"harness": "claude-code",
|
|
15
|
+
"model": "claude-3-5-sonnet",
|
|
16
|
+
"turns": 11,
|
|
17
|
+
"revisions": 1,
|
|
18
|
+
"updated": "2026-10-08T22:53:03.865Z",
|
|
19
|
+
"manifest_sha256": "141e232eb2ad668f59d746828517e646a5cbe2bc914dd976df3c43c209214d3c",
|
|
20
|
+
"integrity": "pass"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "fixture-roundtrip",
|
|
24
|
+
"project": "smoke-test",
|
|
25
|
+
"harness": "codex",
|
|
26
|
+
"model": "gpt-5-codex",
|
|
27
|
+
"turns": 2,
|
|
28
|
+
"revisions": 1,
|
|
29
|
+
"updated": "2026-10-08T22:53:03.964Z",
|
|
30
|
+
"manifest_sha256": "a81d076e3334b8341f2829d0f38daf2cdbaf667269a9909dc523797c74e46ce5",
|
|
31
|
+
"integrity": "pass"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
package/install/CHANGELOG.md
CHANGED
|
@@ -42,7 +42,7 @@ machine that has neither a checkout nor an unpacked archive.
|
|
|
42
42
|
- `install` (default), `update`, `remove`, `verify`, `list` and `where`.
|
|
43
43
|
- Location targets `global`, `local` and `project`, with `--path` for an exact directory.
|
|
44
44
|
- Global root resolution instead of a hard-coded path: an account-skill store that already
|
|
45
|
-
holds `
|
|
45
|
+
holds `agents-handoff`, else `~/.agents/skills`, else an account-skill store found on the
|
|
46
46
|
machine, else `~/.agents/skills`, created on install. `where` prints the resolved root and
|
|
47
47
|
the rule that chose it. `AGENT_HANDOFF_GLOBAL_DIR` overrides it.
|
|
48
48
|
- `--version` to install a specific version, and `--force` to skip confirmations.
|
package/install/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# agents-handoff
|
|
2
2
|
|
|
3
|
-
npx installer for the
|
|
3
|
+
npx installer for the agents-handoff skill.
|
|
4
4
|
|
|
5
5
|
## Quick start
|
|
6
6
|
|
|
@@ -56,13 +56,13 @@ npx agents-handoff where
|
|
|
56
56
|
## Locations
|
|
57
57
|
|
|
58
58
|
- **global**: resolved, not hard-coded — an account-skill root that already holds
|
|
59
|
-
`
|
|
60
|
-
machine (`<store>/<account-id>/<profile-id>/
|
|
59
|
+
`agents-handoff`, else `~/.agents/skills`, else any account-skill store found on this
|
|
60
|
+
machine (`<store>/<account-id>/<profile-id>/agents-handoff/`), else `~/.agents/skills`,
|
|
61
61
|
created on install. See it resolved:
|
|
62
62
|
`npx agents-handoff where`. Override with `AGENT_HANDOFF_GLOBAL_DIR`, or target an
|
|
63
63
|
exact path with `--path`.
|
|
64
|
-
- **local**: `./local/skills/
|
|
65
|
-
- **project**: `./skills/
|
|
64
|
+
- **local**: `./local/skills/agents-handoff/`
|
|
65
|
+
- **project**: `./skills/agents-handoff/` (only detected if in a git repo)
|
|
66
66
|
|
|
67
67
|
## Requirements
|
|
68
68
|
|
|
@@ -71,6 +71,6 @@ npx agents-handoff where
|
|
|
71
71
|
|
|
72
72
|
## Development
|
|
73
73
|
|
|
74
|
-
This installer is part of the
|
|
74
|
+
This installer is part of the agents-handoff skill source code.
|
|
75
75
|
|
|
76
|
-
See the [
|
|
76
|
+
See the [agents-handoff docs](https://github.com/Alot1z/agent-handoff/tree/main/docs) for more.
|