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
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agents-handoff",
|
|
3
|
+
"version": "2.0.2",
|
|
4
|
+
"description": "Internal manifest for the in-tree installer. The published package is the repository root (agents-handoff), whose bin `agents-handoff` points here.",
|
|
5
|
+
"private": true,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"agents-handoff": "./install.mjs"
|
|
9
|
+
},
|
|
10
|
+
"main": "./install.mjs",
|
|
11
|
+
"files": [
|
|
12
|
+
"install.mjs",
|
|
13
|
+
"package.json",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "node ../tools/handoff.test.mjs"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"agent-handoff",
|
|
21
|
+
"installer",
|
|
22
|
+
"npx",
|
|
23
|
+
"skill"
|
|
24
|
+
],
|
|
25
|
+
"author": "Alot1z",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/Alot1z/agent-handoff.git"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://alot1z.github.io/agent-handoff/INSTALL.html",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/Alot1z/agent-handoff/issues"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18.0.0"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {}
|
|
39
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,68 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agents-handoff",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "2.0.2",
|
|
4
|
+
"description": "Write, verify, and hand off complete AI working sessions across any harness (Claude Code, Codex, DeepSeek Harness, plain JSONL or text logs). Cross-harness session capture with sha256 provenance and verified continuation.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "tools/handoff.mjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"agents-handoff": "./install/install.mjs",
|
|
9
|
+
"agent-handoff": "./tools/handoff.mjs"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"install/",
|
|
13
|
+
"tools/",
|
|
14
|
+
"templates/",
|
|
15
|
+
"refs/",
|
|
16
|
+
"schemas/",
|
|
17
|
+
"docs/",
|
|
18
|
+
"tests/",
|
|
19
|
+
"CHANGELOG.md",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE",
|
|
22
|
+
"SKILL.md",
|
|
23
|
+
"skill.json",
|
|
24
|
+
"capability-registry.json",
|
|
25
|
+
"permission-policy.json",
|
|
26
|
+
"handoff.config.schema.json",
|
|
27
|
+
"handoff.config.example.json"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"test": "node tools/handoff.test.mjs",
|
|
31
|
+
"check:docs": "node .github/scripts/check-docs.mjs",
|
|
32
|
+
"check:session-index": "node .github/scripts/build-sessions-index.mjs --check",
|
|
33
|
+
"prepublishOnly": "node tools/handoff.test.mjs && node .github/scripts/check-docs.mjs && node .github/scripts/build-sessions-index.mjs --check",
|
|
34
|
+
"verify": "node tools/handoff.mjs verify",
|
|
35
|
+
"build": "node tools/handoff.mjs build"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"ai",
|
|
42
|
+
"agent",
|
|
43
|
+
"handoff",
|
|
44
|
+
"session",
|
|
45
|
+
"continuation",
|
|
46
|
+
"cross-harness",
|
|
47
|
+
"provenance",
|
|
48
|
+
"claude-code",
|
|
49
|
+
"codex",
|
|
50
|
+
"installer",
|
|
51
|
+
"npx",
|
|
52
|
+
"skill"
|
|
53
|
+
],
|
|
54
|
+
"author": "Alot1z",
|
|
55
|
+
"license": "MIT",
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "git+https://github.com/Alot1z/agent-handoff.git"
|
|
59
|
+
},
|
|
60
|
+
"bugs": {
|
|
61
|
+
"url": "https://github.com/Alot1z/agent-handoff/issues"
|
|
62
|
+
},
|
|
63
|
+
"homepage": "https://alot1z.github.io/agent-handoff/",
|
|
64
|
+
"engines": {
|
|
65
|
+
"node": ">=18.0.0"
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {}
|
|
68
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "1.0-permission-policy",
|
|
3
|
+
"approved_workspaces": [
|
|
4
|
+
".",
|
|
5
|
+
"repo-upstream",
|
|
6
|
+
".agent-handoff",
|
|
7
|
+
".context"
|
|
8
|
+
],
|
|
9
|
+
"system_read_only_roots": [
|
|
10
|
+
"C:\\Windows",
|
|
11
|
+
"C:\\Program Files",
|
|
12
|
+
"C:\\Program Files (x86)"
|
|
13
|
+
],
|
|
14
|
+
"personal_data_roots": [
|
|
15
|
+
"C:\\Users"
|
|
16
|
+
],
|
|
17
|
+
"denied_roots": [],
|
|
18
|
+
"grants": {
|
|
19
|
+
"DISCOVERY_ONLY": "allow",
|
|
20
|
+
"READ_ONLY": "allow",
|
|
21
|
+
"WORKSPACE_WRITE": "allow",
|
|
22
|
+
"EXTERNAL_EFFECT": "needs_auth",
|
|
23
|
+
"DESTRUCTIVE": "needs_auth",
|
|
24
|
+
"IRREVERSIBLE": "needs_auth"
|
|
25
|
+
},
|
|
26
|
+
"risk_to_level": {
|
|
27
|
+
"R0": "READ_ONLY",
|
|
28
|
+
"R1": "WORKSPACE_WRITE",
|
|
29
|
+
"R2": "EXTERNAL_EFFECT",
|
|
30
|
+
"R3": "DESTRUCTIVE",
|
|
31
|
+
"R4": "IRREVERSIBLE"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/refs/ADAPTERS.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Harness adapters — how any client feeds the handoff subsystem
|
|
2
|
+
|
|
3
|
+
No harness is special-cased in code. The engine consumes ONE canonical input shape;
|
|
4
|
+
every adapter below is just "get your store into that shape". Canonical = conversation-vault
|
|
5
|
+
raw JSONL line:
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{"seq":0,"ts":"1787669764492","harness":"dsh","source":"<origin path>",
|
|
9
|
+
"session":"<id>","thread":"<project/thread>","role":"user|assistant|system|tool",
|
|
10
|
+
"kind":"<free-form: reasoning|tool_use|text>","text":"<message body>"}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
| Harness | Store | Adapter route | Status |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| DeepSeek Harness desktop+CI | ~/.dsh/sessions/<proj>/session-*.jsonl.zstd | vault.mjs import (zstd -> canonical) then build --source canonical.jsonl | VERIFIED live (85 sessions archived 2026-08-25) |
|
|
16
|
+
| Desktop client with a SQLite session store (machine-specific path) | <client data dir>/projects/*/desktop-v2.db | vault adapter (sqlite read-only, parts_json -> turns) | VERIFIED live on a client whose turns live in a sqlite table |
|
|
17
|
+
| Claude Code | ~/.claude/projects/**/*.jsonl | vault adapter (native JSONL -> canonical) | VERIFIED live |
|
|
18
|
+
| Codex | ~/.codex/sessions/*.jsonl | generic claude-jsonl parser | OBSERVED compatible shape |
|
|
19
|
+
| CI / anything | any exported JSONL | direct: build --source file.jsonl | VERIFIED (self-test) |
|
|
20
|
+
| Plain text/markdown log | any file | role-marker fallback parser (user:> / assistant:>) | VERIFIED (self-test) |
|
|
21
|
+
|
|
22
|
+
!! Preferred route: archive through conversation-vault FIRST (vault.mjs), then point handoff.mjs
|
|
23
|
+
at the canonical raw file — lossless capture + provenance + render in one chain.
|
|
24
|
+
Direct-to-handoff also works when no vault exists.
|
|
25
|
+
|
|
26
|
+
Class mapping (engine classify()):
|
|
27
|
+
- role=tool or kind contains "tool" -> TOOL
|
|
28
|
+
- kind contains reason|think -> THOUGHT (AI-agent thoughts processing)
|
|
29
|
+
- role=user -> USER
|
|
30
|
+
- role=assistant -> AGENT
|
|
31
|
+
- everything else -> OTHER (kept in raw, omitted from render)
|
|
32
|
+
|
|
33
|
+
Secrets law (#211): no credentials/tokens ever written into handoffs — sources are chat stores only.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Bootstrap — load a handoff into a fresh session (port of choughton/llm-handoff SHARED_REPO_INIT_PROMPT)
|
|
2
|
+
|
|
3
|
+
Use this when a fresh agent session must load repository context before handling
|
|
4
|
+
a `HANDOFF.md` assignment. Replaces re-explaining setup: the next agent starts
|
|
5
|
+
working by *loading*, not by asking.
|
|
6
|
+
|
|
7
|
+
## Bootstrap order
|
|
8
|
+
|
|
9
|
+
1. Read `refs/handbook.md` (shared operating rules) — the equivalent of the source
|
|
10
|
+
HANDBOOK.
|
|
11
|
+
2. Read `refs/protocol.md` (frontmatter/status/evidence/work-packet schema).
|
|
12
|
+
3. Read `PROJECT_STATE.md` if present (durable project-state pointer).
|
|
13
|
+
4. Read the live `HANDOFF.md`.
|
|
14
|
+
5. Read the repo's `README.md` / `AGENTS.md` / architecture doc as needed.
|
|
15
|
+
6. Read only the extra files the specific assignment requires.
|
|
16
|
+
|
|
17
|
+
## State model
|
|
18
|
+
|
|
19
|
+
Agents do not share memory:
|
|
20
|
+
- `HANDOFF.md` — live routing state.
|
|
21
|
+
- `PROJECT_STATE.md` — durable project state (when the repo uses one).
|
|
22
|
+
- Git history — durable execution record.
|
|
23
|
+
|
|
24
|
+
## Fresh-session contract
|
|
25
|
+
|
|
26
|
+
A session loaded this way must:
|
|
27
|
+
- Know its **role** (`refs/roles.md`) and its exact assignment (Work Packet).
|
|
28
|
+
- Know the canonical **status enum** and the **five-field evidence block**
|
|
29
|
+
before it claims anything complete (`refs/protocol.md`).
|
|
30
|
+
- Follow the bootstrap order before touching `HANDOFF.md`.
|
|
31
|
+
|
|
32
|
+
## The operating rule
|
|
33
|
+
|
|
34
|
+
Prompts are advisory; validators and the dispatcher are authoritative. If the
|
|
35
|
+
prompt conflicts with parsed frontmatter, Git state, or repository instructions,
|
|
36
|
+
**stop and report the conflict**.
|
|
37
|
+
|
|
38
|
+
## PROJECT_STATE.md pattern (durable status pointer)
|
|
39
|
+
|
|
40
|
+
Keep it short. Detailed implementation notes go in commits/handoffs/project docs.
|
|
41
|
+
|
|
42
|
+
```markdown
|
|
43
|
+
# Project State
|
|
44
|
+
|
|
45
|
+
## Current Status
|
|
46
|
+
- **Active Epic:** none / <epic>
|
|
47
|
+
- **Current Blocker:** none / <blocker>
|
|
48
|
+
- **Active Branch:** main
|
|
49
|
+
|
|
50
|
+
## Open Followups
|
|
51
|
+
- none / <item>
|
|
52
|
+
|
|
53
|
+
## Completed Scope Ledger
|
|
54
|
+
Append one compact line per approved epic close:
|
|
55
|
+
- **<Epic Name>** - <one-line summary>. SHA `<sha>`. Verification: <checks>.
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Two files, two jobs: `HANDOFF.md` is the live state; `PROJECT_STATE.md` is the
|
|
59
|
+
durable status; Git history is the durable record of completed work.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Brief Discipline — "it's working if" (distilled from aihero.dev/skills-handoff + mattpocock/skills handoff)
|
|
2
|
+
|
|
3
|
+
mattpocock's `/handoff` buys **portability, not compression**. A handoff is a
|
|
4
|
+
transit file for work that must travel — a new harness, a new directory, a
|
|
5
|
+
colleague, or a forked side-task. When nothing is travelling, stay in the
|
|
6
|
+
session and go lighter. This checklist is the quality bar for any brief this
|
|
7
|
+
skill produces.
|
|
8
|
+
|
|
9
|
+
## When a handoff is warranted (the four triggers)
|
|
10
|
+
|
|
11
|
+
1. Swapping harness (Claude Code → Codex → DeepSeek Harness …) — the new harness can't see the old context.
|
|
12
|
+
2. Moving to a different directory/repo — a prototype is the common case.
|
|
13
|
+
3. Sending the work to a colleague — they need something readable cold.
|
|
14
|
+
4. **Forking a side-task mid-phase** — you keep working; a second agent takes the fork.
|
|
15
|
+
|
|
16
|
+
If the same harness and same directory and you're just continuing, a compact is
|
|
17
|
+
better than a handoff. Reach for this skill only when the work must travel.
|
|
18
|
+
|
|
19
|
+
## What travels, what does not
|
|
20
|
+
|
|
21
|
+
Carry:
|
|
22
|
+
- The **live thread**: what's in flight, why, and what's next.
|
|
23
|
+
- A **suggested-skills section** naming what the next agent should reach for.
|
|
24
|
+
- The **next task's focus** (pass the argument: what the next session is for).
|
|
25
|
+
|
|
26
|
+
Reference, never copy:
|
|
27
|
+
- Specs, plans, ADRs, issues, commits, diffs → by **path or URL**, not pasted text.
|
|
28
|
+
Keeps the file small and the settled detail in ONE place (no drift).
|
|
29
|
+
|
|
30
|
+
Redact:
|
|
31
|
+
- API keys, passwords, PII. Nothing in a handoff is a secret.
|
|
32
|
+
|
|
33
|
+
## "It's working if" — the acceptance test
|
|
34
|
+
|
|
35
|
+
The handoff is good when **all** hold:
|
|
36
|
+
|
|
37
|
+
- [ ] The document is a *small fraction* of the conversation, and specs/issues/diffs
|
|
38
|
+
appear as paths/URLs, not copied text.
|
|
39
|
+
- [ ] You can read it **cold**, without the original session open, and know what to do next.
|
|
40
|
+
- [ ] A fresh agent **starts working** instead of asking you to re-explain setup.
|
|
41
|
+
- [ ] In the fork case, your original session is still sitting there untouched when you return.
|
|
42
|
+
- [ ] The suggested-skills section names the skill you'd have reached for yourself.
|
|
43
|
+
- [ ] Nothing in it is a key, a token, or a password.
|
|
44
|
+
|
|
45
|
+
## The false-premise trap (downgrade before handoff)
|
|
46
|
+
|
|
47
|
+
The next agent treats the document as a **contract** and will not re-check it —
|
|
48
|
+
so a belief written as a fact becomes a false premise for everything that follows.
|
|
49
|
+
Before you hand it over: **read it and downgrade anything you only assumed.**
|
|
50
|
+
Unless a claim is oracle-backed, write it at its true evidence level
|
|
51
|
+
(INFERRED/UNKNOWN); this is the same rule as our Doctrine #3 and the KB's
|
|
52
|
+
never-silently-upgrade law.
|
|
53
|
+
|
|
54
|
+
## Handing the file to the next agent
|
|
55
|
+
|
|
56
|
+
Point at the **path**, never paste the summary into a shell command. A summary
|
|
57
|
+
containing backticks or `$(...)` gets mangled by interpolation, and the usual
|
|
58
|
+
failure is **silent truncation** — the next agent starts with a quietly
|
|
59
|
+
incomplete brief. `Read this file, then continue.`
|
|
60
|
+
|
|
61
|
+
## Handoff vs. durable docs
|
|
62
|
+
|
|
63
|
+
Ask: *is this true next month?*
|
|
64
|
+
- **CLAUDE.md / durable docs** — standing context loaded into every session. Facts that keep getting re-explained live here.
|
|
65
|
+
- **Handoff** — one piece of work in flight, dead once that work lands. A half-finished task is a handoff.
|
|
66
|
+
|
|
67
|
+
## handoff vs compact vs clear (the phase-boundary map)
|
|
68
|
+
|
|
69
|
+
| Move | What it preserves | When |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| **continue** | the primary source (conversation as it happened) | first thing to rule out; no summary needed |
|
|
72
|
+
| **/compact** | compresses context, keeps intent, fresh window | same harness, same dir, staying in the loop |
|
|
73
|
+
| **/handoff** | a portable file: the work survives the move | work must travel / fork a side-task |
|
|
74
|
+
| **/clear** | nothing — empty window | everything behind you is disposable (one-way) |
|
|
75
|
+
|
|
76
|
+
All three of compact/handoff/clear turn a primary source into a summary;
|
|
77
|
+
continuing is the only one that doesn't. Our engine's fileset gives you both:
|
|
78
|
+
the brief is the portable summary; `timeline.jsonl` + `TOOLS.md` keep the
|
|
79
|
+
fidelity so nothing is silently lost.
|
package/refs/handbook.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Handbook — shared operating rules for every role (port of choughton/llm-handoff HANDBOOK)
|
|
2
|
+
|
|
3
|
+
Read this before acting on any `HANDOFF.md` assignment. Role prompts (`refs/roles.md`)
|
|
4
|
+
add role-specific rules; this file is the shared protocol.
|
|
5
|
+
|
|
6
|
+
## How the live handoff works
|
|
7
|
+
|
|
8
|
+
`HANDOFF.md` is the **live state file**. Only the active dispatcher role owns it
|
|
9
|
+
during its turn. Provider-native subagents, skills, or helper agents are internal
|
|
10
|
+
support machinery and **must not** independently rewrite the handoff.
|
|
11
|
+
|
|
12
|
+
Two layers, always:
|
|
13
|
+
- **YAML frontmatter** for machine routing (authoritative).
|
|
14
|
+
- **Markdown body** for human-readable context, evidence, findings, and work packets.
|
|
15
|
+
|
|
16
|
+
## State model — no shared memory
|
|
17
|
+
|
|
18
|
+
Agents do not share memory. Version-controlled files are the source of truth:
|
|
19
|
+
|
|
20
|
+
- `HANDOFF.md` — the live routing state.
|
|
21
|
+
- `PROJECT_STATE.md` — the durable project-state pointer (when the repo uses one).
|
|
22
|
+
- Git history — the durable execution record.
|
|
23
|
+
|
|
24
|
+
Our engine's fileset slots into this: `timeline.jsonl` is append-only turn truth,
|
|
25
|
+
`HANDOFF.llm.json` is the machine-replayable payload, `manifest.json` carries the
|
|
26
|
+
sha256 provenance, and `TOOLS.md` holds every tool call verbatim.
|
|
27
|
+
|
|
28
|
+
## Escalation protocol
|
|
29
|
+
|
|
30
|
+
Use **one** of the canonical statuses, never a synonym:
|
|
31
|
+
|
|
32
|
+
- `escalate_to_user` + `next_agent: user` — human input required.
|
|
33
|
+
- `blocked_missing_context` — the missing input is specific and the next human
|
|
34
|
+
question is clear.
|
|
35
|
+
- `blocked_implementation_failure` — an implementation path failed structurally
|
|
36
|
+
and needs re-scoping.
|
|
37
|
+
|
|
38
|
+
## When to flag uncertainty
|
|
39
|
+
|
|
40
|
+
Stop and route to `planner`, `validator`, or `user` when **scope, ownership,
|
|
41
|
+
routing, tests, or Git state** are ambiguous. Do not widen your role boundary to
|
|
42
|
+
avoid asking. Guessing forward on ambiguous state is a protocol violation.
|
|
43
|
+
|
|
44
|
+
## The operating rule
|
|
45
|
+
|
|
46
|
+
**Prompts are advisory. Validators and the dispatcher are authoritative.**
|
|
47
|
+
If a prompt conflicts with parsed frontmatter, Git state, or repository
|
|
48
|
+
instructions, stop and report the conflict — do not silently follow the prompt.
|
|
49
|
+
|
|
50
|
+
## Common failure modes (catch these; they are your reviewers' checklist)
|
|
51
|
+
|
|
52
|
+
- Missing or malformed YAML frontmatter.
|
|
53
|
+
- Provider names (Codex/Gemini/Claude) used as public workflow roles.
|
|
54
|
+
- `scope_sha: HEAD` instead of a concrete SHA.
|
|
55
|
+
- Completion claims without `## Verification Evidence`.
|
|
56
|
+
- Planner assignments without a concrete Work Packet.
|
|
57
|
+
- Auditor approvals that skip spec compliance (phase-1).
|
|
58
|
+
- Repeated implementer/auditor bounces on the same story — signal it early.
|
package/refs/protocol.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Handoff Protocol — live dispatch state, frontmatter, status, evidence (port of choughton/llm-handoff)
|
|
2
|
+
|
|
3
|
+
> Adapted from `choughton/llm-handoff` (Apache-2.0). This fuses its file-based
|
|
4
|
+
> dispatch protocol into agent-handoff's fileset. Where our engine already
|
|
5
|
+
> existed (RESULT/WHAT_CHANGED..., sha256 manifests), this ADDS the live
|
|
6
|
+
> routing layer: a single `HANDOFF.md` file that doubles as **the mutex and the
|
|
7
|
+
> debugger** — every transition is visible as text, and a run only advances when
|
|
8
|
+
> the frontmatter parses, routes, and validates.
|
|
9
|
+
|
|
10
|
+
## The inversion (core doctrine)
|
|
11
|
+
|
|
12
|
+
> **Prompts are advisory. Validators are authoritative.**
|
|
13
|
+
|
|
14
|
+
Agents may write prose, but a run only advances when the handoff state parses,
|
|
15
|
+
routes, and validates. `HANDOFF.md` is the shared state file, `git rev-parse
|
|
16
|
+
HEAD` SHAs are the durable record of completed work, and when routing is
|
|
17
|
+
ambiguous or unsafe the run **fails closed and pauses** instead of guessing.
|
|
18
|
+
|
|
19
|
+
## Two layers of every handoff
|
|
20
|
+
|
|
21
|
+
1. **YAML frontmatter** — machine routing (authoritative; the dispatcher reads
|
|
22
|
+
this, not the prose).
|
|
23
|
+
2. **Markdown body** — human/agent-readable context, evidence, findings, and
|
|
24
|
+
work packets.
|
|
25
|
+
|
|
26
|
+
## Required frontmatter schema
|
|
27
|
+
|
|
28
|
+
Every `HANDOFF.md` write begins with YAML frontmatter. The YAML block is
|
|
29
|
+
authoritative; prose is context.
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
---
|
|
33
|
+
next_agent: <enum> # required: planner | backend | frontend | auditor | validator | finalizer | user
|
|
34
|
+
reason: <string> # required: quote every `reason` value
|
|
35
|
+
epic_id: <string> # optional active epic identifier
|
|
36
|
+
story_id: <string> # optional active story identifier
|
|
37
|
+
story_title: <string> # optional short active story title
|
|
38
|
+
remaining_stories: # optional remaining story IDs/titles
|
|
39
|
+
- <story id/title>
|
|
40
|
+
status: <enum> # canonical status when the handoff claims completion/blockage
|
|
41
|
+
bounce_count: 0 # optional dispatcher-maintained retry count
|
|
42
|
+
evidence_present: true # optional validator hint for evidence-aware handoffs
|
|
43
|
+
scope_sha: <git SHA> # required when close_type is story|epic; concrete 7-40 hex, NEVER "HEAD"
|
|
44
|
+
close_type: <enum> # optional: story | epic
|
|
45
|
+
prior_sha: <git SHA> # optional prior verified SHA
|
|
46
|
+
producer: <string> # required: the role that wrote this handoff
|
|
47
|
+
---
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Hard rules:
|
|
51
|
+
- **Quote every `reason`.**
|
|
52
|
+
- **Run `git rev-parse HEAD`** for concrete SHAs; never write `scope_sha: HEAD`,
|
|
53
|
+
a branch name, or a placeholder.
|
|
54
|
+
- `scope_sha` must be a 7–40 char hex SHA that `git cat-file -t` resolves.
|
|
55
|
+
|
|
56
|
+
## Status enum (canonical — no synonyms)
|
|
57
|
+
|
|
58
|
+
Use exactly one. Do **not** invent `done`, `approved`, or `blocked`.
|
|
59
|
+
|
|
60
|
+
| Status | Meaning | Typical emitter |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `ready_for_review` | Implementation complete, needs audit | backend, frontend |
|
|
63
|
+
| `verified_pass` | Auditor verified assignment + quality gates | auditor |
|
|
64
|
+
| `verified_fail` | Auditor found a defect; routes back to implementer | auditor |
|
|
65
|
+
| `blocked_missing_context` | Cannot proceed without more info | any role |
|
|
66
|
+
| `blocked_implementation_failure` | Implementation attempted but structurally failed | backend, frontend |
|
|
67
|
+
| `escalate_to_user` | Human decision required | any role |
|
|
68
|
+
|
|
69
|
+
Maps to our engine's RESULT values: `ready_for_review`→*needs review*, `verified_pass`→`DONE`, `verified_fail`→*returned*, `blocked_*`→`BLOCKED`, `escalate_to_user`→*needs human*. The two vocabularies coexist: the enum is the routing state, the RESULT is the completion contract.
|
|
70
|
+
|
|
71
|
+
## Verification Evidence block (required for completion statuses)
|
|
72
|
+
|
|
73
|
+
Required when `status` is `ready_for_review`, `verified_pass`, or `verified_fail`.
|
|
74
|
+
Exact five-field shape:
|
|
75
|
+
|
|
76
|
+
```markdown
|
|
77
|
+
## Verification Evidence
|
|
78
|
+
|
|
79
|
+
- **Commands run:** verbatim command lines
|
|
80
|
+
- **Output summary:** one line per command with exit codes
|
|
81
|
+
- **Commit SHA verified:** concrete 7-40 char Git SHA; never `HEAD`
|
|
82
|
+
- **Files changed or reviewed:** relative paths
|
|
83
|
+
- **Unresolved concerns:** list or `none`
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Evidence must come from the current turn.** Prior output, assumptions, and
|
|
87
|
+
model confidence are not evidence. This is the same law as our
|
|
88
|
+
RESULT-without-EVIDENCE-never-becomes-VERIFIED.
|
|
89
|
+
|
|
90
|
+
## Work Packet (planner → backend/frontend)
|
|
91
|
+
|
|
92
|
+
Planner assignments include exactly these six fields:
|
|
93
|
+
|
|
94
|
+
```markdown
|
|
95
|
+
## Work Packet
|
|
96
|
+
|
|
97
|
+
- **Objective:** one bounded result
|
|
98
|
+
- **Files in scope:** relative paths
|
|
99
|
+
- **Files out of bounds:** relative paths or `none` ← never omit, even "none"
|
|
100
|
+
- **Context:** required reading or background
|
|
101
|
+
- **Verification command:** exact command to run
|
|
102
|
+
- **Expected next route:** role after success
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Never use vague placeholders: `add validation`, `handle errors appropriately`,
|
|
106
|
+
`write tests`, `implement later`, `as needed`. Rewrite them into concrete
|
|
107
|
+
acceptance checks, exact files, and specific verification commands.
|
|
108
|
+
|
|
109
|
+
## Common failure modes to catch
|
|
110
|
+
|
|
111
|
+
- Missing or malformed YAML frontmatter.
|
|
112
|
+
- Provider names (Codex/Gemini/Claude) used as public workflow roles — translate to the public role.
|
|
113
|
+
- `scope_sha: HEAD` instead of a concrete SHA.
|
|
114
|
+
- Completion claims without `## Verification Evidence`.
|
|
115
|
+
- Planner assignments without a concrete work packet.
|
|
116
|
+
- Auditor approvals that skip spec compliance.
|
|
117
|
+
- Repeated implementer/auditor bounces on the same story.
|
package/refs/roles.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Roles — the dispatch ladder (port of choughton/llm-handoff role prompts)
|
|
2
|
+
|
|
3
|
+
The public `next_agent` enum is: `planner | backend | frontend | auditor |
|
|
4
|
+
validator | finalizer | user`. Provider names (Codex/Gemini/Claude) are only
|
|
5
|
+
*adapter examples* — an agent filling a role is addressed by its public role,
|
|
6
|
+
never by a model/harness name.
|
|
7
|
+
|
|
8
|
+
Every role follows the same bootstrap before acting (see `refs/bootstrap.md`)
|
|
9
|
+
and holds the shared rules of `refs/handbook.md`.
|
|
10
|
+
|
|
11
|
+
## planner — sequence the work, never implement
|
|
12
|
+
|
|
13
|
+
- Translate project goals into **bounded assignments** with concrete Work Packets
|
|
14
|
+
(see `refs/protocol.md`).
|
|
15
|
+
- Decide the next role. Route backends/data to `backend`, UI to `frontend`,
|
|
16
|
+
completed work needing review to `auditor`, ambiguous/wrong state to `validator`,
|
|
17
|
+
human input to `user`, and `finalizer` only for an approved epic close.
|
|
18
|
+
- Never `git push`. Never write `scope_sha: HEAD`.
|
|
19
|
+
- **Work Packet discipline:** every line must be a concrete acceptance check,
|
|
20
|
+
an exact file, or a specific verification command. Vague placeholders are a defect.
|
|
21
|
+
|
|
22
|
+
## backend — own server/data/CLI/integration work
|
|
23
|
+
|
|
24
|
+
- Owns backend code, data contracts, persistence, CLI glue, tests, integration wiring.
|
|
25
|
+
- Does NOT own frontend-only work, planning, audit verdicts, or finalizer state.
|
|
26
|
+
- On a misroute, rewrite the handoff and route to `planner`/`validator`/`user`
|
|
27
|
+
instead of expanding scope. Do not modify `PROJECT_STATE.md` unless assigned.
|
|
28
|
+
- On completion: route to `auditor`, `status: ready_for_review`, and include the
|
|
29
|
+
`## Verification Evidence` block with a concrete `scope_sha`.
|
|
30
|
+
|
|
31
|
+
## frontend — own UI/browser work
|
|
32
|
+
|
|
33
|
+
- Mirrors `backend` but for UI/browser/app-code. Same roles, evidence, and
|
|
34
|
+
completion contract.
|
|
35
|
+
|
|
36
|
+
## auditor — review, enforce invariants, never silently fix
|
|
37
|
+
|
|
38
|
+
- Two-phase audit:
|
|
39
|
+
1. **Phase 1 — spec compliance:** verify the producer did *exactly* the
|
|
40
|
+
assigned work. Catch missing scope, scope creep, unrequested extras, wrong
|
|
41
|
+
files. **If phase 1 fails, stop** — emit `status: verified_fail`, route
|
|
42
|
+
back to the implementer or `planner`, and give NO code-quality feedback for
|
|
43
|
+
work that does not match the assignment.
|
|
44
|
+
2. **Phase 2 — code quality** (only after phase 1 passes): correctness,
|
|
45
|
+
maintainability, tests, safety, repository fit.
|
|
46
|
+
- Story-level success → `planner`/next implementer; epic-level success → `finalizer`.
|
|
47
|
+
- Never claim `verified_pass` without the `## Verification Evidence` block.
|
|
48
|
+
|
|
49
|
+
## validator — repair and gate (the authoritative check)
|
|
50
|
+
|
|
51
|
+
- A support role that inspects `HANDOFF.md` and reports whether the loop can
|
|
52
|
+
continue **safely**. Does not edit the handoff, re-route, implement, commit, or push.
|
|
53
|
+
- Runs the 12-point check — see `refs/validator.md`.
|
|
54
|
+
- Outcome: `VALID: YES | NO | WARNINGS-ONLY`. Only a FAIL makes `VALID: NO`;
|
|
55
|
+
the loop must not advance on `NO`.
|
|
56
|
+
|
|
57
|
+
## finalizer — close an approved epic
|
|
58
|
+
|
|
59
|
+
- Clears an approved epic-level close (`close_type: epic` only), updates the
|
|
60
|
+
durable `PROJECT_STATE.md` when the repo uses one, rewrites the handoff to route
|
|
61
|
+
the next cycle to `planner` or `user`, and reports a machine-readable result.
|
|
62
|
+
- `next_agent: finalizer` must never persist after finalization.
|
|
63
|
+
- Does not scope the next epic; does not push unless the repo authorizes that role.
|
|
64
|
+
|
|
65
|
+
## user — the human gate
|
|
66
|
+
|
|
67
|
+
- Used when a human decision, credentials, or an unsafe ambiguity is required.
|
|
68
|
+
- The router's escape hatch: when route evidence is insufficient, set
|
|
69
|
+
`next_agent: user` and ask ONE concrete question in the body.
|
|
70
|
+
|
|
71
|
+
## Role boundary doctrine
|
|
72
|
+
|
|
73
|
+
Never widen your role boundary to avoid asking. If scope, ownership, routing,
|
|
74
|
+
tests, or Git state is ambiguous, route to `planner`, `validator`, or `user`. Do
|
|
75
|
+
not guess forward — that is the fail-closed rule made concrete.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Validator Gate — the authoritative check (port of choughton/llm-handoff handoff-validator)
|
|
2
|
+
|
|
3
|
+
The validator is the **authoritative** half of "prompts are advisory, validators
|
|
4
|
+
are authoritative." It inspects the live `HANDOFF.md` routing state and reports
|
|
5
|
+
whether the loop can continue safely. It does **not** modify the handoff,
|
|
6
|
+
re-route the work, implement code, commit, or push.
|
|
7
|
+
|
|
8
|
+
## Routing contract (how ambiguity resolves)
|
|
9
|
+
|
|
10
|
+
| Situation | next_agent |
|
|
11
|
+
|---|---|
|
|
12
|
+
| Backend/data/CLI/integration implementation | `backend` |
|
|
13
|
+
| UI/frontend implementation | `frontend` |
|
|
14
|
+
| Planning, scope decomposition, next-story assignment | `planner` |
|
|
15
|
+
| Completed implementation needing review | `auditor` |
|
|
16
|
+
| Approved final scope, `close_type: epic` only | `finalizer` |
|
|
17
|
+
| Broken/malformed/internally-inconsistent handoff state | `validator` |
|
|
18
|
+
| Missing human decision, missing credentials, unsafe ambiguity | `user` |
|
|
19
|
+
|
|
20
|
+
If the handoff names a provider (Codex/Gemini/Claude), translate it to the public
|
|
21
|
+
role it is serving in this repo. When route evidence is insufficient, set
|
|
22
|
+
`next_agent: user` and ask one concrete question — **never guess.**
|
|
23
|
+
|
|
24
|
+
## The 12-point check
|
|
25
|
+
|
|
26
|
+
Ordered. Each item is `PASS | WARN | FAIL` with a one-line detail:
|
|
27
|
+
|
|
28
|
+
1. YAML frontmatter exists at the top of `HANDOFF.md`.
|
|
29
|
+
2. Frontmatter parses as YAML.
|
|
30
|
+
3. `next_agent` is one of the public enum.
|
|
31
|
+
4. `reason` is present, non-empty, and quoted when it contains punctuation.
|
|
32
|
+
5. `close_type`, when present, is `story` or `epic`.
|
|
33
|
+
6. `scope_sha` is present when `close_type` is set.
|
|
34
|
+
7. `scope_sha` and `prior_sha`, when present, are 7–40 char hex and resolve via
|
|
35
|
+
`git cat-file -t <sha>`.
|
|
36
|
+
8. `finalizer` routing is used only with `close_type: epic`.
|
|
37
|
+
9. `status`, when present, is a canonical enum value.
|
|
38
|
+
10. Completion statuses include the `## Verification Evidence` block.
|
|
39
|
+
11. The body has enough detail to act on: files, checks, findings, ACs.
|
|
40
|
+
12. Current git state is compatible with the handoff claim — report dirty state
|
|
41
|
+
as WARN unless the repo requires clean state.
|
|
42
|
+
|
|
43
|
+
## Output shape (Machine-Readable Result)
|
|
44
|
+
|
|
45
|
+
Return exactly:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
VALID: YES | NO | WARNINGS-ONLY
|
|
49
|
+
CHECKS:
|
|
50
|
+
FRONTMATTER: PASS | WARN | FAIL - <detail>
|
|
51
|
+
SHA-PRESENT: PASS | WARN | FAIL - <detail>
|
|
52
|
+
SHA-FRESH: PASS | WARN | FAIL - <detail>
|
|
53
|
+
ROUTING: PASS | WARN | FAIL - <detail>
|
|
54
|
+
CONTENT: PASS | WARN | FAIL - <detail>
|
|
55
|
+
GIT-STATE: PASS | WARN | FAIL - <detail>
|
|
56
|
+
SUMMARY: <one sentence>
|
|
57
|
+
BLOCKERS: <numbered list if VALID=NO, otherwise "none">
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Only a FAIL makes `VALID: NO`. WARN-only results use `VALID: WARNINGS-ONLY`.
|
|
61
|
+
A handoff that is `NO` or `WARNINGS-ONLY` must **not** advance the run — fail
|
|
62
|
+
closed, never guess forward.
|
|
63
|
+
|
|
64
|
+
## Router summary (when this role is exercised as a router)
|
|
65
|
+
|
|
66
|
+
The router variant *does* rewrite the handoff to make routing deterministic.
|
|
67
|
+
After writing, it returns:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
ROUTING UPDATED: YES
|
|
71
|
+
NEXT_AGENT: <role>
|
|
72
|
+
REASON: <one sentence>
|
|
73
|
+
```
|