agents-handoff 0.0.0-stage → 2.0.2
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 +150 -0
- package/LICENSE +21 -0
- package/README.md +110 -2
- package/SKILL.md +147 -0
- package/capability-registry.json +27 -0
- package/docs/ARCHITECTURE.md +164 -0
- package/docs/CHANGELOG.md +151 -0
- package/docs/CLI.md +196 -0
- package/docs/COMPATIBILITY.md +124 -0
- package/docs/CONTRIBUTING.md +134 -0
- package/docs/FORMAT.md +157 -0
- package/docs/INSTALL.md +179 -0
- package/docs/INTEGRATION.md +188 -0
- package/docs/LEVEL4.md +202 -0
- package/docs/LEVEL5.md +96 -0
- package/docs/PERMISSIONS.md +145 -0
- package/docs/PROVENANCE.md +83 -0
- package/docs/SECURITY.md +93 -0
- package/docs/SESSIONS.md +66 -0
- package/docs/TROUBLESHOOTING.md +158 -0
- package/docs/UNINSTALL.md +122 -0
- package/docs/UPGRADE.md +139 -0
- package/docs/_config.yml +16 -0
- package/docs/_data/nav.yml +36 -0
- package/docs/_layouts/default.html +31 -0
- package/docs/assets/style.css +88 -0
- package/docs/index.md +83 -0
- package/handoff.config.example.json +35 -0
- package/handoff.config.schema.json +117 -0
- package/install/CHANGELOG.md +48 -0
- package/install/README.md +76 -0
- package/install/install.mjs +856 -0
- package/install/package.json +39 -0
- package/package.json +66 -4
- package/permission-policy.json +33 -0
- package/refs/ADAPTERS.md +33 -0
- package/refs/bootstrap.md +59 -0
- package/refs/brief-checklist.md +79 -0
- package/refs/handbook.md +58 -0
- package/refs/protocol.md +117 -0
- package/refs/roles.md +75 -0
- package/refs/validator.md +73 -0
- package/schemas/handoff.schema.json +275 -0
- package/skill.json +147 -0
- package/templates/HANDOFF.llm.schema.json +144 -0
- package/templates/HANDOFF.template.md +40 -0
- package/tests/acceptance/acceptance.yaml +209 -0
- package/tests/fixtures/minimal-transcript.jsonl +2 -0
- package/tools/agent-handoff.mjs +410 -0
- package/tools/capability-registry.mjs +120 -0
- package/tools/handoff.mjs +398 -0
- package/tools/handoff.test.mjs +465 -0
- package/tools/lib/handoff-root.mjs +161 -0
- package/tools/runtime-engine.mjs +330 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to agent-handoff are recorded here.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
6
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Releases before 2.0.0
|
|
7
|
+
were development builds and were never published, so they are not listed.
|
|
8
|
+
|
|
9
|
+
The version in [package.json](https://github.com/Alot1z/agent-handoff/blob/main/package.json)
|
|
10
|
+
and [skill.json](https://github.com/Alot1z/agent-handoff/blob/main/skill.json) is the release
|
|
11
|
+
version, and it is the version published to npm: the repository root is the
|
|
12
|
+
[`agents-handoff`](https://www.npmjs.com/package/agents-handoff) package.
|
|
13
|
+
|
|
14
|
+
## [Unreleased]
|
|
15
|
+
|
|
16
|
+
Add entries under the matching heading as changes land.
|
|
17
|
+
|
|
18
|
+
## [2.0.2] - 2026-10-09
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **[Session index](https://alot1z.github.io/agent-handoff/SESSIONS.html)** (`docs/SESSIONS.md`):
|
|
23
|
+
a page rendered from a real handoff store, listing the captured sessions in
|
|
24
|
+
`examples/sessions/` with their project, harness, turn count, revision, manifest hash and
|
|
25
|
+
integrity verdict, plus the commands that reproduce each check. The sample store is built by
|
|
26
|
+
the engine from the two transcripts this repository ships, and
|
|
27
|
+
`.github/scripts/build-sessions-index.mjs --check` fails the build when the page and the store
|
|
28
|
+
disagree.
|
|
29
|
+
- The skill is published to npm as
|
|
30
|
+
[`agents-handoff`](https://www.npmjs.com/package/agents-handoff), from the repository root,
|
|
31
|
+
and the release workflow publishes it on a tag: it skips a version npm already has, and
|
|
32
|
+
reports — without failing the release — when `NPM_TOKEN` is not configured. The package
|
|
33
|
+
carries the skill tree, so `npx agents-handoff` installs with no download.
|
|
34
|
+
- `npm test`, `npm run check:docs` and `npm run check:session-index` are wired into
|
|
35
|
+
`prepublishOnly`, so a tree whose suite, links or session index are stale cannot be published.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- `npx agents-handoff` now installs the skill as documented. It previously looked for the skill
|
|
40
|
+
files beside itself, found none, and reported success while installing nothing; a bare copy of
|
|
41
|
+
`install/` still falls back to downloading the archive for the requested version.
|
|
42
|
+
- The clean-checkout suite builds its fixture from the shipped projection rather than the
|
|
43
|
+
development tree, which is what let the installer's broken source paths pass every local test.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- The installer lost fourteen files whenever it ran outside the development tree: `README.md`,
|
|
48
|
+
`LICENSE` and the twelve guides were addressed under `repo-upstream/<path>`, a directory only
|
|
49
|
+
the development tree has. Sources are written in the shipped tree's terms and resolved against
|
|
50
|
+
both layouts, and an install that cannot resolve a source now fails with the missing paths
|
|
51
|
+
instead of warning and continuing.
|
|
52
|
+
- CI failed on every run: the runtime-layer smoke test ran `agent-handoff.mjs list`, which is not
|
|
53
|
+
a verb of that tool (it exits 2). The step builds a handoff into a scratch store and runs
|
|
54
|
+
`index`, a verb that exists.
|
|
55
|
+
- The shipped version disagreed across files: `SKILL.md` said 2.0.0 while `skill.json` and
|
|
56
|
+
`package.json` said 2.0.1, and the installer carried its own 2.0.0 constant, so every install
|
|
57
|
+
reported the previous version. `SKILL.md` is now the single source of truth, the installer
|
|
58
|
+
reads it, and the suite asserts the two agree.
|
|
59
|
+
- `install/package.json` pointed `repository` at a different repository from the one serving the
|
|
60
|
+
package; it now names this repository, with `homepage` and `bugs`.
|
|
61
|
+
- `handoff.config.schema.json` declared its `$id` under a path that does not serve the schema.
|
|
62
|
+
- `examples/demo/example-usage.md` addressed the engine as `../../../tools/handoff.mjs`, one
|
|
63
|
+
directory above the repository root, so every command in it failed when pasted.
|
|
64
|
+
- `tests/acceptance/acceptance.yaml` described the development tree: it listed documents that
|
|
65
|
+
are not published, scanned a directory that is not published, and asserted two behaviours the
|
|
66
|
+
shipped CLI does not have (`--help` exiting 0, `list` succeeding on an empty store). Every
|
|
67
|
+
entry was re-run against a clean checkout and now states what was observed.
|
|
68
|
+
- Documentation stopped describing files that are not published: `src/` was listed as part of an
|
|
69
|
+
installation in `INSTALL.md`, `UNINSTALL.md` and `UPGRADE.md`, and documented as a repository
|
|
70
|
+
directory in `CONTRIBUTING.md`.
|
|
71
|
+
- `ARCHITECTURE.md` claimed nothing in the repository makes a network call, which stopped being
|
|
72
|
+
true once the installer fetched archives.
|
|
73
|
+
|
|
74
|
+
## [2.0.1] — 2026-10-09
|
|
75
|
+
|
|
76
|
+
Documentation release. No behaviour changed; no public interface changed.
|
|
77
|
+
|
|
78
|
+
### Added
|
|
79
|
+
|
|
80
|
+
- **[Command reference](https://github.com/Alot1z/agent-handoff/blob/main/docs/CLI.md)**
|
|
81
|
+
(`docs/CLI.md`): every executable, verb, flag, exit code, environment variable and file
|
|
82
|
+
written, in one place.
|
|
83
|
+
- **[Architecture](https://github.com/Alot1z/agent-handoff/blob/main/docs/ARCHITECTURE.md)**
|
|
84
|
+
(`docs/ARCHITECTURE.md`): the five layers, the data flow, store-root resolution, the
|
|
85
|
+
write-safety discipline, and the boundaries the tool does not cross.
|
|
86
|
+
- **[Troubleshooting](https://github.com/Alot1z/agent-handoff/blob/main/docs/TROUBLESHOOTING.md)**
|
|
87
|
+
(`docs/TROUBLESHOOTING.md`): symptom, cause and fix, keyed to the real exit codes.
|
|
88
|
+
- This changelog, and a Changelog page on the site rendered from it, so the repository file
|
|
89
|
+
and the published page cannot drift apart.
|
|
90
|
+
- A docs-consistency check (`.github/scripts/check-docs.mjs`) run in CI: every page under
|
|
91
|
+
`docs/` must appear in the navigation, and every relative link must resolve where it is
|
|
92
|
+
read.
|
|
93
|
+
|
|
94
|
+
### Changed
|
|
95
|
+
|
|
96
|
+
- README now links the published [installation guide](https://alot1z.github.io/agent-handoff/INSTALL.html)
|
|
97
|
+
and the [documentation site](https://alot1z.github.io/agent-handoff/) at the top, and its
|
|
98
|
+
documentation table covers every page.
|
|
99
|
+
- Links in `docs/` that pointed outside the published site are absolute URLs, so they resolve
|
|
100
|
+
for a reader of the documentation instead of returning 404.
|
|
101
|
+
- `package.json` homepage points at the documentation site.
|
|
102
|
+
|
|
103
|
+
## [2.0.0] — 2026-10-08
|
|
104
|
+
|
|
105
|
+
The first public release: a capture engine, a runtime layer over it, an installer, and the
|
|
106
|
+
documentation site.
|
|
107
|
+
|
|
108
|
+
### Added
|
|
109
|
+
|
|
110
|
+
- **Capture engine** (`tools/handoff.mjs`, published as the `agent-handoff` bin). `build`
|
|
111
|
+
reads a JSONL or plain-text transcript and writes a handoff directory:
|
|
112
|
+
`HANDOFF.md`, `HANDOFF.summary.json`, `HANDOFF.llm.json`, `timeline.jsonl`, `TOOLS.md`,
|
|
113
|
+
`manifest.json`. Also `list`, `show`, `verify`, `rename`, `retitle` and `config`.
|
|
114
|
+
- **Incremental builds.** Each build appends only the turns above the recorded `watermark`
|
|
115
|
+
and leaves `timeline.jsonl` untouched, so re-running over a longer transcript extends the
|
|
116
|
+
handoff instead of duplicating it. A rebuild with no new turns and an unchanged source hash
|
|
117
|
+
prints `handoff: up-to-date` and writes nothing.
|
|
118
|
+
- **sha256 provenance.** `manifest.json` carries `raw_sha256` over the source bytes and a
|
|
119
|
+
self-hash `manifest_sha256` over itself. `verify` recomputes the self-hash, checks the
|
|
120
|
+
`timeline.jsonl` line count against `turn_count`, and parses `HANDOFF.llm.json`.
|
|
121
|
+
- **Store-root resolution** (`tools/lib/handoff-root.mjs`): `HANDOFFS_ROOT`, then
|
|
122
|
+
`handoff.config.json` found by walking up, then a `handoffs/` directory on the same walk,
|
|
123
|
+
then the skill directory. Reported by `handoff.mjs config`.
|
|
124
|
+
- **Runtime layer** (`tools/agent-handoff.mjs`): `auto`, `verify-gate`, `promote`, `merge`,
|
|
125
|
+
`federated-merge`, `self-improve`, `index`. Every mutating command takes a lock, backs up
|
|
126
|
+
before writing, verifies after applying, and rolls back on failure.
|
|
127
|
+
- **Bounded execution** (`tools/runtime-engine.mjs`): risk classes `R0`–`R4` evaluated against
|
|
128
|
+
`permission-policy.json` before any operation runs, resumable jobs with sealed checkpoints,
|
|
129
|
+
and a per-decision record in the state directory.
|
|
130
|
+
- **Capability probes** (`tools/capability-registry.mjs`): `file-exists`, `dir-writable` and
|
|
131
|
+
`command` probes that report `healthy` / `unhealthy` / `unknown` with the evidence behind
|
|
132
|
+
each verdict.
|
|
133
|
+
- **Installer** (`install/`, package `agents-handoff`): `install`, `update`, `remove`,
|
|
134
|
+
`verify`, `list`, `where`, targeting a resolved global root, `./local/skills/agent-handoff`,
|
|
135
|
+
or `./skills/agent-handoff`.
|
|
136
|
+
- **Documentation site** at <https://alot1z.github.io/agent-handoff/>, built by GitHub Pages
|
|
137
|
+
from `docs/`.
|
|
138
|
+
- **CI** (`.github/workflows/ci.yml`): the test suite on Node 18, 20 and 22, a runtime-layer
|
|
139
|
+
smoke test, installer help, and a required-file and JSON-validity check.
|
|
140
|
+
|
|
141
|
+
### Security
|
|
142
|
+
|
|
143
|
+
- The engine reads transcripts and writes handoff files. It makes no network calls, and it
|
|
144
|
+
never writes secrets. The limits of what the provenance chain proves are stated in
|
|
145
|
+
[docs/PROVENANCE.md](https://github.com/Alot1z/agent-handoff/blob/main/docs/PROVENANCE.md),
|
|
146
|
+
not implied.
|
|
147
|
+
|
|
148
|
+
[Unreleased]: https://github.com/Alot1z/agent-handoff/compare/v2.0.1...main
|
|
149
|
+
[2.0.1]: https://github.com/Alot1z/agent-handoff/compare/v2.0.0...v2.0.1
|
|
150
|
+
[2.0.0]: https://github.com/Alot1z/agent-handoff/tree/v2.0.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alot1z
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,111 @@
|
|
|
1
|
-
#
|
|
1
|
+
# agent-handoff
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**[Installation guide →](https://alot1z.github.io/agent-handoff/INSTALL.html)** · **[Documentation →](https://alot1z.github.io/agent-handoff/)** · **[Changelog](CHANGELOG.md)**
|
|
4
|
+
|
|
5
|
+
[](https://github.com/Alot1z/agent-handoff/actions/workflows/ci.yml)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](#requirements)
|
|
8
|
+
|
|
9
|
+
One handoff format for every AI coding harness. A working session — messages, tool calls,
|
|
10
|
+
reasoning, and the provenance to prove where each byte came from — is captured as a folder
|
|
11
|
+
that a fresh agent can continue from with zero shared memory.
|
|
12
|
+
|
|
13
|
+
- Zero runtime dependencies; Node.js 18 or newer.
|
|
14
|
+
- Reads any JSONL or plain-text transcript, whatever produced it.
|
|
15
|
+
- Every artifact carries a sha256 provenance chain, and `verify` recomputes it.
|
|
16
|
+
- Writes are backed up, verified and rolled back on failure.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx agents-handoff
|
|
22
|
+
npx agents-handoff where # show the resolved install root, and why it was chosen
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The installer resolves the global root instead of hard-coding one. The resolution order,
|
|
26
|
+
the location targets and the requirements are in the
|
|
27
|
+
**[installation guide](https://alot1z.github.io/agent-handoff/INSTALL.html)** and
|
|
28
|
+
[docs/INSTALL.md](docs/INSTALL.md).
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Capture a session
|
|
34
|
+
node tools/handoff.mjs build --source session.jsonl --harness claude-code --project my-project
|
|
35
|
+
|
|
36
|
+
# List, inspect and verify what you captured
|
|
37
|
+
node tools/handoff.mjs list
|
|
38
|
+
node tools/handoff.mjs show <id-prefix>
|
|
39
|
+
node tools/handoff.mjs verify <id-prefix>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`build` is incremental: re-running it over a longer transcript merges past the recorded
|
|
43
|
+
watermark instead of creating a second handoff. `verify` exits non-zero when the manifest
|
|
44
|
+
hash, the timeline line count or the LLM payload no longer match what was written.
|
|
45
|
+
|
|
46
|
+
## What a handoff folder contains
|
|
47
|
+
|
|
48
|
+
| File | Contents |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `HANDOFF.md` | The brief a reader picks up cold: objective, current state, open loops, recent timeline |
|
|
51
|
+
| `HANDOFF.summary.json` | The same brief as structured fields |
|
|
52
|
+
| `HANDOFF.llm.json` | Payload shaped for a model to consume |
|
|
53
|
+
| `timeline.jsonl` | Every turn, one per line, appended and never paraphrased |
|
|
54
|
+
| `TOOLS.md` | The full tool-call log |
|
|
55
|
+
| `manifest.json` | Counts, classes, source paths, and the sha256 provenance chain |
|
|
56
|
+
|
|
57
|
+
The field-by-field contract is in [docs/FORMAT.md](docs/FORMAT.md).
|
|
58
|
+
|
|
59
|
+
## Documentation
|
|
60
|
+
|
|
61
|
+
Full documentation is published at **<https://alot1z.github.io/agent-handoff/>**.
|
|
62
|
+
|
|
63
|
+
| Document | Covers |
|
|
64
|
+
|---|---|
|
|
65
|
+
| [docs/index.md](docs/index.md) | Start here: what the tool does and how the docs fit together |
|
|
66
|
+
| [docs/INSTALL.md](docs/INSTALL.md) · [site](https://alot1z.github.io/agent-handoff/INSTALL.html) | Install, locations, install options, troubleshooting |
|
|
67
|
+
| [docs/UPGRADE.md](docs/UPGRADE.md) | Updating an install, and what an update leaves alone |
|
|
68
|
+
| [docs/UNINSTALL.md](docs/UNINSTALL.md) | Removing an install, and what is kept |
|
|
69
|
+
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | How the layers fit together, the data flow, and the boundaries |
|
|
70
|
+
| [docs/CLI.md](docs/CLI.md) | Every executable, verb, flag, exit code and state file |
|
|
71
|
+
| [docs/FORMAT.md](docs/FORMAT.md) | Handoff folder layout, manifest fields, provenance chain |
|
|
72
|
+
| [docs/SESSIONS.md](docs/SESSIONS.md) · [site](https://alot1z.github.io/agent-handoff/SESSIONS.html) | Session index: a sample store, its sessions, and the commands that verify them |
|
|
73
|
+
| [docs/INTEGRATION.md](docs/INTEGRATION.md) | Feeding a transcript in from another program or a CI job |
|
|
74
|
+
| [docs/LEVEL4.md](docs/LEVEL4.md) | The runtime layer: verbs, the evidence gate, bounded execution |
|
|
75
|
+
| [docs/LEVEL5.md](docs/LEVEL5.md) | Dispatching a verified handoff to a worker |
|
|
76
|
+
| [docs/PERMISSIONS.md](docs/PERMISSIONS.md) | Permission levels, risk classes, and what is enforced |
|
|
77
|
+
| [docs/SECURITY.md](docs/SECURITY.md) | What is read and written, and the guarantees that are not made |
|
|
78
|
+
| [docs/COMPATIBILITY.md](docs/COMPATIBILITY.md) | Platforms, Node versions, transcript formats |
|
|
79
|
+
| [docs/PROVENANCE.md](docs/PROVENANCE.md) | The hash chain, what it detects, what it cannot |
|
|
80
|
+
| [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) | Symptom, cause and fix, keyed to the real exit codes |
|
|
81
|
+
| [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) | Running the tests and adding an adapter |
|
|
82
|
+
| [CHANGELOG.md](CHANGELOG.md) | What changed in each release |
|
|
83
|
+
| [refs/ADAPTERS.md](refs/ADAPTERS.md) | The canonical input shape and how each store maps onto it |
|
|
84
|
+
|
|
85
|
+
## Repository layout
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
tools/handoff.mjs capture engine (the CLI above)
|
|
89
|
+
tools/agent-handoff.mjs runtime layer: auto, verify-gate, promote, merge, self-improve, index, dispatch
|
|
90
|
+
tools/runtime-engine.mjs bounded execution and the permission gate
|
|
91
|
+
tools/capability-registry.mjs capability health probes
|
|
92
|
+
tools/lib/ shared store-root resolution
|
|
93
|
+
docs/ refs/ templates/ documentation, reference material, output templates
|
|
94
|
+
schemas/ handoff payload and configuration schemas
|
|
95
|
+
install/ the npx installer package
|
|
96
|
+
tests/ acceptance fixture and a minimal transcript
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Requirements
|
|
100
|
+
|
|
101
|
+
Node.js 18 or newer. No dependencies, no build step, no network access at runtime. See
|
|
102
|
+
[docs/COMPATIBILITY.md](docs/COMPATIBILITY.md).
|
|
103
|
+
|
|
104
|
+
## Contributing
|
|
105
|
+
|
|
106
|
+
Run the suite with `node tools/handoff.test.mjs`. It is hermetic — it writes to a scratch
|
|
107
|
+
directory and needs no network. See [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md).
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
MIT — see [LICENSE](LICENSE).
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-handoff
|
|
3
|
+
description: >-
|
|
4
|
+
Write, verify, and hand off complete AI working sessions across any harness
|
|
5
|
+
(Claude Code, Codex, DeepSeek Harness, plain JSONL or text logs). Captures a
|
|
6
|
+
session as a portable, sha256-proven handoff folder a fresh agent can continue
|
|
7
|
+
from with zero shared memory, with versioned contracts, an evidence gate, and
|
|
8
|
+
backup/verify/rollback on every write. Zero runtime dependencies, no network.
|
|
9
|
+
version: 2.0.2
|
|
10
|
+
domain: orchestration
|
|
11
|
+
tokens: 900
|
|
12
|
+
allowed-tools: Bash(node:*), Read, Edit, Write
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Agent Handoff v2 — cross-harness session capture + verified continuation
|
|
16
|
+
|
|
17
|
+
ONE handoff system for every harness, every project, every model — backed by versioned
|
|
18
|
+
contracts, an evidence gate, and backup/verify/rollback on every write. Pick up any
|
|
19
|
+
conversation anywhere, with provenance for every artifact.
|
|
20
|
+
|
|
21
|
+
## Level map (progressive disclosure)
|
|
22
|
+
|
|
23
|
+
| Level | When loaded | Token cost | Content |
|
|
24
|
+
|-------|-------------|-----------|---------|
|
|
25
|
+
| **L1 Metadata** | Always (frontmatter above) | ~100 | name + description |
|
|
26
|
+
| **L2 Instructions** | This file, when triggered | <5k | core workflow + commands below |
|
|
27
|
+
| **L3 Resources** | As needed | none until read | `docs/`, `templates/`, `refs/`, `tools/handoff.mjs` |
|
|
28
|
+
| **L4 Dynamic** | When you need runtime/self-adapting | none until run | `tools/agent-handoff.mjs`: auto, verify-gate, promote, merge, self-improve |
|
|
29
|
+
| **L5 Collaborative** | Verified handoff dispatches a worker | none until run | `tools/agent-handoff.mjs` dispatch + `docs/LEVEL5.md` |
|
|
30
|
+
|
|
31
|
+
## What this skill is (capabilities + contracts)
|
|
32
|
+
|
|
33
|
+
1. **Capture engine** (`tools/handoff.mjs`, zero deps) — builds
|
|
34
|
+
`projects/<project>/<session>/{HANDOFF.md, HANDOFF.summary.json, HANDOFF.llm.json,
|
|
35
|
+
timeline.jsonl, TOOLS.md, manifest.json}` with sha256 watermark-provenance; update-not-recreate.
|
|
36
|
+
2. **Brief discipline** — lossless operational compression (10k-30k token briefs,
|
|
37
|
+
TASK / USER SPECIFICATION / CURRENT STATE / DONE / IN PROGRESS / PLANNED / FAILED / FILES /
|
|
38
|
+
VERIFICATION / ENVIRONMENT / NEXT / DO NOT), with length floors and a bootstrap text.
|
|
39
|
+
3. **Evidence contract** — every handoff states RESULT/WHAT_CHANGED/VALIDATION/
|
|
40
|
+
EVIDENCE/BLOCKERS/RISKS/FOLLOW_UP; no evidence = no verified transition.
|
|
41
|
+
4. **Write safety** — trigger on staleness, lock-guard, backup before write,
|
|
42
|
+
verify after write, rollback on failure, idempotent re-run.
|
|
43
|
+
5. **Pipeline principles**:
|
|
44
|
+
- **Lossless raw**: rawInput/objective is verbatim, never replaced or paraphrased
|
|
45
|
+
(PromptIR rule). Matches handoff "objectives verbatim".
|
|
46
|
+
- **Versioned contracts**: every handoff artifact is a contract (schema v1, sha256);
|
|
47
|
+
re-run merges past watermark. No unversioned writes.
|
|
48
|
+
- **DecisionTrace**: record route/selection stages + provenance on every handoff
|
|
49
|
+
(stages: capture → brief → verify.gate → promote → dispatch).
|
|
50
|
+
- **Evidence-gated completion (ORC-1)**: state transitions only on evidence;
|
|
51
|
+
a worker-DONE is never a verified transition. verify.gate runs before promote/dispatch.
|
|
52
|
+
- **ContextPlan buckets (CTX-1)**: in the brief, classify context as required |
|
|
53
|
+
historical | authoritative | retrievable | sensitive | deferred with budget caps.
|
|
54
|
+
- **EVIDENCE_LEVELS ladder (KNOW-1)**: VERIFIED > OBSERVED > DERIVED > PREDICTED > UNKNOWN;
|
|
55
|
+
never silently upgrade; supersede rather than stack.
|
|
56
|
+
- **Autonomy ladder (CTL-1)**: observe → suggest → request-approval → constrained-execute →
|
|
57
|
+
workflow-execute → autonomous-within-policy. Handoff writes default to constrained-execute;
|
|
58
|
+
dispatch default dry-run.
|
|
59
|
+
- **Honesty rule (FINAL-1)**: oracle registry + success-criteria evaluator; RESULT is
|
|
60
|
+
DONE|PARTIAL|BLOCKED|FAILED — never fabricated.
|
|
61
|
+
|
|
62
|
+
## Doctrine (unchanged + corpus-backed)
|
|
63
|
+
|
|
64
|
+
1. Prompts are advisory; validators are authoritative. Fail closed on ambiguity (BLOCKED).
|
|
65
|
+
2. Portability over compression: fidelity lives verbatim in the fileset (TOOLS.md, timeline.jsonl,
|
|
66
|
+
HANDOFF.llm.json); briefs reference by pointer.
|
|
67
|
+
3. Downgrade unverified claims to their true evidence level — never upgrade.
|
|
68
|
+
4. Handoff is prior knowledge, not ground truth: re-verify against the cheapest available
|
|
69
|
+
oracle, and keep instructions self-contained so a fresh agent can act cold.
|
|
70
|
+
5. Max-local: every engine here runs with zero network deps; harness adapters are
|
|
71
|
+
probe-absent-safe (Claude Code, Codex, DeepSeek Harness, plain JSONL, plain text).
|
|
72
|
+
|
|
73
|
+
## Core workflow
|
|
74
|
+
|
|
75
|
+
### A. Capture (any harness)
|
|
76
|
+
```bash
|
|
77
|
+
cd <handoffs-store> # or set HANDOFFS_ROOT
|
|
78
|
+
node tools/handoff.mjs build --source <transcript.jsonl|.txt|.md> \
|
|
79
|
+
--session <id> --harness claude-code|codex|dsh|generic \
|
|
80
|
+
--model <name> --project <project> [--objective "text"]
|
|
81
|
+
```
|
|
82
|
+
Re-run merges past watermark. `verify <id-prefix>` checks manifest sha + turn-count + JSON parse.
|
|
83
|
+
|
|
84
|
+
### B. Write the lossless brief (COS rules + CTX buckets)
|
|
85
|
+
Headings TASK / USER SPECIFICATION / CURRENT STATE / DONE / IN PROGRESS / PLANNED-DECIDED /
|
|
86
|
+
FAILED-UNRESOLVED / FILES / VERIFICATION / ENVIRONMENT / NEXT / DO NOT. Enforce floors
|
|
87
|
+
(>=200 chars any session; >=1000 chars for >=20k recorded tokens). Preserve exact
|
|
88
|
+
paths/ids/commands/error text. Mark context provenance: required | sensitive | deferred.
|
|
89
|
+
|
|
90
|
+
### C. Gate with evidence (orchestrator + ORC-1)
|
|
91
|
+
```
|
|
92
|
+
RESULT: DONE | PARTIAL | BLOCKED | FAILED
|
|
93
|
+
WHAT_CHANGED:
|
|
94
|
+
VALIDATION:
|
|
95
|
+
EVIDENCE: # artifact + sha; must match pending dispatch (phaseId + dispatchId)
|
|
96
|
+
BLOCKERS:
|
|
97
|
+
RISKS:
|
|
98
|
+
FOLLOW_UP:
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### D. Level 4 runtime + L5 dispatch
|
|
102
|
+
```bash
|
|
103
|
+
HANDOFFS_ROOT=<store> node tools/agent-handoff.mjs auto --source <file> --session <id> --harness <h> --project <p>
|
|
104
|
+
HANDOFFS_ROOT=<store> node tools/agent-handoff.mjs verify-gate <id-prefix>
|
|
105
|
+
HANDOFFS_ROOT=<store> node tools/agent-handoff.mjs promote <id-prefix>
|
|
106
|
+
HANDOFFS_ROOT=<store> node tools/agent-handoff.mjs merge <a> <b>
|
|
107
|
+
HANDOFFS_ROOT=<store> node tools/agent-handoff.mjs self-improve
|
|
108
|
+
HANDOFFS_ROOT=<store> node tools/agent-handoff.mjs index
|
|
109
|
+
HANDOFFS_ROOT=<store> node tools/agent-handoff.mjs dispatch <id-prefix> --task "<objective>" [--broker <orchestrator-root> --live]
|
|
110
|
+
```
|
|
111
|
+
Dispatch re-runs the evidence gate first; carries manifest sha256; dry-run by default
|
|
112
|
+
(autonomy ladder: workflow-execute requires explicit --live).
|
|
113
|
+
|
|
114
|
+
## Rules
|
|
115
|
+
|
|
116
|
+
1. Never dump the whole corpus — load only what the task needs.
|
|
117
|
+
2. Preserve provenance — every artifact carries raw + manifest sha256.
|
|
118
|
+
3. Verbatim objectives (PromptIR lossless).
|
|
119
|
+
4. Evidence gates — RESULT without EVIDENCE never becomes VERIFIED.
|
|
120
|
+
5. Update, never duplicate (watermark merge).
|
|
121
|
+
6. No secrets.
|
|
122
|
+
7. Safety on writes (backup → apply → verify → rollback).
|
|
123
|
+
8. User messages are the highest authority in any brief.
|
|
124
|
+
9. Raw is never altered — handoffs render from canonical data.
|
|
125
|
+
10. Self-improve — a refused/truncated brief is a knowledge candidate.
|
|
126
|
+
11. Max-local: zero external-dependency engines; adapters absent-safe.
|
|
127
|
+
12. Versioned contracts — every artifact has a schema version, a sha256 and a decided autonomy level.
|
|
128
|
+
|
|
129
|
+
## Level map (L3 resources — read on demand)
|
|
130
|
+
|
|
131
|
+
| Need | File |
|
|
132
|
+
|------|------|
|
|
133
|
+
| Live dispatch protocol | `refs/protocol.md` |
|
|
134
|
+
| Role ladder | `refs/roles.md` |
|
|
135
|
+
| Validator gate (12-point) | `refs/validator.md` |
|
|
136
|
+
| Shared operating rules | `refs/handbook.md` |
|
|
137
|
+
| Fresh-session bootstrap | `refs/bootstrap.md` |
|
|
138
|
+
| Brief discipline | `refs/brief-checklist.md` |
|
|
139
|
+
| Engine source | `tools/handoff.mjs` |
|
|
140
|
+
| L4 runtime | `tools/agent-handoff.mjs` |
|
|
141
|
+
| L4/L5 design | `docs/LEVEL4.md`, `docs/LEVEL5.md` |
|
|
142
|
+
| Cross-harness adapters | `refs/ADAPTERS.md` |
|
|
143
|
+
| Handoff format + schema | `docs/FORMAT.md`, `templates/` |
|
|
144
|
+
| Installation | `docs/INSTALL.md` |
|
|
145
|
+
|
|
146
|
+
**Version**: 2.0.0
|
|
147
|
+
**Last Updated**: 2026-10-08
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "1.0-capability-registry",
|
|
3
|
+
"capabilities": [
|
|
4
|
+
{
|
|
5
|
+
"id": "filesystem.read",
|
|
6
|
+
"kind": "file-exists",
|
|
7
|
+
"target": "tests/fixtures/minimal-transcript.jsonl",
|
|
8
|
+
"required": true,
|
|
9
|
+
"purpose": "read transcript sources for handoff builds"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "filesystem.write",
|
|
13
|
+
"kind": "dir-writable",
|
|
14
|
+
"target": ".agent-handoff",
|
|
15
|
+
"required": true,
|
|
16
|
+
"purpose": "persist runtime state and checkpoints"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "process.execute",
|
|
20
|
+
"kind": "command",
|
|
21
|
+
"command": "<node>",
|
|
22
|
+
"args": ["-e", "process.exit(0)"],
|
|
23
|
+
"required": true,
|
|
24
|
+
"purpose": "execute bounded engine subcommands"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Architecture
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Architecture
|
|
6
|
+
|
|
7
|
+
## The problem the shape solves
|
|
8
|
+
|
|
9
|
+
A working session lives inside whatever client recorded it. Continuing that session
|
|
10
|
+
elsewhere means either pasting the chat back in, or starting from memory. Both lose the part
|
|
11
|
+
that matters: the exact turns, the tool calls, and the ability to prove which source bytes
|
|
12
|
+
produced the brief you are reading.
|
|
13
|
+
|
|
14
|
+
agent-handoff turns the session into files instead. A directory of plain text and JSON, a
|
|
15
|
+
hash chain over it, and a fixed folder layout. Anything that can read a file can continue
|
|
16
|
+
from one, with no shared memory between the two sessions.
|
|
17
|
+
|
|
18
|
+
## Layers
|
|
19
|
+
|
|
20
|
+
Five layers, each with one job, and each usable without the ones above it.
|
|
21
|
+
|
|
22
|
+
| Layer | File | Job |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| Capture engine | `tools/handoff.mjs` | Turns one transcript into one handoff folder. Passive: something has to invoke it. |
|
|
25
|
+
| Runtime layer | `tools/agent-handoff.mjs` | Acts on the state of the store: staleness, gates, composition, imports, index. |
|
|
26
|
+
| Bounded execution | `tools/runtime-engine.mjs` | Decides whether an operation may run, before running it. |
|
|
27
|
+
| Capability probes | `tools/capability-registry.mjs` | Reports what a declared capability actually does on this machine. |
|
|
28
|
+
| Distribution | `install/install.mjs` | Puts the skill where a client will look for it. |
|
|
29
|
+
|
|
30
|
+
The capture engine has no opinion about installation, and the runtime layer has no opinion
|
|
31
|
+
about transcripts — it shells out to the engine for builds and verification. That split is
|
|
32
|
+
what lets a store be inspected with one file, `manifest.json`, without loading anything else.
|
|
33
|
+
|
|
34
|
+
## Data flow
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
transcript ─────────────► build ─────────────► <root>/projects/<project>/<session>/
|
|
38
|
+
(.jsonl or .txt) │ HANDOFF.md
|
|
39
|
+
│ HANDOFF.summary.json
|
|
40
|
+
│ HANDOFF.llm.json
|
|
41
|
+
│ timeline.jsonl (append-only)
|
|
42
|
+
│ TOOLS.md
|
|
43
|
+
│ manifest.json (hash chain)
|
|
44
|
+
│
|
|
45
|
+
verify ◄──────────────────┘ recompute manifest_sha256
|
|
46
|
+
count timeline.jsonl lines
|
|
47
|
+
parse HANDOFF.llm.json
|
|
48
|
+
|
|
49
|
+
INDEX.json ◄──── index / build one row per session
|
|
50
|
+
links/*.md ◄──── merge cross-project relation notes
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
A second build over a longer transcript appends only the turns above the watermark. Nothing
|
|
54
|
+
already written to `timeline.jsonl` is rewritten, so a brief can be regenerated without
|
|
55
|
+
invalidating what a consumer already read.
|
|
56
|
+
|
|
57
|
+
## Where the store lives
|
|
58
|
+
|
|
59
|
+
`tools/lib/handoff-root.mjs` is the single implementation of the resolution order, so the
|
|
60
|
+
engine and the runtime layer can never disagree about which store they are operating on.
|
|
61
|
+
First match wins:
|
|
62
|
+
|
|
63
|
+
1. `HANDOFFS_ROOT`, the environment override.
|
|
64
|
+
2. `handoff.config.json`, found by walking up from the current directory, at most 10 levels.
|
|
65
|
+
`storage.path` beats `handoff_dir`; a relative `handoff_dir` resolves against the
|
|
66
|
+
directory holding the config.
|
|
67
|
+
3. A `handoffs/` directory, checked at each level of the same upward walk.
|
|
68
|
+
4. The skill directory, as the last resort.
|
|
69
|
+
|
|
70
|
+
A config file that is present but invalid stops the run with exit 2 instead of falling
|
|
71
|
+
through to rule 3. Falling back would write the session to a different store than the one
|
|
72
|
+
that was configured, which is worse than refusing.
|
|
73
|
+
|
|
74
|
+
`handoff.mjs config` prints the resolved root and the rule that chose it (`env`, `config`,
|
|
75
|
+
`discover`, `default`).
|
|
76
|
+
|
|
77
|
+
## The provenance chain
|
|
78
|
+
|
|
79
|
+
Two hashes, and one of them covers the other.
|
|
80
|
+
|
|
81
|
+
| Value | Definition |
|
|
82
|
+
|---|---|
|
|
83
|
+
| `raw_sha256` | SHA-256 of the exact source bytes read at the last build. |
|
|
84
|
+
| `manifest_sha256` | SHA-256 of the manifest JSON with `manifest_sha256` removed. |
|
|
85
|
+
|
|
86
|
+
`verify` recomputes the self-hash, requires `timeline.jsonl`, compares its line count with
|
|
87
|
+
`turn_count`, and parses `HANDOFF.llm.json`. It prints `PASS` or `FAIL` and exits 0 or 1.
|
|
88
|
+
|
|
89
|
+
What the chain detects: a manifest edited by hand, a truncated or extended timeline, a
|
|
90
|
+
payload that no longer parses. What it does not do is prove that the source was authentic —
|
|
91
|
+
read [PROVENANCE.md](PROVENANCE.md) for the precise boundary.
|
|
92
|
+
|
|
93
|
+
## Concurrency and write safety
|
|
94
|
+
|
|
95
|
+
Every mutating runtime command takes a lock before touching the store. Locks live in
|
|
96
|
+
`<root>/.locks/` and are named after a hash of the operation target, so two runs on
|
|
97
|
+
different sessions do not block each other while two runs on the same session do. A held
|
|
98
|
+
lock exits 3.
|
|
99
|
+
|
|
100
|
+
The discipline for a mutation is the same everywhere: take the lock, back up what is about
|
|
101
|
+
to change, apply, verify the result, and roll back on failure. `federated-merge` backs up a
|
|
102
|
+
local manifest to `manifest.json.bak-federated` before copying over it, and verifies every
|
|
103
|
+
imported session with the engine afterwards. `promote` backs a manifest up to
|
|
104
|
+
`manifest.json.bak` before stamping it.
|
|
105
|
+
|
|
106
|
+
## Bounded execution
|
|
107
|
+
|
|
108
|
+
`runtime-engine.mjs` separates the decision from the act. `evaluate` classifies a target and
|
|
109
|
+
returns a verdict without running anything; `run` evaluates first and only then acts, and a
|
|
110
|
+
denied operation is recorded but never executed. Targets are classified in a fixed order —
|
|
111
|
+
an explicit denial, then the engine's own state directory, then approved workspaces, then
|
|
112
|
+
the broad personal-data roots, then system read-only roots, otherwise external — so a
|
|
113
|
+
personal-data or denied path is refused at any risk class.
|
|
114
|
+
|
|
115
|
+
Every decision is written to `<state>/executions/<id>.json` with
|
|
116
|
+
`enforced_before_execution: true`. Levels, risk classes and grants are in
|
|
117
|
+
[PERMISSIONS.md](PERMISSIONS.md).
|
|
118
|
+
|
|
119
|
+
## Honest verdicts
|
|
120
|
+
|
|
121
|
+
The capability registry reports `healthy`, `unhealthy` or `unknown`, each with the evidence
|
|
122
|
+
that produced it. A probe kind with no implementation returns `unknown` rather than
|
|
123
|
+
`healthy`. `check` exits non-zero when a required capability is `unknown`, because an
|
|
124
|
+
unanswered question is not a pass.
|
|
125
|
+
|
|
126
|
+
The same rule applies to the evidence gate. `verify-gate` returns `REJECTED` in its JSON
|
|
127
|
+
when a check fails, and exits 0 either way, so the verdict has to be read rather than
|
|
128
|
+
inferred from a status code. `promote` prints the gate result without enforcing it, which is
|
|
129
|
+
stated in the command reference rather than left for a caller to discover.
|
|
130
|
+
|
|
131
|
+
## Boundaries
|
|
132
|
+
|
|
133
|
+
- The engine makes no network calls, and neither does the runtime layer. The one component
|
|
134
|
+
that reaches the network is the installer, and only when it runs as the published package:
|
|
135
|
+
it downloads the archive for the version being installed. See
|
|
136
|
+
[COMPATIBILITY.md](COMPATIBILITY.md) and [INSTALL.md](INSTALL.md).
|
|
137
|
+
- The source transcript is read and never written.
|
|
138
|
+
- No secrets are stored. The code reads no credential files.
|
|
139
|
+
- No model is called. The `.llm.json` payload is shaped for a model to read, not produced by
|
|
140
|
+
one.
|
|
141
|
+
- `spawn` runs only the local node binary, with a 15000 ms timeout and its output captured
|
|
142
|
+
and hashed rather than streamed.
|
|
143
|
+
|
|
144
|
+
## Repository layout
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
tools/handoff.mjs capture engine
|
|
148
|
+
tools/agent-handoff.mjs runtime layer
|
|
149
|
+
tools/runtime-engine.mjs bounded execution
|
|
150
|
+
tools/capability-registry.mjs capability probes
|
|
151
|
+
tools/lib/handoff-root.mjs store-root resolution (single owner)
|
|
152
|
+
tools/handoff.test.mjs the hermetic test suite
|
|
153
|
+
docs/ this documentation and the Pages site
|
|
154
|
+
refs/ reference material: adapters, protocol, roles, brief checklist
|
|
155
|
+
templates/ handoff templates and the LLM payload schema
|
|
156
|
+
schemas/ the portable handoff payload schema
|
|
157
|
+
install/ the npx installer package
|
|
158
|
+
tests/ acceptance fixture and a minimal transcript
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The documentation site at <https://alot1z.github.io/agent-handoff/> is built by GitHub Pages
|
|
162
|
+
directly from `docs/`. `docs/_data/nav.yml` is the navigation, `docs/_config.yml` is the
|
|
163
|
+
Jekyll configuration, and `.github/scripts/check-docs.mjs` fails CI when a page is missing
|
|
164
|
+
from the navigation or a relative link does not resolve.
|