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.
Files changed (54) hide show
  1. package/CHANGELOG.md +150 -0
  2. package/LICENSE +21 -0
  3. package/README.md +110 -2
  4. package/SKILL.md +147 -0
  5. package/capability-registry.json +27 -0
  6. package/docs/ARCHITECTURE.md +164 -0
  7. package/docs/CHANGELOG.md +151 -0
  8. package/docs/CLI.md +196 -0
  9. package/docs/COMPATIBILITY.md +124 -0
  10. package/docs/CONTRIBUTING.md +134 -0
  11. package/docs/FORMAT.md +157 -0
  12. package/docs/INSTALL.md +179 -0
  13. package/docs/INTEGRATION.md +188 -0
  14. package/docs/LEVEL4.md +202 -0
  15. package/docs/LEVEL5.md +96 -0
  16. package/docs/PERMISSIONS.md +145 -0
  17. package/docs/PROVENANCE.md +83 -0
  18. package/docs/SECURITY.md +93 -0
  19. package/docs/SESSIONS.md +66 -0
  20. package/docs/TROUBLESHOOTING.md +158 -0
  21. package/docs/UNINSTALL.md +122 -0
  22. package/docs/UPGRADE.md +139 -0
  23. package/docs/_config.yml +16 -0
  24. package/docs/_data/nav.yml +36 -0
  25. package/docs/_layouts/default.html +31 -0
  26. package/docs/assets/style.css +88 -0
  27. package/docs/index.md +83 -0
  28. package/handoff.config.example.json +35 -0
  29. package/handoff.config.schema.json +117 -0
  30. package/install/CHANGELOG.md +48 -0
  31. package/install/README.md +76 -0
  32. package/install/install.mjs +856 -0
  33. package/install/package.json +39 -0
  34. package/package.json +66 -4
  35. package/permission-policy.json +33 -0
  36. package/refs/ADAPTERS.md +33 -0
  37. package/refs/bootstrap.md +59 -0
  38. package/refs/brief-checklist.md +79 -0
  39. package/refs/handbook.md +58 -0
  40. package/refs/protocol.md +117 -0
  41. package/refs/roles.md +75 -0
  42. package/refs/validator.md +73 -0
  43. package/schemas/handoff.schema.json +275 -0
  44. package/skill.json +147 -0
  45. package/templates/HANDOFF.llm.schema.json +144 -0
  46. package/templates/HANDOFF.template.md +40 -0
  47. package/tests/acceptance/acceptance.yaml +209 -0
  48. package/tests/fixtures/minimal-transcript.jsonl +2 -0
  49. package/tools/agent-handoff.mjs +410 -0
  50. package/tools/capability-registry.mjs +120 -0
  51. package/tools/handoff.mjs +398 -0
  52. package/tools/handoff.test.mjs +465 -0
  53. package/tools/lib/handoff-root.mjs +161 -0
  54. 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": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
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
+ }
@@ -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.
@@ -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.
@@ -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
+ ```