agents-handoff 0.0.0-stage → 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 +192 -0
- package/LICENSE +21 -0
- package/README.md +150 -2
- package/SKILL.md +147 -0
- package/capability-registry.json +27 -0
- package/docs/ARCHITECTURE.md +187 -0
- package/docs/CHANGELOG.md +196 -0
- package/docs/CLI.md +299 -0
- package/docs/COMPATIBILITY.md +124 -0
- package/docs/CONTRIBUTING.md +134 -0
- package/docs/FORMAT.md +185 -0
- package/docs/INSTALL.md +394 -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 +110 -0
- package/docs/SECURITY.md +93 -0
- package/docs/SESSIONS.md +97 -0
- package/docs/TROUBLESHOOTING.md +158 -0
- package/docs/UNINSTALL.md +148 -0
- package/docs/UPGRADE.md +177 -0
- package/docs/_config.yml +18 -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 +92 -0
- package/docs/sessions.json +34 -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 +1455 -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 +22 -0
- package/tools/agents-handoff.mjs +410 -0
- package/tools/capability-registry.mjs +120 -0
- package/tools/handoff.mjs +398 -0
- package/tools/handoff.test.mjs +668 -0
- package/tools/lib/handoff-root.mjs +161 -0
- package/tools/runtime-engine.mjs +330 -0
|
@@ -0,0 +1,187 @@
|
|
|
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
|
+
agents-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/agents-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 — one harness, several at once, or an exact directory — and records what it installed. |
|
|
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
|
+
## Install provenance
|
|
94
|
+
|
|
95
|
+
A handoff folder proves what it was built from. An installation answers a different question:
|
|
96
|
+
what is on this machine, and where did it come from. The installer writes
|
|
97
|
+
`.agents-handoff-install.json` into every copy it makes, and `verify` re-hashes the same file
|
|
98
|
+
set to compare the copy with that record.
|
|
99
|
+
|
|
100
|
+
| Value | Definition |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `files_sha256` | SHA-256 over the sorted `path\0sha256(file)` lines of every manifest file. |
|
|
103
|
+
| `files` | Per-file sha256 values, so a mismatch names the file that changed. |
|
|
104
|
+
| `source` | `tree` for a copy made from a checkout or archive beside the installer, or `archive` with the tag and the archive's own sha256 when the copy was fetched. |
|
|
105
|
+
|
|
106
|
+
The install record is a record, not a signature: it proves what was installed and detects
|
|
107
|
+
drift, and it cannot prove the tree it came from was trustworthy. That distinction is stated
|
|
108
|
+
in full in [PROVENANCE.md](PROVENANCE.md).
|
|
109
|
+
|
|
110
|
+
## Concurrency and write safety
|
|
111
|
+
|
|
112
|
+
Every mutating runtime command takes a lock before touching the store. Locks live in
|
|
113
|
+
`<root>/.locks/` and are named after a hash of the operation target, so two runs on
|
|
114
|
+
different sessions do not block each other while two runs on the same session do. A held
|
|
115
|
+
lock exits 3.
|
|
116
|
+
|
|
117
|
+
The discipline for a mutation is the same everywhere: take the lock, back up what is about
|
|
118
|
+
to change, apply, verify the result, and roll back on failure. `federated-merge` backs up a
|
|
119
|
+
local manifest to `manifest.json.bak-federated` before copying over it, and verifies every
|
|
120
|
+
imported session with the engine afterwards. `promote` backs a manifest up to
|
|
121
|
+
`manifest.json.bak` before stamping it.
|
|
122
|
+
|
|
123
|
+
## Bounded execution
|
|
124
|
+
|
|
125
|
+
`runtime-engine.mjs` separates the decision from the act. `evaluate` classifies a target and
|
|
126
|
+
returns a verdict without running anything; `run` evaluates first and only then acts, and a
|
|
127
|
+
denied operation is recorded but never executed. Targets are classified in a fixed order —
|
|
128
|
+
an explicit denial, then the engine's own state directory, then approved workspaces, then
|
|
129
|
+
the broad personal-data roots, then system read-only roots, otherwise external — so a
|
|
130
|
+
personal-data or denied path is refused at any risk class.
|
|
131
|
+
|
|
132
|
+
Every decision is written to `<state>/executions/<id>.json` with
|
|
133
|
+
`enforced_before_execution: true`. Levels, risk classes and grants are in
|
|
134
|
+
[PERMISSIONS.md](PERMISSIONS.md).
|
|
135
|
+
|
|
136
|
+
## Honest verdicts
|
|
137
|
+
|
|
138
|
+
The capability registry reports `healthy`, `unhealthy` or `unknown`, each with the evidence
|
|
139
|
+
that produced it. A probe kind with no implementation returns `unknown` rather than
|
|
140
|
+
`healthy`. `check` exits non-zero when a required capability is `unknown`, because an
|
|
141
|
+
unanswered question is not a pass.
|
|
142
|
+
|
|
143
|
+
The same rule applies to the evidence gate. `verify-gate` returns `REJECTED` in its JSON
|
|
144
|
+
when a check fails, and exits 0 either way, so the verdict has to be read rather than
|
|
145
|
+
inferred from a status code. `promote` prints the gate result without enforcing it, which is
|
|
146
|
+
stated in the command reference rather than left for a caller to discover.
|
|
147
|
+
|
|
148
|
+
## Boundaries
|
|
149
|
+
|
|
150
|
+
- The engine makes no network calls, and neither does the runtime layer. The one component
|
|
151
|
+
that reaches the network is the installer, and only when it runs as the published package:
|
|
152
|
+
it downloads the archive for the version being installed. See
|
|
153
|
+
[COMPATIBILITY.md](COMPATIBILITY.md) and [INSTALL.md](INSTALL.md).
|
|
154
|
+
- The source transcript is read and never written.
|
|
155
|
+
- No secrets are stored. The code reads no credential files.
|
|
156
|
+
- No model is called. The `.llm.json` payload is shaped for a model to read, not produced by
|
|
157
|
+
one.
|
|
158
|
+
- `spawn` runs only the local node binary, with a 15000 ms timeout and its output captured
|
|
159
|
+
and hashed rather than streamed.
|
|
160
|
+
|
|
161
|
+
## Repository layout
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
tools/handoff.mjs capture engine
|
|
165
|
+
tools/agents-handoff.mjs runtime layer
|
|
166
|
+
tools/agent-handoff.mjs forwarder from the runtime layer's pre-rename path
|
|
167
|
+
tools/runtime-engine.mjs bounded execution
|
|
168
|
+
tools/capability-registry.mjs capability probes
|
|
169
|
+
tools/lib/handoff-root.mjs store-root resolution (single owner)
|
|
170
|
+
tools/handoff.test.mjs the hermetic test suite
|
|
171
|
+
docs/ this documentation and the Pages site
|
|
172
|
+
docs/SESSIONS.md the session index, rendered from a real store
|
|
173
|
+
.github/scripts/ generators and checks: the session index, the doc link check
|
|
174
|
+
refs/ reference material: adapters, protocol, roles, brief checklist
|
|
175
|
+
templates/ handoff templates and the LLM payload schema
|
|
176
|
+
schemas/ the portable handoff payload schema
|
|
177
|
+
install/ the installer behind the agents-handoff npx package
|
|
178
|
+
tests/ acceptance fixture and a minimal transcript
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Inside an installed copy — not in this repository — the installer adds
|
|
182
|
+
`.agents-handoff-install.json`, the record of what landed there and what it was made from.
|
|
183
|
+
|
|
184
|
+
The documentation site at <https://alot1z.github.io/agent-handoff/> is built by GitHub Pages
|
|
185
|
+
directly from `docs/`. `docs/_data/nav.yml` is the navigation, `docs/_config.yml` is the
|
|
186
|
+
Jekyll configuration, and `.github/scripts/check-docs.mjs` fails CI when a page is missing
|
|
187
|
+
from the navigation or a relative link does not resolve.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Changelog
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Changelog
|
|
6
|
+
|
|
7
|
+
All notable changes to agents-handoff are recorded here.
|
|
8
|
+
|
|
9
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
10
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Releases before 2.0.0
|
|
11
|
+
were development builds and were never published, so they are not listed.
|
|
12
|
+
|
|
13
|
+
The version in [package.json](https://github.com/Alot1z/agent-handoff/blob/main/package.json)
|
|
14
|
+
and [skill.json](https://github.com/Alot1z/agent-handoff/blob/main/skill.json) is the release
|
|
15
|
+
version, and it is the version published to npm: the repository root is the
|
|
16
|
+
[`agents-handoff`](https://www.npmjs.com/package/agents-handoff) package.
|
|
17
|
+
|
|
18
|
+
## [Unreleased]
|
|
19
|
+
|
|
20
|
+
Add entries under the matching heading as changes land.
|
|
21
|
+
|
|
22
|
+
## [2.0.3] - 2026-10-09
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **Named harness targets.** One run can install the skill into Claude Code, Codex CLI and the
|
|
27
|
+
harness-neutral `~/.agents/skills` at once: `--claude`, `--codex`, `--agents`,
|
|
28
|
+
`--harness claude,codex` (repeatable), `--all` for every harness whose directory exists on
|
|
29
|
+
this machine, `--skills-dir <dir>` for any other stack, and `--project` for the
|
|
30
|
+
per-repository form. Every target gets its own copy and its own install record.
|
|
31
|
+
- **`verify-package`**, a verb that checks an installation against the package npm is actually
|
|
32
|
+
serving for its version: it verifies the downloaded tarball against the registry's own
|
|
33
|
+
`integrity` and `shasum`, compares the published file set with the installed one file by
|
|
34
|
+
file, and compares the tarball sha256 with the value recorded for that install. `--record`
|
|
35
|
+
stores the tarball hashes in the install record, so later runs compare with a stored value.
|
|
36
|
+
- The install record (`.agents-handoff-install.json`) now carries a `package` block — name,
|
|
37
|
+
version, registry, tarball URL, and the sha256/sha512/integrity/shasum filled in by
|
|
38
|
+
`verify-package` — so an installation can be checked against the published artifact rather
|
|
39
|
+
than only against itself.
|
|
40
|
+
- Installing from the repository without publishing: `npx github:Alot1z/agent-handoff` runs the
|
|
41
|
+
same installer straight from GitHub, and the installation guide documents both that and the
|
|
42
|
+
clone-and-run path.
|
|
43
|
+
- Five installer behaviour tests — multi-harness install with a record per target, `--update`
|
|
44
|
+
over every installation, `--verify` failing on a tampered copy, `remove` keeping user data,
|
|
45
|
+
and `verify-package` refusing a version npm does not serve. The suite is 34 tests.
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- `--update` and `--verify` with no harness flag now act on **every** installation found on the
|
|
50
|
+
machine instead of the one resolved target. A machine holding the skill in `~/.claude/skills`
|
|
51
|
+
and in `~/.agents/skills` has two copies, and updating only the resolved one left the other
|
|
52
|
+
silently stale; both verbs print a per-target summary.
|
|
53
|
+
- The runtime layer's entry point is `tools/agents-handoff.mjs`, matching the product name.
|
|
54
|
+
`tools/agent-handoff.mjs` is installed alongside it as a forwarder, so notes and scripts that
|
|
55
|
+
name the old path keep working.
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- `remove` deleted anything that was not one of three expected directory names, which meant a
|
|
60
|
+
handoff store kept under any other name was destroyed by `remove --force`. Removal is now
|
|
61
|
+
driven by the install manifest — what an install owns is what it copied — and the run prints
|
|
62
|
+
the entries it deliberately kept, including the store and `handoff.config.json`.
|
|
63
|
+
|
|
64
|
+
## [2.0.2] - 2026-10-09
|
|
65
|
+
|
|
66
|
+
### Added
|
|
67
|
+
|
|
68
|
+
- **[Session index](https://alot1z.github.io/agent-handoff/SESSIONS.html)** (`docs/SESSIONS.md`):
|
|
69
|
+
a page rendered from a real handoff store, listing the captured sessions in
|
|
70
|
+
`examples/sessions/` with their project, harness, turn count, revision, manifest hash and
|
|
71
|
+
integrity verdict, plus the commands that reproduce each check. The sample store is built by
|
|
72
|
+
the engine from the two transcripts this repository ships, and
|
|
73
|
+
`.github/scripts/build-sessions-index.mjs --check` fails the build when the page and the store
|
|
74
|
+
disagree.
|
|
75
|
+
- The skill is published to npm as
|
|
76
|
+
[`agents-handoff`](https://www.npmjs.com/package/agents-handoff), from the repository root,
|
|
77
|
+
and the release workflow publishes it on a tag: it skips a version npm already has, and
|
|
78
|
+
reports — without failing the release — when `NPM_TOKEN` is not configured. The package
|
|
79
|
+
carries the skill tree, so `npx agents-handoff` installs with no download.
|
|
80
|
+
- `npm test`, `npm run check:docs` and `npm run check:session-index` are wired into
|
|
81
|
+
`prepublishOnly`, so a tree whose suite, links or session index are stale cannot be published.
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- `npx agents-handoff` now installs the skill as documented. It previously looked for the skill
|
|
86
|
+
files beside itself, found none, and reported success while installing nothing; a bare copy of
|
|
87
|
+
`install/` still falls back to downloading the archive for the requested version.
|
|
88
|
+
- The clean-checkout suite builds its fixture from the shipped projection rather than the
|
|
89
|
+
development tree, which is what let the installer's broken source paths pass every local test.
|
|
90
|
+
|
|
91
|
+
### Fixed
|
|
92
|
+
|
|
93
|
+
- The installer lost fourteen files whenever it ran outside the development tree: `README.md`,
|
|
94
|
+
`LICENSE` and the twelve guides were addressed under `repo-upstream/<path>`, a directory only
|
|
95
|
+
the development tree has. Sources are written in the shipped tree's terms and resolved against
|
|
96
|
+
both layouts, and an install that cannot resolve a source now fails with the missing paths
|
|
97
|
+
instead of warning and continuing.
|
|
98
|
+
- CI failed on every run: the runtime-layer smoke test ran `agents-handoff.mjs list`, which is not
|
|
99
|
+
a verb of that tool (it exits 2). The step builds a handoff into a scratch store and runs
|
|
100
|
+
`index`, a verb that exists.
|
|
101
|
+
- The shipped version disagreed across files: `SKILL.md` said 2.0.0 while `skill.json` and
|
|
102
|
+
`package.json` said 2.0.1, and the installer carried its own 2.0.0 constant, so every install
|
|
103
|
+
reported the previous version. `SKILL.md` is now the single source of truth, the installer
|
|
104
|
+
reads it, and the suite asserts the two agree.
|
|
105
|
+
- `install/package.json` pointed `repository` at a different repository from the one serving the
|
|
106
|
+
package; it now names this repository, with `homepage` and `bugs`.
|
|
107
|
+
- `handoff.config.schema.json` declared its `$id` under a path that does not serve the schema.
|
|
108
|
+
- `examples/demo/example-usage.md` addressed the engine as `../../../tools/handoff.mjs`, one
|
|
109
|
+
directory above the repository root, so every command in it failed when pasted.
|
|
110
|
+
- `tests/acceptance/acceptance.yaml` described the development tree: it listed documents that
|
|
111
|
+
are not published, scanned a directory that is not published, and asserted two behaviours the
|
|
112
|
+
shipped CLI does not have (`--help` exiting 0, `list` succeeding on an empty store). Every
|
|
113
|
+
entry was re-run against a clean checkout and now states what was observed.
|
|
114
|
+
- Documentation stopped describing files that are not published: `src/` was listed as part of an
|
|
115
|
+
installation in `INSTALL.md`, `UNINSTALL.md` and `UPGRADE.md`, and documented as a repository
|
|
116
|
+
directory in `CONTRIBUTING.md`.
|
|
117
|
+
- `ARCHITECTURE.md` claimed nothing in the repository makes a network call, which stopped being
|
|
118
|
+
true once the installer fetched archives.
|
|
119
|
+
|
|
120
|
+
## [2.0.1] — 2026-10-09
|
|
121
|
+
|
|
122
|
+
Documentation release. No behaviour changed; no public interface changed.
|
|
123
|
+
|
|
124
|
+
### Added
|
|
125
|
+
|
|
126
|
+
- **[Command reference](https://github.com/Alot1z/agent-handoff/blob/main/docs/CLI.md)**
|
|
127
|
+
(`docs/CLI.md`): every executable, verb, flag, exit code, environment variable and file
|
|
128
|
+
written, in one place.
|
|
129
|
+
- **[Architecture](https://github.com/Alot1z/agent-handoff/blob/main/docs/ARCHITECTURE.md)**
|
|
130
|
+
(`docs/ARCHITECTURE.md`): the five layers, the data flow, store-root resolution, the
|
|
131
|
+
write-safety discipline, and the boundaries the tool does not cross.
|
|
132
|
+
- **[Troubleshooting](https://github.com/Alot1z/agent-handoff/blob/main/docs/TROUBLESHOOTING.md)**
|
|
133
|
+
(`docs/TROUBLESHOOTING.md`): symptom, cause and fix, keyed to the real exit codes.
|
|
134
|
+
- This changelog, and a Changelog page on the site rendered from it, so the repository file
|
|
135
|
+
and the published page cannot drift apart.
|
|
136
|
+
- A docs-consistency check (`.github/scripts/check-docs.mjs`) run in CI: every page under
|
|
137
|
+
`docs/` must appear in the navigation, and every relative link must resolve where it is
|
|
138
|
+
read.
|
|
139
|
+
|
|
140
|
+
### Changed
|
|
141
|
+
|
|
142
|
+
- README now links the published [installation guide](https://alot1z.github.io/agent-handoff/INSTALL.html)
|
|
143
|
+
and the [documentation site](https://alot1z.github.io/agent-handoff/) at the top, and its
|
|
144
|
+
documentation table covers every page.
|
|
145
|
+
- Links in `docs/` that pointed outside the published site are absolute URLs, so they resolve
|
|
146
|
+
for a reader of the documentation instead of returning 404.
|
|
147
|
+
- `package.json` homepage points at the documentation site.
|
|
148
|
+
|
|
149
|
+
## [2.0.0] — 2026-10-08
|
|
150
|
+
|
|
151
|
+
The first public release: a capture engine, a runtime layer over it, an installer, and the
|
|
152
|
+
documentation site.
|
|
153
|
+
|
|
154
|
+
### Added
|
|
155
|
+
|
|
156
|
+
- **Capture engine** (`tools/handoff.mjs`, published as the `agents-handoff` bin). `build`
|
|
157
|
+
reads a JSONL or plain-text transcript and writes a handoff directory:
|
|
158
|
+
`HANDOFF.md`, `HANDOFF.summary.json`, `HANDOFF.llm.json`, `timeline.jsonl`, `TOOLS.md`,
|
|
159
|
+
`manifest.json`. Also `list`, `show`, `verify`, `rename`, `retitle` and `config`.
|
|
160
|
+
- **Incremental builds.** Each build appends only the turns above the recorded `watermark`
|
|
161
|
+
and leaves `timeline.jsonl` untouched, so re-running over a longer transcript extends the
|
|
162
|
+
handoff instead of duplicating it. A rebuild with no new turns and an unchanged source hash
|
|
163
|
+
prints `handoff: up-to-date` and writes nothing.
|
|
164
|
+
- **sha256 provenance.** `manifest.json` carries `raw_sha256` over the source bytes and a
|
|
165
|
+
self-hash `manifest_sha256` over itself. `verify` recomputes the self-hash, checks the
|
|
166
|
+
`timeline.jsonl` line count against `turn_count`, and parses `HANDOFF.llm.json`.
|
|
167
|
+
- **Store-root resolution** (`tools/lib/handoff-root.mjs`): `HANDOFFS_ROOT`, then
|
|
168
|
+
`handoff.config.json` found by walking up, then a `handoffs/` directory on the same walk,
|
|
169
|
+
then the skill directory. Reported by `handoff.mjs config`.
|
|
170
|
+
- **Runtime layer** (`tools/agents-handoff.mjs`): `auto`, `verify-gate`, `promote`, `merge`,
|
|
171
|
+
`federated-merge`, `self-improve`, `index`. Every mutating command takes a lock, backs up
|
|
172
|
+
before writing, verifies after applying, and rolls back on failure.
|
|
173
|
+
- **Bounded execution** (`tools/runtime-engine.mjs`): risk classes `R0`–`R4` evaluated against
|
|
174
|
+
`permission-policy.json` before any operation runs, resumable jobs with sealed checkpoints,
|
|
175
|
+
and a per-decision record in the state directory.
|
|
176
|
+
- **Capability probes** (`tools/capability-registry.mjs`): `file-exists`, `dir-writable` and
|
|
177
|
+
`command` probes that report `healthy` / `unhealthy` / `unknown` with the evidence behind
|
|
178
|
+
each verdict.
|
|
179
|
+
- **Installer** (`install/`, package `agents-handoff`): `install`, `update`, `remove`,
|
|
180
|
+
`verify`, `list`, `where`, targeting a resolved global root, `./local/skills/agents-handoff`,
|
|
181
|
+
or `./skills/agents-handoff`.
|
|
182
|
+
- **Documentation site** at <https://alot1z.github.io/agent-handoff/>, built by GitHub Pages
|
|
183
|
+
from `docs/`.
|
|
184
|
+
- **CI** (`.github/workflows/ci.yml`): the test suite on Node 18, 20 and 22, a runtime-layer
|
|
185
|
+
smoke test, installer help, and a required-file and JSON-validity check.
|
|
186
|
+
|
|
187
|
+
### Security
|
|
188
|
+
|
|
189
|
+
- The engine reads transcripts and writes handoff files. It makes no network calls, and it
|
|
190
|
+
never writes secrets. The limits of what the provenance chain proves are stated in
|
|
191
|
+
[docs/PROVENANCE.md](https://github.com/Alot1z/agent-handoff/blob/main/docs/PROVENANCE.md),
|
|
192
|
+
not implied.
|
|
193
|
+
|
|
194
|
+
[Unreleased]: https://github.com/Alot1z/agent-handoff/compare/v2.0.1...main
|
|
195
|
+
[2.0.1]: https://github.com/Alot1z/agent-handoff/compare/v2.0.0...v2.0.1
|
|
196
|
+
[2.0.0]: https://github.com/Alot1z/agent-handoff/tree/v2.0.0
|