From a4a399b75920902c5e156dd0d4061cb1d145242a Mon Sep 17 00:00:00 2001 From: "vanillagreen-fleet-lanes[bot]" <328550061+vanillagreen-fleet-lanes[bot]@users.noreply.github.com> Date: Sun, 18 Oct 2026 10:25:14 +0000 Subject: [PATCH] chore: refresh kendex renders --- .agents/skills/bot-instructions/SKILL.md | 6 +- .../bot-instructions/schemas/renders.md | 6 +- .../bot-instructions/schemas/validators.md | 2 + .../bot-instructions/scripts/bot-instructions | 2 +- .../bot-instructions/scripts/lib/cli.py | 34 +- .../bot-instructions/scripts/lib/render.py | 31 +- .../scripts/lib/render_markdown.py | 8 +- .../bot-instructions/scripts/lib/run.py | 40 +- .../bot-instructions/scripts/lib/spec.py | 7 +- .../scripts/lib/validators_repo.py | 10 +- .../bot-instructions/scripts/lib/verbs.py | 46 +- .../bot-instructions/scripts/lib/writer.py | 6 +- .agents/skills/communication/SKILL.md | 2 +- .../communication/references/messages.md | 16 +- .../communication/references/questions.md | 8 +- .../communication/references/reports.md | 24 +- .agents/skills/mailbox/scripts/lane-mail | 44 +- .../skills/orch/scripts/lib/adapters/codex.sh | 7 +- .claude/hooks/lane-mail-check.sh | 42 +- .codex/hooks/lane-mail-check.sh | 42 +- .github/hooks/lane-mail-check.sh | 42 +- .kendex-lock.json | 530 +++++++++--------- .pi/kendex/hooks/lane-mail-check.sh | 42 +- 23 files changed, 590 insertions(+), 407 deletions(-) diff --git a/.agents/skills/bot-instructions/SKILL.md b/.agents/skills/bot-instructions/SKILL.md index 03a3905a..5d167a99 100644 --- a/.agents/skills/bot-instructions/SKILL.md +++ b/.agents/skills/bot-instructions/SKILL.md @@ -42,7 +42,9 @@ repo-effects: .agents/skills/bot-instructions/scripts/bot-instructions retire # revoke kendex automatic rendering on removal ``` -Flags: `--repo`, `--spec`, `--staged`, `--dry-run`; `bot-instructions --help`. Python 3.11+. +Flags: `--repo`, `--spec`, `--staged`, `--output full|local`, `--dry-run`; `bot-instructions --help`. Python 3.11+. + +`--output local` limits `render`, `check` and `adopt` to the `AGENTS.md` review region. The doctrine loader selects `SKILL.md` or `SKILL.md.disabled`. The pointer uses that filename and the `#doctrine` anchor inside the selected checkout installation. Checkout parent paths resolve through their symlinks. The installation's own symlink keeps its checkout path. Source reads use its canonical target. An external `--spec` needs a matching selected installation inside the checkout. Otherwise local mode refuses: use `--output full` or install the package inside the checkout. Remote files are excluded from validation, adoption, writes, orphan removal and ownership reports. Local review reads the package doctrine directly; repository doctrine overrides remain in the full render. The default `--output full` keeps every enabled bot output. `adopt --dry-run` reports the content to take over and its divergence, writes no marker, and refuses symlinked targets. Exit codes: 0 clean, 1 findings, 2 could not complete. An unconfigured repository follows [schemas/validators.md](schemas/validators.md) § `orphan`, including its empty JSON ownership report. The `commit-guards` chain runs `check --staged` itself where this package is installed. A pre-commit lane blocks on nonzero codes, except an older check's `unconfigured` refusal carrying its `renders=none` attestation. @@ -76,7 +78,7 @@ The generator owns only the `AGENTS.md` § Code Review Rules region and never cr ## The doctrine lives in one file per repo -`[bot-instructions.bots] codex` writes the complete doctrine to `[bot-instructions.repo] code_review_path`, which defaults to `.github/instructions/code-review.md`, and writes the `AGENTS.md` owned region as one directive line naming it. A longer region is a finding: `adopt` reports it under `agents-region` and still writes the marker, `check` reports it under `drift`, and `render` replaces it. A repo migrates by rendering. Body and bounds: [schemas/renders.md](schemas/renders.md) § `code-review.md`. +In full mode, `[bot-instructions.bots] codex` writes the complete doctrine to `[bot-instructions.repo] code_review_path`, which defaults to `.github/instructions/code-review.md`, and writes the `AGENTS.md` owned region as one directive line naming it. A longer region is a finding: `adopt` reports it under `agents-region` and still writes the marker unless `--dry-run` is set, `check` reports it under `drift`, and `render` replaces it. A repo migrates by rendering. Body and bounds: [schemas/renders.md](schemas/renders.md) § `code-review.md`. **No vendor page documents a bot following an in-file reference.** CodeRabbit's `code_guidelines.filePatterns` is a real load, so its doctrine is not at issue; Codex and Copilot reach the pointed file only by opening what the directive names, and a bot that does not reviews with no repo rules at all. A repo enabling `codex` renders a canary to find out — one harmless rule that is exclusive among the files the bot under test reads, so its appearance in a comment proves the comment was written against the pointed file. A `[bot-instructions.doctrine.append]` on a block the `copilot-instructions.md` routing column does not carry gives that exclusivity for Codex and Copilot, which read no other file carrying that block; [schemas/renders.md](schemas/renders.md) § Doctrine routing note (b) defines that column. An append to a block the column does carry, today `severity`, is not a Copilot canary: Copilot loads `copilot-instructions.md` itself, so the append can appear in its comments without Copilot following the pointer. No append is exclusive in general, since an append reaches every destination its block routes to, Qodo's and Macroscope's included. [references/limits.md](references/limits.md) § GitHub Copilot code review carries the evidence and the failure mode. diff --git a/.agents/skills/bot-instructions/schemas/renders.md b/.agents/skills/bot-instructions/schemas/renders.md index f33e0b16..cc4c8d3c 100644 --- a/.agents/skills/bot-instructions/schemas/renders.md +++ b/.agents/skills/bot-instructions/schemas/renders.md @@ -2,6 +2,8 @@ One section per output. Each names the exact path, what the generator owns inside it, which doctrine blocks it carries and in what order, and how repo text from `[bot-instructions]` is escaped into that file's syntax. +Whole-file outputs in this reference apply to full mode. SKILL.md documents local mode and its installed-doctrine pointer. + Doctrine block ids are the `###` headings of the doctrine source, whose parse rule is SKILL.md § Doctrine. The routing table below is the only other place they are written down, and `doctrine-routing` holds the two to the same set. ## Common rules @@ -119,9 +121,9 @@ If you are a review agent reviewing code, read before you com No doctrine block reaches this region, so the routing table has no column for it. Every harness loads this file at the start of every session, in this repo and in every repo the package renders, and a working session never uses the review rules; what the region owes a review agent is the name of the file that holds them. -**Any longer region is a finding**, so a repo cannot keep the doctrine here by hand. `adopt` reports one under `agents-region` and still writes the marker, because the marker is what makes the repair a single `render`. `check` reports one under `drift`, which holds the region against a fresh render and is that comparison's only owner. `render` replaces it, which is the migration. +**Any longer region is a finding**, so a repo cannot keep the doctrine here by hand. `adopt` reports one under `agents-region` and writes the marker unless `--dry-run` is set, because the marker is what makes the repair a single `render`. `check` reports one under `drift`, which holds the region against a fresh render and is that comparison's only owner. `render` replaces it, which is the migration. -**Escaping.** Nothing is interpolated but the configured path, whose class `repo-toml.md` § `[bot-instructions.repo]` fixes. No doctrine or repo string reaches this region at all, so the heading predicate has nothing to do here; the surfaces it protects are the whole-file markdown outputs those strings do reach, which `repo-toml.md` § Render-side second checks names. +**Escaping.** Full mode interpolates only the configured path, whose class `repo-toml.md` § `[bot-instructions.repo]` fixes. Local mode uses the selected installation's checkout path and Doctrine anchor, under SKILL.md's `--output local` contract. No doctrine or repo string reaches this region at all, so the heading predicate has nothing to do here; the surfaces it protects are the whole-file markdown outputs those strings do reach, which `repo-toml.md` § Render-side second checks names. ## `code-review.md` diff --git a/.agents/skills/bot-instructions/schemas/validators.md b/.agents/skills/bot-instructions/schemas/validators.md index b8228eec..1c812c94 100644 --- a/.agents/skills/bot-instructions/schemas/validators.md +++ b/.agents/skills/bot-instructions/schemas/validators.md @@ -4,6 +4,8 @@ Every bot in this set fails silently. A rejected config, a mistyped enum, an exc So each validator below names the silent failure it exists to catch, then what it rejects. A failure fails the run; none of them warns. Which tree each one reads, and which verb runs it, is § Where these run, and it is not the same answer for all of them. +Remote-file validation below applies to full mode. Local mode judges the `AGENTS.md` region only, as SKILL.md defines. + **No validator parses a render back.** One whose input is bytes this run emitted checks the emitter against itself and needs a reader for every format this package writes. The structure is in hand before it is serialised, so a validator that judges a document reads that structure. What is left to judge on bytes is size, which has no pre-emission form. A validator whose input is the REPO's own files is a different thing: `orphan`, `drift` and `agents-section` are it. ## Controls diff --git a/.agents/skills/bot-instructions/scripts/bot-instructions b/.agents/skills/bot-instructions/scripts/bot-instructions index 47bb73d1..d16bcf99 100755 --- a/.agents/skills/bot-instructions/scripts/bot-instructions +++ b/.agents/skills/bot-instructions/scripts/bot-instructions @@ -9,7 +9,7 @@ # check with what it already has. set -euo pipefail -here="$(cd -- "$(dirname -- "$0")" && pwd -P)" +here="$(cd -- "$(dirname -- "$0")" && pwd -L)" if ! command -v python3 >/dev/null 2>&1; then echo "bot-instructions: python3=missing" >&2 diff --git a/.agents/skills/bot-instructions/scripts/lib/cli.py b/.agents/skills/bot-instructions/scripts/lib/cli.py index 1f0d3b7a..34f0b7c2 100644 --- a/.agents/skills/bot-instructions/scripts/lib/cli.py +++ b/.agents/skills/bot-instructions/scripts/lib/cli.py @@ -82,7 +82,9 @@ def parser(): help="read the index rather than the working tree, for every render input as " "well as the outputs, so a pre-commit lane judges one coherent state", ) - p.add_argument("--dry-run", action="store_true", help="render: validate and write nothing") + p.add_argument("--output", choices=("full", "local"), default="full", + help="render, check, adopt: full bot files (default), or only the local AGENTS.md region") + p.add_argument("--dry-run", action="store_true", help="render, adopt: preview and write nothing") p.add_argument("--json", action="store_true", help="check: report verified whole-file paths as JSON") p.add_argument("--input", default=None, help=argparse.SUPPRESS) return p @@ -94,6 +96,22 @@ def running_copy(): return os.path.dirname(os.path.dirname(os.path.dirname(here))) +def _installed_spec(repo, named, spec_root): + """Keep the selected checkout installation, including a package-store symlink. + + The launcher can select that installation when an explicit canonical + --spec names the same package. Source reads still use spec_root. + """ + invoked = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + for candidate in (os.path.abspath(named) if named else invoked, invoked): + # Resolve checkout aliases while retaining the installation's own link. + candidate = os.path.join(os.path.realpath(os.path.dirname(candidate)), os.path.basename(candidate)) + relative = os.path.relpath(candidate, repo) + if relative.split(os.sep)[0] != os.pardir and os.path.realpath(candidate) == spec_root: + return candidate + return None + + def _region_bounds(path): """Report the package-owned body span for one host-supplied snapshot.""" try: @@ -147,11 +165,9 @@ def main(argv=None): print("--staged is a check mode; render and adopt write the working tree", file=sys.stderr) return 2 - if args.dry_run and args.verb != "render": - # `adopt` is the one-time verb that writes, so a flag it accepted and - # ignored would take the files over on a run meant to preview. + if args.dry_run and args.verb not in ("render", "adopt"): print("bot-instructions: usage=--dry-run", file=sys.stderr) - print(f"--dry-run is a render mode; {args.verb} does not write a set to preview", + print(f"--dry-run belongs to render and adopt; {args.verb} does not write a set to preview", file=sys.stderr) return 2 if args.verb == "retire": @@ -169,10 +185,14 @@ def main(argv=None): try: work = tree.open_tree(repo, args.staged) spec_tree, spec_paths = _spec_source(repo, spec_root, work, args.staged) + installed_spec = _installed_spec(repo, args.spec, spec_root) launcher = os.path.join(package_root, "scripts", "bot-instructions") + if args.output == "local" and installed_spec is not None: + launcher = os.path.join(installed_spec, "scripts", "bot-instructions") ctx = run.Context(repo, work, spec_tree, spec_paths, "render" if args.verb == "render" else "check", - spec_names=SPEC_FILES, launcher=launcher) + spec_names=SPEC_FILES, launcher=launcher, output_mode=args.output, + installed_spec=installed_spec) if isinstance(ctx.config, Unconfigured): if args.verb == "adopt": raise ctx.config @@ -183,7 +203,7 @@ def main(argv=None): elif args.verb == "check": lines = verbs.check_verb(ctx) else: - lines = verbs.adopt_verb(ctx, repo) + lines = verbs.adopt_verb(ctx, repo, dry_run=args.dry_run) except ValidationFailed as exc: for line in exc.report: print(line) diff --git a/.agents/skills/bot-instructions/scripts/lib/render.py b/.agents/skills/bot-instructions/scripts/lib/render.py index 009c81c6..9b685932 100644 --- a/.agents/skills/bot-instructions/scripts/lib/render.py +++ b/.agents/skills/bot-instructions/scripts/lib/render.py @@ -14,7 +14,7 @@ class Build: - def __init__(self, model, files, data, region_body): + def __init__(self, model, files, data, region_body, output_mode="full"): self.model = model self.files = files # repo-relative path -> text # The structure each of those paths was serialised FROM, for the @@ -23,18 +23,31 @@ def __init__(self, model, files, data, region_body): # itself, and would need a reader for every format this writes. self.data = data # repo-relative path -> structure self.region_body = region_body # None when [bot-instructions.bots] codex is false + self.remote = output_mode == "full" + self.schema = None + self.review_path = None + def command(self, verb): + """Keep repair and retry commands in this build's output selection.""" + return verb if self.remote else f"{verb} --output local" -def build(model, schema=None): - """The scratch tree. `schema` is the vendored CodeRabbit schema, already - read under `coderabbit-schema`'s own clause: reading it again here would - report a second failure as a `toml-schema` finding at - `[bot-instructions]`.""" + +def build(model, schema=None, output_mode="full", schema_loader=None, local_review_path=None): + """The selected scratch tree. Load the remote schema only when needed; + the context's loader attributes its failures to `coderabbit-schema`.""" bots = model.config.bots files, data = {}, {} - region = None + result = Build(model, files, data, None, output_mode) + # Local review reads the installed doctrine directly. It must not point + # at the remote doctrine file this output set deliberately leaves alone. + result.review_path = model.code_review_path if result.remote else local_review_path if bots["codex"]: - region = render_markdown.agents_region_body(model) + result.region_body = render_markdown.agents_region_body(model, result.review_path) + if not result.remote: + return result + if bots["coderabbit"] and schema is None and schema_loader is not None: + schema = schema_loader() + result.schema = schema if bots["copilot"]: files[".github/copilot-instructions.md"] = render_markdown.copilot_instructions(model) for surface in model.surfaces: @@ -79,7 +92,7 @@ def build(model, schema=None): "file, and only the later one would survive" ) files[path] = render_markdown.code_review(model) - return Build(model, files, data, region) + return result def load_schema(tree): diff --git a/.agents/skills/bot-instructions/scripts/lib/render_markdown.py b/.agents/skills/bot-instructions/scripts/lib/render_markdown.py index abcb20e3..365f3ada 100644 --- a/.agents/skills/bot-instructions/scripts/lib/render_markdown.py +++ b/.agents/skills/bot-instructions/scripts/lib/render_markdown.py @@ -67,17 +67,17 @@ def block_paragraphs(model, bid, text): return paragraphs(text) -def agents_directive(model): +def agents_directive(model, path=None): """The one line the owned region carries below its marker. Read twice: the render writes it, and `adopt` asks whether the region it found is already this. A second spelling there would let a region pass the adopt report and still differ from what `render` writes. """ - return AGENTS_DIRECTIVE.format(path=model.code_review_path) + return AGENTS_DIRECTIVE.format(path=path or model.code_review_path) -def agents_region_body(model): +def agents_region_body(model, path=None): """The body the write phase splices under the `## Code Review Rules` line. The marker and the directive, and no doctrine at all. Every harness loads @@ -85,7 +85,7 @@ def agents_region_body(model): the review rules, so what the region carries is the pointer to the file that does. """ - return "\n".join([model.marker("html"), "", agents_directive(model), ""]) + return "\n".join([model.marker("html"), "", agents_directive(model, path), ""]) def code_review(model): diff --git a/.agents/skills/bot-instructions/scripts/lib/run.py b/.agents/skills/bot-instructions/scripts/lib/run.py index fc04fee4..a90335fe 100644 --- a/.agents/skills/bot-instructions/scripts/lib/run.py +++ b/.agents/skills/bot-instructions/scripts/lib/run.py @@ -12,10 +12,11 @@ """ import contextlib +import os from .constants import CODERABBIT_SCHEMA_PATH from . import manifest -from .errors import (Finding, InputError, ManifestError, SourceUnavailable, +from .errors import (Finding, InputError, ManifestError, SourceUnavailable, SpecError, Unconfigured, ValidationFailed) from . import config as config_mod from . import model as model_mod @@ -63,7 +64,8 @@ def _as_finding(validator, path, other=None, other_path=None): class Context: - def __init__(self, root, tree, spec_tree, spec_paths, verb, spec_names, launcher): + def __init__(self, root, tree, spec_tree, spec_paths, verb, spec_names, launcher, + output_mode="full", installed_spec=None): # `spec_paths` is how the spec copy is READ; `spec_names` is how the # marker records it. They differ under `--staged`, where the spec copy # is read from the index at its repo-relative path, and wherever the @@ -82,20 +84,33 @@ def __init__(self, root, tree, spec_tree, spec_paths, verb, spec_names, launcher config_path = resolved.chosen if "bot-instructions" not in resolved.data: # `validators.md` § `orphan`, the no-table case. - stranded = vr.unconfigured_orphans(tree, config_path) + self.build = render_mod.Build(None, {}, {}, None, output_mode) + stranded = vr.unconfigured_orphans(tree, config_path, self.build.remote) if stranded: raise ValidationFailed(stranded) # The orphan scan proves this empty result. Keep it as the # configuration state so render and every check mode agree; # adopt still needs a configured set to take ownership of. self.config = Unconfigured(config_path) - self.build = render_mod.Build(None, {}, {}, None) return with _as_finding("toml-schema", config_path): self.config = config_mod.parse( resolved.data.get("bot-instructions"), f"{config_path} [bot-instructions]" ) self.doctrine = spec_mod.load(spec_tree, *spec_paths) + local_review_path = None + if output_mode == "local": + if installed_spec is None: + external = os.path.join(spec_tree.root, self.doctrine.skill_path) + error = SpecError( + f"{external}: local output needs an installation inside the checkout. " + "Use --output full, or install the package inside the checkout" + ) + error.subject = external + raise error + local_review_path = os.path.relpath( + os.path.join(installed_spec, os.path.basename(self.doctrine.skill_path)), root + ).replace(os.sep, "/") + "#doctrine" self.frozen_ids = spec_mod.frozen_ids() # An unknown `[bot-instructions.doctrine.*]` block id is a `toml-schema` clause; a # manifest that declares no install is an `exclusion-consistency` one. @@ -104,12 +119,14 @@ def __init__(self, root, tree, spec_tree, spec_paths, verb, spec_names, launcher # asserts on the validator's own identity. with _as_finding("toml-schema", config_path, "exclusion-consistency"): self.model = model_mod.build(tree, self.config, self.doctrine, spec_names, resolved) - self.schema = None - if self.config.bots["coderabbit"]: + def schema_loader(): with _as_finding("coderabbit-schema", CODERABBIT_SCHEMA_PATH): - self.schema = render_mod.load_schema(tree) + return render_mod.load_schema(tree) with _as_finding("toml-schema", config_path): - self.build = render_mod.build(self.model, self.schema) + self.build = render_mod.build(self.model, output_mode=output_mode, + schema_loader=schema_loader, + local_review_path=local_review_path) + self.schema = self.build.schema self._tracked = None def read(self, rel): @@ -127,9 +144,10 @@ def tracked_paths(self): def validate(ctx): """Every finding, from every validator the verb runs.""" findings = [] - for check in BYTE_VALIDATORS: - check(ctx, findings) - vr.exclusion_consistency(ctx, findings) + if ctx.build.remote: + for check in BYTE_VALIDATORS: + check(ctx, findings) + vr.exclusion_consistency(ctx, findings) for check in REPO_VALIDATORS: if ctx.verb == "render" and check in RENDER_SKIPS: ctx.skipped.append(RENDER_SKIPS[check]) diff --git a/.agents/skills/bot-instructions/scripts/lib/spec.py b/.agents/skills/bot-instructions/scripts/lib/spec.py index bfb0c335..1775ccab 100644 --- a/.agents/skills/bot-instructions/scripts/lib/spec.py +++ b/.agents/skills/bot-instructions/scripts/lib/spec.py @@ -31,7 +31,7 @@ class Doctrine: - def __init__(self, blocks, routing, positions, surfaces): + def __init__(self, blocks, routing, positions, surfaces, skill_path): self.blocks = blocks # id -> text self.routing = routing # column -> [block ids in order] # The `## Default surfaces` entries as the TOML parsed them. Validated @@ -43,6 +43,9 @@ def __init__(self, blocks, routing, positions, surfaces): # above: a sentinel key there makes any iteration over `routing` read # one entry that is not a column. self.positions = positions + # The loader's selected path belongs to the tree that supplied the + # doctrine. A pointer must not select a filename from another tree. + self.skill_path = skill_path def in_path_class(path): @@ -230,7 +233,7 @@ def load(spec_tree, skill_rel, renders_rel): # command line holds the spec root it resolved and fills it in. exc.from_spec = True raise - return Doctrine(blocks, routing, positions, surfaces) + return Doctrine(blocks, routing, positions, surfaces, skill_rel) def frozen_ids(): diff --git a/.agents/skills/bot-instructions/scripts/lib/validators_repo.py b/.agents/skills/bot-instructions/scripts/lib/validators_repo.py index a617c1c7..ad4d3094 100644 --- a/.agents/skills/bot-instructions/scripts/lib/validators_repo.py +++ b/.agents/skills/bot-instructions/scripts/lib/validators_repo.py @@ -87,6 +87,8 @@ def _marked_region(tree): def orphan_files(ctx): """Every marked file the current TOML does not produce, sorted.""" + if not ctx.build.remote: + return [] return _marked_files(ctx.tree, ctx.build.files) @@ -100,6 +102,8 @@ def removed_orphans(ctx, index): has come and gone, still stages the deletion `check --staged` asks for. `index` reads the staged blobs, the one place their marker still is. """ + if not ctx.build.remote: + return [] return [path for path in sorted(ctx.tracked_paths()) if _retired(ctx.build.files, path) and ctx.read(path) is None and marker.carries_marker(index.read(path))] @@ -127,7 +131,7 @@ def orphan_region(ctx, out): "AGENTS.md")) -def unconfigured_orphans(tree, manifest): +def unconfigured_orphans(tree, manifest, remote=True): """Every marked render `tree` holds while `manifest` declares no `[bot-instructions]` table, as `orphan` findings: `validators.md` § `orphan`, the no-table case. @@ -135,7 +139,7 @@ def unconfigured_orphans(tree, manifest): found = [Finding("orphan", f"carries this package's marker and {manifest} declares no " "[bot-instructions] table. Restore the table, or delete the file", path) - for path in _marked_files(tree, ())] + for path in (_marked_files(tree, ()) if remote else ())] if _marked_region(tree): found.append(Finding("orphan", "the `## Code Review Rules` region carries the marker and " f"{manifest} declares no [bot-instructions] table. Restore " @@ -158,7 +162,7 @@ def _drift_finding(ctx, message, path): relative = os.path.relpath(ctx.launcher, ctx.root) launcher = relative if relative.split(os.sep)[0] != os.pardir else ctx.launcher command = shlex.quote(launcher.replace(os.sep, "/")) - remedy = f"\n remedy: run `{command} render`, then stage every file it changes" + remedy = f"\n remedy: run `{command} {ctx.build.command('render')}`, then stage every file it changes" return Finding("drift", message + where + remedy) diff --git a/.agents/skills/bot-instructions/scripts/lib/verbs.py b/.agents/skills/bot-instructions/scripts/lib/verbs.py index 359e1c5d..80e13bd2 100644 --- a/.agents/skills/bot-instructions/scripts/lib/verbs.py +++ b/.agents/skills/bot-instructions/scripts/lib/verbs.py @@ -34,7 +34,8 @@ def render_verb(ctx, root, dry_run=False): paths = [path for path in paths if writer.inspect(root, path)[1]] region = ctx.build.region_body is not None and (not dry_run or _region_owned(root)) nothing = [] if paths or region else [ - "nothing to render: every [bot-instructions.bots] flag is false" + "nothing to render: every [bot-instructions.bots] flag is false" if ctx.build.remote else + "nothing to render: local output needs [bot-instructions.bots] codex = true" ] if dry_run: lines = [f"would write {p}" for p in paths] @@ -65,7 +66,7 @@ def render_verb(ctx, root, dry_run=False): "replaced before the failure: " + (", ".join(written) or "none"), "removed before the failure: " + (", ".join(removed) or "none"), "every path above holds either its old bytes or its new ones — re-run " - "render to finish the set", + f"{ctx.build.command('render')} to finish the set", ])) from exc lines = [f"wrote {p}" for p in written] if region: @@ -97,7 +98,7 @@ def transform(existing): # refuses. The bootstrap is adopt, then render. raise RenderError( "AGENTS.md: the `## Code Review Rules` region carries no marker at its " - "canonical position, so it is the repo's own — run `adopt` to take it over" + f"canonical position, so it is the repo's own — run `{ctx.build.command('adopt')}` to take it over" ) return render.splice(existing, ctx.build.region_body) @@ -120,7 +121,7 @@ def check_verb(ctx): return [f"check clean: {len(ctx.build.files)} generated path(s) agree with a fresh render"] -def adopt_verb(ctx, root): +def adopt_verb(ctx, root, dry_run=False): """Take hand-written files at generated paths over, and say what they held. A file it takes over keeps its bytes and gains the marker: the next render @@ -128,26 +129,28 @@ def adopt_verb(ctx, root): survive in the TOML. """ lines, pointers, findings = [], set(), [] + action = "would adopt" if dry_run else "adopted" try: for path in sorted(ctx.build.files): - held = _adopt_file(ctx, root, path) + held = _adopt_file(ctx, root, path, dry_run) if held is None: continue - lines.append(f"adopted {path} ({len(held.splitlines())} lines it held)") + lines.append(f"{action} {path} ({len(held.splitlines())} lines it held)") pointers |= points_at(held) if ctx.build.region_body is not None: - lines.extend(_adopt_region(ctx, root, pointers, findings)) + lines.extend(_adopt_region(ctx, root, pointers, findings, dry_run)) except BaseException as exc: # The report IS the output of this verb: what each file held is the # diff the TOML has to absorb, and the pointer list is what the # operator is told to read against it. A second adopt finishes the set # and finds neither, because those files now carry the marker. + state = ("preview wrote nothing" if dry_run else + "the paths named above were taken over before the failure and " + f"nothing else was — re-run {ctx.build.command('adopt')} to finish the set") raise RenderError("\n".join( lines + _pointer_lines(pointers) - + [f"adopt failed: {_cause(exc)}", - "the paths named above were taken over before the failure and " - "nothing else was — re-run adopt to finish the set"] + + [f"adopt failed: {_cause(exc)}", state] )) from exc lines.extend(_pointer_lines(pointers)) if not lines: @@ -162,7 +165,7 @@ def _pointer_lines(pointers): return [f"points at {t} — read it against the TOML" for t in sorted(pointers)] -def _adopt_file(ctx, root, path): +def _adopt_file(ctx, root, path, dry_run=False): """Take one generated path over, or leave it. Returns the bytes it held. Ownership is decided on the bytes being replaced rather than on an earlier @@ -178,12 +181,12 @@ def transform(existing): held.append(existing) return marker.insert(existing, ctx.model.marker(marker.style_for(path))) - if not writer.replace(root, path, transform=transform, require_marker=False): + if not writer.replace(root, path, transform=transform, require_marker=False, dry_run=dry_run): return None return held[0] -def _adopt_region(ctx, root, pointers, findings): +def _adopt_region(ctx, root, pointers, findings, dry_run=False): """The region form of `_adopt_file`, and it shares the reason: the region read, the ownership decision and the splice come from one open. @@ -207,16 +210,18 @@ def transform(existing): body = ctx.model.marker("html") + ("\n\n" + current if current.strip() else "") return render.splice(existing, body) - wrote = writer.replace(root, "AGENTS.md", transform=transform, require_marker=False) + wrote = writer.replace(root, "AGENTS.md", transform=transform, require_marker=False, + dry_run=dry_run) if seen: - _region_finding(ctx, seen[0], findings) + _region_finding(ctx, seen[0], findings, dry_run) if not wrote: return [] pointers |= points_at(held[0]) - return [f"adopted AGENTS.md § Code Review Rules ({len(held[0].splitlines())} lines it held)"] + action = "would adopt" if dry_run else "adopted" + return [f"{action} AGENTS.md § Code Review Rules ({len(held[0].splitlines())} lines it held)"] -def _region_finding(ctx, current, findings): +def _region_finding(ctx, current, findings, dry_run=False): """A region holding more than the directive line is a finding here. `adopt` runs no validator, so without this a repo could adopt eight blocks @@ -233,13 +238,16 @@ def _region_finding(ctx, current, findings): # An empty region is the documented starting state, not a finding: # `references/checklist.md` step 6 adds a bare heading by hand and step 8 # adopts it. There is nothing there for `render` to migrate. - if body in ([], [render_markdown.agents_directive(ctx.model)]): + if body in ([], [render_markdown.agents_directive(ctx.model, ctx.build.review_path)]): return + adopt, render_cmd = ctx.build.command("adopt"), ctx.build.command("render") + repair = (f"Run `{adopt}` without --dry-run, then `{render_cmd}` to migrate it" if dry_run else + f"The marker is in place, so `{render_cmd}` migrates it") findings.append(Finding( "agents-region", f"the `{render_markdown.AGENTS_HEADING}` region carries {len(body)} line(s) " f"below its marker; the managed region is the one directive line naming " - f"{ctx.model.code_review_path}. The marker is in place, so `render` migrates it", + f"{ctx.build.review_path}. {repair}", "AGENTS.md", )) diff --git a/.agents/skills/bot-instructions/scripts/lib/writer.py b/.agents/skills/bot-instructions/scripts/lib/writer.py index b97a3694..d391d3ac 100644 --- a/.agents/skills/bot-instructions/scripts/lib/writer.py +++ b/.agents/skills/bot-instructions/scripts/lib/writer.py @@ -52,7 +52,7 @@ def remove(root, rel): os.unlink(os.path.join(root, rel)) -def replace(root, rel, data=None, transform=None, require_marker=True): +def replace(root, rel, data=None, transform=None, require_marker=True, dry_run=False): """Replace `rel` with `data`, atomically, behind the marker gate. `transform` is the read-modify-write form: it is handed the file's current @@ -68,6 +68,8 @@ def replace(root, rel, data=None, transform=None, require_marker=True): f"{rel}: writer.replace takes exactly one of data= and transform=; " f"got {'neither' if data is None else 'both'}" ) + if dry_run and os.path.islink(os.path.join(root, rel)): + raise RenderError(f"{rel}: a symlink cannot be adopted") existing, owned = inspect(root, rel, require_marker=require_marker) if not owned: raise RenderError( @@ -82,6 +84,8 @@ def replace(root, rel, data=None, transform=None, require_marker=True): return False if isinstance(data, str): data = data.encode("utf-8") + if dry_run: + return True target = os.path.join(root, rel) parent = os.path.dirname(target) if parent: diff --git a/.agents/skills/communication/SKILL.md b/.agents/skills/communication/SKILL.md index deefd254..1a4fb721 100644 --- a/.agents/skills/communication/SKILL.md +++ b/.agents/skills/communication/SKILL.md @@ -25,7 +25,7 @@ Read [messages](references/messages.md) before every message. Add only the refer | Task | Read | |---|---| | Request a decision or action | [questions](references/questions.md) | -| Write a report or briefing | [reports](references/reports.md) | +| Write a report, briefing, work-item description, comment or completion summary | [reports](references/reports.md) | | Answer a voice request | [voice](references/voice.md) | ## User instruction diff --git a/.agents/skills/communication/references/messages.md b/.agents/skills/communication/references/messages.md index 04e5597f..aae83b2a 100644 --- a/.agents/skills/communication/references/messages.md +++ b/.agents/skills/communication/references/messages.md @@ -35,7 +35,7 @@ Use the reader mode the caller supplies. The default prose is for a CEO with mod - Give every number its yardstick and verdict in the same bullet: the earlier value, target or normal range; good, bad or not known; and what is done about it. If the yardstick is unread, say so and name the reading that settles it. - Give a measure that depends on load with that load: session length beside the work handled, or machine use beside what ran. Length or use alone never claims an improvement. - Before posting, read each topic as the person and ask "so what for me?". Add that answer or cut the topic. -- State a cost as its figure and source. Compare added CI time against the plan's 50,000 private-repository minutes each month. +- State a cost as its figure and source. Compare added CI time against the plan's included monthly allowance. The yardstick, load and so-what rules come from the owner's Slack messages 1792172820, 1792172887 and 1792172957, relayed in Jarvis note 1792173119. @@ -48,6 +48,11 @@ When describing a mechanism, give its effect on the person and the likelihood of - Omit acknowledgements, unneeded mechanisms and history that do not affect the person's action. - A critical notice states the failure, its effect and the action the person must take. - When introducing a rule or setting, name the file or service that will hold it. +- For a work update, use the [work story](reports.md#work-story). A simple reply needs no fixed status labels. +- Name planned work by its tracker item, or state that it was dropped and why. Vague promises of future work do not replace either. +- Attribute another agent's work to that agent by name. Use I only for work the speaking session did. +- When a message says a fix is coming, say in the same sentence whether it existed before the person's message, with its item and filing date, or was filed because of that message. +- Review the saved text before sending. Message-format checks are advisory. A tool must not refuse a message because of its wording or layout. ## Medium and threads @@ -62,6 +67,12 @@ When describing a mechanism, give its effect on the person and the likelihood of Write times in the person's time zone with am or pm. Do not use a `Z` stamp. +## Names + +- Give a tracker item its subject words beside its link. +- Use distinct names for different things. Replace a pronoun with the thing's name when it could refer to more than one thing. +- When a short reply could refer to different earlier items, name the item the reply acts on before acting. + ## References and markup - Link each pull request, commit, issue and tracker item with its short name. Use `[REPO#N](https://github.com/OWNER/REPO/pull/N)`, `[SHORT_SHA](https://github.com/OWNER/REPO/commit/SHORT_SHA)` or `[KEY-N](TRACKER_ISSUE_URL)` as the form. Never put a tracker id in a code span. @@ -69,6 +80,7 @@ Write times in the person's time zone with am or pm. Do not use a `Z` stamp. - Use headings and bold labels or decisions for structure. Never use bold for emphasis or on a whole sentence. Use sentence case. Use italics seldom. - Use inline code for a command or path. Use a code block for output longer than one line. Keep paragraphs to a few sentences. - Put text the person must send in a code block. Name the recipient above it. +- Report changed rules, guidance or directives after their commit is pushed. Name each changed file once as `repo/folder/file.md`, linked to `https://github.com/OWNER/REPO/blob/COMMIT/path#heading` at that commit. - Beside a file, including a Slack file comment, use Slack mrkdwn: `*Label*` for bold, `` for a link and plain lines for a list. The other markup rules still hold. ## Corrections @@ -77,4 +89,4 @@ Own a mistake in one line, with its repair. ## Attachments -Attach a screenshot or image when it explains the point better than words. +Attach a screenshot or image when it explains the point better than words. Send a picture for review as a direct file post in its topic's thread. Evidence-only pictures can stay on the tracker item with its link. diff --git a/.agents/skills/communication/references/questions.md b/.agents/skills/communication/references/questions.md index fc13412d..14afad62 100644 --- a/.agents/skills/communication/references/questions.md +++ b/.agents/skills/communication/references/questions.md @@ -4,7 +4,11 @@ Read when requesting a decision or action. The caller decides whether to ask and ## Decision requests -Ask one question per message. Give the options and a recommendation. Each option states its gain, its cost and the likelihood of that cost. Use the reader mode from [messages](messages.md#reader-modes). +Ask one question per message. Give the options and a recommendation. Use the [visible comparison](#today-and-after). Each option states its gain, its cost and the likelihood of that cost. Use the reader mode from [messages](messages.md#reader-modes). + +## Today and After + +Show Today and After side by side in the words of the screen or app the person uses. Put this comparison first in work-item descriptions, comments and completion summaries. ## CEO questions @@ -32,7 +36,7 @@ Use outcomes only. Name no mechanism the person does not act on and no option by ## Action requests -Use plain words to say what the person does and what evidence closes the request. State what the deadline does. Omit the recommendation when the caller's ask form records none. +Give numbered steps in plain words, with one action per step. Say what evidence closes the request. State what the deadline does. Omit the recommendation when the caller's ask form records none. ## Opening question diff --git a/.agents/skills/communication/references/reports.md b/.agents/skills/communication/references/reports.md index 108beb8b..a165a090 100644 --- a/.agents/skills/communication/references/reports.md +++ b/.agents/skills/communication/references/reports.md @@ -1,10 +1,20 @@ # Reports and briefings -Read when writing a report or briefing. Use the wording and markup in [messages](messages.md). +Read when writing a report, briefing, work-item description, comment or completion summary. Use the wording and markup in [messages](messages.md). + +## Work story + +Write a plain briefing as a chain of events. Open each area with good or bad, done or incomplete, and why. Then connect its goal, progress, completed work, remaining work, failures and the action taken. Use the person's words for the problem, its state and the outcome they experience. + +State the goal as the outcome the person needs. Put the observed reading beside it. A measure alone is not the goal. + +Work-item descriptions, comments and completion summaries use this story too. Apply the [visible comparison](questions.md#today-and-after). Keep technical detail on the tracker item. + +A report names the author's own misses since the previous report. Give each miss its cause and the fix, or the reason no fix is needed. ## Reports -Say the outcome for the person or fleet, not the issue title. Link each work item to its owning tracker issue: the Linear issue for a Linear item or the GitHub issue for an `issue-N` item. Do not use its pull request or commit as the work-item link. The tracker issue links to its pull request. +Say the outcome for the person or fleet. A project name or item title does not replace its effect. Link each work item to its owning tracker issue: the Linear issue for a Linear item or the GitHub issue for an `issue-N` item. Do not use its pull request or commit as the work-item link. The tracker issue links to its pull request. Put detail in the report file. Send one post per report, not a thread of fragments. Give each blocked item its cause and next action. @@ -28,7 +38,9 @@ Report account headroom for every harness the fleet runs, including Claude, Code ## Summary shape -- Put one item per line, at most 20 words. A line may carry two links. +A consumer's user instruction that sets a report format for its reader overrides the shared format for that reader. + +- Put one item and one sentence per line, at most 20 words. A line may carry two links. - Put a blank line before each label. Each label stands alone: **Landed**, **Running**, **Blocked**, **Waiting on you**. - Put each figure on its own line. Group account headroom after the opening outcome readings. - Use at most `ORCH_REPORT_SUMMARY_LINES` item lines for an orch report, default 20. Blank lines, labels and the first opening line do not count. Leave excess items in the report file. Never pack a line to fit the cap. @@ -36,7 +48,7 @@ Report account headroom for every harness the fleet runs, including Claude, Code ## Owner summary template -Use this mrkdwn template for the report file's comment. For a post without a file, use standard Markdown under [References and markup](messages.md#references-and-markup). +Jarvis and overseer reports use this shared summary shape. Use this mrkdwn template for the report file's comment. For a post without a file, use standard Markdown under [References and markup](messages.md#references-and-markup). ```text [DATE]: [REPOSITORY OUTCOME READING] () @@ -45,10 +57,10 @@ Use this mrkdwn template for the report file's comment. For a post without a fil [ACCOUNT HEADROOM FIGURE] *Landed* -- [OUTCOME] () +- [OUTCOME] () *Running* -- [OUTCOME IN PROGRESS] () +- [OUTCOME IN PROGRESS] () *Blocked* - Nothing diff --git a/.agents/skills/mailbox/scripts/lane-mail b/.agents/skills/mailbox/scripts/lane-mail index 3b9e9f6c..a18e0849 100755 --- a/.agents/skills/mailbox/scripts/lane-mail +++ b/.agents/skills/mailbox/scripts/lane-mail @@ -2534,27 +2534,35 @@ case "$VERB" in # resolved: the turn may run it from another checkout, where a read with # no root would open that checkout's mailbox instead. printf -v WATCH_READ '%q inbox --item %q --root %q' "$SCRIPT_DIR/lane-mail" "$ITEM" "$ROOT" - # A trapped signal ends a wait below at once, and the EXIT trap then - # withdraws the liveness record, so a send stops reading this monitor as - # live the moment it is stopped. Bash runs a trapped signal only once a - # foreground child returns, so the poll and the sleep both run in the - # background under a wait. A poll still running at the exit finishes alone - # and writes no record. A KILL runs no trap: the record then goes stale - # within its window, and the work directory stays. + # Bash defers a trapped signal during any foreground external command, + # including the heartbeat's date and mv. One job owns the whole iteration; + # this shell only waits and reads its completed result. Job control gives + # that job a group, so stopping it also stops a child that could republish + # the record after the EXIT trap withdraws it. The jobspec holds ownership + # without signalling a saved process number after it could be reused. trap 'rm -f -- "$WATCH_FILE"; lm_cleanup' EXIT - trap 'exit 129' HUP - trap 'exit 130' INT - trap 'exit 143' TERM + lm_watch_stop() { + trap '' HUP INT TERM + # The mkdir lock fallback needs TERM to run its release trap. + kill -TERM %+ 2>/dev/null || : + wait %+ 2>/dev/null || : + exit "$1" + } + trap 'lm_watch_stop 129' HUP + trap 'lm_watch_stop 130' INT + trap 'lm_watch_stop 143' TERM # Lines up to here are announced, or read before this watch started; the # cursor the lane's own `inbox` moves raises it, so mail already read is # never announced, and a fresh watch announces what stands unread. ANNOUNCED=0 + set -m while :; do - [ -d "$BOX" ] || refuse mailbox-missing "$BOX" - printf 'at=%s interval=%s\n' "$(date -u +%s)" "$INTERVAL" >"$WORK_DIR/watch.rec" && - mv -- "$WORK_DIR/watch.rec" "$WATCH_FILE" || refuse write-failed "$WATCH_FILE" - # The poll's subshell hands its counts back through the poll file. { + set +m + trap - EXIT + [ -d "$BOX" ] || refuse mailbox-missing "$BOX" + printf 'at=%s interval=%s\n' "$(date -u +%s)" "$INTERVAL" >"$WORK_DIR/watch.rec" && + mv -- "$WORK_DIR/watch.rec" "$WATCH_FILE" || refuse write-failed "$WATCH_FILE" lm_cursor_read [ "$ANNOUNCED" -ge "$SEEN" ] || ANNOUNCED="$SEEN" lm_fetch "$TO_LANE" "$WORK_DIR/lane.raw" @@ -2571,15 +2579,13 @@ case "$VERB" in # watch killed there leaves none of the lane's messages behind. rm -f -- "$WORK_DIR/lane.raw" "$WORK_DIR/lane.jsonl" "$WORK_DIR/unread" printf '%s %s\n' "$ANNOUNCED" "$NEW" >"$WORK_DIR/poll" || refuse write-failed "$WORK_DIR/poll" + if [ "$ONCE" -eq 0 ] || [ "$NEW" -eq 0 ]; then sleep "$INTERVAL"; fi } & wait "$!" read -r ANNOUNCED NEW <"$WORK_DIR/poll" - # The exit is the wake, and the EXIT trap above withdraws the liveness - # record with it, so a send meanwhile reads the monitor as the none it - # is until the lane re-arms. + # The exit is the wake, and the EXIT trap withdraws the record until + # the lane re-arms its monitor. [ "$ONCE" -eq 0 ] || [ "$NEW" -eq 0 ] || exit 0 - sleep "$INTERVAL" & - wait "$!" done ;; diff --git a/.agents/skills/orch/scripts/lib/adapters/codex.sh b/.agents/skills/orch/scripts/lib/adapters/codex.sh index 49f0dfde..36317ae5 100644 --- a/.agents/skills/orch/scripts/lib/adapters/codex.sh +++ b/.agents/skills/orch/scripts/lib/adapters/codex.sh @@ -53,7 +53,8 @@ lane_adapter_codex_reading() { # UNREAD # earlier launch even where its call is already in the rollout: # https://learn.chatgpt.com/docs/hooks#pretooluse # AgentStatus and agent/status.rs in Codex 0.163.0 define the states below. -# Interrupted is not final. A later full list replaces uncertain observations, +# Interrupted releases the reserve until a followup puts the agent out again. +# A later full list replaces uncertain observations, # but cannot settle a call that has not returned yet. # Codex dispatch scheduling can differ from result recording order. A list # that overlaps a launch or followup cannot establish the roster after it. @@ -67,8 +68,8 @@ lane_adapter_codex_agents() { # [CURRENT_CALL_ID] else "unknown" end else . end | if . == "idle" or . == "completed" then "completed" - elif . == "errored" or . == "shutdown" or . == "not_found" then "completed" - elif . == "running" or . == "pending_init" or . == "interrupted" then "running" + elif . == "errored" or . == "shutdown" or . == "not_found" or . == "interrupted" then "completed" + elif . == "running" or . == "pending_init" then "running" else "unknown" end; def name: if type == "string" and test("^/root(/[A-Za-z0-9_-]+)*$") then . else error("invalid agent name") end; diff --git a/.claude/hooks/lane-mail-check.sh b/.claude/hooks/lane-mail-check.sh index 73306ecc..ba719e94 100644 --- a/.claude/hooks/lane-mail-check.sh +++ b/.claude/hooks/lane-mail-check.sh @@ -3,7 +3,7 @@ # name: lane-mail-check # event: Stop # matcher: -# description: Blocks a lane's turn end while its overseer mailbox holds unread lines, so a directive or a ruling reaches the lane without a keystroke, a pane or a question tool. The lane is the work item `LANE_MAIL_ITEM` names, or the one directory under `/tmp/lane-mail/` whose name lowercases to the current branch; a session with neither is not a lane; a lane whose mailbox holds no unread line passes silently, as does a directory git reports no repository for and that holds no mailbox of its own. The checkout's overseer mailbox, `/tmp/lane-mail/overseer`, has one reader: the session whose tmux server and pane the checkout's oversee workflow state names under `.overseer`, the pair every writer the orch `schemas/workflow-state.md` `overseer` row names writes, `oversee register` among them for a session opened by hand, and the one the fleet's OVERSEER is established by below, so a record naming a dead pane names no reader. The native session must also match the recorded harness, readable caller home and payload session id; `ol_record_heal` binds the first matching native id from the recorded pane, and `oversee register` clears that binding after a resume. Pi and any harness whose `lane_context_caller_home` reports no home compare the harness and native session id only. The pair names a session only on the tmux server started at the record's `server_start`, so a server a tmux restart handed the recorded pid and pane id names no reader either; a record carrying no start at all names the session in that pane, which writes its server's start into it. Where a file stands there, that session is handed the notes `lane-mail peer send --repo` wrote there at its turn end and after its tool calls, under the same `unread=` line, unless a live watch holds the fleet state: the `oversee-watch.pid` record a repeat `oversee-watch` writes beside the fleet state on every surface and removes on exit, judged by the orch `lib/watch-pid.sh` library's `watch_pid_live`, which reads the mailbox itself, so the named session is handed nothing from it beside that watch. A fleet watched in single passes writes no watch record, so its named overseer is handed the notes as `unread=` lines and the next pass does not report them. A Jarvis session's wake, the process `ORCH_WAKE_PROCESS` matches, is no such watch: it moves no cursor, so that session is handed each note in full here once and acknowledges it here, and its wake carries no note's body, at most the count and read command `lane-mail watch` prints. Where the payload's `kendex_ack` is `caller`, which the pi-hooks lane mail wake sends, the context carries the reader's `--ack` command as `kendex_ack` and nothing is acknowledged here: the wake runs it once its send returns, so a send that throws leaves the lines unread. Every other session in the checkout, one the owner opened there for other work included, is handed nothing from that mailbox, and so is a session whose install has no reader beside this hook. For the named session, where the install's `workflow-state path oversee` prints no path, or the library cannot be sourced or answers neither way, the hook refuses, opening `lane-mail-check: fleet-state=` with that file's own words under it; the halt arm never reads that mailbox, a subagent's turn end is handed nothing from it, and a session in a checkout with no overseer mailbox pays two file tests for the question. `` is the lane's root, resolved in this order: `CLAUDE_PROJECT_DIR`, the directory Claude Code started the session in; else the root the launch marker for `LANE_MAIL_ITEM` binds, where that root exists; else the directory the hook runs in, which on Codex and Pi is the session's start directory and on Claude Code without the variable is the call's own. A Claude Code lane working from the main clone is therefore still judged on its own mailbox. A root its launch marker binds that has no `tmp/lane-mail` directory is refused at a turn end, before any tool call and after the lead's finished one, opening `lane-mail-check: mailbox-missing=` with the marker and the one `mkdir` command that restores the directory, and that command alone passes a tool call. Before a tool call a subagent is refused whatever it runs, and a call whose caller is unknown may run that command; after one a subagent is handed nothing and refused nothing, as with any mail, and its next call meets the refusal. The marker is looked up for the item `LANE_MAIL_ITEM` names or else the branch names, so that check costs one stat in a repository whose common git directory holds no `lane-mail` directory, and one branch read and one marker stat in one that does. A mailbox belongs to a lane only where a launch recorded one: `open-terminal` and `lane-host create` write the lane's root to `lane-mail/` under the repository's common git directory and create the lane's own `tmp/lane-mail/`, and a mailbox with no marker bound to this root passes silently. Unread lines are peeked through the orch skill's own `lane-mail inbox --peek`, the one reader of the mailbox and its cursor, and acknowledged with `inbox --ack` only once the refusal is written, so a hook killed at its budget leaves them unread and a line acknowledged here is never handed over twice. That reader is resolved from this hook's own install, walking up to the home directory for `skills/mailbox/scripts/lane-mail` or the shared `.agents/skills/mailbox/scripts/lane-mail` beside it, then the home's own shared tree for a harness root relocated out of it; the open repository's `.agents/skills/mailbox/scripts/lane-mail` is used only where this hook is installed in that repository, and a reader outside that containment is refused rather than run. The refusal opens with `lane-mail-check: unread=` and carries one JSON envelope per line under it, and for the lead, where a halt is among them, the one `lane-mail inbox` command that reads it; the turn then continues with them. Run with the argument `deliver` by the lane-mail-deliver hook after a tool call, it exits 0 with the harness's JSON on stdout, whose `additionalContext` carries the same lines. That run first judges the context mark of the fleet's OVERSEER, below, for a lead's call in tmux in a checkout whose `tmp/lane-mail/overseer` directory stands, so a mark crossed mid-turn is read at the next tool call: the context is read and recorded as the overseer's turn end reads it and judged at `ORCH_HANDOFF_CONTEXT_PCT` by the rule the orch `references/oversee-events.md` § Judgement rules states for the overseer's context mark. On Pi the window is the payload's own `context_window`, which the pi-hooks carrier puts on the PostToolUse payload of every tool call; a Pi payload naming none, the lane mail wake's run or a tool call from an older carrier, takes no reading, writes no record and hands nothing over, so the turn end's reading and judgement stand. A reached mark, or a setting it cannot be judged on, is handed over as that `additionalContext`, opening `lane-mail-check: context=` with the succession and the handoff record as the route, at every tool call until that record stands. Every other line that judgement writes, a judgement that could not run, a transcript it could not read or an `orch-env` this install has not got, is handed over the same way once per session and first line, the last told kept in `tmp/lane-mail/overseer/context-told`, written only once the run's output carrying it is written and cleared by a clean reading; only the bound native session the fleet record names, or the overseer it lost whose native identity still matches a nonempty recorded binding, writes or clears that file. Either opens the same context as any mail the call hands over, above its `unread=` line, and a refusal the mailbox check makes on the same call, above its keyed line, whether that refusal is Copilot's `additionalContext` or stderr at exit 2. The judgement itself refuses no call, and no account is read there. Run with `start` by the lane-mail-start hook at a session start, or with `prompt` by the lane-mail-prompt hook at a prompt, both on Copilot alone, it hands the same lines over the same way. A session start acknowledges them only once that context is written. A prompt leaves the lines unread because Copilot can discard its output, so a later inbox read or hook delivery can repeat them. Neither arm refuses anything: every refusal this description names is its keyed line on stderr at exit 0, with nothing on stdout and nothing acknowledged. Before an attached agent launch, the halt arm also judges the lead of a launched lane or the identified fleet overseer at the context mark, refusing missing context with the orch job runner or a separate session as the route. While an attached agent of the session may still be out, the mark is less ORCH_HANDOFF_AGENT_RESERVE_TOKENS, default 150000 tokens, equality refused: Claude Code reads that roster from its task registry where the payload carries one, else from the transcript's Agent-call results, task notifications, teammate idle notifications and sends, and reads an unreadable roster or an entry neither read classifies as unknown; Codex reads ordered collaboration snapshots, launches and followups from its rollout. Idle, completed, errored, shutdown and not-found children release the reserve; initializing, running and interrupted children keep it. A full unfiltered snapshot replaces earlier unknown observations only when its call does not overlap a launch or followup; pending calls and unreadable current observations keep the roster unknown. After waiting, Codex must call list_agents with no path filter to observe returns. Other harnesses read none, so their rosters are unknown. With none out the launch meets the plain mark. A launch the reserve alone refuses with an agent out is keyed `agent-reserve` and names waiting for those agents, the job runner or a separate session, never a handoff, since the turn end and every succession judge the plain mark. With the roster unknown no wait can be observed, so the refusal is keyed `agent-unobserved` and names the job runner or a separate session, and for a lane its handoff record. On Pi the lead launches through subagent; delegate_subagent carries child identity and is outside this lead-only reserve rule. At a context hold, a live session waits for attached agent returns in this turn; Claude Stop background_tasks is preferred, with the transcript's measured Agent-call results, async launch and teammate spawn records, task notifications, teammate idle notifications and sends as the fallback when absent. Other harnesses name known unfinished children and known output paths, or unknown paths, in the emergency handoff. A standing handoff retains its escape, and the successor reads existing output before repeating work. Run with `halt` by the lane-mail-halt hook before one, it acknowledges nothing and refuses the call while an unread directive sent with `lane-mail send --halt` stands, opening `lane-mail-check: halt=` with the directive and the one `lane-mail inbox` command that reads it, which names the lane's root with `--root` so it reads the same mailbox from any checkout; that command alone passes. Run with `row` and the event by the session-start-row, session-end-row and stop-failure-row hooks, it writes the event row of a session with no lane of its own, only for the pane's top-level harness and, on Copilot, only for a session the caller rule names the lead, through the orch skill's `lib/session-rows.sh`, the file those hooks describe, and refuses nothing: every gap below its payload read is reported and passed; the overseer's own turn end writes a Stop row there through the same library at every turn end, compact, its time, event, harness and session alone, except over a standing StopFailure row, which it lifts and where it keeps the turn's last message. Run with `lane` by the critical-path-deny hook, it prints `lane` where the launch marker for the session's item binds the session's root and its mailbox directory stands, else `none`, records and judges nothing else, and exits 0; a gap past its payload read is reported on stderr and passed with nothing on stdout. On a Pi install a launched lane's lead writes its own turn rows through that library into its mailbox directory, `session-rows.jsonl`: a Stop row at each turn end, carrying the `stopReason` of the turn's last assistant message in the transcript and Pi's `errorMessage` where that reason is `error`, and a PreToolUse row at the first tool call of each turn, after a turn end or on an empty file, written ahead of the mailbox check; oversee-watch and `lanes state` judge a Pi lane idle, working or walled from those rows in place of its pane, and a gap in the write is reported under `lane-rows-skipped` or `lane-rows-unwritten` and passed. The Pi install is the hook directory under `.pi` or `.pi/agent`, or under the user root `PI_CODING_AGENT_DIR` names; an install naming no harness writes no row, which a launched lane's turn end reports under `harness-unlisted`. Who made a call is answered once for every arm: the lead, a subagent, or unknown. A SubagentStop payload or one carrying a non-empty `agent_id` or `agent_type` is a subagent's on every harness, handed no mail and acknowledging none, and while a halt stands refused without that command. On Copilot, whose payloads name no agent, a preToolUse or postToolUse call, a preCompact and a context reading the usage arm is handed are the lead's where the session id they carry is a lead session this install recorded, the one rule for all four: one empty file per session under `~/.cache/lane-mail/copilot-leads`, written at the session's sessionStart, which Copilot fires for the lead alone, and at each turn end the transcript rule below proves the lead's, and pruned at a start once untouched for 30 days. A custom subagent's call was measured on Copilot CLI 1.0.88 carrying its own session id, which nothing recorded; whether a built-in task-tool subagent's calls carry their own session id or the lead's is a pending live-lane proof, and one whose calls carry the lead's is read as the lead, handed the lead's mail after its calls, which marks it read, and under a halt shown the read that clears it. A call whose session is no recorded lead, a custom subagent's among them, is unknown: the deliver arm hands it nothing and acknowledges nothing, writing `lane-mail-check: session-unrecorded=` to stderr, the compact arm flags nothing and writes the same line at exit 0, the usage arm records nothing and refuses under that key at exit 2, so the lead's turn end hands the lines over and acknowledges them, and the halt arm refuses it without showing that command yet passes the command, because the reader's `--ack` stops short of an unread halt and a lead whose record could not be written would otherwise be refused for good; the lead is shown the command by every notice and refusal that hands it the halt, its turn end's included. A record that cannot be written is reported on stderr under `lane-mail-check: lead-unrecorded=`, or `=none` for a session start naming no session id, and never refused. A Copilot sessionStart or userPromptSubmitted is the lead's, and an agentStop is ruled by its transcript, below; a prompt records no lead, since that a subagent's prompt fires no userPromptSubmitted is unmeasured. `stop_hook_active` true skips the mailbox check whole on the turn-end run. The flag is in the payload, so nothing above the payload read knows a turn was continued, and `arm`, the `missing-tools` refusal for `jq` or `cat`, `payload=unreadable` and `payload=invalid-json` are refused on every turn, the continued one included. Below that read one rule holds and every refusal is on one side of it: a refusal the lane itself can clear is still made, and a refusal it cannot is reported on stderr and passed. The lane clears the two handoff marks, and `script`, `setting`, `setting-range` and both `transcript` refusals, by writing its handoff record, and `mailbox-missing` by running the command it names, so those are refused on a continued turn as on any other. It clears `idle` by sending a lane-mail ask or notice, or by updating `tmp/lane-status-.md` under its launch root, so `idle` is refused on a turn another stop hook continued, except on Pi, as the idle rule below states. It clears none of `workdir`, `git`, `item`, `marker` or the `missing-tools` refusal for `git`, `tr`, `awk`, `mktemp` or `tail`, so each of those is reported and the turn ends, where a fresh turn refuses it. The halt arm reports and passes that same set at every tool call: a lane whose tool calls are refused can clear nothing, since clearing it takes a tool call, so there only the payload refusals and the mailbox's own, `reader`, `inbox`, `halt` and `mailbox-missing`, are refused, the last two each passing the one command that clears it. The same turn-end run hands the lane off before it runs out, so the handoff never waits on an overseer reading a pane. It reads this session's context use from the `transcript_path` the payload names, through the orch adapter for the harness this hook's install directory names, `.claude/hooks`, `.codex/hooks` or Pi's `kendex/hooks`: the tokens the last response left in context and effective capacity, with Pi reading the payload's own `context_window`. It records that reading as `context.json` in the lane's mailbox directory, where `lanes context` reads it, and refuses the turn end when `lane_context_handoff_due` requires handoff under the shared context rule in orch `references/oversee-events.md`, Judgement rules. It reads the account the credential this session runs on still has through the orch skill's own `lanes pick --lane`, judging a Claude lane on its own model, and refuses at or below `ORCH_HANDOFF_HEADROOM_PCT` (default 3). A Pi session's account is the one its model's provider bills, by the orch `lane_pick_harness` rule on the `/` its transcript names: a `pi-claude/` model spends the Claude seat `CLAUDE_CONFIG_DIR` names and is judged there on that model, a `github-copilot/` model spends the Copilot pool on Pi's own root, and any other provider, or a reading naming none, is left unjudged under `account=unmeasured`. Either refusal opens `lane-mail-check: context=` or `lane-mail-check: headroom=` and carries one instruction: reach the next safe point, write the record with `workflow-state set handoff`, send a `handoff` notice, and exit. The record is read where `workflow-state --help` § Handoff record says, a launched lane naming the root its launch marker binds as the worktree, and the instruction names the state directory the read found, so a record written as told ends both refusals. The instruction opens with the `workflow-state init ` that `set` needs where the item has no state file yet, so it is enough on its own. It repeats at every turn end, `stop_hook_active` included, until the item's workflow state carries a `.handoff` object no relaunch has resumed; only the lane can write that record, so a single refusal it declines to act on would end the session with nothing recorded. That record is judged before every mark, before every read they rest on and before `orch-env` and `lanes` are looked for, so no failure but the record's own writer can hold a lane that has already done what it was asked. `orch-env` or `lanes` missing from this hook's install, a mark setting that is not a whole number in range, and a transcript the payload names and nothing can read are refusals too, each on the lane path alone and each carrying the same instruction. What the marks cannot judge is reported and passed, never refused: a payload naming no transcript leaves the context unread, and so does a transcript whose last usage line is an object carrying none of the field names its adapter reads, which is reported under `usage-unread=` rather than summed to a figure of zero and read as room, a reading below the independent token limit whose capacity the adapter could not name, reported under `window-unread=`, and an install directory naming no harness, reported under `harness-unlisted=`; a reading that could not be recorded is reported under `context-unrecorded=` and still judged; an account `lanes` keeps no inventory for, one it could not measure and a read that passed this hook's own ceiling each leave the account unjudged under `account=unlisted`, `account=unmeasured` or `account=timeout`, never read as room, so a setup with no usage endpoint still ends its turns; and a lane whose handoff record cannot be judged leaves both marks unjudged under one of four keys, `handoff-skipped=` for a reader or a script this install has not got, or `handoff-skipped=unlocatable` where this hook's own directory could not be resolved and none of them could be looked for, `handoff-outside=` for one only the open repository supplies, `handoff-unanswered=` for one that is there and answered nothing this hook can read, and `handoff-unreadable=` for a state file the install's own `workflow-state` could not read. Passing the turn is the answer for all four. For the first three it is because an install whose orch scripts cannot answer cannot run `workflow-state set` either, so a lane told to record a handoff with them could never end a turn again; for `handoff-unreadable` the install answers and the fault is the item's own state file, which is the file the record would be written into, so that write could not land either and the refusal would be as uncloseable. A subagent's turn end is judged on neither mark. The fleet's OVERSEER meets four triggers of its own on its turn end: a session with no lane of its own whose tmux server and pane are the pair the oversee workflow state records under `.overseer` is that overseer, and nothing weaker establishes one, so an ordinary session in a fleet checkout is judged on nothing. A session whose native identity matches a nonempty binding in the fleet record but whose pane only the overseer's `context.json` names, the overseer the record lost, is judged on nothing either, and reports `pane-unrecorded=` with the recorded key under it and writes that record with no reading and the gap `pane-unrecorded`; any other session the record does not name writes nothing, so the real overseer's reading stands. A fleet record naming this session's pane that lacks its server start, its harness, its launch home or its native session id is healed from an authorized native session first, at a turn end and at a tool call alike: the start of this session's own tmux server, the harness this install names and the launch home the harness variable of this session's own environment carries, `CLAUDE_CONFIG_DIR`, `CODEX_HOME` or `COPILOT_HOME` or that harness's default where it is unset, are written into it through the orch `lib/overseer-launch.sh` `ol_record_heal`, which writes only a fact the record lacks, and the transcript is bound to that home on the same run; a write that fails is reported under `record-unhealed=` with the writer's words, and the caller remains unbound until a later binding write succeeds. Before it reads that transcript for the overseer it binds it to the current session: the `transcript_path` the payload names is read only where it is this session's own native file, held to the `session_id` the payload carries and the launch home the fleet record names under `.overseer.home`, through the orch adapter for a claude, codex or copilot install; a Pi install states no transcript shape and reads the payload's own window as a Pi lane does. If `lane_context_transcript_owned` refuses an admitted overseer's transcript binding, the hook reports `transcript-unowned=` with the reason the library returns. Nothing is read then, and the context record is written with a null token count and that reason as its `gap` (orch `workflow-state.md`, `context.json` row), so it still advances at every turn end and oversee-watch reports the gap, and the judge is handed this install's harness and no context figure, so it judges the account triggers alone, the `transcript-unowned` line is this hook's one report that the context went unmeasured, and a session is never judged on a file it does not own. Every overseer turn end whose orch context library loads writes that record, a reading or a null token count with a `gap` naming why none was taken: the binding library's reason, `transcript-unnamed` for a payload naming no transcript, `usage-absent` for a transcript holding no usage line, `usage-unread` for a usage object its adapter does not read, which is also reported under `usage-unread=`, `session-record` for a Copilot session with no extension reading whose statusLine session record does not answer either, which is also reported under `session-record=`, or `pane-unrecorded` below. A Copilot statusLine record reporting allow_all_enabled false, read whether or not an extension reading stands, in a session whose `COPILOT_ALLOW_ALL` is true (a launch line granting `--allow-all` or `--yolo`), is reported under `stop-cause=allow-all-blocked-by-policy`, and the turn end judged as usual. An install naming no harness an adapter reads writes no gap, since its context is never read, and leaves the record as it was, and a Copilot one names none where the reading its usage arm wrote for this session stands, its turn end reading that record rather than taking a reading of its own; a gap record that cannot be written is reported under `context-gap-unrecorded=`, the record keeping its earlier entry. This hook records the overseer's own context reading as `context.json` in the overseer mailbox directory at the main checkout, naming the session and its pane, and hands that reading to `oversee-succeed --check-marks --context :` from this hook's own install, which judges those marks on it and on no stored figure, and nothing at the turn end here judges them, under the same ceiling the account read runs under, so the turn-end refusal and the `overseer-mark` watch event cannot describe one overseer differently. Its refusal opens with the `context=`, `headroom=`, `rate=` or `qualifying=` key, carrying the figure that judgement read, and names `oversee-succeed`, handed the same reading, as the route, with `workflow-state set oversee handoff` under it for a succession that refuses, so the refusal always has an escape the overseer can reach. That record names the session that wrote it, in the native `session_id` the payload gives. A payload with no native session id is refused and cannot read mail or write overseer context or gaps. `overseer_identify` owns its native refusal diagnostics. One other refusal stands on that path, `script` for an `oversee-succeed` this install has not got, and the record clears it as it clears the marks. `ORCH_OVERSEER_SUCCESSION=off`, read off the judgement's own line and never here, turns the account-mark refusals off with the succession they name, the watch's `overseer-mark` event still reporting those marks; the context mark is refused whatever the setting, since no watch event reports it, and the handoff record ends that refusal. An answer this hook cannot act on, one the ceiling abandoned, and one whose own reading was unmeasured are reported under `marks=unjudged`, `marks=timeout` and `marks=unmeasured` and the turn ends, never held. A lane asks its overseer only through lane mail. Before a tool call in a launched lane, the halt arm refuses the harness question tool by its name, whichever of the four names the payload's `tool_name` carries, Claude Code's `AskUserQuestion` and `EnterPlanMode`, Codex's `request_user_input` and Pi's `question`, opening `lane-mail-check: question-tool=` and naming the `lane-mail ask --item --file ` send and the `lane-mail wait` on its printed id as the route, because a dialog on the pane reaches no overseer; an unread halt is refused ahead of it, a subagent's call is refused and told to report its question to the lead, and a session that is no launched lane passes the call silently, a committed mailbox and status file included. At a launched lane lead's turn end, once the handoff marks pass, the lane is judged idle on lane-mail sends and its lane status file update state, never on words in its pane, on Claude Code, Codex, Pi and Copilot; OpenCode and Cursor run no kendex hooks, and Gemini and Antigravity do not run this one, so a lane there is never judged idle. The reader's own `lane-mail events` listing, which moves no cursor, counts the asks and notices in the lane's outbound file against the count this hook recorded at the lane's last judged turn end, `sent-count` in the lane's mailbox directory: a line holding the count, the word `held` where this judge refused that turn end, and an optional encoded status file update state; no record is a count of zero with no status state. A status file update since that record, including a rewrite of the same text, passes without a notice. A count other than the recorded one is a send this turn and passes, a standing handoff record ends the run before this judge, the newest directive the overseer sent carrying `halt` passes, and a lane whose launch marker no longer binds its root, the close-out's state, is no lane. With none of these the turn is refused and the hold recorded, opening `lane-mail-check: idle=` with one continuation, the lane's `lane-mail inbox` read and then its workflow, beside the ask route and the `lane-mail notice` send, which follows the orch Coordination notice rule: changed work sends a notice, and a continuing wait on a dispatched agent or an armed wake updates the lane status file only. On a turn the harness continued for this judge's own recorded hold it refuses nothing and sends the overseer a lane notice stating what it checked, opening `lane-mail-check: idle-notice=`, or `idle-notice-unsent=` with the sender's words where the send fails, so an idle lane is reported and never looped. A turn another stop hook's refusal continued is held as a fresh one, except on Pi, whose pi-hooks carrier runs no further request after a continued turn, so there the notice is sent with no hold before it. The record counts that notice, so the lane's next turn is judged on what the lane itself sends. An `events` listing that fails, or whose envelopes jq cannot read, is reported under `events=` or `events=envelope`, and a record that is not a plain file holding a whole number, an optional `held` mark and an optional encoded status state under `idle-record=` and rewritten. A record that cannot be written is reported under `idle-unrecorded=`; under `idle-hold-unrecorded=` where it was to take a hold, which is then not made, since one with no record would be made again on every continued turn; and under `idle-notice-unrecorded=` where it was to count the notice, which the next turn end then reads as the lane's own send. Each of these ends the turn, because nothing a lane does at its turn end repairs its mailbox; an install with no reader leaves the turn unjudged under the marks' own `handoff-skipped` line. On Copilot the event is `agentStop`, registered in Copilot's own hook file under its camelCase name, so the payload spells its fields `sessionId`, `transcriptPath` and `toolArgs`, which this hook reads beside the snake_case spellings; its reference spells `stop_hook_active` so on both, and `toolName` identifies an attached launch. The `lane-mail-halt` description owns the Copilot preToolUse decision and deadline contract. Copilot also runs the hooks `.claude/settings.json` registers, under their PascalCase names, but the registration kendex writes there exits 0 before its script in a Copilot hook process, so a Copilot call reaches an install that is not Copilot's, the claude copy of this hook among them, only through a registration made there by hand or one kendex wrote before that skip and no refresh has rewritten. Whether Copilot made the call is read from the call, never from the install: a payload carrying `timestamp`, which both of Copilot's payload formats carry and no Claude, Codex or Pi payload does, or naming the session `sessionId`, is Copilot's, and any install but Copilot's own passes it silently, exit 0 with nothing written and nothing acknowledged, so the Copilot install is the one reader of the mailbox for a Copilot call. A Copilot agentStop names no agent: the stop whose `transcriptPath` sits in the directory named for the `sessionId`, Copilot's `session-state//events.jsonl`, is the lead's and records it, a stop naming a transcript under another directory is read as a subagent's, handed nothing and judged on nothing, and a payload naming no transcript, or no session, is the lead's and records nothing. Copilot CLI 1.0.88 was measured firing agentStop at a custom subagent's end too, with the subagent's own `sessionId` and the lead's `transcriptPath`, which this rule reads as a subagent's. A refusal on Copilot is the documented answer for its event, on stdout beside the keyed stderr line: at a turn end `{"decision":"block","reason":}` with exit 0, which Copilot stops honouring after 8 consecutive blocks, ending that turn unheld, so a handoff refusal holds a Copilot session for 8 continued turns and then returns at its next turn end, and after a tool call `{"additionalContext":}` with exit 0, since Copilot reads a postToolUse answer only at exit 0. A Copilot session's context is read through Copilot's own SDK event `session.usage_info`: the orch `copilot-lane-context` extension, which `open-terminal` installs in a Copilot fleet lane's `COPILOT_HOME` with the EXTENSIONS feature on, runs this hook with the argument `usage` at each reading of the session's root agent, handing it `{session_id, cwd, current_tokens, token_limit}` on stdin, and for a recorded lead session that is a launched lane's lead or the fleet's overseer, named by the same gate every arm that judges the marks asks, it records `current_tokens` as the tokens and, as the capacity, the limit Copilot compacts at: 80 percent of `token_limit`, the SDK's documented `backgroundCompactionThreshold` default, named in the record's `capacity_source`. It writes nothing on stdout; a gap is refused on stderr at exit 2, which the extension writes to the session timeline: `payload=invalid-json`, an orch install it cannot use under the key its turn end reports that gap under, `handoff-skipped=`, `handoff-outside=` or `handoff-unanswered=`, or `context-unrecorded=` for a reading that could not be written, where the session's earlier reading is removed too so its turn end reports the context unmeasured rather than judging an older figure as room. Any other session passes silently. The Copilot turn end judges this session's record under the shared context rule exactly as it judges a transcript reading, the capacity putting the handoff before Copilot's own compaction; no reading of this session, no record or a gap record, is read from the fallback below; where the pending marker the extension leaves at `~/.cache/lane-mail/copilot-usage/` for a reading it handed on and no run has recorded yet still stands after a wait of 5 seconds, the turn end reports `reading-pending=` and passes with the context unmeasured, reading no fallback, since the extension runs for that session, and never judging the earlier record as room, since nothing orders the extension's run before the turn end; and a record that stands and cannot be read is refused under `record=`. Where no pending marker stands and no reading of the extension's stands for this session, no record, one naming another session, a gap record or one the fallback below wrote, which its `capacity_source` tells apart, the turn end reads the fallback: the session record the orch `copilot-statusline` command writes as the account's `statusLine`, under `/lane-status/.json`, through the orch adapter for copilot, which holds the record to the payload's `sessionId`, its `transcriptPath` where one is named, the account directory and a freshness bound, and hands the shared judge the same compaction point of the window as the capacity; that reading is judged and recorded as any other harness's, and a record that does not answer leaves the context unmeasured under `reading-unrecorded=` and `session-record=`, reported and passed, never read as room. An extension reading below the mark is never overridden by a statusLine record past it. Run with `compact` by the lane-mail-compact hook at a preCompact whose `trigger` is `auto`, from a recorded lead session that gate names, it flags that compaction as `compaction.json` beside the reading, the backstop for a turn that crossed into the compaction before a reading past the mark reached a turn end, and the turn end then refuses under `compacted=auto` until the handoff record stands, the overseer's whatever its succession setting; a gap there is refused under `compaction-unrecorded=` on stderr at exit 2, which Copilot shows the operator without holding the compaction. A Copilot account is judged through `lanes pick --lane` like any other. A session the Jarvis runtime launched, which carries `JARVIS_RECORD`, has its lead's tool calls, on Copilot any call under the session id the record's start bound, and on Claude Code its turn ends, stamp that runtime record's launch row once as its Start brief taken, the fact the Jarvis launch worker reads beside the pane; another harness's turn end is no stamp, since Pi's carrier also dispatches it on a run that ended on an error and Codex and Copilot have no turn-failure event to tell one apart; a stamp that cannot be written is reported under `jarvis-rows-unwritten=` and passed, and the next such call writes it. Not run on gemini: it has no Stop event. Not run on antigravity: its Stop payload carries no `stop_hook_active`. +# description: Blocks a lane's turn end while its overseer mailbox holds unread lines, so a directive or a ruling reaches the lane without a keystroke, a pane or a question tool. The lane is the work item `LANE_MAIL_ITEM` names, or the one directory under `/tmp/lane-mail/` whose name lowercases to the current branch; a session with neither is not a lane; a lane whose mailbox holds no unread line passes silently, as does a directory git reports no repository for and that holds no mailbox of its own. The checkout's overseer mailbox, `/tmp/lane-mail/overseer`, has one reader: the session whose tmux server and pane the checkout's oversee workflow state names under `.overseer`, the pair every writer the orch `schemas/workflow-state.md` `overseer` row names writes, `oversee register` among them for a session opened by hand, and the one the fleet's OVERSEER is established by below, so a record naming a dead pane names no reader. The native session must also match the recorded harness, readable caller home and payload session id; `ol_record_heal` binds the first matching native id from the recorded pane, and `oversee register` clears that binding after a resume. Pi and any harness whose `lane_context_caller_home` reports no home compare the harness and native session id only. The pair names a session only on the tmux server started at the record's `server_start`, so a server a tmux restart handed the recorded pid and pane id names no reader either; a record carrying no start at all names the session in that pane, which writes its server's start into it. Where a file stands there, that session is handed the notes `lane-mail peer send --repo` wrote there at its turn end and after its tool calls, under the same `unread=` line, unless a live watch holds the fleet state: the `oversee-watch.pid` record a repeat `oversee-watch` writes beside the fleet state on every surface and removes on exit, judged by the orch `lib/watch-pid.sh` library's `watch_pid_live`, which reads the mailbox itself, so the named session is handed nothing from it beside that watch. A fleet watched in single passes writes no watch record, so its named overseer is handed the notes as `unread=` lines and the next pass does not report them. A Jarvis session's wake, the process `ORCH_WAKE_PROCESS` matches, is no such watch: it moves no cursor, so that session is handed each note in full here once and acknowledges it here, and its wake carries no note's body, at most the count and read command `lane-mail watch` prints. Where the payload's `kendex_ack` is `caller`, which the pi-hooks lane mail wake sends, the context carries the reader's `--ack` command as `kendex_ack` and nothing is acknowledged here: the wake runs it once its send returns, so a send that throws leaves the lines unread. Every other session in the checkout, one the owner opened there for other work included, is handed nothing from that mailbox, and so is a session whose install has no reader beside this hook. For the named session, where the install's `workflow-state path oversee` prints no path, or the library cannot be sourced or answers neither way, the hook refuses, opening `lane-mail-check: fleet-state=` with that file's own words under it; the halt arm never reads that mailbox, a subagent's turn end is handed nothing from it, and a session in a checkout with no overseer mailbox pays two file tests for the question. `` is the lane's root, resolved in this order: `CLAUDE_PROJECT_DIR`, the directory Claude Code started the session in; else the root the launch marker for `LANE_MAIL_ITEM` binds, where that root exists; else the directory the hook runs in, which on Codex and Pi is the session's start directory and on Claude Code without the variable is the call's own. A Claude Code lane working from the main clone is therefore still judged on its own mailbox. A root its launch marker binds that has no `tmp/lane-mail` directory is refused at a turn end, before any tool call and after the lead's finished one, opening `lane-mail-check: mailbox-missing=` with the marker and the one `mkdir` command that restores the directory, and that command alone passes a tool call. Before a tool call a subagent is refused whatever it runs, and a call whose caller is unknown may run that command; after one a subagent is handed nothing and refused nothing, as with any mail, and its next call meets the refusal. The marker is looked up for the item `LANE_MAIL_ITEM` names or else the branch names, so that check costs one stat in a repository whose common git directory holds no `lane-mail` directory, and one branch read and one marker stat in one that does. A mailbox belongs to a lane only where a launch recorded one: `open-terminal` and `lane-host create` write the lane's root to `lane-mail/` under the repository's common git directory and create the lane's own `tmp/lane-mail/`, and a mailbox with no marker bound to this root passes silently. Unread lines are peeked through the orch skill's own `lane-mail inbox --peek`, the one reader of the mailbox and its cursor, and acknowledged with `inbox --ack` only once the refusal is written, so a hook killed at its budget leaves them unread and a line acknowledged here is never handed over twice. That reader is resolved from this hook's own install, walking up to the home directory for `skills/mailbox/scripts/lane-mail` or the shared `.agents/skills/mailbox/scripts/lane-mail` beside it, then the home's own shared tree for a harness root relocated out of it; the open repository's `.agents/skills/mailbox/scripts/lane-mail` is used only where this hook is installed in that repository, and a reader outside that containment is refused rather than run. The refusal opens with `lane-mail-check: unread=` and carries one JSON envelope per line under it, and for the lead, where a halt is among them, the one `lane-mail inbox` command that reads it; the turn then continues with them. Run with the argument `deliver` by the lane-mail-deliver hook after a tool call, it exits 0 with the harness's JSON on stdout, whose `additionalContext` carries the same lines. That run first judges the context mark of the fleet's OVERSEER, below, for a lead's call in tmux in a checkout whose `tmp/lane-mail/overseer` directory stands, so a mark crossed mid-turn is read at the next tool call: the context is read and recorded as the overseer's turn end reads it and judged at `ORCH_HANDOFF_CONTEXT_PCT` by the rule the orch `references/oversee-events.md` § Judgement rules states for the overseer's context mark. On Pi the window is the payload's own `context_window`, which the pi-hooks carrier puts on the PostToolUse payload of every tool call; a Pi payload naming none, the lane mail wake's run or a tool call from an older carrier, takes no reading, writes no record and hands nothing over, so the turn end's reading and judgement stand. A reached mark, or a setting it cannot be judged on, is handed over as that `additionalContext`, opening `lane-mail-check: context=` with the succession and the handoff record as the route, at every tool call until that record stands. Every other line that judgement writes, a judgement that could not run, a transcript it could not read or an `orch-env` this install has not got, is handed over the same way once per session and first line, the last told kept in `tmp/lane-mail/overseer/context-told`, written only once the run's output carrying it is written and cleared by a clean reading; only the bound native session the fleet record names, or the overseer it lost whose native identity still matches a nonempty recorded binding, writes or clears that file. Either opens the same context as any mail the call hands over, above its `unread=` line, and a refusal the mailbox check makes on the same call, above its keyed line, whether that refusal is Copilot's `additionalContext` or stderr at exit 2. The judgement itself refuses no call, and no account is read there. Run with `start` by the lane-mail-start hook at a session start, or with `prompt` by the lane-mail-prompt hook at a prompt, both on Copilot alone, it hands the same lines over the same way. A session start acknowledges them only once that context is written. A prompt leaves the lines unread because Copilot can discard its output, so a later inbox read or hook delivery can repeat them. Neither arm refuses anything: every refusal this description names is its keyed line on stderr at exit 0, with nothing on stdout and nothing acknowledged. Before an attached agent launch, the halt arm also judges the lead of a launched lane or the identified fleet overseer at the context mark, refusing missing context with the orch job runner or a separate session as the route. While an attached agent of the session may still be out, the mark is less ORCH_HANDOFF_AGENT_RESERVE_TOKENS, default 150000 tokens, equality refused: Claude Code reads that roster from its task registry where the payload carries one, else from the transcript's Agent-call results, task notifications, teammate idle notifications and sends, and reads an unreadable roster or an entry neither read classifies as unknown; Codex reads ordered collaboration snapshots, launches and followups from its rollout. Idle, completed, errored, shutdown and not-found children release the reserve; initializing, running and interrupted children keep it. A full unfiltered snapshot replaces earlier unknown observations only when its call does not overlap a launch or followup; pending calls and unreadable current observations keep the roster unknown. After waiting, Codex must call list_agents with no path filter to observe returns. Other harnesses read none, so their rosters are unknown. With none out the launch meets the plain mark. A launch the reserve alone refuses with an agent out is keyed `agent-reserve` and names waiting for those agents, the job runner or a separate session, never a handoff, since the turn end and every succession judge the plain mark. With the roster unknown no wait can be observed, so the refusal is keyed `agent-unobserved` and names the job runner or a separate session, and for a lane its handoff record. On Pi the lead launches through subagent; delegate_subagent carries child identity and is outside this lead-only reserve rule. At a context hold, a live session waits for attached agent returns in this turn; Claude Stop background_tasks is preferred, with the transcript's measured Agent-call results, async launch and teammate spawn records, task notifications, teammate idle notifications and sends as the fallback when absent. Other harnesses name known unfinished children and known output paths, or unknown paths, in the emergency handoff. A standing handoff retains its escape, and the successor reads existing output before repeating work. Run with `halt` by the lane-mail-halt hook before one, it acknowledges nothing and refuses the call while an unread directive sent with `lane-mail send --halt` stands, opening `lane-mail-check: halt=` with the directive and the one `lane-mail inbox` command that reads it, which names the lane's root with `--root` so it reads the same mailbox from any checkout; that command alone passes. Run with `row` and the event by the session-start-row, session-end-row and stop-failure-row hooks, it writes the event row of a session with no lane of its own, only for the pane's top-level harness and, on Copilot, only for a session the caller rule names the lead, through the orch skill's `lib/session-rows.sh`, the file those hooks describe, and refuses nothing: every gap below its payload read is reported and passed; the overseer's own turn end writes a Stop row there through the same library at every turn end, compact, its time, event, harness and session alone, except over a standing StopFailure row, which it lifts and where it keeps the turn's last message. Run with `lane` by the critical-path-deny hook, it prints `lane` where the launch marker for the session's item binds the session's root and its mailbox directory stands, else `none`, records and judges nothing else, and exits 0; a gap past its payload read is reported on stderr and passed with nothing on stdout. On a Pi install a launched lane's lead writes its own turn rows through that library into its mailbox directory, `session-rows.jsonl`: a Stop row at each turn end, carrying the `stopReason` of the turn's last assistant message in the transcript and Pi's `errorMessage` where that reason is `error`, and a PreToolUse row at the first tool call of each turn, after a turn end or on an empty file, written ahead of the mailbox check; oversee-watch and `lanes state` judge a Pi lane idle, working or walled from those rows in place of its pane, and a gap in the write is reported under `lane-rows-skipped` or `lane-rows-unwritten` and passed. The Pi install is the hook directory under `.pi` or `.pi/agent`, or under the user root `PI_CODING_AGENT_DIR` names; an install naming no harness writes no row, which a launched lane's turn end reports under `harness-unlisted`. Who made a call is answered once for every arm: the lead, a subagent, or unknown. A SubagentStop payload or one carrying a non-empty `agent_id` or `agent_type` is a subagent's on every harness, handed no mail and acknowledging none, and while a halt stands refused without that command. On Copilot, whose payloads name no agent, a preToolUse or postToolUse call, a preCompact and a context reading the usage arm is handed are the lead's where the session id they carry is a lead session this install recorded, the one rule for all four: one empty file per session under `~/.cache/lane-mail/copilot-leads`, written at the session's sessionStart, which Copilot fires for the lead alone, and at each turn end the transcript rule below proves the lead's, and pruned at a start once untouched for 30 days. A custom subagent's call was measured on Copilot CLI 1.0.88 carrying its own session id, which nothing recorded; whether a built-in task-tool subagent's calls carry their own session id or the lead's is a pending live-lane proof, and one whose calls carry the lead's is read as the lead, handed the lead's mail after its calls, which marks it read, and under a halt shown the read that clears it. A call whose session is no recorded lead, a custom subagent's among them, is unknown: the deliver arm hands it nothing and acknowledges nothing, writing `lane-mail-check: session-unrecorded=` to stderr, the compact arm flags nothing and writes the same line at exit 0, the usage arm records nothing and refuses under that key at exit 2, so the lead's turn end hands the lines over and acknowledges them, and the halt arm refuses it without showing that command yet passes the command, because the reader's `--ack` stops short of an unread halt and a lead whose record could not be written would otherwise be refused for good; the lead is shown the command by every notice and refusal that hands it the halt, its turn end's included. A record that cannot be written is reported on stderr under `lane-mail-check: lead-unrecorded=`, or `=none` for a session start naming no session id, and never refused. A Copilot sessionStart or userPromptSubmitted is the lead's, and an agentStop is ruled by its transcript, below; a prompt records no lead, since that a subagent's prompt fires no userPromptSubmitted is unmeasured. `stop_hook_active` true skips the mailbox check whole on the turn-end run. The flag is in the payload, so nothing above the payload read knows a turn was continued, and `arm`, the `missing-tools` refusal for `jq` or `cat`, `payload=unreadable` and `payload=invalid-json` are refused on every turn, the continued one included. Below that read one rule holds and every refusal is on one side of it: a refusal the lane itself can clear is still made, and a refusal it cannot is reported on stderr and passed. The lane clears the handoff refusals, and `script`, `setting`, `setting-range` and both `transcript` refusals, by writing its handoff record, and `mailbox-missing` by running the command it names, so those are refused on a continued turn as on any other. It clears `idle` by sending a lane-mail ask or notice, or by updating `tmp/lane-status-.md` under its launch root, so `idle` is refused on a turn another stop hook continued, except on Pi, as the idle rule below states. It clears none of `workdir`, `git`, `item`, `marker` or the `missing-tools` refusal for `git`, `tr`, `awk`, `mktemp` or `tail`, so each of those is reported and the turn ends, where a fresh turn refuses it. The halt arm reports and passes that same set at every tool call: a lane whose tool calls are refused can clear nothing, since clearing it takes a tool call, so there only the payload refusals and the mailbox's own, `reader`, `inbox`, `halt` and `mailbox-missing`, are refused, the last two each passing the one command that clears it. The same turn-end run hands the lane off before it runs out, so the handoff never waits on an overseer reading a pane. It reads this session's context use from the `transcript_path` the payload names, through the orch adapter for the harness this hook's install directory names, `.claude/hooks`, `.codex/hooks` or Pi's `kendex/hooks`: the tokens the last response left in context and effective capacity, with Pi reading the payload's own `context_window`. It records that reading as `context.json` in the lane's mailbox directory, where `lanes context` reads it, and refuses the turn end when `lane_context_handoff_due` requires handoff under the shared context rule in orch `references/oversee-events.md`, Judgement rules. It reads the account the credential this session runs on still has through the orch skill's own `lanes pick --lane`, judging a Claude lane on its own model. The picker owns the account handoff decision. For an ordinary account wall, the hook refuses the turn end and names the binding bucket's headroom against `ORCH_HANDOFF_HEADROOM_PCT` (default 3). When that picker reports `seat-reserve` for an overseer seat, the hook refuses the turn end. That refusal names the binding bucket's headroom and the configured `ORCH_OVERSEER_SEAT_RESERVE_PCT` (default 50) as independent facts. A Pi session's account is the one its model's provider bills, by the orch `lane_pick_harness` rule on the `/` its transcript names: a `pi-claude/` model spends the Claude seat `CLAUDE_CONFIG_DIR` names and is judged there on that model, a `github-copilot/` model spends the Copilot pool on Pi's own root, and any other provider, or a reading naming none, is left unjudged under `account=unmeasured`. A lane's context and account mark refusals open `lane-mail-check: context=`, `lane-mail-check: headroom= bucket= mark=` or `lane-mail-check: seat-reserve= bucket= reserve=`. Each carries one instruction: reach the next safe point, write the record with `workflow-state set handoff`, send a `handoff` notice, and exit. The record is read where `workflow-state --help` § Handoff record says, a launched lane naming the root its launch marker binds as the worktree, and the instruction names the state directory the read found, so a record written as told ends both refusals. The instruction opens with the `workflow-state init ` that `set` needs where the item has no state file yet, so it is enough on its own. It repeats at every turn end, `stop_hook_active` included, until the item's workflow state carries a `.handoff` object no relaunch has resumed; only the lane can write that record, so a single refusal it declines to act on would end the session with nothing recorded. That record is judged before every mark, before every read they rest on and before `orch-env` and `lanes` are looked for, so no failure but the record's own writer can hold a lane that has already done what it was asked. `orch-env` or `lanes` missing from this hook's install, a mark setting that is not a whole number in range, and a transcript the payload names and nothing can read are refusals too, each on the lane path alone and each carrying the same instruction. What the marks cannot judge is reported and passed, never refused: a payload naming no transcript leaves the context unread, and so does a transcript whose last usage line is an object carrying none of the field names its adapter reads, which is reported under `usage-unread=` rather than summed to a figure of zero and read as room, a reading below the independent token limit whose capacity the adapter could not name, reported under `window-unread=`, and an install directory naming no harness, reported under `harness-unlisted=`; a reading that could not be recorded is reported under `context-unrecorded=` and still judged; an account `lanes` keeps no inventory for, one it could not measure and a read that passed this hook's own ceiling each leave the account unjudged under `account=unlisted`, `account=unmeasured` or `account=timeout`, never read as room, so a setup with no usage endpoint still ends its turns; and a lane whose handoff record cannot be judged leaves both marks unjudged under one of four keys, `handoff-skipped=` for a reader or a script this install has not got, or `handoff-skipped=unlocatable` where this hook's own directory could not be resolved and none of them could be looked for, `handoff-outside=` for one only the open repository supplies, `handoff-unanswered=` for one that is there and answered nothing this hook can read, and `handoff-unreadable=` for a state file the install's own `workflow-state` could not read. Passing the turn is the answer for all four. For the first three it is because an install whose orch scripts cannot answer cannot run `workflow-state set` either, so a lane told to record a handoff with them could never end a turn again; for `handoff-unreadable` the install answers and the fault is the item's own state file, which is the file the record would be written into, so that write could not land either and the refusal would be as uncloseable. A subagent's turn end is judged on neither mark. The fleet's OVERSEER meets four triggers of its own on its turn end: a session with no lane of its own whose tmux server and pane are the pair the oversee workflow state records under `.overseer` is that overseer, and nothing weaker establishes one, so an ordinary session in a fleet checkout is judged on nothing. A session whose native identity matches a nonempty binding in the fleet record but whose pane only the overseer's `context.json` names, the overseer the record lost, is judged on nothing either, and reports `pane-unrecorded=` with the recorded key under it and writes that record with no reading and the gap `pane-unrecorded`; any other session the record does not name writes nothing, so the real overseer's reading stands. A fleet record naming this session's pane that lacks its server start, its harness, its launch home or its native session id is healed from an authorized native session first, at a turn end and at a tool call alike: the start of this session's own tmux server, the harness this install names and the launch home the harness variable of this session's own environment carries, `CLAUDE_CONFIG_DIR`, `CODEX_HOME` or `COPILOT_HOME` or that harness's default where it is unset, are written into it through the orch `lib/overseer-launch.sh` `ol_record_heal`, which writes only a fact the record lacks, and the transcript is bound to that home on the same run; a write that fails is reported under `record-unhealed=` with the writer's words, and the caller remains unbound until a later binding write succeeds. Before it reads that transcript for the overseer it binds it to the current session: the `transcript_path` the payload names is read only where it is this session's own native file, held to the `session_id` the payload carries and the launch home the fleet record names under `.overseer.home`, through the orch adapter for a claude, codex or copilot install; a Pi install states no transcript shape and reads the payload's own window as a Pi lane does. If `lane_context_transcript_owned` refuses an admitted overseer's transcript binding, the hook reports `transcript-unowned=` with the reason the library returns. Nothing is read then, and the context record is written with a null token count and that reason as its `gap` (orch `workflow-state.md`, `context.json` row), so it still advances at every turn end and oversee-watch reports the gap, and the judge is handed this install's harness and no context figure, so it judges the account triggers alone, the `transcript-unowned` line is this hook's one report that the context went unmeasured, and a session is never judged on a file it does not own. Every overseer turn end whose orch context library loads writes that record, a reading or a null token count with a `gap` naming why none was taken: the binding library's reason, `transcript-unnamed` for a payload naming no transcript, `usage-absent` for a transcript holding no usage line, `usage-unread` for a usage object its adapter does not read, which is also reported under `usage-unread=`, `session-record` for a Copilot session with no extension reading whose statusLine session record does not answer either, which is also reported under `session-record=`, or `pane-unrecorded` below. A Copilot statusLine record reporting allow_all_enabled false, read whether or not an extension reading stands, in a session whose `COPILOT_ALLOW_ALL` is true (a launch line granting `--allow-all` or `--yolo`), is reported under `stop-cause=allow-all-blocked-by-policy`, and the turn end judged as usual. An install naming no harness an adapter reads writes no gap, since its context is never read, and leaves the record as it was, and a Copilot one names none where the reading its usage arm wrote for this session stands, its turn end reading that record rather than taking a reading of its own; a gap record that cannot be written is reported under `context-gap-unrecorded=`, the record keeping its earlier entry. This hook records the overseer's own context reading as `context.json` in the overseer mailbox directory at the main checkout, naming the session and its pane, and hands that reading to `oversee-succeed --check-marks --context :` from this hook's own install, which judges those marks on it and on no stored figure, and nothing at the turn end here judges them, under the same ceiling the account read runs under, so the turn-end refusal and the `overseer-mark` watch event cannot describe one overseer differently. Its refusal opens with the `context=`, `headroom=`, `rate=` or `qualifying=` key, carrying the figure that judgement read, and names `oversee-succeed`, handed the same reading, as the route, with `workflow-state set oversee handoff` under it for a succession that refuses, so the refusal always has an escape the overseer can reach. That record names the session that wrote it, in the native `session_id` the payload gives. A payload with no native session id is refused and cannot read mail or write overseer context or gaps. `overseer_identify` owns its native refusal diagnostics. One other refusal stands on that path, `script` for an `oversee-succeed` this install has not got, and the record clears it as it clears the marks. `ORCH_OVERSEER_SUCCESSION=off`, read off the judgement's own line and never here, turns the account-mark refusals off with the succession they name, the watch's `overseer-mark` event still reporting those marks; the context mark is refused whatever the setting, since no watch event reports it, and the handoff record ends that refusal. An answer this hook cannot act on, one the ceiling abandoned, and one whose own reading was unmeasured are reported under `marks=unjudged`, `marks=timeout` and `marks=unmeasured` and the turn ends, never held. A lane asks its overseer only through lane mail. Before a tool call in a launched lane, the halt arm refuses the harness question tool by its name, whichever of the four names the payload's `tool_name` carries, Claude Code's `AskUserQuestion` and `EnterPlanMode`, Codex's `request_user_input` and Pi's `question`, opening `lane-mail-check: question-tool=` and naming the `lane-mail ask --item --file ` send and the `lane-mail wait` on its printed id as the route, because a dialog on the pane reaches no overseer; an unread halt is refused ahead of it, a subagent's call is refused and told to report its question to the lead, and a session that is no launched lane passes the call silently, a committed mailbox and status file included. At a launched lane lead's turn end, once the handoff marks pass, the lane is judged idle on lane-mail sends and its lane status file update state, never on words in its pane, on Claude Code, Codex, Pi and Copilot; OpenCode and Cursor run no kendex hooks, and Gemini and Antigravity do not run this one, so a lane there is never judged idle. The reader's own `lane-mail events` listing, which moves no cursor, counts the asks and notices in the lane's outbound file against the count this hook recorded at the lane's last judged turn end, `sent-count` in the lane's mailbox directory: a line holding the count, the word `held` where this judge refused that turn end, and an optional encoded status file update state; no record is a count of zero with no status state. A status file update since that record, including a rewrite of the same text, passes without a notice. A count other than the recorded one is a send this turn and passes, a standing handoff record ends the run before this judge, the newest directive the overseer sent carrying `halt` passes, and a lane whose launch marker no longer binds its root, the close-out's state, is no lane. With none of these the turn is refused and the hold recorded, opening `lane-mail-check: idle=` with one continuation, the lane's `lane-mail inbox` read and then its workflow, beside the ask route and the `lane-mail notice` send, which follows the orch Coordination notice rule: changed work sends a notice, and a continuing wait on a dispatched agent or an armed wake updates the lane status file only. On a turn the harness continued for this judge's own recorded hold it refuses nothing and sends the overseer a lane notice stating what it checked, opening `lane-mail-check: idle-notice=`, or `idle-notice-unsent=` with the sender's words where the send fails, so an idle lane is reported and never looped. A turn another stop hook's refusal continued is held as a fresh one, except on Pi, whose pi-hooks carrier runs no further request after a continued turn, so there the notice is sent with no hold before it. The record counts that notice, so the lane's next turn is judged on what the lane itself sends. An `events` listing that fails, or whose envelopes jq cannot read, is reported under `events=` or `events=envelope`, and a record that is not a plain file holding a whole number, an optional `held` mark and an optional encoded status state under `idle-record=` and rewritten. A record that cannot be written is reported under `idle-unrecorded=`; under `idle-hold-unrecorded=` where it was to take a hold, which is then not made, since one with no record would be made again on every continued turn; and under `idle-notice-unrecorded=` where it was to count the notice, which the next turn end then reads as the lane's own send. Each of these ends the turn, because nothing a lane does at its turn end repairs its mailbox; an install with no reader leaves the turn unjudged under the marks' own `handoff-skipped` line. On Copilot the event is `agentStop`, registered in Copilot's own hook file under its camelCase name, so the payload spells its fields `sessionId`, `transcriptPath` and `toolArgs`, which this hook reads beside the snake_case spellings; its reference spells `stop_hook_active` so on both, and `toolName` identifies an attached launch. The `lane-mail-halt` description owns the Copilot preToolUse decision and deadline contract. Copilot also runs the hooks `.claude/settings.json` registers, under their PascalCase names, but the registration kendex writes there exits 0 before its script in a Copilot hook process, so a Copilot call reaches an install that is not Copilot's, the claude copy of this hook among them, only through a registration made there by hand or one kendex wrote before that skip and no refresh has rewritten. Whether Copilot made the call is read from the call, never from the install: a payload carrying `timestamp`, which both of Copilot's payload formats carry and no Claude, Codex or Pi payload does, or naming the session `sessionId`, is Copilot's, and any install but Copilot's own passes it silently, exit 0 with nothing written and nothing acknowledged, so the Copilot install is the one reader of the mailbox for a Copilot call. A Copilot agentStop names no agent: the stop whose `transcriptPath` sits in the directory named for the `sessionId`, Copilot's `session-state//events.jsonl`, is the lead's and records it, a stop naming a transcript under another directory is read as a subagent's, handed nothing and judged on nothing, and a payload naming no transcript, or no session, is the lead's and records nothing. Copilot CLI 1.0.88 was measured firing agentStop at a custom subagent's end too, with the subagent's own `sessionId` and the lead's `transcriptPath`, which this rule reads as a subagent's. A refusal on Copilot is the documented answer for its event, on stdout beside the keyed stderr line: at a turn end `{"decision":"block","reason":}` with exit 0, which Copilot stops honouring after 8 consecutive blocks, ending that turn unheld, so a handoff refusal holds a Copilot session for 8 continued turns and then returns at its next turn end, and after a tool call `{"additionalContext":}` with exit 0, since Copilot reads a postToolUse answer only at exit 0. A Copilot session's context is read through Copilot's own SDK event `session.usage_info`: the orch `copilot-lane-context` extension, which `open-terminal` installs in a Copilot fleet lane's `COPILOT_HOME` with the EXTENSIONS feature on, runs this hook with the argument `usage` at each reading of the session's root agent, handing it `{session_id, cwd, current_tokens, token_limit}` on stdin, and for a recorded lead session that is a launched lane's lead or the fleet's overseer, named by the same gate every arm that judges the marks asks, it records `current_tokens` as the tokens and, as the capacity, the limit Copilot compacts at: 80 percent of `token_limit`, the SDK's documented `backgroundCompactionThreshold` default, named in the record's `capacity_source`. It writes nothing on stdout; a gap is refused on stderr at exit 2, which the extension writes to the session timeline: `payload=invalid-json`, an orch install it cannot use under the key its turn end reports that gap under, `handoff-skipped=`, `handoff-outside=` or `handoff-unanswered=`, or `context-unrecorded=` for a reading that could not be written, where the session's earlier reading is removed too so its turn end reports the context unmeasured rather than judging an older figure as room. Any other session passes silently. The Copilot turn end judges this session's record under the shared context rule exactly as it judges a transcript reading, the capacity putting the handoff before Copilot's own compaction; no reading of this session, no record or a gap record, is read from the fallback below; where the pending marker the extension leaves at `~/.cache/lane-mail/copilot-usage/` for a reading it handed on and no run has recorded yet still stands after a wait of 5 seconds, the turn end reports `reading-pending=` and passes with the context unmeasured, reading no fallback, since the extension runs for that session, and never judging the earlier record as room, since nothing orders the extension's run before the turn end; and a record that stands and cannot be read is refused under `record=`. Where no pending marker stands and no reading of the extension's stands for this session, no record, one naming another session, a gap record or one the fallback below wrote, which its `capacity_source` tells apart, the turn end reads the fallback: the session record the orch `copilot-statusline` command writes as the account's `statusLine`, under `/lane-status/.json`, through the orch adapter for copilot, which holds the record to the payload's `sessionId`, its `transcriptPath` where one is named, the account directory and a freshness bound, and hands the shared judge the same compaction point of the window as the capacity; that reading is judged and recorded as any other harness's, and a record that does not answer leaves the context unmeasured under `reading-unrecorded=` and `session-record=`, reported and passed, never read as room. An extension reading below the mark is never overridden by a statusLine record past it. Run with `compact` by the lane-mail-compact hook at a preCompact whose `trigger` is `auto`, from a recorded lead session that gate names, it flags that compaction as `compaction.json` beside the reading, the backstop for a turn that crossed into the compaction before a reading past the mark reached a turn end, and the turn end then refuses under `compacted=auto` until the handoff record stands, the overseer's whatever its succession setting; a gap there is refused under `compaction-unrecorded=` on stderr at exit 2, which Copilot shows the operator without holding the compaction. A Copilot account is judged through `lanes pick --lane` like any other. A session the Jarvis runtime launched, which carries `JARVIS_RECORD`, has its lead's tool calls, on Copilot any call under the session id the record's start bound, and on Claude Code its turn ends, stamp that runtime record's launch row once as its Start brief taken, the fact the Jarvis launch worker reads beside the pane; another harness's turn end is no stamp, since Pi's carrier also dispatches it on a run that ended on an error and Codex and Copilot have no turn-failure event to tell one apart; a stamp that cannot be written is reported under `jarvis-rows-unwritten=` and passed, and the next such call writes it. Not run on gemini: it has no Stop event. Not run on antigravity: its Stop payload carries no `stop_hook_active`. # summary: Uses orch and mailbox to hand lanes their overseer's mail and hold turn ends for handoff or idle checks, plus a `wake=unarmed` refusal for the registered overseer without its repeat follow or the Jarvis session whose `ORCH_WAKE_PROCESS` does not match, printing `ORCH_WAKE_START`; empty Jarvis session keys with no watch claim disable the check, and a running single pass is its own wake. Pi's wake check is partial; a continued turn or an unavailable check only warns. # safety: Reads the payload, the repository's branch, the lane's launch marker, read with the shell's own `read`, and the lane mailbox directory, and for a session that is no lane the checkout's overseer mailbox and, where a file stands there and the fleet record names this session's pane, the fleet state's path from the identity read, with `workflow-state path oversee` as its fallback and the watch record beside it, read by the orch watch record library `lib/watch-pid.sh` sourced in a child shell from the same install as the mailbox reader, which checks the record's pid with `kill -0` and `ps`; the writes are the mailbox cursor the orch reader advances, the session's context reading, `context.json`, and a Copilot session's compaction flag, `compaction.json`, each renamed into its mailbox directory, and on a Pi lane its turn rows, `session-rows.jsonl`, appended there under that file's own lock at a turn end and at the first tool call of each turn, and for the overseer one row appended to its rows file, `session--.jsonl` in the overseer mailbox directory, under that file's own lock, a compact Stop at every overseer turn end, the overseer's directory made where the fleet has not made it yet, the fleet record's `.overseer` server start, harness, launch home and native session id where a record naming this session's pane lacks one, through `workflow-state update oversee`, and after each overseer tool call its `context.json` and, where a gap is told, `tmp/lane-mail/overseer/context-told`, and on Copilot a lead session's empty record under `~/.cache/lane-mail/copilot-leads`, touched at its session start and at each turn end its transcript proves the lead's, with records untouched for 30 days removed by one `find` at each start, as are the extension's pending markers under `~/.cache/lane-mail/copilot-usage`, which a Copilot turn end reads and polls for 5 seconds. For a session the Jarvis runtime launched it also reads, at its lead's tool calls and Claude Code, Codex and Copilot CLI turn ends, the runtime record `JARVIS_RECORD` names, in one child shell sourcing the orch session rows library from the same install, and where that launch is starting and unstamped, reads it again under that record's `.lock` and renames a new record over it once: at a tool call or Claude Code turn end with its brief delivered, stamping its launch row's `brief_taken`; at a Codex or Copilot CLI turn end before the brief, stamping its `kickoff_ended`. Exit 2 names the unread count and the messages, and asks for them to be acted on, never bypassed. The reader it runs comes from its own install, never from the repository a session has open, so a repository that tracks a mailbox and an executable at that path cannot have it run. jq and cat read the payload; a payload it cannot read is refused on every turn, the continued one included, because the flag that marks a continued turn is in the payload none of those refusals reached. A mailbox whose reader is missing or fails is refused on the turns the mailbox check runs, which is every turn end but a continued one; on a continued turn that check is skipped whole, and the same missing reader is reported under `handoff-skipped` or `handoff-outside` and the turn is passed. An item name outside the alphabet a work item is spelled in, a branch that matches more than one mailbox, and a repository state git cannot report where a mailbox sits under the working directory are refused on a fresh turn and reported on a continued one and before a tool call, by the one rule the description states; none of them is ever passed in silence. For a lane's handoff marks it also reads the transcript the payload names and runs `orch-env`, `lanes` and `workflow-state` and sources the orch context library from the same install as the mailbox reader, never the open repository's, and on Pi one child shell sourcing that install's `lib/lane-launch.sh` to name the account the session's provider bills; the context reading is the one thing it writes for them. A session that names no lane costs two file tests of the checkout's overseer mailbox; where a file stands there it adds that install's resolution and, inside tmux, the overseer test below, and for the session the record names the identity read's fleet path, one child shell sourcing the watch record library, and the reader's peek where no live watch stands. Outside tmux it costs nothing more, where the overseer test stops at its first condition. After a tool call a lead session with no lane of its own, in tmux, in a checkout with no `tmp/lane-mail/overseer` directory costs one stat more; where that directory stands it pays the overseer test below, and for the overseer one transcript read, one `workflow-state handoff-standing`, one `orch-env` read and one record write, the reads the turn end makes but for the account judgement; the overseer test runs once per call, and the mailbox check takes its answer. Inside tmux the overseer test resolves that install and reads the caller's pane key, the fleet record and the server start in a child shell loading the orch context and overseer launch libraries and their dependencies. A required heal loads `lib/overseer-launch.sh` and its dependencies in a child shell and rechecks the recorded native identity before the state update; a session whose native identity matches a nonempty recorded binding but whose pane the state does not name adds one child shell loading the orch context library, one `git-context` call and one read of the overseer's `context.json`; where that record names this session's pane, it reports `pane-unrecorded` and rewrites that record. Any other unbound caller stops before those context reads and writes. The overseer's own marks are then judged by `oversee-succeed --check-marks` from that same install, under the same 20 second ceiling the lane's account read runs under. That judgement measures the one account the overseer session runs on, through the same `lanes pick --lane` this hook asks about a lane, renewing an expired token in that account's credential file and refreshing that account's usage cache, the writes `lanes` states in its own contract; it opens no window and launches nothing. The context-usage reader first parses the last 1 MiB, and reads the whole file only when that window carries no usage line. When native Claude Stop background_tasks is absent, the transcript roster fallback reads complete ordered history; its work grows with transcript size. It runs only under the remaining hook deadline, with three seconds reserved for refusal emission and a one-second kill grace. An unavailable bound, exhausted budget, timeout or failed parse reports agents=unknown and discards partial rows. `lanes pick --lane` judges a Claude lane on its own model, measures one account and renews that account's expired token, the write its own contract states; it can wait on a credentials lock and two network calls, and on a cache miss on the host-wide usage refresh lock for up to 10 seconds and, after a 429 with nothing cached, one sleep of up to 5 seconds and one more usage request, so it runs under a 20 second ceiling that leaves the rest of the run inside this hook's 30 second budget, and a read that reaches the ceiling is reported as a gap rather than refused. Where `timeout` is not installed that read runs unbounded, and a hook the harness then kills at its budget leaves the account unjudged, the same outcome the reported gap gives without the line. Before a tool call it reads `tool_name` or Copilot `toolName`; the question-tool rule and attached-launch check consume that normalized name. For the idle judge at a lane lead's turn end it runs the reader's `events` listing, which moves no cursor, and reads the kind, the box and the halt flag of each envelope, never its text and never the transcript; it reads stat metadata for the fixed regular `tmp/lane-status-.md` file under the lane's launch root, with no symbolic link at the status file itself, and writes that update state beside the count in the lane's `sent-count` record, renamed into its mailbox directory, and the one idle notice the description names, through the reader's `notice`. Every refusal opens with `lane-mail-check: =`; what a command this hook runs writes is captured at the site and replayed under that line, so nothing precedes the key. For a launched lane or the bound fleet overseer, PostModelSwitch reads its to_model target and the recorded launch identity. It writes model checks and switch history through workflow-state. A lane replacement that reaches its first Stop without a mismatch writes one model-recovery-reset row and a passed model check in the same fleet state. Lane recovery preserves the standing handoff and checks the recorded arguments before stopping the verified predecessor through the existing lane stop owner. Account selection and launch follow that stop. Overseer recovery passes a durable handoff to oversee-succeed. That owner preserves the executable model selector and account, verifies the successor, then stops its predecessor. Unreadable PostModelSwitch dependencies reach the model as once-only unavailable context. A failed first-turn reset reports a keyed Stop warning on stderr and leaves later checks active. # timeout: 30 @@ -50,7 +50,7 @@ UNREAD="" HALT_TEXT="" ACK_COMMAND="" MAILBOX_COMMAND="" -# The handoff marks: the two settings judged and the commands that end the +# The handoff marks: the settings judged and the commands that end the # refusal, and the window the context mark is judged against. Empty until each # is known. MARK="" @@ -218,6 +218,8 @@ message() { # KEY VALUE [CAUSE] { if [ "$1" = headroom ] && [ "$ROLE" = lane ]; then printf 'lane-mail-check: headroom=%s bucket=%s mark=%s\n' "$2" "$BINDING_BUCKET" "$PCT" + elif [ "$1" = seat-reserve ]; then + printf 'lane-mail-check: seat-reserve=%s bucket=%s reserve=%s\n' "$2" "$BINDING_BUCKET" "$PCT" else printf 'lane-mail-check: %s=%s\n' "$1" "$2" fi @@ -456,6 +458,10 @@ message() { # KEY VALUE [CAUSE] "$BINDING_BUCKET" "$2" "$PCT" "$HANDOFF_INSTRUCTION" fi ;; + seat-reserve=*) + printf 'The account picker requires handoff from this overseer seat. The binding bucket %s has %s percent headroom left. ORCH_OVERSEER_SEAT_RESERVE_PCT is %s. No handoff record stands. Hand this lane off at the next safe point.\n%s\n' \ + "$BINDING_BUCKET" "$2" "$PCT" "$HANDOFF_INSTRUCTION" + ;; rate=*) printf 'oversee-succeed projects that this overseer account will reach its wall in %s minutes, at or before the ORCH_OVERSEER_WALL_MINUTES mark of %s. Succeed this session yourself before the account walls.\n%s\n' \ "$2" "$MARK" "$HANDOFF_INSTRUCTION" @@ -3427,10 +3433,10 @@ handoff_check() { fi # The account the credential THIS session runs on still has, judged by the - # one script that measures a lane and against the one setting that marks a - # lane for handoff. `pick --lane` answers about that directory alone: 0 has - # room, 3 is at or below the mark, and 4 is a directory that is no configured - # lane of this harness. Every other exit, and a read that passes the ceiling, + # one script that measures a lane and judges its handoff marks. + # `pick --lane` answers about that directory alone: 0 has room, 3 reaches + # the headroom mark or overseer seat reserve, and 4 is a directory that is + # no configured lane of this harness. Every other exit, and a read that passes the ceiling, # is an account nothing measured: reported and passed, never read as room and # never held, because a setup with no usage endpoint must still end its turns. # `lanes` keeps an inventory for claude, codex and copilot, and a Pi lane is @@ -3465,9 +3471,9 @@ handoff_check() { ${PICK_MODEL[@]+"${PICK_MODEL[@]}"} --min-headroom-pct "$PCT" --json 2>"$WORK_DIR/lanes.err") || PICK_RC=$? # `lanes` keeps a status-only contract where `workflow-state handoff-standing` # could not, and one reservation is what makes that safe here: every status - # with an arm of its own below — 3 for a lane at its mark, 4 for one this - # harness keeps no inventory for, 124 for a read the ceiling abandoned — is - # one no death before the verb can produce. `lanes` loads the same + # with an arm of its own below (3 for a lane at its mark or seat reserve, + # 4 for one this harness keeps no inventory for, 124 for a read the ceiling + # abandoned) is one no death before the verb can produce. `lanes` loads the same # `.env.local` through the same loader, and a file bash 3.2 cannot parse # kills it with 1 or 2; both fall to `*` and are reported as an account # nothing measured, which is as true of a script that died in its loader as @@ -3479,10 +3485,22 @@ handoff_check() { 3) # pick's wall is the binding bucket's used percent, including a scoped # model window. Account-wide headroom can still show room at that wall. - BINDING=$(jq -r '[.binding_bucket // "unknown", + # Only seat-reserve keeps its verdict in pick's public record; the + # ordinary wall omits it. Exit 3 alone cannot name the reached mark. + BINDING=$(jq -r '[.verdict // "walled", .binding_bucket // "unknown", (if .wall == null then "unknown" else 100 - .wall end)] | @tsv' <<<"$PICK" 2>/dev/null) || - BINDING=$'unknown\tunknown' - IFS=$'\t' read -r BINDING_BUCKET HEADROOM <<<"$BINDING" + BINDING=$'unknown\tunknown\tunknown' + IFS=$'\t' read -r PICK_VERDICT BINDING_BUCKET HEADROOM <<<"$BINDING" + case "$PICK_VERDICT" in + seat-reserve) + PCT=$("$SCRIPTS/orch-env" ORCH_OVERSEER_SEAT_RESERVE_PCT 50 2>"$WORK_DIR/env.err") || + refuse_handoff setting ORCH_OVERSEER_SEAT_RESERVE_PCT "$(cat -- "$WORK_DIR/env.err")" + percent_in_range "$PCT" || refuse_handoff setting-range "ORCH_OVERSEER_SEAT_RESERVE_PCT=$PCT" + refuse_handoff seat-reserve "$HEADROOM" + ;; + walled) ;; + *) message account unmeasured "lanes pick returned an unreadable refusal record"; return 0 ;; + esac refuse_handoff headroom "$HEADROOM" ;; 4) message account unlisted "$(cat -- "$WORK_DIR/lanes.err")" ;; diff --git a/.codex/hooks/lane-mail-check.sh b/.codex/hooks/lane-mail-check.sh index 73306ecc..ba719e94 100644 --- a/.codex/hooks/lane-mail-check.sh +++ b/.codex/hooks/lane-mail-check.sh @@ -3,7 +3,7 @@ # name: lane-mail-check # event: Stop # matcher: -# description: Blocks a lane's turn end while its overseer mailbox holds unread lines, so a directive or a ruling reaches the lane without a keystroke, a pane or a question tool. The lane is the work item `LANE_MAIL_ITEM` names, or the one directory under `/tmp/lane-mail/` whose name lowercases to the current branch; a session with neither is not a lane; a lane whose mailbox holds no unread line passes silently, as does a directory git reports no repository for and that holds no mailbox of its own. The checkout's overseer mailbox, `/tmp/lane-mail/overseer`, has one reader: the session whose tmux server and pane the checkout's oversee workflow state names under `.overseer`, the pair every writer the orch `schemas/workflow-state.md` `overseer` row names writes, `oversee register` among them for a session opened by hand, and the one the fleet's OVERSEER is established by below, so a record naming a dead pane names no reader. The native session must also match the recorded harness, readable caller home and payload session id; `ol_record_heal` binds the first matching native id from the recorded pane, and `oversee register` clears that binding after a resume. Pi and any harness whose `lane_context_caller_home` reports no home compare the harness and native session id only. The pair names a session only on the tmux server started at the record's `server_start`, so a server a tmux restart handed the recorded pid and pane id names no reader either; a record carrying no start at all names the session in that pane, which writes its server's start into it. Where a file stands there, that session is handed the notes `lane-mail peer send --repo` wrote there at its turn end and after its tool calls, under the same `unread=` line, unless a live watch holds the fleet state: the `oversee-watch.pid` record a repeat `oversee-watch` writes beside the fleet state on every surface and removes on exit, judged by the orch `lib/watch-pid.sh` library's `watch_pid_live`, which reads the mailbox itself, so the named session is handed nothing from it beside that watch. A fleet watched in single passes writes no watch record, so its named overseer is handed the notes as `unread=` lines and the next pass does not report them. A Jarvis session's wake, the process `ORCH_WAKE_PROCESS` matches, is no such watch: it moves no cursor, so that session is handed each note in full here once and acknowledges it here, and its wake carries no note's body, at most the count and read command `lane-mail watch` prints. Where the payload's `kendex_ack` is `caller`, which the pi-hooks lane mail wake sends, the context carries the reader's `--ack` command as `kendex_ack` and nothing is acknowledged here: the wake runs it once its send returns, so a send that throws leaves the lines unread. Every other session in the checkout, one the owner opened there for other work included, is handed nothing from that mailbox, and so is a session whose install has no reader beside this hook. For the named session, where the install's `workflow-state path oversee` prints no path, or the library cannot be sourced or answers neither way, the hook refuses, opening `lane-mail-check: fleet-state=` with that file's own words under it; the halt arm never reads that mailbox, a subagent's turn end is handed nothing from it, and a session in a checkout with no overseer mailbox pays two file tests for the question. `` is the lane's root, resolved in this order: `CLAUDE_PROJECT_DIR`, the directory Claude Code started the session in; else the root the launch marker for `LANE_MAIL_ITEM` binds, where that root exists; else the directory the hook runs in, which on Codex and Pi is the session's start directory and on Claude Code without the variable is the call's own. A Claude Code lane working from the main clone is therefore still judged on its own mailbox. A root its launch marker binds that has no `tmp/lane-mail` directory is refused at a turn end, before any tool call and after the lead's finished one, opening `lane-mail-check: mailbox-missing=` with the marker and the one `mkdir` command that restores the directory, and that command alone passes a tool call. Before a tool call a subagent is refused whatever it runs, and a call whose caller is unknown may run that command; after one a subagent is handed nothing and refused nothing, as with any mail, and its next call meets the refusal. The marker is looked up for the item `LANE_MAIL_ITEM` names or else the branch names, so that check costs one stat in a repository whose common git directory holds no `lane-mail` directory, and one branch read and one marker stat in one that does. A mailbox belongs to a lane only where a launch recorded one: `open-terminal` and `lane-host create` write the lane's root to `lane-mail/` under the repository's common git directory and create the lane's own `tmp/lane-mail/`, and a mailbox with no marker bound to this root passes silently. Unread lines are peeked through the orch skill's own `lane-mail inbox --peek`, the one reader of the mailbox and its cursor, and acknowledged with `inbox --ack` only once the refusal is written, so a hook killed at its budget leaves them unread and a line acknowledged here is never handed over twice. That reader is resolved from this hook's own install, walking up to the home directory for `skills/mailbox/scripts/lane-mail` or the shared `.agents/skills/mailbox/scripts/lane-mail` beside it, then the home's own shared tree for a harness root relocated out of it; the open repository's `.agents/skills/mailbox/scripts/lane-mail` is used only where this hook is installed in that repository, and a reader outside that containment is refused rather than run. The refusal opens with `lane-mail-check: unread=` and carries one JSON envelope per line under it, and for the lead, where a halt is among them, the one `lane-mail inbox` command that reads it; the turn then continues with them. Run with the argument `deliver` by the lane-mail-deliver hook after a tool call, it exits 0 with the harness's JSON on stdout, whose `additionalContext` carries the same lines. That run first judges the context mark of the fleet's OVERSEER, below, for a lead's call in tmux in a checkout whose `tmp/lane-mail/overseer` directory stands, so a mark crossed mid-turn is read at the next tool call: the context is read and recorded as the overseer's turn end reads it and judged at `ORCH_HANDOFF_CONTEXT_PCT` by the rule the orch `references/oversee-events.md` § Judgement rules states for the overseer's context mark. On Pi the window is the payload's own `context_window`, which the pi-hooks carrier puts on the PostToolUse payload of every tool call; a Pi payload naming none, the lane mail wake's run or a tool call from an older carrier, takes no reading, writes no record and hands nothing over, so the turn end's reading and judgement stand. A reached mark, or a setting it cannot be judged on, is handed over as that `additionalContext`, opening `lane-mail-check: context=` with the succession and the handoff record as the route, at every tool call until that record stands. Every other line that judgement writes, a judgement that could not run, a transcript it could not read or an `orch-env` this install has not got, is handed over the same way once per session and first line, the last told kept in `tmp/lane-mail/overseer/context-told`, written only once the run's output carrying it is written and cleared by a clean reading; only the bound native session the fleet record names, or the overseer it lost whose native identity still matches a nonempty recorded binding, writes or clears that file. Either opens the same context as any mail the call hands over, above its `unread=` line, and a refusal the mailbox check makes on the same call, above its keyed line, whether that refusal is Copilot's `additionalContext` or stderr at exit 2. The judgement itself refuses no call, and no account is read there. Run with `start` by the lane-mail-start hook at a session start, or with `prompt` by the lane-mail-prompt hook at a prompt, both on Copilot alone, it hands the same lines over the same way. A session start acknowledges them only once that context is written. A prompt leaves the lines unread because Copilot can discard its output, so a later inbox read or hook delivery can repeat them. Neither arm refuses anything: every refusal this description names is its keyed line on stderr at exit 0, with nothing on stdout and nothing acknowledged. Before an attached agent launch, the halt arm also judges the lead of a launched lane or the identified fleet overseer at the context mark, refusing missing context with the orch job runner or a separate session as the route. While an attached agent of the session may still be out, the mark is less ORCH_HANDOFF_AGENT_RESERVE_TOKENS, default 150000 tokens, equality refused: Claude Code reads that roster from its task registry where the payload carries one, else from the transcript's Agent-call results, task notifications, teammate idle notifications and sends, and reads an unreadable roster or an entry neither read classifies as unknown; Codex reads ordered collaboration snapshots, launches and followups from its rollout. Idle, completed, errored, shutdown and not-found children release the reserve; initializing, running and interrupted children keep it. A full unfiltered snapshot replaces earlier unknown observations only when its call does not overlap a launch or followup; pending calls and unreadable current observations keep the roster unknown. After waiting, Codex must call list_agents with no path filter to observe returns. Other harnesses read none, so their rosters are unknown. With none out the launch meets the plain mark. A launch the reserve alone refuses with an agent out is keyed `agent-reserve` and names waiting for those agents, the job runner or a separate session, never a handoff, since the turn end and every succession judge the plain mark. With the roster unknown no wait can be observed, so the refusal is keyed `agent-unobserved` and names the job runner or a separate session, and for a lane its handoff record. On Pi the lead launches through subagent; delegate_subagent carries child identity and is outside this lead-only reserve rule. At a context hold, a live session waits for attached agent returns in this turn; Claude Stop background_tasks is preferred, with the transcript's measured Agent-call results, async launch and teammate spawn records, task notifications, teammate idle notifications and sends as the fallback when absent. Other harnesses name known unfinished children and known output paths, or unknown paths, in the emergency handoff. A standing handoff retains its escape, and the successor reads existing output before repeating work. Run with `halt` by the lane-mail-halt hook before one, it acknowledges nothing and refuses the call while an unread directive sent with `lane-mail send --halt` stands, opening `lane-mail-check: halt=` with the directive and the one `lane-mail inbox` command that reads it, which names the lane's root with `--root` so it reads the same mailbox from any checkout; that command alone passes. Run with `row` and the event by the session-start-row, session-end-row and stop-failure-row hooks, it writes the event row of a session with no lane of its own, only for the pane's top-level harness and, on Copilot, only for a session the caller rule names the lead, through the orch skill's `lib/session-rows.sh`, the file those hooks describe, and refuses nothing: every gap below its payload read is reported and passed; the overseer's own turn end writes a Stop row there through the same library at every turn end, compact, its time, event, harness and session alone, except over a standing StopFailure row, which it lifts and where it keeps the turn's last message. Run with `lane` by the critical-path-deny hook, it prints `lane` where the launch marker for the session's item binds the session's root and its mailbox directory stands, else `none`, records and judges nothing else, and exits 0; a gap past its payload read is reported on stderr and passed with nothing on stdout. On a Pi install a launched lane's lead writes its own turn rows through that library into its mailbox directory, `session-rows.jsonl`: a Stop row at each turn end, carrying the `stopReason` of the turn's last assistant message in the transcript and Pi's `errorMessage` where that reason is `error`, and a PreToolUse row at the first tool call of each turn, after a turn end or on an empty file, written ahead of the mailbox check; oversee-watch and `lanes state` judge a Pi lane idle, working or walled from those rows in place of its pane, and a gap in the write is reported under `lane-rows-skipped` or `lane-rows-unwritten` and passed. The Pi install is the hook directory under `.pi` or `.pi/agent`, or under the user root `PI_CODING_AGENT_DIR` names; an install naming no harness writes no row, which a launched lane's turn end reports under `harness-unlisted`. Who made a call is answered once for every arm: the lead, a subagent, or unknown. A SubagentStop payload or one carrying a non-empty `agent_id` or `agent_type` is a subagent's on every harness, handed no mail and acknowledging none, and while a halt stands refused without that command. On Copilot, whose payloads name no agent, a preToolUse or postToolUse call, a preCompact and a context reading the usage arm is handed are the lead's where the session id they carry is a lead session this install recorded, the one rule for all four: one empty file per session under `~/.cache/lane-mail/copilot-leads`, written at the session's sessionStart, which Copilot fires for the lead alone, and at each turn end the transcript rule below proves the lead's, and pruned at a start once untouched for 30 days. A custom subagent's call was measured on Copilot CLI 1.0.88 carrying its own session id, which nothing recorded; whether a built-in task-tool subagent's calls carry their own session id or the lead's is a pending live-lane proof, and one whose calls carry the lead's is read as the lead, handed the lead's mail after its calls, which marks it read, and under a halt shown the read that clears it. A call whose session is no recorded lead, a custom subagent's among them, is unknown: the deliver arm hands it nothing and acknowledges nothing, writing `lane-mail-check: session-unrecorded=` to stderr, the compact arm flags nothing and writes the same line at exit 0, the usage arm records nothing and refuses under that key at exit 2, so the lead's turn end hands the lines over and acknowledges them, and the halt arm refuses it without showing that command yet passes the command, because the reader's `--ack` stops short of an unread halt and a lead whose record could not be written would otherwise be refused for good; the lead is shown the command by every notice and refusal that hands it the halt, its turn end's included. A record that cannot be written is reported on stderr under `lane-mail-check: lead-unrecorded=`, or `=none` for a session start naming no session id, and never refused. A Copilot sessionStart or userPromptSubmitted is the lead's, and an agentStop is ruled by its transcript, below; a prompt records no lead, since that a subagent's prompt fires no userPromptSubmitted is unmeasured. `stop_hook_active` true skips the mailbox check whole on the turn-end run. The flag is in the payload, so nothing above the payload read knows a turn was continued, and `arm`, the `missing-tools` refusal for `jq` or `cat`, `payload=unreadable` and `payload=invalid-json` are refused on every turn, the continued one included. Below that read one rule holds and every refusal is on one side of it: a refusal the lane itself can clear is still made, and a refusal it cannot is reported on stderr and passed. The lane clears the two handoff marks, and `script`, `setting`, `setting-range` and both `transcript` refusals, by writing its handoff record, and `mailbox-missing` by running the command it names, so those are refused on a continued turn as on any other. It clears `idle` by sending a lane-mail ask or notice, or by updating `tmp/lane-status-.md` under its launch root, so `idle` is refused on a turn another stop hook continued, except on Pi, as the idle rule below states. It clears none of `workdir`, `git`, `item`, `marker` or the `missing-tools` refusal for `git`, `tr`, `awk`, `mktemp` or `tail`, so each of those is reported and the turn ends, where a fresh turn refuses it. The halt arm reports and passes that same set at every tool call: a lane whose tool calls are refused can clear nothing, since clearing it takes a tool call, so there only the payload refusals and the mailbox's own, `reader`, `inbox`, `halt` and `mailbox-missing`, are refused, the last two each passing the one command that clears it. The same turn-end run hands the lane off before it runs out, so the handoff never waits on an overseer reading a pane. It reads this session's context use from the `transcript_path` the payload names, through the orch adapter for the harness this hook's install directory names, `.claude/hooks`, `.codex/hooks` or Pi's `kendex/hooks`: the tokens the last response left in context and effective capacity, with Pi reading the payload's own `context_window`. It records that reading as `context.json` in the lane's mailbox directory, where `lanes context` reads it, and refuses the turn end when `lane_context_handoff_due` requires handoff under the shared context rule in orch `references/oversee-events.md`, Judgement rules. It reads the account the credential this session runs on still has through the orch skill's own `lanes pick --lane`, judging a Claude lane on its own model, and refuses at or below `ORCH_HANDOFF_HEADROOM_PCT` (default 3). A Pi session's account is the one its model's provider bills, by the orch `lane_pick_harness` rule on the `/` its transcript names: a `pi-claude/` model spends the Claude seat `CLAUDE_CONFIG_DIR` names and is judged there on that model, a `github-copilot/` model spends the Copilot pool on Pi's own root, and any other provider, or a reading naming none, is left unjudged under `account=unmeasured`. Either refusal opens `lane-mail-check: context=` or `lane-mail-check: headroom=` and carries one instruction: reach the next safe point, write the record with `workflow-state set handoff`, send a `handoff` notice, and exit. The record is read where `workflow-state --help` § Handoff record says, a launched lane naming the root its launch marker binds as the worktree, and the instruction names the state directory the read found, so a record written as told ends both refusals. The instruction opens with the `workflow-state init ` that `set` needs where the item has no state file yet, so it is enough on its own. It repeats at every turn end, `stop_hook_active` included, until the item's workflow state carries a `.handoff` object no relaunch has resumed; only the lane can write that record, so a single refusal it declines to act on would end the session with nothing recorded. That record is judged before every mark, before every read they rest on and before `orch-env` and `lanes` are looked for, so no failure but the record's own writer can hold a lane that has already done what it was asked. `orch-env` or `lanes` missing from this hook's install, a mark setting that is not a whole number in range, and a transcript the payload names and nothing can read are refusals too, each on the lane path alone and each carrying the same instruction. What the marks cannot judge is reported and passed, never refused: a payload naming no transcript leaves the context unread, and so does a transcript whose last usage line is an object carrying none of the field names its adapter reads, which is reported under `usage-unread=` rather than summed to a figure of zero and read as room, a reading below the independent token limit whose capacity the adapter could not name, reported under `window-unread=`, and an install directory naming no harness, reported under `harness-unlisted=`; a reading that could not be recorded is reported under `context-unrecorded=` and still judged; an account `lanes` keeps no inventory for, one it could not measure and a read that passed this hook's own ceiling each leave the account unjudged under `account=unlisted`, `account=unmeasured` or `account=timeout`, never read as room, so a setup with no usage endpoint still ends its turns; and a lane whose handoff record cannot be judged leaves both marks unjudged under one of four keys, `handoff-skipped=` for a reader or a script this install has not got, or `handoff-skipped=unlocatable` where this hook's own directory could not be resolved and none of them could be looked for, `handoff-outside=` for one only the open repository supplies, `handoff-unanswered=` for one that is there and answered nothing this hook can read, and `handoff-unreadable=` for a state file the install's own `workflow-state` could not read. Passing the turn is the answer for all four. For the first three it is because an install whose orch scripts cannot answer cannot run `workflow-state set` either, so a lane told to record a handoff with them could never end a turn again; for `handoff-unreadable` the install answers and the fault is the item's own state file, which is the file the record would be written into, so that write could not land either and the refusal would be as uncloseable. A subagent's turn end is judged on neither mark. The fleet's OVERSEER meets four triggers of its own on its turn end: a session with no lane of its own whose tmux server and pane are the pair the oversee workflow state records under `.overseer` is that overseer, and nothing weaker establishes one, so an ordinary session in a fleet checkout is judged on nothing. A session whose native identity matches a nonempty binding in the fleet record but whose pane only the overseer's `context.json` names, the overseer the record lost, is judged on nothing either, and reports `pane-unrecorded=` with the recorded key under it and writes that record with no reading and the gap `pane-unrecorded`; any other session the record does not name writes nothing, so the real overseer's reading stands. A fleet record naming this session's pane that lacks its server start, its harness, its launch home or its native session id is healed from an authorized native session first, at a turn end and at a tool call alike: the start of this session's own tmux server, the harness this install names and the launch home the harness variable of this session's own environment carries, `CLAUDE_CONFIG_DIR`, `CODEX_HOME` or `COPILOT_HOME` or that harness's default where it is unset, are written into it through the orch `lib/overseer-launch.sh` `ol_record_heal`, which writes only a fact the record lacks, and the transcript is bound to that home on the same run; a write that fails is reported under `record-unhealed=` with the writer's words, and the caller remains unbound until a later binding write succeeds. Before it reads that transcript for the overseer it binds it to the current session: the `transcript_path` the payload names is read only where it is this session's own native file, held to the `session_id` the payload carries and the launch home the fleet record names under `.overseer.home`, through the orch adapter for a claude, codex or copilot install; a Pi install states no transcript shape and reads the payload's own window as a Pi lane does. If `lane_context_transcript_owned` refuses an admitted overseer's transcript binding, the hook reports `transcript-unowned=` with the reason the library returns. Nothing is read then, and the context record is written with a null token count and that reason as its `gap` (orch `workflow-state.md`, `context.json` row), so it still advances at every turn end and oversee-watch reports the gap, and the judge is handed this install's harness and no context figure, so it judges the account triggers alone, the `transcript-unowned` line is this hook's one report that the context went unmeasured, and a session is never judged on a file it does not own. Every overseer turn end whose orch context library loads writes that record, a reading or a null token count with a `gap` naming why none was taken: the binding library's reason, `transcript-unnamed` for a payload naming no transcript, `usage-absent` for a transcript holding no usage line, `usage-unread` for a usage object its adapter does not read, which is also reported under `usage-unread=`, `session-record` for a Copilot session with no extension reading whose statusLine session record does not answer either, which is also reported under `session-record=`, or `pane-unrecorded` below. A Copilot statusLine record reporting allow_all_enabled false, read whether or not an extension reading stands, in a session whose `COPILOT_ALLOW_ALL` is true (a launch line granting `--allow-all` or `--yolo`), is reported under `stop-cause=allow-all-blocked-by-policy`, and the turn end judged as usual. An install naming no harness an adapter reads writes no gap, since its context is never read, and leaves the record as it was, and a Copilot one names none where the reading its usage arm wrote for this session stands, its turn end reading that record rather than taking a reading of its own; a gap record that cannot be written is reported under `context-gap-unrecorded=`, the record keeping its earlier entry. This hook records the overseer's own context reading as `context.json` in the overseer mailbox directory at the main checkout, naming the session and its pane, and hands that reading to `oversee-succeed --check-marks --context :` from this hook's own install, which judges those marks on it and on no stored figure, and nothing at the turn end here judges them, under the same ceiling the account read runs under, so the turn-end refusal and the `overseer-mark` watch event cannot describe one overseer differently. Its refusal opens with the `context=`, `headroom=`, `rate=` or `qualifying=` key, carrying the figure that judgement read, and names `oversee-succeed`, handed the same reading, as the route, with `workflow-state set oversee handoff` under it for a succession that refuses, so the refusal always has an escape the overseer can reach. That record names the session that wrote it, in the native `session_id` the payload gives. A payload with no native session id is refused and cannot read mail or write overseer context or gaps. `overseer_identify` owns its native refusal diagnostics. One other refusal stands on that path, `script` for an `oversee-succeed` this install has not got, and the record clears it as it clears the marks. `ORCH_OVERSEER_SUCCESSION=off`, read off the judgement's own line and never here, turns the account-mark refusals off with the succession they name, the watch's `overseer-mark` event still reporting those marks; the context mark is refused whatever the setting, since no watch event reports it, and the handoff record ends that refusal. An answer this hook cannot act on, one the ceiling abandoned, and one whose own reading was unmeasured are reported under `marks=unjudged`, `marks=timeout` and `marks=unmeasured` and the turn ends, never held. A lane asks its overseer only through lane mail. Before a tool call in a launched lane, the halt arm refuses the harness question tool by its name, whichever of the four names the payload's `tool_name` carries, Claude Code's `AskUserQuestion` and `EnterPlanMode`, Codex's `request_user_input` and Pi's `question`, opening `lane-mail-check: question-tool=` and naming the `lane-mail ask --item --file ` send and the `lane-mail wait` on its printed id as the route, because a dialog on the pane reaches no overseer; an unread halt is refused ahead of it, a subagent's call is refused and told to report its question to the lead, and a session that is no launched lane passes the call silently, a committed mailbox and status file included. At a launched lane lead's turn end, once the handoff marks pass, the lane is judged idle on lane-mail sends and its lane status file update state, never on words in its pane, on Claude Code, Codex, Pi and Copilot; OpenCode and Cursor run no kendex hooks, and Gemini and Antigravity do not run this one, so a lane there is never judged idle. The reader's own `lane-mail events` listing, which moves no cursor, counts the asks and notices in the lane's outbound file against the count this hook recorded at the lane's last judged turn end, `sent-count` in the lane's mailbox directory: a line holding the count, the word `held` where this judge refused that turn end, and an optional encoded status file update state; no record is a count of zero with no status state. A status file update since that record, including a rewrite of the same text, passes without a notice. A count other than the recorded one is a send this turn and passes, a standing handoff record ends the run before this judge, the newest directive the overseer sent carrying `halt` passes, and a lane whose launch marker no longer binds its root, the close-out's state, is no lane. With none of these the turn is refused and the hold recorded, opening `lane-mail-check: idle=` with one continuation, the lane's `lane-mail inbox` read and then its workflow, beside the ask route and the `lane-mail notice` send, which follows the orch Coordination notice rule: changed work sends a notice, and a continuing wait on a dispatched agent or an armed wake updates the lane status file only. On a turn the harness continued for this judge's own recorded hold it refuses nothing and sends the overseer a lane notice stating what it checked, opening `lane-mail-check: idle-notice=`, or `idle-notice-unsent=` with the sender's words where the send fails, so an idle lane is reported and never looped. A turn another stop hook's refusal continued is held as a fresh one, except on Pi, whose pi-hooks carrier runs no further request after a continued turn, so there the notice is sent with no hold before it. The record counts that notice, so the lane's next turn is judged on what the lane itself sends. An `events` listing that fails, or whose envelopes jq cannot read, is reported under `events=` or `events=envelope`, and a record that is not a plain file holding a whole number, an optional `held` mark and an optional encoded status state under `idle-record=` and rewritten. A record that cannot be written is reported under `idle-unrecorded=`; under `idle-hold-unrecorded=` where it was to take a hold, which is then not made, since one with no record would be made again on every continued turn; and under `idle-notice-unrecorded=` where it was to count the notice, which the next turn end then reads as the lane's own send. Each of these ends the turn, because nothing a lane does at its turn end repairs its mailbox; an install with no reader leaves the turn unjudged under the marks' own `handoff-skipped` line. On Copilot the event is `agentStop`, registered in Copilot's own hook file under its camelCase name, so the payload spells its fields `sessionId`, `transcriptPath` and `toolArgs`, which this hook reads beside the snake_case spellings; its reference spells `stop_hook_active` so on both, and `toolName` identifies an attached launch. The `lane-mail-halt` description owns the Copilot preToolUse decision and deadline contract. Copilot also runs the hooks `.claude/settings.json` registers, under their PascalCase names, but the registration kendex writes there exits 0 before its script in a Copilot hook process, so a Copilot call reaches an install that is not Copilot's, the claude copy of this hook among them, only through a registration made there by hand or one kendex wrote before that skip and no refresh has rewritten. Whether Copilot made the call is read from the call, never from the install: a payload carrying `timestamp`, which both of Copilot's payload formats carry and no Claude, Codex or Pi payload does, or naming the session `sessionId`, is Copilot's, and any install but Copilot's own passes it silently, exit 0 with nothing written and nothing acknowledged, so the Copilot install is the one reader of the mailbox for a Copilot call. A Copilot agentStop names no agent: the stop whose `transcriptPath` sits in the directory named for the `sessionId`, Copilot's `session-state//events.jsonl`, is the lead's and records it, a stop naming a transcript under another directory is read as a subagent's, handed nothing and judged on nothing, and a payload naming no transcript, or no session, is the lead's and records nothing. Copilot CLI 1.0.88 was measured firing agentStop at a custom subagent's end too, with the subagent's own `sessionId` and the lead's `transcriptPath`, which this rule reads as a subagent's. A refusal on Copilot is the documented answer for its event, on stdout beside the keyed stderr line: at a turn end `{"decision":"block","reason":}` with exit 0, which Copilot stops honouring after 8 consecutive blocks, ending that turn unheld, so a handoff refusal holds a Copilot session for 8 continued turns and then returns at its next turn end, and after a tool call `{"additionalContext":}` with exit 0, since Copilot reads a postToolUse answer only at exit 0. A Copilot session's context is read through Copilot's own SDK event `session.usage_info`: the orch `copilot-lane-context` extension, which `open-terminal` installs in a Copilot fleet lane's `COPILOT_HOME` with the EXTENSIONS feature on, runs this hook with the argument `usage` at each reading of the session's root agent, handing it `{session_id, cwd, current_tokens, token_limit}` on stdin, and for a recorded lead session that is a launched lane's lead or the fleet's overseer, named by the same gate every arm that judges the marks asks, it records `current_tokens` as the tokens and, as the capacity, the limit Copilot compacts at: 80 percent of `token_limit`, the SDK's documented `backgroundCompactionThreshold` default, named in the record's `capacity_source`. It writes nothing on stdout; a gap is refused on stderr at exit 2, which the extension writes to the session timeline: `payload=invalid-json`, an orch install it cannot use under the key its turn end reports that gap under, `handoff-skipped=`, `handoff-outside=` or `handoff-unanswered=`, or `context-unrecorded=` for a reading that could not be written, where the session's earlier reading is removed too so its turn end reports the context unmeasured rather than judging an older figure as room. Any other session passes silently. The Copilot turn end judges this session's record under the shared context rule exactly as it judges a transcript reading, the capacity putting the handoff before Copilot's own compaction; no reading of this session, no record or a gap record, is read from the fallback below; where the pending marker the extension leaves at `~/.cache/lane-mail/copilot-usage/` for a reading it handed on and no run has recorded yet still stands after a wait of 5 seconds, the turn end reports `reading-pending=` and passes with the context unmeasured, reading no fallback, since the extension runs for that session, and never judging the earlier record as room, since nothing orders the extension's run before the turn end; and a record that stands and cannot be read is refused under `record=`. Where no pending marker stands and no reading of the extension's stands for this session, no record, one naming another session, a gap record or one the fallback below wrote, which its `capacity_source` tells apart, the turn end reads the fallback: the session record the orch `copilot-statusline` command writes as the account's `statusLine`, under `/lane-status/.json`, through the orch adapter for copilot, which holds the record to the payload's `sessionId`, its `transcriptPath` where one is named, the account directory and a freshness bound, and hands the shared judge the same compaction point of the window as the capacity; that reading is judged and recorded as any other harness's, and a record that does not answer leaves the context unmeasured under `reading-unrecorded=` and `session-record=`, reported and passed, never read as room. An extension reading below the mark is never overridden by a statusLine record past it. Run with `compact` by the lane-mail-compact hook at a preCompact whose `trigger` is `auto`, from a recorded lead session that gate names, it flags that compaction as `compaction.json` beside the reading, the backstop for a turn that crossed into the compaction before a reading past the mark reached a turn end, and the turn end then refuses under `compacted=auto` until the handoff record stands, the overseer's whatever its succession setting; a gap there is refused under `compaction-unrecorded=` on stderr at exit 2, which Copilot shows the operator without holding the compaction. A Copilot account is judged through `lanes pick --lane` like any other. A session the Jarvis runtime launched, which carries `JARVIS_RECORD`, has its lead's tool calls, on Copilot any call under the session id the record's start bound, and on Claude Code its turn ends, stamp that runtime record's launch row once as its Start brief taken, the fact the Jarvis launch worker reads beside the pane; another harness's turn end is no stamp, since Pi's carrier also dispatches it on a run that ended on an error and Codex and Copilot have no turn-failure event to tell one apart; a stamp that cannot be written is reported under `jarvis-rows-unwritten=` and passed, and the next such call writes it. Not run on gemini: it has no Stop event. Not run on antigravity: its Stop payload carries no `stop_hook_active`. +# description: Blocks a lane's turn end while its overseer mailbox holds unread lines, so a directive or a ruling reaches the lane without a keystroke, a pane or a question tool. The lane is the work item `LANE_MAIL_ITEM` names, or the one directory under `/tmp/lane-mail/` whose name lowercases to the current branch; a session with neither is not a lane; a lane whose mailbox holds no unread line passes silently, as does a directory git reports no repository for and that holds no mailbox of its own. The checkout's overseer mailbox, `/tmp/lane-mail/overseer`, has one reader: the session whose tmux server and pane the checkout's oversee workflow state names under `.overseer`, the pair every writer the orch `schemas/workflow-state.md` `overseer` row names writes, `oversee register` among them for a session opened by hand, and the one the fleet's OVERSEER is established by below, so a record naming a dead pane names no reader. The native session must also match the recorded harness, readable caller home and payload session id; `ol_record_heal` binds the first matching native id from the recorded pane, and `oversee register` clears that binding after a resume. Pi and any harness whose `lane_context_caller_home` reports no home compare the harness and native session id only. The pair names a session only on the tmux server started at the record's `server_start`, so a server a tmux restart handed the recorded pid and pane id names no reader either; a record carrying no start at all names the session in that pane, which writes its server's start into it. Where a file stands there, that session is handed the notes `lane-mail peer send --repo` wrote there at its turn end and after its tool calls, under the same `unread=` line, unless a live watch holds the fleet state: the `oversee-watch.pid` record a repeat `oversee-watch` writes beside the fleet state on every surface and removes on exit, judged by the orch `lib/watch-pid.sh` library's `watch_pid_live`, which reads the mailbox itself, so the named session is handed nothing from it beside that watch. A fleet watched in single passes writes no watch record, so its named overseer is handed the notes as `unread=` lines and the next pass does not report them. A Jarvis session's wake, the process `ORCH_WAKE_PROCESS` matches, is no such watch: it moves no cursor, so that session is handed each note in full here once and acknowledges it here, and its wake carries no note's body, at most the count and read command `lane-mail watch` prints. Where the payload's `kendex_ack` is `caller`, which the pi-hooks lane mail wake sends, the context carries the reader's `--ack` command as `kendex_ack` and nothing is acknowledged here: the wake runs it once its send returns, so a send that throws leaves the lines unread. Every other session in the checkout, one the owner opened there for other work included, is handed nothing from that mailbox, and so is a session whose install has no reader beside this hook. For the named session, where the install's `workflow-state path oversee` prints no path, or the library cannot be sourced or answers neither way, the hook refuses, opening `lane-mail-check: fleet-state=` with that file's own words under it; the halt arm never reads that mailbox, a subagent's turn end is handed nothing from it, and a session in a checkout with no overseer mailbox pays two file tests for the question. `` is the lane's root, resolved in this order: `CLAUDE_PROJECT_DIR`, the directory Claude Code started the session in; else the root the launch marker for `LANE_MAIL_ITEM` binds, where that root exists; else the directory the hook runs in, which on Codex and Pi is the session's start directory and on Claude Code without the variable is the call's own. A Claude Code lane working from the main clone is therefore still judged on its own mailbox. A root its launch marker binds that has no `tmp/lane-mail` directory is refused at a turn end, before any tool call and after the lead's finished one, opening `lane-mail-check: mailbox-missing=` with the marker and the one `mkdir` command that restores the directory, and that command alone passes a tool call. Before a tool call a subagent is refused whatever it runs, and a call whose caller is unknown may run that command; after one a subagent is handed nothing and refused nothing, as with any mail, and its next call meets the refusal. The marker is looked up for the item `LANE_MAIL_ITEM` names or else the branch names, so that check costs one stat in a repository whose common git directory holds no `lane-mail` directory, and one branch read and one marker stat in one that does. A mailbox belongs to a lane only where a launch recorded one: `open-terminal` and `lane-host create` write the lane's root to `lane-mail/` under the repository's common git directory and create the lane's own `tmp/lane-mail/`, and a mailbox with no marker bound to this root passes silently. Unread lines are peeked through the orch skill's own `lane-mail inbox --peek`, the one reader of the mailbox and its cursor, and acknowledged with `inbox --ack` only once the refusal is written, so a hook killed at its budget leaves them unread and a line acknowledged here is never handed over twice. That reader is resolved from this hook's own install, walking up to the home directory for `skills/mailbox/scripts/lane-mail` or the shared `.agents/skills/mailbox/scripts/lane-mail` beside it, then the home's own shared tree for a harness root relocated out of it; the open repository's `.agents/skills/mailbox/scripts/lane-mail` is used only where this hook is installed in that repository, and a reader outside that containment is refused rather than run. The refusal opens with `lane-mail-check: unread=` and carries one JSON envelope per line under it, and for the lead, where a halt is among them, the one `lane-mail inbox` command that reads it; the turn then continues with them. Run with the argument `deliver` by the lane-mail-deliver hook after a tool call, it exits 0 with the harness's JSON on stdout, whose `additionalContext` carries the same lines. That run first judges the context mark of the fleet's OVERSEER, below, for a lead's call in tmux in a checkout whose `tmp/lane-mail/overseer` directory stands, so a mark crossed mid-turn is read at the next tool call: the context is read and recorded as the overseer's turn end reads it and judged at `ORCH_HANDOFF_CONTEXT_PCT` by the rule the orch `references/oversee-events.md` § Judgement rules states for the overseer's context mark. On Pi the window is the payload's own `context_window`, which the pi-hooks carrier puts on the PostToolUse payload of every tool call; a Pi payload naming none, the lane mail wake's run or a tool call from an older carrier, takes no reading, writes no record and hands nothing over, so the turn end's reading and judgement stand. A reached mark, or a setting it cannot be judged on, is handed over as that `additionalContext`, opening `lane-mail-check: context=` with the succession and the handoff record as the route, at every tool call until that record stands. Every other line that judgement writes, a judgement that could not run, a transcript it could not read or an `orch-env` this install has not got, is handed over the same way once per session and first line, the last told kept in `tmp/lane-mail/overseer/context-told`, written only once the run's output carrying it is written and cleared by a clean reading; only the bound native session the fleet record names, or the overseer it lost whose native identity still matches a nonempty recorded binding, writes or clears that file. Either opens the same context as any mail the call hands over, above its `unread=` line, and a refusal the mailbox check makes on the same call, above its keyed line, whether that refusal is Copilot's `additionalContext` or stderr at exit 2. The judgement itself refuses no call, and no account is read there. Run with `start` by the lane-mail-start hook at a session start, or with `prompt` by the lane-mail-prompt hook at a prompt, both on Copilot alone, it hands the same lines over the same way. A session start acknowledges them only once that context is written. A prompt leaves the lines unread because Copilot can discard its output, so a later inbox read or hook delivery can repeat them. Neither arm refuses anything: every refusal this description names is its keyed line on stderr at exit 0, with nothing on stdout and nothing acknowledged. Before an attached agent launch, the halt arm also judges the lead of a launched lane or the identified fleet overseer at the context mark, refusing missing context with the orch job runner or a separate session as the route. While an attached agent of the session may still be out, the mark is less ORCH_HANDOFF_AGENT_RESERVE_TOKENS, default 150000 tokens, equality refused: Claude Code reads that roster from its task registry where the payload carries one, else from the transcript's Agent-call results, task notifications, teammate idle notifications and sends, and reads an unreadable roster or an entry neither read classifies as unknown; Codex reads ordered collaboration snapshots, launches and followups from its rollout. Idle, completed, errored, shutdown and not-found children release the reserve; initializing, running and interrupted children keep it. A full unfiltered snapshot replaces earlier unknown observations only when its call does not overlap a launch or followup; pending calls and unreadable current observations keep the roster unknown. After waiting, Codex must call list_agents with no path filter to observe returns. Other harnesses read none, so their rosters are unknown. With none out the launch meets the plain mark. A launch the reserve alone refuses with an agent out is keyed `agent-reserve` and names waiting for those agents, the job runner or a separate session, never a handoff, since the turn end and every succession judge the plain mark. With the roster unknown no wait can be observed, so the refusal is keyed `agent-unobserved` and names the job runner or a separate session, and for a lane its handoff record. On Pi the lead launches through subagent; delegate_subagent carries child identity and is outside this lead-only reserve rule. At a context hold, a live session waits for attached agent returns in this turn; Claude Stop background_tasks is preferred, with the transcript's measured Agent-call results, async launch and teammate spawn records, task notifications, teammate idle notifications and sends as the fallback when absent. Other harnesses name known unfinished children and known output paths, or unknown paths, in the emergency handoff. A standing handoff retains its escape, and the successor reads existing output before repeating work. Run with `halt` by the lane-mail-halt hook before one, it acknowledges nothing and refuses the call while an unread directive sent with `lane-mail send --halt` stands, opening `lane-mail-check: halt=` with the directive and the one `lane-mail inbox` command that reads it, which names the lane's root with `--root` so it reads the same mailbox from any checkout; that command alone passes. Run with `row` and the event by the session-start-row, session-end-row and stop-failure-row hooks, it writes the event row of a session with no lane of its own, only for the pane's top-level harness and, on Copilot, only for a session the caller rule names the lead, through the orch skill's `lib/session-rows.sh`, the file those hooks describe, and refuses nothing: every gap below its payload read is reported and passed; the overseer's own turn end writes a Stop row there through the same library at every turn end, compact, its time, event, harness and session alone, except over a standing StopFailure row, which it lifts and where it keeps the turn's last message. Run with `lane` by the critical-path-deny hook, it prints `lane` where the launch marker for the session's item binds the session's root and its mailbox directory stands, else `none`, records and judges nothing else, and exits 0; a gap past its payload read is reported on stderr and passed with nothing on stdout. On a Pi install a launched lane's lead writes its own turn rows through that library into its mailbox directory, `session-rows.jsonl`: a Stop row at each turn end, carrying the `stopReason` of the turn's last assistant message in the transcript and Pi's `errorMessage` where that reason is `error`, and a PreToolUse row at the first tool call of each turn, after a turn end or on an empty file, written ahead of the mailbox check; oversee-watch and `lanes state` judge a Pi lane idle, working or walled from those rows in place of its pane, and a gap in the write is reported under `lane-rows-skipped` or `lane-rows-unwritten` and passed. The Pi install is the hook directory under `.pi` or `.pi/agent`, or under the user root `PI_CODING_AGENT_DIR` names; an install naming no harness writes no row, which a launched lane's turn end reports under `harness-unlisted`. Who made a call is answered once for every arm: the lead, a subagent, or unknown. A SubagentStop payload or one carrying a non-empty `agent_id` or `agent_type` is a subagent's on every harness, handed no mail and acknowledging none, and while a halt stands refused without that command. On Copilot, whose payloads name no agent, a preToolUse or postToolUse call, a preCompact and a context reading the usage arm is handed are the lead's where the session id they carry is a lead session this install recorded, the one rule for all four: one empty file per session under `~/.cache/lane-mail/copilot-leads`, written at the session's sessionStart, which Copilot fires for the lead alone, and at each turn end the transcript rule below proves the lead's, and pruned at a start once untouched for 30 days. A custom subagent's call was measured on Copilot CLI 1.0.88 carrying its own session id, which nothing recorded; whether a built-in task-tool subagent's calls carry their own session id or the lead's is a pending live-lane proof, and one whose calls carry the lead's is read as the lead, handed the lead's mail after its calls, which marks it read, and under a halt shown the read that clears it. A call whose session is no recorded lead, a custom subagent's among them, is unknown: the deliver arm hands it nothing and acknowledges nothing, writing `lane-mail-check: session-unrecorded=` to stderr, the compact arm flags nothing and writes the same line at exit 0, the usage arm records nothing and refuses under that key at exit 2, so the lead's turn end hands the lines over and acknowledges them, and the halt arm refuses it without showing that command yet passes the command, because the reader's `--ack` stops short of an unread halt and a lead whose record could not be written would otherwise be refused for good; the lead is shown the command by every notice and refusal that hands it the halt, its turn end's included. A record that cannot be written is reported on stderr under `lane-mail-check: lead-unrecorded=`, or `=none` for a session start naming no session id, and never refused. A Copilot sessionStart or userPromptSubmitted is the lead's, and an agentStop is ruled by its transcript, below; a prompt records no lead, since that a subagent's prompt fires no userPromptSubmitted is unmeasured. `stop_hook_active` true skips the mailbox check whole on the turn-end run. The flag is in the payload, so nothing above the payload read knows a turn was continued, and `arm`, the `missing-tools` refusal for `jq` or `cat`, `payload=unreadable` and `payload=invalid-json` are refused on every turn, the continued one included. Below that read one rule holds and every refusal is on one side of it: a refusal the lane itself can clear is still made, and a refusal it cannot is reported on stderr and passed. The lane clears the handoff refusals, and `script`, `setting`, `setting-range` and both `transcript` refusals, by writing its handoff record, and `mailbox-missing` by running the command it names, so those are refused on a continued turn as on any other. It clears `idle` by sending a lane-mail ask or notice, or by updating `tmp/lane-status-.md` under its launch root, so `idle` is refused on a turn another stop hook continued, except on Pi, as the idle rule below states. It clears none of `workdir`, `git`, `item`, `marker` or the `missing-tools` refusal for `git`, `tr`, `awk`, `mktemp` or `tail`, so each of those is reported and the turn ends, where a fresh turn refuses it. The halt arm reports and passes that same set at every tool call: a lane whose tool calls are refused can clear nothing, since clearing it takes a tool call, so there only the payload refusals and the mailbox's own, `reader`, `inbox`, `halt` and `mailbox-missing`, are refused, the last two each passing the one command that clears it. The same turn-end run hands the lane off before it runs out, so the handoff never waits on an overseer reading a pane. It reads this session's context use from the `transcript_path` the payload names, through the orch adapter for the harness this hook's install directory names, `.claude/hooks`, `.codex/hooks` or Pi's `kendex/hooks`: the tokens the last response left in context and effective capacity, with Pi reading the payload's own `context_window`. It records that reading as `context.json` in the lane's mailbox directory, where `lanes context` reads it, and refuses the turn end when `lane_context_handoff_due` requires handoff under the shared context rule in orch `references/oversee-events.md`, Judgement rules. It reads the account the credential this session runs on still has through the orch skill's own `lanes pick --lane`, judging a Claude lane on its own model. The picker owns the account handoff decision. For an ordinary account wall, the hook refuses the turn end and names the binding bucket's headroom against `ORCH_HANDOFF_HEADROOM_PCT` (default 3). When that picker reports `seat-reserve` for an overseer seat, the hook refuses the turn end. That refusal names the binding bucket's headroom and the configured `ORCH_OVERSEER_SEAT_RESERVE_PCT` (default 50) as independent facts. A Pi session's account is the one its model's provider bills, by the orch `lane_pick_harness` rule on the `/` its transcript names: a `pi-claude/` model spends the Claude seat `CLAUDE_CONFIG_DIR` names and is judged there on that model, a `github-copilot/` model spends the Copilot pool on Pi's own root, and any other provider, or a reading naming none, is left unjudged under `account=unmeasured`. A lane's context and account mark refusals open `lane-mail-check: context=`, `lane-mail-check: headroom= bucket= mark=` or `lane-mail-check: seat-reserve= bucket= reserve=`. Each carries one instruction: reach the next safe point, write the record with `workflow-state set handoff`, send a `handoff` notice, and exit. The record is read where `workflow-state --help` § Handoff record says, a launched lane naming the root its launch marker binds as the worktree, and the instruction names the state directory the read found, so a record written as told ends both refusals. The instruction opens with the `workflow-state init ` that `set` needs where the item has no state file yet, so it is enough on its own. It repeats at every turn end, `stop_hook_active` included, until the item's workflow state carries a `.handoff` object no relaunch has resumed; only the lane can write that record, so a single refusal it declines to act on would end the session with nothing recorded. That record is judged before every mark, before every read they rest on and before `orch-env` and `lanes` are looked for, so no failure but the record's own writer can hold a lane that has already done what it was asked. `orch-env` or `lanes` missing from this hook's install, a mark setting that is not a whole number in range, and a transcript the payload names and nothing can read are refusals too, each on the lane path alone and each carrying the same instruction. What the marks cannot judge is reported and passed, never refused: a payload naming no transcript leaves the context unread, and so does a transcript whose last usage line is an object carrying none of the field names its adapter reads, which is reported under `usage-unread=` rather than summed to a figure of zero and read as room, a reading below the independent token limit whose capacity the adapter could not name, reported under `window-unread=`, and an install directory naming no harness, reported under `harness-unlisted=`; a reading that could not be recorded is reported under `context-unrecorded=` and still judged; an account `lanes` keeps no inventory for, one it could not measure and a read that passed this hook's own ceiling each leave the account unjudged under `account=unlisted`, `account=unmeasured` or `account=timeout`, never read as room, so a setup with no usage endpoint still ends its turns; and a lane whose handoff record cannot be judged leaves both marks unjudged under one of four keys, `handoff-skipped=` for a reader or a script this install has not got, or `handoff-skipped=unlocatable` where this hook's own directory could not be resolved and none of them could be looked for, `handoff-outside=` for one only the open repository supplies, `handoff-unanswered=` for one that is there and answered nothing this hook can read, and `handoff-unreadable=` for a state file the install's own `workflow-state` could not read. Passing the turn is the answer for all four. For the first three it is because an install whose orch scripts cannot answer cannot run `workflow-state set` either, so a lane told to record a handoff with them could never end a turn again; for `handoff-unreadable` the install answers and the fault is the item's own state file, which is the file the record would be written into, so that write could not land either and the refusal would be as uncloseable. A subagent's turn end is judged on neither mark. The fleet's OVERSEER meets four triggers of its own on its turn end: a session with no lane of its own whose tmux server and pane are the pair the oversee workflow state records under `.overseer` is that overseer, and nothing weaker establishes one, so an ordinary session in a fleet checkout is judged on nothing. A session whose native identity matches a nonempty binding in the fleet record but whose pane only the overseer's `context.json` names, the overseer the record lost, is judged on nothing either, and reports `pane-unrecorded=` with the recorded key under it and writes that record with no reading and the gap `pane-unrecorded`; any other session the record does not name writes nothing, so the real overseer's reading stands. A fleet record naming this session's pane that lacks its server start, its harness, its launch home or its native session id is healed from an authorized native session first, at a turn end and at a tool call alike: the start of this session's own tmux server, the harness this install names and the launch home the harness variable of this session's own environment carries, `CLAUDE_CONFIG_DIR`, `CODEX_HOME` or `COPILOT_HOME` or that harness's default where it is unset, are written into it through the orch `lib/overseer-launch.sh` `ol_record_heal`, which writes only a fact the record lacks, and the transcript is bound to that home on the same run; a write that fails is reported under `record-unhealed=` with the writer's words, and the caller remains unbound until a later binding write succeeds. Before it reads that transcript for the overseer it binds it to the current session: the `transcript_path` the payload names is read only where it is this session's own native file, held to the `session_id` the payload carries and the launch home the fleet record names under `.overseer.home`, through the orch adapter for a claude, codex or copilot install; a Pi install states no transcript shape and reads the payload's own window as a Pi lane does. If `lane_context_transcript_owned` refuses an admitted overseer's transcript binding, the hook reports `transcript-unowned=` with the reason the library returns. Nothing is read then, and the context record is written with a null token count and that reason as its `gap` (orch `workflow-state.md`, `context.json` row), so it still advances at every turn end and oversee-watch reports the gap, and the judge is handed this install's harness and no context figure, so it judges the account triggers alone, the `transcript-unowned` line is this hook's one report that the context went unmeasured, and a session is never judged on a file it does not own. Every overseer turn end whose orch context library loads writes that record, a reading or a null token count with a `gap` naming why none was taken: the binding library's reason, `transcript-unnamed` for a payload naming no transcript, `usage-absent` for a transcript holding no usage line, `usage-unread` for a usage object its adapter does not read, which is also reported under `usage-unread=`, `session-record` for a Copilot session with no extension reading whose statusLine session record does not answer either, which is also reported under `session-record=`, or `pane-unrecorded` below. A Copilot statusLine record reporting allow_all_enabled false, read whether or not an extension reading stands, in a session whose `COPILOT_ALLOW_ALL` is true (a launch line granting `--allow-all` or `--yolo`), is reported under `stop-cause=allow-all-blocked-by-policy`, and the turn end judged as usual. An install naming no harness an adapter reads writes no gap, since its context is never read, and leaves the record as it was, and a Copilot one names none where the reading its usage arm wrote for this session stands, its turn end reading that record rather than taking a reading of its own; a gap record that cannot be written is reported under `context-gap-unrecorded=`, the record keeping its earlier entry. This hook records the overseer's own context reading as `context.json` in the overseer mailbox directory at the main checkout, naming the session and its pane, and hands that reading to `oversee-succeed --check-marks --context :` from this hook's own install, which judges those marks on it and on no stored figure, and nothing at the turn end here judges them, under the same ceiling the account read runs under, so the turn-end refusal and the `overseer-mark` watch event cannot describe one overseer differently. Its refusal opens with the `context=`, `headroom=`, `rate=` or `qualifying=` key, carrying the figure that judgement read, and names `oversee-succeed`, handed the same reading, as the route, with `workflow-state set oversee handoff` under it for a succession that refuses, so the refusal always has an escape the overseer can reach. That record names the session that wrote it, in the native `session_id` the payload gives. A payload with no native session id is refused and cannot read mail or write overseer context or gaps. `overseer_identify` owns its native refusal diagnostics. One other refusal stands on that path, `script` for an `oversee-succeed` this install has not got, and the record clears it as it clears the marks. `ORCH_OVERSEER_SUCCESSION=off`, read off the judgement's own line and never here, turns the account-mark refusals off with the succession they name, the watch's `overseer-mark` event still reporting those marks; the context mark is refused whatever the setting, since no watch event reports it, and the handoff record ends that refusal. An answer this hook cannot act on, one the ceiling abandoned, and one whose own reading was unmeasured are reported under `marks=unjudged`, `marks=timeout` and `marks=unmeasured` and the turn ends, never held. A lane asks its overseer only through lane mail. Before a tool call in a launched lane, the halt arm refuses the harness question tool by its name, whichever of the four names the payload's `tool_name` carries, Claude Code's `AskUserQuestion` and `EnterPlanMode`, Codex's `request_user_input` and Pi's `question`, opening `lane-mail-check: question-tool=` and naming the `lane-mail ask --item --file ` send and the `lane-mail wait` on its printed id as the route, because a dialog on the pane reaches no overseer; an unread halt is refused ahead of it, a subagent's call is refused and told to report its question to the lead, and a session that is no launched lane passes the call silently, a committed mailbox and status file included. At a launched lane lead's turn end, once the handoff marks pass, the lane is judged idle on lane-mail sends and its lane status file update state, never on words in its pane, on Claude Code, Codex, Pi and Copilot; OpenCode and Cursor run no kendex hooks, and Gemini and Antigravity do not run this one, so a lane there is never judged idle. The reader's own `lane-mail events` listing, which moves no cursor, counts the asks and notices in the lane's outbound file against the count this hook recorded at the lane's last judged turn end, `sent-count` in the lane's mailbox directory: a line holding the count, the word `held` where this judge refused that turn end, and an optional encoded status file update state; no record is a count of zero with no status state. A status file update since that record, including a rewrite of the same text, passes without a notice. A count other than the recorded one is a send this turn and passes, a standing handoff record ends the run before this judge, the newest directive the overseer sent carrying `halt` passes, and a lane whose launch marker no longer binds its root, the close-out's state, is no lane. With none of these the turn is refused and the hold recorded, opening `lane-mail-check: idle=` with one continuation, the lane's `lane-mail inbox` read and then its workflow, beside the ask route and the `lane-mail notice` send, which follows the orch Coordination notice rule: changed work sends a notice, and a continuing wait on a dispatched agent or an armed wake updates the lane status file only. On a turn the harness continued for this judge's own recorded hold it refuses nothing and sends the overseer a lane notice stating what it checked, opening `lane-mail-check: idle-notice=`, or `idle-notice-unsent=` with the sender's words where the send fails, so an idle lane is reported and never looped. A turn another stop hook's refusal continued is held as a fresh one, except on Pi, whose pi-hooks carrier runs no further request after a continued turn, so there the notice is sent with no hold before it. The record counts that notice, so the lane's next turn is judged on what the lane itself sends. An `events` listing that fails, or whose envelopes jq cannot read, is reported under `events=` or `events=envelope`, and a record that is not a plain file holding a whole number, an optional `held` mark and an optional encoded status state under `idle-record=` and rewritten. A record that cannot be written is reported under `idle-unrecorded=`; under `idle-hold-unrecorded=` where it was to take a hold, which is then not made, since one with no record would be made again on every continued turn; and under `idle-notice-unrecorded=` where it was to count the notice, which the next turn end then reads as the lane's own send. Each of these ends the turn, because nothing a lane does at its turn end repairs its mailbox; an install with no reader leaves the turn unjudged under the marks' own `handoff-skipped` line. On Copilot the event is `agentStop`, registered in Copilot's own hook file under its camelCase name, so the payload spells its fields `sessionId`, `transcriptPath` and `toolArgs`, which this hook reads beside the snake_case spellings; its reference spells `stop_hook_active` so on both, and `toolName` identifies an attached launch. The `lane-mail-halt` description owns the Copilot preToolUse decision and deadline contract. Copilot also runs the hooks `.claude/settings.json` registers, under their PascalCase names, but the registration kendex writes there exits 0 before its script in a Copilot hook process, so a Copilot call reaches an install that is not Copilot's, the claude copy of this hook among them, only through a registration made there by hand or one kendex wrote before that skip and no refresh has rewritten. Whether Copilot made the call is read from the call, never from the install: a payload carrying `timestamp`, which both of Copilot's payload formats carry and no Claude, Codex or Pi payload does, or naming the session `sessionId`, is Copilot's, and any install but Copilot's own passes it silently, exit 0 with nothing written and nothing acknowledged, so the Copilot install is the one reader of the mailbox for a Copilot call. A Copilot agentStop names no agent: the stop whose `transcriptPath` sits in the directory named for the `sessionId`, Copilot's `session-state//events.jsonl`, is the lead's and records it, a stop naming a transcript under another directory is read as a subagent's, handed nothing and judged on nothing, and a payload naming no transcript, or no session, is the lead's and records nothing. Copilot CLI 1.0.88 was measured firing agentStop at a custom subagent's end too, with the subagent's own `sessionId` and the lead's `transcriptPath`, which this rule reads as a subagent's. A refusal on Copilot is the documented answer for its event, on stdout beside the keyed stderr line: at a turn end `{"decision":"block","reason":}` with exit 0, which Copilot stops honouring after 8 consecutive blocks, ending that turn unheld, so a handoff refusal holds a Copilot session for 8 continued turns and then returns at its next turn end, and after a tool call `{"additionalContext":}` with exit 0, since Copilot reads a postToolUse answer only at exit 0. A Copilot session's context is read through Copilot's own SDK event `session.usage_info`: the orch `copilot-lane-context` extension, which `open-terminal` installs in a Copilot fleet lane's `COPILOT_HOME` with the EXTENSIONS feature on, runs this hook with the argument `usage` at each reading of the session's root agent, handing it `{session_id, cwd, current_tokens, token_limit}` on stdin, and for a recorded lead session that is a launched lane's lead or the fleet's overseer, named by the same gate every arm that judges the marks asks, it records `current_tokens` as the tokens and, as the capacity, the limit Copilot compacts at: 80 percent of `token_limit`, the SDK's documented `backgroundCompactionThreshold` default, named in the record's `capacity_source`. It writes nothing on stdout; a gap is refused on stderr at exit 2, which the extension writes to the session timeline: `payload=invalid-json`, an orch install it cannot use under the key its turn end reports that gap under, `handoff-skipped=`, `handoff-outside=` or `handoff-unanswered=`, or `context-unrecorded=` for a reading that could not be written, where the session's earlier reading is removed too so its turn end reports the context unmeasured rather than judging an older figure as room. Any other session passes silently. The Copilot turn end judges this session's record under the shared context rule exactly as it judges a transcript reading, the capacity putting the handoff before Copilot's own compaction; no reading of this session, no record or a gap record, is read from the fallback below; where the pending marker the extension leaves at `~/.cache/lane-mail/copilot-usage/` for a reading it handed on and no run has recorded yet still stands after a wait of 5 seconds, the turn end reports `reading-pending=` and passes with the context unmeasured, reading no fallback, since the extension runs for that session, and never judging the earlier record as room, since nothing orders the extension's run before the turn end; and a record that stands and cannot be read is refused under `record=`. Where no pending marker stands and no reading of the extension's stands for this session, no record, one naming another session, a gap record or one the fallback below wrote, which its `capacity_source` tells apart, the turn end reads the fallback: the session record the orch `copilot-statusline` command writes as the account's `statusLine`, under `/lane-status/.json`, through the orch adapter for copilot, which holds the record to the payload's `sessionId`, its `transcriptPath` where one is named, the account directory and a freshness bound, and hands the shared judge the same compaction point of the window as the capacity; that reading is judged and recorded as any other harness's, and a record that does not answer leaves the context unmeasured under `reading-unrecorded=` and `session-record=`, reported and passed, never read as room. An extension reading below the mark is never overridden by a statusLine record past it. Run with `compact` by the lane-mail-compact hook at a preCompact whose `trigger` is `auto`, from a recorded lead session that gate names, it flags that compaction as `compaction.json` beside the reading, the backstop for a turn that crossed into the compaction before a reading past the mark reached a turn end, and the turn end then refuses under `compacted=auto` until the handoff record stands, the overseer's whatever its succession setting; a gap there is refused under `compaction-unrecorded=` on stderr at exit 2, which Copilot shows the operator without holding the compaction. A Copilot account is judged through `lanes pick --lane` like any other. A session the Jarvis runtime launched, which carries `JARVIS_RECORD`, has its lead's tool calls, on Copilot any call under the session id the record's start bound, and on Claude Code its turn ends, stamp that runtime record's launch row once as its Start brief taken, the fact the Jarvis launch worker reads beside the pane; another harness's turn end is no stamp, since Pi's carrier also dispatches it on a run that ended on an error and Codex and Copilot have no turn-failure event to tell one apart; a stamp that cannot be written is reported under `jarvis-rows-unwritten=` and passed, and the next such call writes it. Not run on gemini: it has no Stop event. Not run on antigravity: its Stop payload carries no `stop_hook_active`. # summary: Uses orch and mailbox to hand lanes their overseer's mail and hold turn ends for handoff or idle checks, plus a `wake=unarmed` refusal for the registered overseer without its repeat follow or the Jarvis session whose `ORCH_WAKE_PROCESS` does not match, printing `ORCH_WAKE_START`; empty Jarvis session keys with no watch claim disable the check, and a running single pass is its own wake. Pi's wake check is partial; a continued turn or an unavailable check only warns. # safety: Reads the payload, the repository's branch, the lane's launch marker, read with the shell's own `read`, and the lane mailbox directory, and for a session that is no lane the checkout's overseer mailbox and, where a file stands there and the fleet record names this session's pane, the fleet state's path from the identity read, with `workflow-state path oversee` as its fallback and the watch record beside it, read by the orch watch record library `lib/watch-pid.sh` sourced in a child shell from the same install as the mailbox reader, which checks the record's pid with `kill -0` and `ps`; the writes are the mailbox cursor the orch reader advances, the session's context reading, `context.json`, and a Copilot session's compaction flag, `compaction.json`, each renamed into its mailbox directory, and on a Pi lane its turn rows, `session-rows.jsonl`, appended there under that file's own lock at a turn end and at the first tool call of each turn, and for the overseer one row appended to its rows file, `session--.jsonl` in the overseer mailbox directory, under that file's own lock, a compact Stop at every overseer turn end, the overseer's directory made where the fleet has not made it yet, the fleet record's `.overseer` server start, harness, launch home and native session id where a record naming this session's pane lacks one, through `workflow-state update oversee`, and after each overseer tool call its `context.json` and, where a gap is told, `tmp/lane-mail/overseer/context-told`, and on Copilot a lead session's empty record under `~/.cache/lane-mail/copilot-leads`, touched at its session start and at each turn end its transcript proves the lead's, with records untouched for 30 days removed by one `find` at each start, as are the extension's pending markers under `~/.cache/lane-mail/copilot-usage`, which a Copilot turn end reads and polls for 5 seconds. For a session the Jarvis runtime launched it also reads, at its lead's tool calls and Claude Code, Codex and Copilot CLI turn ends, the runtime record `JARVIS_RECORD` names, in one child shell sourcing the orch session rows library from the same install, and where that launch is starting and unstamped, reads it again under that record's `.lock` and renames a new record over it once: at a tool call or Claude Code turn end with its brief delivered, stamping its launch row's `brief_taken`; at a Codex or Copilot CLI turn end before the brief, stamping its `kickoff_ended`. Exit 2 names the unread count and the messages, and asks for them to be acted on, never bypassed. The reader it runs comes from its own install, never from the repository a session has open, so a repository that tracks a mailbox and an executable at that path cannot have it run. jq and cat read the payload; a payload it cannot read is refused on every turn, the continued one included, because the flag that marks a continued turn is in the payload none of those refusals reached. A mailbox whose reader is missing or fails is refused on the turns the mailbox check runs, which is every turn end but a continued one; on a continued turn that check is skipped whole, and the same missing reader is reported under `handoff-skipped` or `handoff-outside` and the turn is passed. An item name outside the alphabet a work item is spelled in, a branch that matches more than one mailbox, and a repository state git cannot report where a mailbox sits under the working directory are refused on a fresh turn and reported on a continued one and before a tool call, by the one rule the description states; none of them is ever passed in silence. For a lane's handoff marks it also reads the transcript the payload names and runs `orch-env`, `lanes` and `workflow-state` and sources the orch context library from the same install as the mailbox reader, never the open repository's, and on Pi one child shell sourcing that install's `lib/lane-launch.sh` to name the account the session's provider bills; the context reading is the one thing it writes for them. A session that names no lane costs two file tests of the checkout's overseer mailbox; where a file stands there it adds that install's resolution and, inside tmux, the overseer test below, and for the session the record names the identity read's fleet path, one child shell sourcing the watch record library, and the reader's peek where no live watch stands. Outside tmux it costs nothing more, where the overseer test stops at its first condition. After a tool call a lead session with no lane of its own, in tmux, in a checkout with no `tmp/lane-mail/overseer` directory costs one stat more; where that directory stands it pays the overseer test below, and for the overseer one transcript read, one `workflow-state handoff-standing`, one `orch-env` read and one record write, the reads the turn end makes but for the account judgement; the overseer test runs once per call, and the mailbox check takes its answer. Inside tmux the overseer test resolves that install and reads the caller's pane key, the fleet record and the server start in a child shell loading the orch context and overseer launch libraries and their dependencies. A required heal loads `lib/overseer-launch.sh` and its dependencies in a child shell and rechecks the recorded native identity before the state update; a session whose native identity matches a nonempty recorded binding but whose pane the state does not name adds one child shell loading the orch context library, one `git-context` call and one read of the overseer's `context.json`; where that record names this session's pane, it reports `pane-unrecorded` and rewrites that record. Any other unbound caller stops before those context reads and writes. The overseer's own marks are then judged by `oversee-succeed --check-marks` from that same install, under the same 20 second ceiling the lane's account read runs under. That judgement measures the one account the overseer session runs on, through the same `lanes pick --lane` this hook asks about a lane, renewing an expired token in that account's credential file and refreshing that account's usage cache, the writes `lanes` states in its own contract; it opens no window and launches nothing. The context-usage reader first parses the last 1 MiB, and reads the whole file only when that window carries no usage line. When native Claude Stop background_tasks is absent, the transcript roster fallback reads complete ordered history; its work grows with transcript size. It runs only under the remaining hook deadline, with three seconds reserved for refusal emission and a one-second kill grace. An unavailable bound, exhausted budget, timeout or failed parse reports agents=unknown and discards partial rows. `lanes pick --lane` judges a Claude lane on its own model, measures one account and renews that account's expired token, the write its own contract states; it can wait on a credentials lock and two network calls, and on a cache miss on the host-wide usage refresh lock for up to 10 seconds and, after a 429 with nothing cached, one sleep of up to 5 seconds and one more usage request, so it runs under a 20 second ceiling that leaves the rest of the run inside this hook's 30 second budget, and a read that reaches the ceiling is reported as a gap rather than refused. Where `timeout` is not installed that read runs unbounded, and a hook the harness then kills at its budget leaves the account unjudged, the same outcome the reported gap gives without the line. Before a tool call it reads `tool_name` or Copilot `toolName`; the question-tool rule and attached-launch check consume that normalized name. For the idle judge at a lane lead's turn end it runs the reader's `events` listing, which moves no cursor, and reads the kind, the box and the halt flag of each envelope, never its text and never the transcript; it reads stat metadata for the fixed regular `tmp/lane-status-.md` file under the lane's launch root, with no symbolic link at the status file itself, and writes that update state beside the count in the lane's `sent-count` record, renamed into its mailbox directory, and the one idle notice the description names, through the reader's `notice`. Every refusal opens with `lane-mail-check: =`; what a command this hook runs writes is captured at the site and replayed under that line, so nothing precedes the key. For a launched lane or the bound fleet overseer, PostModelSwitch reads its to_model target and the recorded launch identity. It writes model checks and switch history through workflow-state. A lane replacement that reaches its first Stop without a mismatch writes one model-recovery-reset row and a passed model check in the same fleet state. Lane recovery preserves the standing handoff and checks the recorded arguments before stopping the verified predecessor through the existing lane stop owner. Account selection and launch follow that stop. Overseer recovery passes a durable handoff to oversee-succeed. That owner preserves the executable model selector and account, verifies the successor, then stops its predecessor. Unreadable PostModelSwitch dependencies reach the model as once-only unavailable context. A failed first-turn reset reports a keyed Stop warning on stderr and leaves later checks active. # timeout: 30 @@ -50,7 +50,7 @@ UNREAD="" HALT_TEXT="" ACK_COMMAND="" MAILBOX_COMMAND="" -# The handoff marks: the two settings judged and the commands that end the +# The handoff marks: the settings judged and the commands that end the # refusal, and the window the context mark is judged against. Empty until each # is known. MARK="" @@ -218,6 +218,8 @@ message() { # KEY VALUE [CAUSE] { if [ "$1" = headroom ] && [ "$ROLE" = lane ]; then printf 'lane-mail-check: headroom=%s bucket=%s mark=%s\n' "$2" "$BINDING_BUCKET" "$PCT" + elif [ "$1" = seat-reserve ]; then + printf 'lane-mail-check: seat-reserve=%s bucket=%s reserve=%s\n' "$2" "$BINDING_BUCKET" "$PCT" else printf 'lane-mail-check: %s=%s\n' "$1" "$2" fi @@ -456,6 +458,10 @@ message() { # KEY VALUE [CAUSE] "$BINDING_BUCKET" "$2" "$PCT" "$HANDOFF_INSTRUCTION" fi ;; + seat-reserve=*) + printf 'The account picker requires handoff from this overseer seat. The binding bucket %s has %s percent headroom left. ORCH_OVERSEER_SEAT_RESERVE_PCT is %s. No handoff record stands. Hand this lane off at the next safe point.\n%s\n' \ + "$BINDING_BUCKET" "$2" "$PCT" "$HANDOFF_INSTRUCTION" + ;; rate=*) printf 'oversee-succeed projects that this overseer account will reach its wall in %s minutes, at or before the ORCH_OVERSEER_WALL_MINUTES mark of %s. Succeed this session yourself before the account walls.\n%s\n' \ "$2" "$MARK" "$HANDOFF_INSTRUCTION" @@ -3427,10 +3433,10 @@ handoff_check() { fi # The account the credential THIS session runs on still has, judged by the - # one script that measures a lane and against the one setting that marks a - # lane for handoff. `pick --lane` answers about that directory alone: 0 has - # room, 3 is at or below the mark, and 4 is a directory that is no configured - # lane of this harness. Every other exit, and a read that passes the ceiling, + # one script that measures a lane and judges its handoff marks. + # `pick --lane` answers about that directory alone: 0 has room, 3 reaches + # the headroom mark or overseer seat reserve, and 4 is a directory that is + # no configured lane of this harness. Every other exit, and a read that passes the ceiling, # is an account nothing measured: reported and passed, never read as room and # never held, because a setup with no usage endpoint must still end its turns. # `lanes` keeps an inventory for claude, codex and copilot, and a Pi lane is @@ -3465,9 +3471,9 @@ handoff_check() { ${PICK_MODEL[@]+"${PICK_MODEL[@]}"} --min-headroom-pct "$PCT" --json 2>"$WORK_DIR/lanes.err") || PICK_RC=$? # `lanes` keeps a status-only contract where `workflow-state handoff-standing` # could not, and one reservation is what makes that safe here: every status - # with an arm of its own below — 3 for a lane at its mark, 4 for one this - # harness keeps no inventory for, 124 for a read the ceiling abandoned — is - # one no death before the verb can produce. `lanes` loads the same + # with an arm of its own below (3 for a lane at its mark or seat reserve, + # 4 for one this harness keeps no inventory for, 124 for a read the ceiling + # abandoned) is one no death before the verb can produce. `lanes` loads the same # `.env.local` through the same loader, and a file bash 3.2 cannot parse # kills it with 1 or 2; both fall to `*` and are reported as an account # nothing measured, which is as true of a script that died in its loader as @@ -3479,10 +3485,22 @@ handoff_check() { 3) # pick's wall is the binding bucket's used percent, including a scoped # model window. Account-wide headroom can still show room at that wall. - BINDING=$(jq -r '[.binding_bucket // "unknown", + # Only seat-reserve keeps its verdict in pick's public record; the + # ordinary wall omits it. Exit 3 alone cannot name the reached mark. + BINDING=$(jq -r '[.verdict // "walled", .binding_bucket // "unknown", (if .wall == null then "unknown" else 100 - .wall end)] | @tsv' <<<"$PICK" 2>/dev/null) || - BINDING=$'unknown\tunknown' - IFS=$'\t' read -r BINDING_BUCKET HEADROOM <<<"$BINDING" + BINDING=$'unknown\tunknown\tunknown' + IFS=$'\t' read -r PICK_VERDICT BINDING_BUCKET HEADROOM <<<"$BINDING" + case "$PICK_VERDICT" in + seat-reserve) + PCT=$("$SCRIPTS/orch-env" ORCH_OVERSEER_SEAT_RESERVE_PCT 50 2>"$WORK_DIR/env.err") || + refuse_handoff setting ORCH_OVERSEER_SEAT_RESERVE_PCT "$(cat -- "$WORK_DIR/env.err")" + percent_in_range "$PCT" || refuse_handoff setting-range "ORCH_OVERSEER_SEAT_RESERVE_PCT=$PCT" + refuse_handoff seat-reserve "$HEADROOM" + ;; + walled) ;; + *) message account unmeasured "lanes pick returned an unreadable refusal record"; return 0 ;; + esac refuse_handoff headroom "$HEADROOM" ;; 4) message account unlisted "$(cat -- "$WORK_DIR/lanes.err")" ;; diff --git a/.github/hooks/lane-mail-check.sh b/.github/hooks/lane-mail-check.sh index 73306ecc..ba719e94 100644 --- a/.github/hooks/lane-mail-check.sh +++ b/.github/hooks/lane-mail-check.sh @@ -3,7 +3,7 @@ # name: lane-mail-check # event: Stop # matcher: -# description: Blocks a lane's turn end while its overseer mailbox holds unread lines, so a directive or a ruling reaches the lane without a keystroke, a pane or a question tool. The lane is the work item `LANE_MAIL_ITEM` names, or the one directory under `/tmp/lane-mail/` whose name lowercases to the current branch; a session with neither is not a lane; a lane whose mailbox holds no unread line passes silently, as does a directory git reports no repository for and that holds no mailbox of its own. The checkout's overseer mailbox, `/tmp/lane-mail/overseer`, has one reader: the session whose tmux server and pane the checkout's oversee workflow state names under `.overseer`, the pair every writer the orch `schemas/workflow-state.md` `overseer` row names writes, `oversee register` among them for a session opened by hand, and the one the fleet's OVERSEER is established by below, so a record naming a dead pane names no reader. The native session must also match the recorded harness, readable caller home and payload session id; `ol_record_heal` binds the first matching native id from the recorded pane, and `oversee register` clears that binding after a resume. Pi and any harness whose `lane_context_caller_home` reports no home compare the harness and native session id only. The pair names a session only on the tmux server started at the record's `server_start`, so a server a tmux restart handed the recorded pid and pane id names no reader either; a record carrying no start at all names the session in that pane, which writes its server's start into it. Where a file stands there, that session is handed the notes `lane-mail peer send --repo` wrote there at its turn end and after its tool calls, under the same `unread=` line, unless a live watch holds the fleet state: the `oversee-watch.pid` record a repeat `oversee-watch` writes beside the fleet state on every surface and removes on exit, judged by the orch `lib/watch-pid.sh` library's `watch_pid_live`, which reads the mailbox itself, so the named session is handed nothing from it beside that watch. A fleet watched in single passes writes no watch record, so its named overseer is handed the notes as `unread=` lines and the next pass does not report them. A Jarvis session's wake, the process `ORCH_WAKE_PROCESS` matches, is no such watch: it moves no cursor, so that session is handed each note in full here once and acknowledges it here, and its wake carries no note's body, at most the count and read command `lane-mail watch` prints. Where the payload's `kendex_ack` is `caller`, which the pi-hooks lane mail wake sends, the context carries the reader's `--ack` command as `kendex_ack` and nothing is acknowledged here: the wake runs it once its send returns, so a send that throws leaves the lines unread. Every other session in the checkout, one the owner opened there for other work included, is handed nothing from that mailbox, and so is a session whose install has no reader beside this hook. For the named session, where the install's `workflow-state path oversee` prints no path, or the library cannot be sourced or answers neither way, the hook refuses, opening `lane-mail-check: fleet-state=` with that file's own words under it; the halt arm never reads that mailbox, a subagent's turn end is handed nothing from it, and a session in a checkout with no overseer mailbox pays two file tests for the question. `` is the lane's root, resolved in this order: `CLAUDE_PROJECT_DIR`, the directory Claude Code started the session in; else the root the launch marker for `LANE_MAIL_ITEM` binds, where that root exists; else the directory the hook runs in, which on Codex and Pi is the session's start directory and on Claude Code without the variable is the call's own. A Claude Code lane working from the main clone is therefore still judged on its own mailbox. A root its launch marker binds that has no `tmp/lane-mail` directory is refused at a turn end, before any tool call and after the lead's finished one, opening `lane-mail-check: mailbox-missing=` with the marker and the one `mkdir` command that restores the directory, and that command alone passes a tool call. Before a tool call a subagent is refused whatever it runs, and a call whose caller is unknown may run that command; after one a subagent is handed nothing and refused nothing, as with any mail, and its next call meets the refusal. The marker is looked up for the item `LANE_MAIL_ITEM` names or else the branch names, so that check costs one stat in a repository whose common git directory holds no `lane-mail` directory, and one branch read and one marker stat in one that does. A mailbox belongs to a lane only where a launch recorded one: `open-terminal` and `lane-host create` write the lane's root to `lane-mail/` under the repository's common git directory and create the lane's own `tmp/lane-mail/`, and a mailbox with no marker bound to this root passes silently. Unread lines are peeked through the orch skill's own `lane-mail inbox --peek`, the one reader of the mailbox and its cursor, and acknowledged with `inbox --ack` only once the refusal is written, so a hook killed at its budget leaves them unread and a line acknowledged here is never handed over twice. That reader is resolved from this hook's own install, walking up to the home directory for `skills/mailbox/scripts/lane-mail` or the shared `.agents/skills/mailbox/scripts/lane-mail` beside it, then the home's own shared tree for a harness root relocated out of it; the open repository's `.agents/skills/mailbox/scripts/lane-mail` is used only where this hook is installed in that repository, and a reader outside that containment is refused rather than run. The refusal opens with `lane-mail-check: unread=` and carries one JSON envelope per line under it, and for the lead, where a halt is among them, the one `lane-mail inbox` command that reads it; the turn then continues with them. Run with the argument `deliver` by the lane-mail-deliver hook after a tool call, it exits 0 with the harness's JSON on stdout, whose `additionalContext` carries the same lines. That run first judges the context mark of the fleet's OVERSEER, below, for a lead's call in tmux in a checkout whose `tmp/lane-mail/overseer` directory stands, so a mark crossed mid-turn is read at the next tool call: the context is read and recorded as the overseer's turn end reads it and judged at `ORCH_HANDOFF_CONTEXT_PCT` by the rule the orch `references/oversee-events.md` § Judgement rules states for the overseer's context mark. On Pi the window is the payload's own `context_window`, which the pi-hooks carrier puts on the PostToolUse payload of every tool call; a Pi payload naming none, the lane mail wake's run or a tool call from an older carrier, takes no reading, writes no record and hands nothing over, so the turn end's reading and judgement stand. A reached mark, or a setting it cannot be judged on, is handed over as that `additionalContext`, opening `lane-mail-check: context=` with the succession and the handoff record as the route, at every tool call until that record stands. Every other line that judgement writes, a judgement that could not run, a transcript it could not read or an `orch-env` this install has not got, is handed over the same way once per session and first line, the last told kept in `tmp/lane-mail/overseer/context-told`, written only once the run's output carrying it is written and cleared by a clean reading; only the bound native session the fleet record names, or the overseer it lost whose native identity still matches a nonempty recorded binding, writes or clears that file. Either opens the same context as any mail the call hands over, above its `unread=` line, and a refusal the mailbox check makes on the same call, above its keyed line, whether that refusal is Copilot's `additionalContext` or stderr at exit 2. The judgement itself refuses no call, and no account is read there. Run with `start` by the lane-mail-start hook at a session start, or with `prompt` by the lane-mail-prompt hook at a prompt, both on Copilot alone, it hands the same lines over the same way. A session start acknowledges them only once that context is written. A prompt leaves the lines unread because Copilot can discard its output, so a later inbox read or hook delivery can repeat them. Neither arm refuses anything: every refusal this description names is its keyed line on stderr at exit 0, with nothing on stdout and nothing acknowledged. Before an attached agent launch, the halt arm also judges the lead of a launched lane or the identified fleet overseer at the context mark, refusing missing context with the orch job runner or a separate session as the route. While an attached agent of the session may still be out, the mark is less ORCH_HANDOFF_AGENT_RESERVE_TOKENS, default 150000 tokens, equality refused: Claude Code reads that roster from its task registry where the payload carries one, else from the transcript's Agent-call results, task notifications, teammate idle notifications and sends, and reads an unreadable roster or an entry neither read classifies as unknown; Codex reads ordered collaboration snapshots, launches and followups from its rollout. Idle, completed, errored, shutdown and not-found children release the reserve; initializing, running and interrupted children keep it. A full unfiltered snapshot replaces earlier unknown observations only when its call does not overlap a launch or followup; pending calls and unreadable current observations keep the roster unknown. After waiting, Codex must call list_agents with no path filter to observe returns. Other harnesses read none, so their rosters are unknown. With none out the launch meets the plain mark. A launch the reserve alone refuses with an agent out is keyed `agent-reserve` and names waiting for those agents, the job runner or a separate session, never a handoff, since the turn end and every succession judge the plain mark. With the roster unknown no wait can be observed, so the refusal is keyed `agent-unobserved` and names the job runner or a separate session, and for a lane its handoff record. On Pi the lead launches through subagent; delegate_subagent carries child identity and is outside this lead-only reserve rule. At a context hold, a live session waits for attached agent returns in this turn; Claude Stop background_tasks is preferred, with the transcript's measured Agent-call results, async launch and teammate spawn records, task notifications, teammate idle notifications and sends as the fallback when absent. Other harnesses name known unfinished children and known output paths, or unknown paths, in the emergency handoff. A standing handoff retains its escape, and the successor reads existing output before repeating work. Run with `halt` by the lane-mail-halt hook before one, it acknowledges nothing and refuses the call while an unread directive sent with `lane-mail send --halt` stands, opening `lane-mail-check: halt=` with the directive and the one `lane-mail inbox` command that reads it, which names the lane's root with `--root` so it reads the same mailbox from any checkout; that command alone passes. Run with `row` and the event by the session-start-row, session-end-row and stop-failure-row hooks, it writes the event row of a session with no lane of its own, only for the pane's top-level harness and, on Copilot, only for a session the caller rule names the lead, through the orch skill's `lib/session-rows.sh`, the file those hooks describe, and refuses nothing: every gap below its payload read is reported and passed; the overseer's own turn end writes a Stop row there through the same library at every turn end, compact, its time, event, harness and session alone, except over a standing StopFailure row, which it lifts and where it keeps the turn's last message. Run with `lane` by the critical-path-deny hook, it prints `lane` where the launch marker for the session's item binds the session's root and its mailbox directory stands, else `none`, records and judges nothing else, and exits 0; a gap past its payload read is reported on stderr and passed with nothing on stdout. On a Pi install a launched lane's lead writes its own turn rows through that library into its mailbox directory, `session-rows.jsonl`: a Stop row at each turn end, carrying the `stopReason` of the turn's last assistant message in the transcript and Pi's `errorMessage` where that reason is `error`, and a PreToolUse row at the first tool call of each turn, after a turn end or on an empty file, written ahead of the mailbox check; oversee-watch and `lanes state` judge a Pi lane idle, working or walled from those rows in place of its pane, and a gap in the write is reported under `lane-rows-skipped` or `lane-rows-unwritten` and passed. The Pi install is the hook directory under `.pi` or `.pi/agent`, or under the user root `PI_CODING_AGENT_DIR` names; an install naming no harness writes no row, which a launched lane's turn end reports under `harness-unlisted`. Who made a call is answered once for every arm: the lead, a subagent, or unknown. A SubagentStop payload or one carrying a non-empty `agent_id` or `agent_type` is a subagent's on every harness, handed no mail and acknowledging none, and while a halt stands refused without that command. On Copilot, whose payloads name no agent, a preToolUse or postToolUse call, a preCompact and a context reading the usage arm is handed are the lead's where the session id they carry is a lead session this install recorded, the one rule for all four: one empty file per session under `~/.cache/lane-mail/copilot-leads`, written at the session's sessionStart, which Copilot fires for the lead alone, and at each turn end the transcript rule below proves the lead's, and pruned at a start once untouched for 30 days. A custom subagent's call was measured on Copilot CLI 1.0.88 carrying its own session id, which nothing recorded; whether a built-in task-tool subagent's calls carry their own session id or the lead's is a pending live-lane proof, and one whose calls carry the lead's is read as the lead, handed the lead's mail after its calls, which marks it read, and under a halt shown the read that clears it. A call whose session is no recorded lead, a custom subagent's among them, is unknown: the deliver arm hands it nothing and acknowledges nothing, writing `lane-mail-check: session-unrecorded=` to stderr, the compact arm flags nothing and writes the same line at exit 0, the usage arm records nothing and refuses under that key at exit 2, so the lead's turn end hands the lines over and acknowledges them, and the halt arm refuses it without showing that command yet passes the command, because the reader's `--ack` stops short of an unread halt and a lead whose record could not be written would otherwise be refused for good; the lead is shown the command by every notice and refusal that hands it the halt, its turn end's included. A record that cannot be written is reported on stderr under `lane-mail-check: lead-unrecorded=`, or `=none` for a session start naming no session id, and never refused. A Copilot sessionStart or userPromptSubmitted is the lead's, and an agentStop is ruled by its transcript, below; a prompt records no lead, since that a subagent's prompt fires no userPromptSubmitted is unmeasured. `stop_hook_active` true skips the mailbox check whole on the turn-end run. The flag is in the payload, so nothing above the payload read knows a turn was continued, and `arm`, the `missing-tools` refusal for `jq` or `cat`, `payload=unreadable` and `payload=invalid-json` are refused on every turn, the continued one included. Below that read one rule holds and every refusal is on one side of it: a refusal the lane itself can clear is still made, and a refusal it cannot is reported on stderr and passed. The lane clears the two handoff marks, and `script`, `setting`, `setting-range` and both `transcript` refusals, by writing its handoff record, and `mailbox-missing` by running the command it names, so those are refused on a continued turn as on any other. It clears `idle` by sending a lane-mail ask or notice, or by updating `tmp/lane-status-.md` under its launch root, so `idle` is refused on a turn another stop hook continued, except on Pi, as the idle rule below states. It clears none of `workdir`, `git`, `item`, `marker` or the `missing-tools` refusal for `git`, `tr`, `awk`, `mktemp` or `tail`, so each of those is reported and the turn ends, where a fresh turn refuses it. The halt arm reports and passes that same set at every tool call: a lane whose tool calls are refused can clear nothing, since clearing it takes a tool call, so there only the payload refusals and the mailbox's own, `reader`, `inbox`, `halt` and `mailbox-missing`, are refused, the last two each passing the one command that clears it. The same turn-end run hands the lane off before it runs out, so the handoff never waits on an overseer reading a pane. It reads this session's context use from the `transcript_path` the payload names, through the orch adapter for the harness this hook's install directory names, `.claude/hooks`, `.codex/hooks` or Pi's `kendex/hooks`: the tokens the last response left in context and effective capacity, with Pi reading the payload's own `context_window`. It records that reading as `context.json` in the lane's mailbox directory, where `lanes context` reads it, and refuses the turn end when `lane_context_handoff_due` requires handoff under the shared context rule in orch `references/oversee-events.md`, Judgement rules. It reads the account the credential this session runs on still has through the orch skill's own `lanes pick --lane`, judging a Claude lane on its own model, and refuses at or below `ORCH_HANDOFF_HEADROOM_PCT` (default 3). A Pi session's account is the one its model's provider bills, by the orch `lane_pick_harness` rule on the `/` its transcript names: a `pi-claude/` model spends the Claude seat `CLAUDE_CONFIG_DIR` names and is judged there on that model, a `github-copilot/` model spends the Copilot pool on Pi's own root, and any other provider, or a reading naming none, is left unjudged under `account=unmeasured`. Either refusal opens `lane-mail-check: context=` or `lane-mail-check: headroom=` and carries one instruction: reach the next safe point, write the record with `workflow-state set handoff`, send a `handoff` notice, and exit. The record is read where `workflow-state --help` § Handoff record says, a launched lane naming the root its launch marker binds as the worktree, and the instruction names the state directory the read found, so a record written as told ends both refusals. The instruction opens with the `workflow-state init ` that `set` needs where the item has no state file yet, so it is enough on its own. It repeats at every turn end, `stop_hook_active` included, until the item's workflow state carries a `.handoff` object no relaunch has resumed; only the lane can write that record, so a single refusal it declines to act on would end the session with nothing recorded. That record is judged before every mark, before every read they rest on and before `orch-env` and `lanes` are looked for, so no failure but the record's own writer can hold a lane that has already done what it was asked. `orch-env` or `lanes` missing from this hook's install, a mark setting that is not a whole number in range, and a transcript the payload names and nothing can read are refusals too, each on the lane path alone and each carrying the same instruction. What the marks cannot judge is reported and passed, never refused: a payload naming no transcript leaves the context unread, and so does a transcript whose last usage line is an object carrying none of the field names its adapter reads, which is reported under `usage-unread=` rather than summed to a figure of zero and read as room, a reading below the independent token limit whose capacity the adapter could not name, reported under `window-unread=`, and an install directory naming no harness, reported under `harness-unlisted=`; a reading that could not be recorded is reported under `context-unrecorded=` and still judged; an account `lanes` keeps no inventory for, one it could not measure and a read that passed this hook's own ceiling each leave the account unjudged under `account=unlisted`, `account=unmeasured` or `account=timeout`, never read as room, so a setup with no usage endpoint still ends its turns; and a lane whose handoff record cannot be judged leaves both marks unjudged under one of four keys, `handoff-skipped=` for a reader or a script this install has not got, or `handoff-skipped=unlocatable` where this hook's own directory could not be resolved and none of them could be looked for, `handoff-outside=` for one only the open repository supplies, `handoff-unanswered=` for one that is there and answered nothing this hook can read, and `handoff-unreadable=` for a state file the install's own `workflow-state` could not read. Passing the turn is the answer for all four. For the first three it is because an install whose orch scripts cannot answer cannot run `workflow-state set` either, so a lane told to record a handoff with them could never end a turn again; for `handoff-unreadable` the install answers and the fault is the item's own state file, which is the file the record would be written into, so that write could not land either and the refusal would be as uncloseable. A subagent's turn end is judged on neither mark. The fleet's OVERSEER meets four triggers of its own on its turn end: a session with no lane of its own whose tmux server and pane are the pair the oversee workflow state records under `.overseer` is that overseer, and nothing weaker establishes one, so an ordinary session in a fleet checkout is judged on nothing. A session whose native identity matches a nonempty binding in the fleet record but whose pane only the overseer's `context.json` names, the overseer the record lost, is judged on nothing either, and reports `pane-unrecorded=` with the recorded key under it and writes that record with no reading and the gap `pane-unrecorded`; any other session the record does not name writes nothing, so the real overseer's reading stands. A fleet record naming this session's pane that lacks its server start, its harness, its launch home or its native session id is healed from an authorized native session first, at a turn end and at a tool call alike: the start of this session's own tmux server, the harness this install names and the launch home the harness variable of this session's own environment carries, `CLAUDE_CONFIG_DIR`, `CODEX_HOME` or `COPILOT_HOME` or that harness's default where it is unset, are written into it through the orch `lib/overseer-launch.sh` `ol_record_heal`, which writes only a fact the record lacks, and the transcript is bound to that home on the same run; a write that fails is reported under `record-unhealed=` with the writer's words, and the caller remains unbound until a later binding write succeeds. Before it reads that transcript for the overseer it binds it to the current session: the `transcript_path` the payload names is read only where it is this session's own native file, held to the `session_id` the payload carries and the launch home the fleet record names under `.overseer.home`, through the orch adapter for a claude, codex or copilot install; a Pi install states no transcript shape and reads the payload's own window as a Pi lane does. If `lane_context_transcript_owned` refuses an admitted overseer's transcript binding, the hook reports `transcript-unowned=` with the reason the library returns. Nothing is read then, and the context record is written with a null token count and that reason as its `gap` (orch `workflow-state.md`, `context.json` row), so it still advances at every turn end and oversee-watch reports the gap, and the judge is handed this install's harness and no context figure, so it judges the account triggers alone, the `transcript-unowned` line is this hook's one report that the context went unmeasured, and a session is never judged on a file it does not own. Every overseer turn end whose orch context library loads writes that record, a reading or a null token count with a `gap` naming why none was taken: the binding library's reason, `transcript-unnamed` for a payload naming no transcript, `usage-absent` for a transcript holding no usage line, `usage-unread` for a usage object its adapter does not read, which is also reported under `usage-unread=`, `session-record` for a Copilot session with no extension reading whose statusLine session record does not answer either, which is also reported under `session-record=`, or `pane-unrecorded` below. A Copilot statusLine record reporting allow_all_enabled false, read whether or not an extension reading stands, in a session whose `COPILOT_ALLOW_ALL` is true (a launch line granting `--allow-all` or `--yolo`), is reported under `stop-cause=allow-all-blocked-by-policy`, and the turn end judged as usual. An install naming no harness an adapter reads writes no gap, since its context is never read, and leaves the record as it was, and a Copilot one names none where the reading its usage arm wrote for this session stands, its turn end reading that record rather than taking a reading of its own; a gap record that cannot be written is reported under `context-gap-unrecorded=`, the record keeping its earlier entry. This hook records the overseer's own context reading as `context.json` in the overseer mailbox directory at the main checkout, naming the session and its pane, and hands that reading to `oversee-succeed --check-marks --context :` from this hook's own install, which judges those marks on it and on no stored figure, and nothing at the turn end here judges them, under the same ceiling the account read runs under, so the turn-end refusal and the `overseer-mark` watch event cannot describe one overseer differently. Its refusal opens with the `context=`, `headroom=`, `rate=` or `qualifying=` key, carrying the figure that judgement read, and names `oversee-succeed`, handed the same reading, as the route, with `workflow-state set oversee handoff` under it for a succession that refuses, so the refusal always has an escape the overseer can reach. That record names the session that wrote it, in the native `session_id` the payload gives. A payload with no native session id is refused and cannot read mail or write overseer context or gaps. `overseer_identify` owns its native refusal diagnostics. One other refusal stands on that path, `script` for an `oversee-succeed` this install has not got, and the record clears it as it clears the marks. `ORCH_OVERSEER_SUCCESSION=off`, read off the judgement's own line and never here, turns the account-mark refusals off with the succession they name, the watch's `overseer-mark` event still reporting those marks; the context mark is refused whatever the setting, since no watch event reports it, and the handoff record ends that refusal. An answer this hook cannot act on, one the ceiling abandoned, and one whose own reading was unmeasured are reported under `marks=unjudged`, `marks=timeout` and `marks=unmeasured` and the turn ends, never held. A lane asks its overseer only through lane mail. Before a tool call in a launched lane, the halt arm refuses the harness question tool by its name, whichever of the four names the payload's `tool_name` carries, Claude Code's `AskUserQuestion` and `EnterPlanMode`, Codex's `request_user_input` and Pi's `question`, opening `lane-mail-check: question-tool=` and naming the `lane-mail ask --item --file ` send and the `lane-mail wait` on its printed id as the route, because a dialog on the pane reaches no overseer; an unread halt is refused ahead of it, a subagent's call is refused and told to report its question to the lead, and a session that is no launched lane passes the call silently, a committed mailbox and status file included. At a launched lane lead's turn end, once the handoff marks pass, the lane is judged idle on lane-mail sends and its lane status file update state, never on words in its pane, on Claude Code, Codex, Pi and Copilot; OpenCode and Cursor run no kendex hooks, and Gemini and Antigravity do not run this one, so a lane there is never judged idle. The reader's own `lane-mail events` listing, which moves no cursor, counts the asks and notices in the lane's outbound file against the count this hook recorded at the lane's last judged turn end, `sent-count` in the lane's mailbox directory: a line holding the count, the word `held` where this judge refused that turn end, and an optional encoded status file update state; no record is a count of zero with no status state. A status file update since that record, including a rewrite of the same text, passes without a notice. A count other than the recorded one is a send this turn and passes, a standing handoff record ends the run before this judge, the newest directive the overseer sent carrying `halt` passes, and a lane whose launch marker no longer binds its root, the close-out's state, is no lane. With none of these the turn is refused and the hold recorded, opening `lane-mail-check: idle=` with one continuation, the lane's `lane-mail inbox` read and then its workflow, beside the ask route and the `lane-mail notice` send, which follows the orch Coordination notice rule: changed work sends a notice, and a continuing wait on a dispatched agent or an armed wake updates the lane status file only. On a turn the harness continued for this judge's own recorded hold it refuses nothing and sends the overseer a lane notice stating what it checked, opening `lane-mail-check: idle-notice=`, or `idle-notice-unsent=` with the sender's words where the send fails, so an idle lane is reported and never looped. A turn another stop hook's refusal continued is held as a fresh one, except on Pi, whose pi-hooks carrier runs no further request after a continued turn, so there the notice is sent with no hold before it. The record counts that notice, so the lane's next turn is judged on what the lane itself sends. An `events` listing that fails, or whose envelopes jq cannot read, is reported under `events=` or `events=envelope`, and a record that is not a plain file holding a whole number, an optional `held` mark and an optional encoded status state under `idle-record=` and rewritten. A record that cannot be written is reported under `idle-unrecorded=`; under `idle-hold-unrecorded=` where it was to take a hold, which is then not made, since one with no record would be made again on every continued turn; and under `idle-notice-unrecorded=` where it was to count the notice, which the next turn end then reads as the lane's own send. Each of these ends the turn, because nothing a lane does at its turn end repairs its mailbox; an install with no reader leaves the turn unjudged under the marks' own `handoff-skipped` line. On Copilot the event is `agentStop`, registered in Copilot's own hook file under its camelCase name, so the payload spells its fields `sessionId`, `transcriptPath` and `toolArgs`, which this hook reads beside the snake_case spellings; its reference spells `stop_hook_active` so on both, and `toolName` identifies an attached launch. The `lane-mail-halt` description owns the Copilot preToolUse decision and deadline contract. Copilot also runs the hooks `.claude/settings.json` registers, under their PascalCase names, but the registration kendex writes there exits 0 before its script in a Copilot hook process, so a Copilot call reaches an install that is not Copilot's, the claude copy of this hook among them, only through a registration made there by hand or one kendex wrote before that skip and no refresh has rewritten. Whether Copilot made the call is read from the call, never from the install: a payload carrying `timestamp`, which both of Copilot's payload formats carry and no Claude, Codex or Pi payload does, or naming the session `sessionId`, is Copilot's, and any install but Copilot's own passes it silently, exit 0 with nothing written and nothing acknowledged, so the Copilot install is the one reader of the mailbox for a Copilot call. A Copilot agentStop names no agent: the stop whose `transcriptPath` sits in the directory named for the `sessionId`, Copilot's `session-state//events.jsonl`, is the lead's and records it, a stop naming a transcript under another directory is read as a subagent's, handed nothing and judged on nothing, and a payload naming no transcript, or no session, is the lead's and records nothing. Copilot CLI 1.0.88 was measured firing agentStop at a custom subagent's end too, with the subagent's own `sessionId` and the lead's `transcriptPath`, which this rule reads as a subagent's. A refusal on Copilot is the documented answer for its event, on stdout beside the keyed stderr line: at a turn end `{"decision":"block","reason":}` with exit 0, which Copilot stops honouring after 8 consecutive blocks, ending that turn unheld, so a handoff refusal holds a Copilot session for 8 continued turns and then returns at its next turn end, and after a tool call `{"additionalContext":}` with exit 0, since Copilot reads a postToolUse answer only at exit 0. A Copilot session's context is read through Copilot's own SDK event `session.usage_info`: the orch `copilot-lane-context` extension, which `open-terminal` installs in a Copilot fleet lane's `COPILOT_HOME` with the EXTENSIONS feature on, runs this hook with the argument `usage` at each reading of the session's root agent, handing it `{session_id, cwd, current_tokens, token_limit}` on stdin, and for a recorded lead session that is a launched lane's lead or the fleet's overseer, named by the same gate every arm that judges the marks asks, it records `current_tokens` as the tokens and, as the capacity, the limit Copilot compacts at: 80 percent of `token_limit`, the SDK's documented `backgroundCompactionThreshold` default, named in the record's `capacity_source`. It writes nothing on stdout; a gap is refused on stderr at exit 2, which the extension writes to the session timeline: `payload=invalid-json`, an orch install it cannot use under the key its turn end reports that gap under, `handoff-skipped=`, `handoff-outside=` or `handoff-unanswered=`, or `context-unrecorded=` for a reading that could not be written, where the session's earlier reading is removed too so its turn end reports the context unmeasured rather than judging an older figure as room. Any other session passes silently. The Copilot turn end judges this session's record under the shared context rule exactly as it judges a transcript reading, the capacity putting the handoff before Copilot's own compaction; no reading of this session, no record or a gap record, is read from the fallback below; where the pending marker the extension leaves at `~/.cache/lane-mail/copilot-usage/` for a reading it handed on and no run has recorded yet still stands after a wait of 5 seconds, the turn end reports `reading-pending=` and passes with the context unmeasured, reading no fallback, since the extension runs for that session, and never judging the earlier record as room, since nothing orders the extension's run before the turn end; and a record that stands and cannot be read is refused under `record=`. Where no pending marker stands and no reading of the extension's stands for this session, no record, one naming another session, a gap record or one the fallback below wrote, which its `capacity_source` tells apart, the turn end reads the fallback: the session record the orch `copilot-statusline` command writes as the account's `statusLine`, under `/lane-status/.json`, through the orch adapter for copilot, which holds the record to the payload's `sessionId`, its `transcriptPath` where one is named, the account directory and a freshness bound, and hands the shared judge the same compaction point of the window as the capacity; that reading is judged and recorded as any other harness's, and a record that does not answer leaves the context unmeasured under `reading-unrecorded=` and `session-record=`, reported and passed, never read as room. An extension reading below the mark is never overridden by a statusLine record past it. Run with `compact` by the lane-mail-compact hook at a preCompact whose `trigger` is `auto`, from a recorded lead session that gate names, it flags that compaction as `compaction.json` beside the reading, the backstop for a turn that crossed into the compaction before a reading past the mark reached a turn end, and the turn end then refuses under `compacted=auto` until the handoff record stands, the overseer's whatever its succession setting; a gap there is refused under `compaction-unrecorded=` on stderr at exit 2, which Copilot shows the operator without holding the compaction. A Copilot account is judged through `lanes pick --lane` like any other. A session the Jarvis runtime launched, which carries `JARVIS_RECORD`, has its lead's tool calls, on Copilot any call under the session id the record's start bound, and on Claude Code its turn ends, stamp that runtime record's launch row once as its Start brief taken, the fact the Jarvis launch worker reads beside the pane; another harness's turn end is no stamp, since Pi's carrier also dispatches it on a run that ended on an error and Codex and Copilot have no turn-failure event to tell one apart; a stamp that cannot be written is reported under `jarvis-rows-unwritten=` and passed, and the next such call writes it. Not run on gemini: it has no Stop event. Not run on antigravity: its Stop payload carries no `stop_hook_active`. +# description: Blocks a lane's turn end while its overseer mailbox holds unread lines, so a directive or a ruling reaches the lane without a keystroke, a pane or a question tool. The lane is the work item `LANE_MAIL_ITEM` names, or the one directory under `/tmp/lane-mail/` whose name lowercases to the current branch; a session with neither is not a lane; a lane whose mailbox holds no unread line passes silently, as does a directory git reports no repository for and that holds no mailbox of its own. The checkout's overseer mailbox, `/tmp/lane-mail/overseer`, has one reader: the session whose tmux server and pane the checkout's oversee workflow state names under `.overseer`, the pair every writer the orch `schemas/workflow-state.md` `overseer` row names writes, `oversee register` among them for a session opened by hand, and the one the fleet's OVERSEER is established by below, so a record naming a dead pane names no reader. The native session must also match the recorded harness, readable caller home and payload session id; `ol_record_heal` binds the first matching native id from the recorded pane, and `oversee register` clears that binding after a resume. Pi and any harness whose `lane_context_caller_home` reports no home compare the harness and native session id only. The pair names a session only on the tmux server started at the record's `server_start`, so a server a tmux restart handed the recorded pid and pane id names no reader either; a record carrying no start at all names the session in that pane, which writes its server's start into it. Where a file stands there, that session is handed the notes `lane-mail peer send --repo` wrote there at its turn end and after its tool calls, under the same `unread=` line, unless a live watch holds the fleet state: the `oversee-watch.pid` record a repeat `oversee-watch` writes beside the fleet state on every surface and removes on exit, judged by the orch `lib/watch-pid.sh` library's `watch_pid_live`, which reads the mailbox itself, so the named session is handed nothing from it beside that watch. A fleet watched in single passes writes no watch record, so its named overseer is handed the notes as `unread=` lines and the next pass does not report them. A Jarvis session's wake, the process `ORCH_WAKE_PROCESS` matches, is no such watch: it moves no cursor, so that session is handed each note in full here once and acknowledges it here, and its wake carries no note's body, at most the count and read command `lane-mail watch` prints. Where the payload's `kendex_ack` is `caller`, which the pi-hooks lane mail wake sends, the context carries the reader's `--ack` command as `kendex_ack` and nothing is acknowledged here: the wake runs it once its send returns, so a send that throws leaves the lines unread. Every other session in the checkout, one the owner opened there for other work included, is handed nothing from that mailbox, and so is a session whose install has no reader beside this hook. For the named session, where the install's `workflow-state path oversee` prints no path, or the library cannot be sourced or answers neither way, the hook refuses, opening `lane-mail-check: fleet-state=` with that file's own words under it; the halt arm never reads that mailbox, a subagent's turn end is handed nothing from it, and a session in a checkout with no overseer mailbox pays two file tests for the question. `` is the lane's root, resolved in this order: `CLAUDE_PROJECT_DIR`, the directory Claude Code started the session in; else the root the launch marker for `LANE_MAIL_ITEM` binds, where that root exists; else the directory the hook runs in, which on Codex and Pi is the session's start directory and on Claude Code without the variable is the call's own. A Claude Code lane working from the main clone is therefore still judged on its own mailbox. A root its launch marker binds that has no `tmp/lane-mail` directory is refused at a turn end, before any tool call and after the lead's finished one, opening `lane-mail-check: mailbox-missing=` with the marker and the one `mkdir` command that restores the directory, and that command alone passes a tool call. Before a tool call a subagent is refused whatever it runs, and a call whose caller is unknown may run that command; after one a subagent is handed nothing and refused nothing, as with any mail, and its next call meets the refusal. The marker is looked up for the item `LANE_MAIL_ITEM` names or else the branch names, so that check costs one stat in a repository whose common git directory holds no `lane-mail` directory, and one branch read and one marker stat in one that does. A mailbox belongs to a lane only where a launch recorded one: `open-terminal` and `lane-host create` write the lane's root to `lane-mail/` under the repository's common git directory and create the lane's own `tmp/lane-mail/`, and a mailbox with no marker bound to this root passes silently. Unread lines are peeked through the orch skill's own `lane-mail inbox --peek`, the one reader of the mailbox and its cursor, and acknowledged with `inbox --ack` only once the refusal is written, so a hook killed at its budget leaves them unread and a line acknowledged here is never handed over twice. That reader is resolved from this hook's own install, walking up to the home directory for `skills/mailbox/scripts/lane-mail` or the shared `.agents/skills/mailbox/scripts/lane-mail` beside it, then the home's own shared tree for a harness root relocated out of it; the open repository's `.agents/skills/mailbox/scripts/lane-mail` is used only where this hook is installed in that repository, and a reader outside that containment is refused rather than run. The refusal opens with `lane-mail-check: unread=` and carries one JSON envelope per line under it, and for the lead, where a halt is among them, the one `lane-mail inbox` command that reads it; the turn then continues with them. Run with the argument `deliver` by the lane-mail-deliver hook after a tool call, it exits 0 with the harness's JSON on stdout, whose `additionalContext` carries the same lines. That run first judges the context mark of the fleet's OVERSEER, below, for a lead's call in tmux in a checkout whose `tmp/lane-mail/overseer` directory stands, so a mark crossed mid-turn is read at the next tool call: the context is read and recorded as the overseer's turn end reads it and judged at `ORCH_HANDOFF_CONTEXT_PCT` by the rule the orch `references/oversee-events.md` § Judgement rules states for the overseer's context mark. On Pi the window is the payload's own `context_window`, which the pi-hooks carrier puts on the PostToolUse payload of every tool call; a Pi payload naming none, the lane mail wake's run or a tool call from an older carrier, takes no reading, writes no record and hands nothing over, so the turn end's reading and judgement stand. A reached mark, or a setting it cannot be judged on, is handed over as that `additionalContext`, opening `lane-mail-check: context=` with the succession and the handoff record as the route, at every tool call until that record stands. Every other line that judgement writes, a judgement that could not run, a transcript it could not read or an `orch-env` this install has not got, is handed over the same way once per session and first line, the last told kept in `tmp/lane-mail/overseer/context-told`, written only once the run's output carrying it is written and cleared by a clean reading; only the bound native session the fleet record names, or the overseer it lost whose native identity still matches a nonempty recorded binding, writes or clears that file. Either opens the same context as any mail the call hands over, above its `unread=` line, and a refusal the mailbox check makes on the same call, above its keyed line, whether that refusal is Copilot's `additionalContext` or stderr at exit 2. The judgement itself refuses no call, and no account is read there. Run with `start` by the lane-mail-start hook at a session start, or with `prompt` by the lane-mail-prompt hook at a prompt, both on Copilot alone, it hands the same lines over the same way. A session start acknowledges them only once that context is written. A prompt leaves the lines unread because Copilot can discard its output, so a later inbox read or hook delivery can repeat them. Neither arm refuses anything: every refusal this description names is its keyed line on stderr at exit 0, with nothing on stdout and nothing acknowledged. Before an attached agent launch, the halt arm also judges the lead of a launched lane or the identified fleet overseer at the context mark, refusing missing context with the orch job runner or a separate session as the route. While an attached agent of the session may still be out, the mark is less ORCH_HANDOFF_AGENT_RESERVE_TOKENS, default 150000 tokens, equality refused: Claude Code reads that roster from its task registry where the payload carries one, else from the transcript's Agent-call results, task notifications, teammate idle notifications and sends, and reads an unreadable roster or an entry neither read classifies as unknown; Codex reads ordered collaboration snapshots, launches and followups from its rollout. Idle, completed, errored, shutdown and not-found children release the reserve; initializing, running and interrupted children keep it. A full unfiltered snapshot replaces earlier unknown observations only when its call does not overlap a launch or followup; pending calls and unreadable current observations keep the roster unknown. After waiting, Codex must call list_agents with no path filter to observe returns. Other harnesses read none, so their rosters are unknown. With none out the launch meets the plain mark. A launch the reserve alone refuses with an agent out is keyed `agent-reserve` and names waiting for those agents, the job runner or a separate session, never a handoff, since the turn end and every succession judge the plain mark. With the roster unknown no wait can be observed, so the refusal is keyed `agent-unobserved` and names the job runner or a separate session, and for a lane its handoff record. On Pi the lead launches through subagent; delegate_subagent carries child identity and is outside this lead-only reserve rule. At a context hold, a live session waits for attached agent returns in this turn; Claude Stop background_tasks is preferred, with the transcript's measured Agent-call results, async launch and teammate spawn records, task notifications, teammate idle notifications and sends as the fallback when absent. Other harnesses name known unfinished children and known output paths, or unknown paths, in the emergency handoff. A standing handoff retains its escape, and the successor reads existing output before repeating work. Run with `halt` by the lane-mail-halt hook before one, it acknowledges nothing and refuses the call while an unread directive sent with `lane-mail send --halt` stands, opening `lane-mail-check: halt=` with the directive and the one `lane-mail inbox` command that reads it, which names the lane's root with `--root` so it reads the same mailbox from any checkout; that command alone passes. Run with `row` and the event by the session-start-row, session-end-row and stop-failure-row hooks, it writes the event row of a session with no lane of its own, only for the pane's top-level harness and, on Copilot, only for a session the caller rule names the lead, through the orch skill's `lib/session-rows.sh`, the file those hooks describe, and refuses nothing: every gap below its payload read is reported and passed; the overseer's own turn end writes a Stop row there through the same library at every turn end, compact, its time, event, harness and session alone, except over a standing StopFailure row, which it lifts and where it keeps the turn's last message. Run with `lane` by the critical-path-deny hook, it prints `lane` where the launch marker for the session's item binds the session's root and its mailbox directory stands, else `none`, records and judges nothing else, and exits 0; a gap past its payload read is reported on stderr and passed with nothing on stdout. On a Pi install a launched lane's lead writes its own turn rows through that library into its mailbox directory, `session-rows.jsonl`: a Stop row at each turn end, carrying the `stopReason` of the turn's last assistant message in the transcript and Pi's `errorMessage` where that reason is `error`, and a PreToolUse row at the first tool call of each turn, after a turn end or on an empty file, written ahead of the mailbox check; oversee-watch and `lanes state` judge a Pi lane idle, working or walled from those rows in place of its pane, and a gap in the write is reported under `lane-rows-skipped` or `lane-rows-unwritten` and passed. The Pi install is the hook directory under `.pi` or `.pi/agent`, or under the user root `PI_CODING_AGENT_DIR` names; an install naming no harness writes no row, which a launched lane's turn end reports under `harness-unlisted`. Who made a call is answered once for every arm: the lead, a subagent, or unknown. A SubagentStop payload or one carrying a non-empty `agent_id` or `agent_type` is a subagent's on every harness, handed no mail and acknowledging none, and while a halt stands refused without that command. On Copilot, whose payloads name no agent, a preToolUse or postToolUse call, a preCompact and a context reading the usage arm is handed are the lead's where the session id they carry is a lead session this install recorded, the one rule for all four: one empty file per session under `~/.cache/lane-mail/copilot-leads`, written at the session's sessionStart, which Copilot fires for the lead alone, and at each turn end the transcript rule below proves the lead's, and pruned at a start once untouched for 30 days. A custom subagent's call was measured on Copilot CLI 1.0.88 carrying its own session id, which nothing recorded; whether a built-in task-tool subagent's calls carry their own session id or the lead's is a pending live-lane proof, and one whose calls carry the lead's is read as the lead, handed the lead's mail after its calls, which marks it read, and under a halt shown the read that clears it. A call whose session is no recorded lead, a custom subagent's among them, is unknown: the deliver arm hands it nothing and acknowledges nothing, writing `lane-mail-check: session-unrecorded=` to stderr, the compact arm flags nothing and writes the same line at exit 0, the usage arm records nothing and refuses under that key at exit 2, so the lead's turn end hands the lines over and acknowledges them, and the halt arm refuses it without showing that command yet passes the command, because the reader's `--ack` stops short of an unread halt and a lead whose record could not be written would otherwise be refused for good; the lead is shown the command by every notice and refusal that hands it the halt, its turn end's included. A record that cannot be written is reported on stderr under `lane-mail-check: lead-unrecorded=`, or `=none` for a session start naming no session id, and never refused. A Copilot sessionStart or userPromptSubmitted is the lead's, and an agentStop is ruled by its transcript, below; a prompt records no lead, since that a subagent's prompt fires no userPromptSubmitted is unmeasured. `stop_hook_active` true skips the mailbox check whole on the turn-end run. The flag is in the payload, so nothing above the payload read knows a turn was continued, and `arm`, the `missing-tools` refusal for `jq` or `cat`, `payload=unreadable` and `payload=invalid-json` are refused on every turn, the continued one included. Below that read one rule holds and every refusal is on one side of it: a refusal the lane itself can clear is still made, and a refusal it cannot is reported on stderr and passed. The lane clears the handoff refusals, and `script`, `setting`, `setting-range` and both `transcript` refusals, by writing its handoff record, and `mailbox-missing` by running the command it names, so those are refused on a continued turn as on any other. It clears `idle` by sending a lane-mail ask or notice, or by updating `tmp/lane-status-.md` under its launch root, so `idle` is refused on a turn another stop hook continued, except on Pi, as the idle rule below states. It clears none of `workdir`, `git`, `item`, `marker` or the `missing-tools` refusal for `git`, `tr`, `awk`, `mktemp` or `tail`, so each of those is reported and the turn ends, where a fresh turn refuses it. The halt arm reports and passes that same set at every tool call: a lane whose tool calls are refused can clear nothing, since clearing it takes a tool call, so there only the payload refusals and the mailbox's own, `reader`, `inbox`, `halt` and `mailbox-missing`, are refused, the last two each passing the one command that clears it. The same turn-end run hands the lane off before it runs out, so the handoff never waits on an overseer reading a pane. It reads this session's context use from the `transcript_path` the payload names, through the orch adapter for the harness this hook's install directory names, `.claude/hooks`, `.codex/hooks` or Pi's `kendex/hooks`: the tokens the last response left in context and effective capacity, with Pi reading the payload's own `context_window`. It records that reading as `context.json` in the lane's mailbox directory, where `lanes context` reads it, and refuses the turn end when `lane_context_handoff_due` requires handoff under the shared context rule in orch `references/oversee-events.md`, Judgement rules. It reads the account the credential this session runs on still has through the orch skill's own `lanes pick --lane`, judging a Claude lane on its own model. The picker owns the account handoff decision. For an ordinary account wall, the hook refuses the turn end and names the binding bucket's headroom against `ORCH_HANDOFF_HEADROOM_PCT` (default 3). When that picker reports `seat-reserve` for an overseer seat, the hook refuses the turn end. That refusal names the binding bucket's headroom and the configured `ORCH_OVERSEER_SEAT_RESERVE_PCT` (default 50) as independent facts. A Pi session's account is the one its model's provider bills, by the orch `lane_pick_harness` rule on the `/` its transcript names: a `pi-claude/` model spends the Claude seat `CLAUDE_CONFIG_DIR` names and is judged there on that model, a `github-copilot/` model spends the Copilot pool on Pi's own root, and any other provider, or a reading naming none, is left unjudged under `account=unmeasured`. A lane's context and account mark refusals open `lane-mail-check: context=`, `lane-mail-check: headroom= bucket= mark=` or `lane-mail-check: seat-reserve= bucket= reserve=`. Each carries one instruction: reach the next safe point, write the record with `workflow-state set handoff`, send a `handoff` notice, and exit. The record is read where `workflow-state --help` § Handoff record says, a launched lane naming the root its launch marker binds as the worktree, and the instruction names the state directory the read found, so a record written as told ends both refusals. The instruction opens with the `workflow-state init ` that `set` needs where the item has no state file yet, so it is enough on its own. It repeats at every turn end, `stop_hook_active` included, until the item's workflow state carries a `.handoff` object no relaunch has resumed; only the lane can write that record, so a single refusal it declines to act on would end the session with nothing recorded. That record is judged before every mark, before every read they rest on and before `orch-env` and `lanes` are looked for, so no failure but the record's own writer can hold a lane that has already done what it was asked. `orch-env` or `lanes` missing from this hook's install, a mark setting that is not a whole number in range, and a transcript the payload names and nothing can read are refusals too, each on the lane path alone and each carrying the same instruction. What the marks cannot judge is reported and passed, never refused: a payload naming no transcript leaves the context unread, and so does a transcript whose last usage line is an object carrying none of the field names its adapter reads, which is reported under `usage-unread=` rather than summed to a figure of zero and read as room, a reading below the independent token limit whose capacity the adapter could not name, reported under `window-unread=`, and an install directory naming no harness, reported under `harness-unlisted=`; a reading that could not be recorded is reported under `context-unrecorded=` and still judged; an account `lanes` keeps no inventory for, one it could not measure and a read that passed this hook's own ceiling each leave the account unjudged under `account=unlisted`, `account=unmeasured` or `account=timeout`, never read as room, so a setup with no usage endpoint still ends its turns; and a lane whose handoff record cannot be judged leaves both marks unjudged under one of four keys, `handoff-skipped=` for a reader or a script this install has not got, or `handoff-skipped=unlocatable` where this hook's own directory could not be resolved and none of them could be looked for, `handoff-outside=` for one only the open repository supplies, `handoff-unanswered=` for one that is there and answered nothing this hook can read, and `handoff-unreadable=` for a state file the install's own `workflow-state` could not read. Passing the turn is the answer for all four. For the first three it is because an install whose orch scripts cannot answer cannot run `workflow-state set` either, so a lane told to record a handoff with them could never end a turn again; for `handoff-unreadable` the install answers and the fault is the item's own state file, which is the file the record would be written into, so that write could not land either and the refusal would be as uncloseable. A subagent's turn end is judged on neither mark. The fleet's OVERSEER meets four triggers of its own on its turn end: a session with no lane of its own whose tmux server and pane are the pair the oversee workflow state records under `.overseer` is that overseer, and nothing weaker establishes one, so an ordinary session in a fleet checkout is judged on nothing. A session whose native identity matches a nonempty binding in the fleet record but whose pane only the overseer's `context.json` names, the overseer the record lost, is judged on nothing either, and reports `pane-unrecorded=` with the recorded key under it and writes that record with no reading and the gap `pane-unrecorded`; any other session the record does not name writes nothing, so the real overseer's reading stands. A fleet record naming this session's pane that lacks its server start, its harness, its launch home or its native session id is healed from an authorized native session first, at a turn end and at a tool call alike: the start of this session's own tmux server, the harness this install names and the launch home the harness variable of this session's own environment carries, `CLAUDE_CONFIG_DIR`, `CODEX_HOME` or `COPILOT_HOME` or that harness's default where it is unset, are written into it through the orch `lib/overseer-launch.sh` `ol_record_heal`, which writes only a fact the record lacks, and the transcript is bound to that home on the same run; a write that fails is reported under `record-unhealed=` with the writer's words, and the caller remains unbound until a later binding write succeeds. Before it reads that transcript for the overseer it binds it to the current session: the `transcript_path` the payload names is read only where it is this session's own native file, held to the `session_id` the payload carries and the launch home the fleet record names under `.overseer.home`, through the orch adapter for a claude, codex or copilot install; a Pi install states no transcript shape and reads the payload's own window as a Pi lane does. If `lane_context_transcript_owned` refuses an admitted overseer's transcript binding, the hook reports `transcript-unowned=` with the reason the library returns. Nothing is read then, and the context record is written with a null token count and that reason as its `gap` (orch `workflow-state.md`, `context.json` row), so it still advances at every turn end and oversee-watch reports the gap, and the judge is handed this install's harness and no context figure, so it judges the account triggers alone, the `transcript-unowned` line is this hook's one report that the context went unmeasured, and a session is never judged on a file it does not own. Every overseer turn end whose orch context library loads writes that record, a reading or a null token count with a `gap` naming why none was taken: the binding library's reason, `transcript-unnamed` for a payload naming no transcript, `usage-absent` for a transcript holding no usage line, `usage-unread` for a usage object its adapter does not read, which is also reported under `usage-unread=`, `session-record` for a Copilot session with no extension reading whose statusLine session record does not answer either, which is also reported under `session-record=`, or `pane-unrecorded` below. A Copilot statusLine record reporting allow_all_enabled false, read whether or not an extension reading stands, in a session whose `COPILOT_ALLOW_ALL` is true (a launch line granting `--allow-all` or `--yolo`), is reported under `stop-cause=allow-all-blocked-by-policy`, and the turn end judged as usual. An install naming no harness an adapter reads writes no gap, since its context is never read, and leaves the record as it was, and a Copilot one names none where the reading its usage arm wrote for this session stands, its turn end reading that record rather than taking a reading of its own; a gap record that cannot be written is reported under `context-gap-unrecorded=`, the record keeping its earlier entry. This hook records the overseer's own context reading as `context.json` in the overseer mailbox directory at the main checkout, naming the session and its pane, and hands that reading to `oversee-succeed --check-marks --context :` from this hook's own install, which judges those marks on it and on no stored figure, and nothing at the turn end here judges them, under the same ceiling the account read runs under, so the turn-end refusal and the `overseer-mark` watch event cannot describe one overseer differently. Its refusal opens with the `context=`, `headroom=`, `rate=` or `qualifying=` key, carrying the figure that judgement read, and names `oversee-succeed`, handed the same reading, as the route, with `workflow-state set oversee handoff` under it for a succession that refuses, so the refusal always has an escape the overseer can reach. That record names the session that wrote it, in the native `session_id` the payload gives. A payload with no native session id is refused and cannot read mail or write overseer context or gaps. `overseer_identify` owns its native refusal diagnostics. One other refusal stands on that path, `script` for an `oversee-succeed` this install has not got, and the record clears it as it clears the marks. `ORCH_OVERSEER_SUCCESSION=off`, read off the judgement's own line and never here, turns the account-mark refusals off with the succession they name, the watch's `overseer-mark` event still reporting those marks; the context mark is refused whatever the setting, since no watch event reports it, and the handoff record ends that refusal. An answer this hook cannot act on, one the ceiling abandoned, and one whose own reading was unmeasured are reported under `marks=unjudged`, `marks=timeout` and `marks=unmeasured` and the turn ends, never held. A lane asks its overseer only through lane mail. Before a tool call in a launched lane, the halt arm refuses the harness question tool by its name, whichever of the four names the payload's `tool_name` carries, Claude Code's `AskUserQuestion` and `EnterPlanMode`, Codex's `request_user_input` and Pi's `question`, opening `lane-mail-check: question-tool=` and naming the `lane-mail ask --item --file ` send and the `lane-mail wait` on its printed id as the route, because a dialog on the pane reaches no overseer; an unread halt is refused ahead of it, a subagent's call is refused and told to report its question to the lead, and a session that is no launched lane passes the call silently, a committed mailbox and status file included. At a launched lane lead's turn end, once the handoff marks pass, the lane is judged idle on lane-mail sends and its lane status file update state, never on words in its pane, on Claude Code, Codex, Pi and Copilot; OpenCode and Cursor run no kendex hooks, and Gemini and Antigravity do not run this one, so a lane there is never judged idle. The reader's own `lane-mail events` listing, which moves no cursor, counts the asks and notices in the lane's outbound file against the count this hook recorded at the lane's last judged turn end, `sent-count` in the lane's mailbox directory: a line holding the count, the word `held` where this judge refused that turn end, and an optional encoded status file update state; no record is a count of zero with no status state. A status file update since that record, including a rewrite of the same text, passes without a notice. A count other than the recorded one is a send this turn and passes, a standing handoff record ends the run before this judge, the newest directive the overseer sent carrying `halt` passes, and a lane whose launch marker no longer binds its root, the close-out's state, is no lane. With none of these the turn is refused and the hold recorded, opening `lane-mail-check: idle=` with one continuation, the lane's `lane-mail inbox` read and then its workflow, beside the ask route and the `lane-mail notice` send, which follows the orch Coordination notice rule: changed work sends a notice, and a continuing wait on a dispatched agent or an armed wake updates the lane status file only. On a turn the harness continued for this judge's own recorded hold it refuses nothing and sends the overseer a lane notice stating what it checked, opening `lane-mail-check: idle-notice=`, or `idle-notice-unsent=` with the sender's words where the send fails, so an idle lane is reported and never looped. A turn another stop hook's refusal continued is held as a fresh one, except on Pi, whose pi-hooks carrier runs no further request after a continued turn, so there the notice is sent with no hold before it. The record counts that notice, so the lane's next turn is judged on what the lane itself sends. An `events` listing that fails, or whose envelopes jq cannot read, is reported under `events=` or `events=envelope`, and a record that is not a plain file holding a whole number, an optional `held` mark and an optional encoded status state under `idle-record=` and rewritten. A record that cannot be written is reported under `idle-unrecorded=`; under `idle-hold-unrecorded=` where it was to take a hold, which is then not made, since one with no record would be made again on every continued turn; and under `idle-notice-unrecorded=` where it was to count the notice, which the next turn end then reads as the lane's own send. Each of these ends the turn, because nothing a lane does at its turn end repairs its mailbox; an install with no reader leaves the turn unjudged under the marks' own `handoff-skipped` line. On Copilot the event is `agentStop`, registered in Copilot's own hook file under its camelCase name, so the payload spells its fields `sessionId`, `transcriptPath` and `toolArgs`, which this hook reads beside the snake_case spellings; its reference spells `stop_hook_active` so on both, and `toolName` identifies an attached launch. The `lane-mail-halt` description owns the Copilot preToolUse decision and deadline contract. Copilot also runs the hooks `.claude/settings.json` registers, under their PascalCase names, but the registration kendex writes there exits 0 before its script in a Copilot hook process, so a Copilot call reaches an install that is not Copilot's, the claude copy of this hook among them, only through a registration made there by hand or one kendex wrote before that skip and no refresh has rewritten. Whether Copilot made the call is read from the call, never from the install: a payload carrying `timestamp`, which both of Copilot's payload formats carry and no Claude, Codex or Pi payload does, or naming the session `sessionId`, is Copilot's, and any install but Copilot's own passes it silently, exit 0 with nothing written and nothing acknowledged, so the Copilot install is the one reader of the mailbox for a Copilot call. A Copilot agentStop names no agent: the stop whose `transcriptPath` sits in the directory named for the `sessionId`, Copilot's `session-state//events.jsonl`, is the lead's and records it, a stop naming a transcript under another directory is read as a subagent's, handed nothing and judged on nothing, and a payload naming no transcript, or no session, is the lead's and records nothing. Copilot CLI 1.0.88 was measured firing agentStop at a custom subagent's end too, with the subagent's own `sessionId` and the lead's `transcriptPath`, which this rule reads as a subagent's. A refusal on Copilot is the documented answer for its event, on stdout beside the keyed stderr line: at a turn end `{"decision":"block","reason":}` with exit 0, which Copilot stops honouring after 8 consecutive blocks, ending that turn unheld, so a handoff refusal holds a Copilot session for 8 continued turns and then returns at its next turn end, and after a tool call `{"additionalContext":}` with exit 0, since Copilot reads a postToolUse answer only at exit 0. A Copilot session's context is read through Copilot's own SDK event `session.usage_info`: the orch `copilot-lane-context` extension, which `open-terminal` installs in a Copilot fleet lane's `COPILOT_HOME` with the EXTENSIONS feature on, runs this hook with the argument `usage` at each reading of the session's root agent, handing it `{session_id, cwd, current_tokens, token_limit}` on stdin, and for a recorded lead session that is a launched lane's lead or the fleet's overseer, named by the same gate every arm that judges the marks asks, it records `current_tokens` as the tokens and, as the capacity, the limit Copilot compacts at: 80 percent of `token_limit`, the SDK's documented `backgroundCompactionThreshold` default, named in the record's `capacity_source`. It writes nothing on stdout; a gap is refused on stderr at exit 2, which the extension writes to the session timeline: `payload=invalid-json`, an orch install it cannot use under the key its turn end reports that gap under, `handoff-skipped=`, `handoff-outside=` or `handoff-unanswered=`, or `context-unrecorded=` for a reading that could not be written, where the session's earlier reading is removed too so its turn end reports the context unmeasured rather than judging an older figure as room. Any other session passes silently. The Copilot turn end judges this session's record under the shared context rule exactly as it judges a transcript reading, the capacity putting the handoff before Copilot's own compaction; no reading of this session, no record or a gap record, is read from the fallback below; where the pending marker the extension leaves at `~/.cache/lane-mail/copilot-usage/` for a reading it handed on and no run has recorded yet still stands after a wait of 5 seconds, the turn end reports `reading-pending=` and passes with the context unmeasured, reading no fallback, since the extension runs for that session, and never judging the earlier record as room, since nothing orders the extension's run before the turn end; and a record that stands and cannot be read is refused under `record=`. Where no pending marker stands and no reading of the extension's stands for this session, no record, one naming another session, a gap record or one the fallback below wrote, which its `capacity_source` tells apart, the turn end reads the fallback: the session record the orch `copilot-statusline` command writes as the account's `statusLine`, under `/lane-status/.json`, through the orch adapter for copilot, which holds the record to the payload's `sessionId`, its `transcriptPath` where one is named, the account directory and a freshness bound, and hands the shared judge the same compaction point of the window as the capacity; that reading is judged and recorded as any other harness's, and a record that does not answer leaves the context unmeasured under `reading-unrecorded=` and `session-record=`, reported and passed, never read as room. An extension reading below the mark is never overridden by a statusLine record past it. Run with `compact` by the lane-mail-compact hook at a preCompact whose `trigger` is `auto`, from a recorded lead session that gate names, it flags that compaction as `compaction.json` beside the reading, the backstop for a turn that crossed into the compaction before a reading past the mark reached a turn end, and the turn end then refuses under `compacted=auto` until the handoff record stands, the overseer's whatever its succession setting; a gap there is refused under `compaction-unrecorded=` on stderr at exit 2, which Copilot shows the operator without holding the compaction. A Copilot account is judged through `lanes pick --lane` like any other. A session the Jarvis runtime launched, which carries `JARVIS_RECORD`, has its lead's tool calls, on Copilot any call under the session id the record's start bound, and on Claude Code its turn ends, stamp that runtime record's launch row once as its Start brief taken, the fact the Jarvis launch worker reads beside the pane; another harness's turn end is no stamp, since Pi's carrier also dispatches it on a run that ended on an error and Codex and Copilot have no turn-failure event to tell one apart; a stamp that cannot be written is reported under `jarvis-rows-unwritten=` and passed, and the next such call writes it. Not run on gemini: it has no Stop event. Not run on antigravity: its Stop payload carries no `stop_hook_active`. # summary: Uses orch and mailbox to hand lanes their overseer's mail and hold turn ends for handoff or idle checks, plus a `wake=unarmed` refusal for the registered overseer without its repeat follow or the Jarvis session whose `ORCH_WAKE_PROCESS` does not match, printing `ORCH_WAKE_START`; empty Jarvis session keys with no watch claim disable the check, and a running single pass is its own wake. Pi's wake check is partial; a continued turn or an unavailable check only warns. # safety: Reads the payload, the repository's branch, the lane's launch marker, read with the shell's own `read`, and the lane mailbox directory, and for a session that is no lane the checkout's overseer mailbox and, where a file stands there and the fleet record names this session's pane, the fleet state's path from the identity read, with `workflow-state path oversee` as its fallback and the watch record beside it, read by the orch watch record library `lib/watch-pid.sh` sourced in a child shell from the same install as the mailbox reader, which checks the record's pid with `kill -0` and `ps`; the writes are the mailbox cursor the orch reader advances, the session's context reading, `context.json`, and a Copilot session's compaction flag, `compaction.json`, each renamed into its mailbox directory, and on a Pi lane its turn rows, `session-rows.jsonl`, appended there under that file's own lock at a turn end and at the first tool call of each turn, and for the overseer one row appended to its rows file, `session--.jsonl` in the overseer mailbox directory, under that file's own lock, a compact Stop at every overseer turn end, the overseer's directory made where the fleet has not made it yet, the fleet record's `.overseer` server start, harness, launch home and native session id where a record naming this session's pane lacks one, through `workflow-state update oversee`, and after each overseer tool call its `context.json` and, where a gap is told, `tmp/lane-mail/overseer/context-told`, and on Copilot a lead session's empty record under `~/.cache/lane-mail/copilot-leads`, touched at its session start and at each turn end its transcript proves the lead's, with records untouched for 30 days removed by one `find` at each start, as are the extension's pending markers under `~/.cache/lane-mail/copilot-usage`, which a Copilot turn end reads and polls for 5 seconds. For a session the Jarvis runtime launched it also reads, at its lead's tool calls and Claude Code, Codex and Copilot CLI turn ends, the runtime record `JARVIS_RECORD` names, in one child shell sourcing the orch session rows library from the same install, and where that launch is starting and unstamped, reads it again under that record's `.lock` and renames a new record over it once: at a tool call or Claude Code turn end with its brief delivered, stamping its launch row's `brief_taken`; at a Codex or Copilot CLI turn end before the brief, stamping its `kickoff_ended`. Exit 2 names the unread count and the messages, and asks for them to be acted on, never bypassed. The reader it runs comes from its own install, never from the repository a session has open, so a repository that tracks a mailbox and an executable at that path cannot have it run. jq and cat read the payload; a payload it cannot read is refused on every turn, the continued one included, because the flag that marks a continued turn is in the payload none of those refusals reached. A mailbox whose reader is missing or fails is refused on the turns the mailbox check runs, which is every turn end but a continued one; on a continued turn that check is skipped whole, and the same missing reader is reported under `handoff-skipped` or `handoff-outside` and the turn is passed. An item name outside the alphabet a work item is spelled in, a branch that matches more than one mailbox, and a repository state git cannot report where a mailbox sits under the working directory are refused on a fresh turn and reported on a continued one and before a tool call, by the one rule the description states; none of them is ever passed in silence. For a lane's handoff marks it also reads the transcript the payload names and runs `orch-env`, `lanes` and `workflow-state` and sources the orch context library from the same install as the mailbox reader, never the open repository's, and on Pi one child shell sourcing that install's `lib/lane-launch.sh` to name the account the session's provider bills; the context reading is the one thing it writes for them. A session that names no lane costs two file tests of the checkout's overseer mailbox; where a file stands there it adds that install's resolution and, inside tmux, the overseer test below, and for the session the record names the identity read's fleet path, one child shell sourcing the watch record library, and the reader's peek where no live watch stands. Outside tmux it costs nothing more, where the overseer test stops at its first condition. After a tool call a lead session with no lane of its own, in tmux, in a checkout with no `tmp/lane-mail/overseer` directory costs one stat more; where that directory stands it pays the overseer test below, and for the overseer one transcript read, one `workflow-state handoff-standing`, one `orch-env` read and one record write, the reads the turn end makes but for the account judgement; the overseer test runs once per call, and the mailbox check takes its answer. Inside tmux the overseer test resolves that install and reads the caller's pane key, the fleet record and the server start in a child shell loading the orch context and overseer launch libraries and their dependencies. A required heal loads `lib/overseer-launch.sh` and its dependencies in a child shell and rechecks the recorded native identity before the state update; a session whose native identity matches a nonempty recorded binding but whose pane the state does not name adds one child shell loading the orch context library, one `git-context` call and one read of the overseer's `context.json`; where that record names this session's pane, it reports `pane-unrecorded` and rewrites that record. Any other unbound caller stops before those context reads and writes. The overseer's own marks are then judged by `oversee-succeed --check-marks` from that same install, under the same 20 second ceiling the lane's account read runs under. That judgement measures the one account the overseer session runs on, through the same `lanes pick --lane` this hook asks about a lane, renewing an expired token in that account's credential file and refreshing that account's usage cache, the writes `lanes` states in its own contract; it opens no window and launches nothing. The context-usage reader first parses the last 1 MiB, and reads the whole file only when that window carries no usage line. When native Claude Stop background_tasks is absent, the transcript roster fallback reads complete ordered history; its work grows with transcript size. It runs only under the remaining hook deadline, with three seconds reserved for refusal emission and a one-second kill grace. An unavailable bound, exhausted budget, timeout or failed parse reports agents=unknown and discards partial rows. `lanes pick --lane` judges a Claude lane on its own model, measures one account and renews that account's expired token, the write its own contract states; it can wait on a credentials lock and two network calls, and on a cache miss on the host-wide usage refresh lock for up to 10 seconds and, after a 429 with nothing cached, one sleep of up to 5 seconds and one more usage request, so it runs under a 20 second ceiling that leaves the rest of the run inside this hook's 30 second budget, and a read that reaches the ceiling is reported as a gap rather than refused. Where `timeout` is not installed that read runs unbounded, and a hook the harness then kills at its budget leaves the account unjudged, the same outcome the reported gap gives without the line. Before a tool call it reads `tool_name` or Copilot `toolName`; the question-tool rule and attached-launch check consume that normalized name. For the idle judge at a lane lead's turn end it runs the reader's `events` listing, which moves no cursor, and reads the kind, the box and the halt flag of each envelope, never its text and never the transcript; it reads stat metadata for the fixed regular `tmp/lane-status-.md` file under the lane's launch root, with no symbolic link at the status file itself, and writes that update state beside the count in the lane's `sent-count` record, renamed into its mailbox directory, and the one idle notice the description names, through the reader's `notice`. Every refusal opens with `lane-mail-check: =`; what a command this hook runs writes is captured at the site and replayed under that line, so nothing precedes the key. For a launched lane or the bound fleet overseer, PostModelSwitch reads its to_model target and the recorded launch identity. It writes model checks and switch history through workflow-state. A lane replacement that reaches its first Stop without a mismatch writes one model-recovery-reset row and a passed model check in the same fleet state. Lane recovery preserves the standing handoff and checks the recorded arguments before stopping the verified predecessor through the existing lane stop owner. Account selection and launch follow that stop. Overseer recovery passes a durable handoff to oversee-succeed. That owner preserves the executable model selector and account, verifies the successor, then stops its predecessor. Unreadable PostModelSwitch dependencies reach the model as once-only unavailable context. A failed first-turn reset reports a keyed Stop warning on stderr and leaves later checks active. # timeout: 30 @@ -50,7 +50,7 @@ UNREAD="" HALT_TEXT="" ACK_COMMAND="" MAILBOX_COMMAND="" -# The handoff marks: the two settings judged and the commands that end the +# The handoff marks: the settings judged and the commands that end the # refusal, and the window the context mark is judged against. Empty until each # is known. MARK="" @@ -218,6 +218,8 @@ message() { # KEY VALUE [CAUSE] { if [ "$1" = headroom ] && [ "$ROLE" = lane ]; then printf 'lane-mail-check: headroom=%s bucket=%s mark=%s\n' "$2" "$BINDING_BUCKET" "$PCT" + elif [ "$1" = seat-reserve ]; then + printf 'lane-mail-check: seat-reserve=%s bucket=%s reserve=%s\n' "$2" "$BINDING_BUCKET" "$PCT" else printf 'lane-mail-check: %s=%s\n' "$1" "$2" fi @@ -456,6 +458,10 @@ message() { # KEY VALUE [CAUSE] "$BINDING_BUCKET" "$2" "$PCT" "$HANDOFF_INSTRUCTION" fi ;; + seat-reserve=*) + printf 'The account picker requires handoff from this overseer seat. The binding bucket %s has %s percent headroom left. ORCH_OVERSEER_SEAT_RESERVE_PCT is %s. No handoff record stands. Hand this lane off at the next safe point.\n%s\n' \ + "$BINDING_BUCKET" "$2" "$PCT" "$HANDOFF_INSTRUCTION" + ;; rate=*) printf 'oversee-succeed projects that this overseer account will reach its wall in %s minutes, at or before the ORCH_OVERSEER_WALL_MINUTES mark of %s. Succeed this session yourself before the account walls.\n%s\n' \ "$2" "$MARK" "$HANDOFF_INSTRUCTION" @@ -3427,10 +3433,10 @@ handoff_check() { fi # The account the credential THIS session runs on still has, judged by the - # one script that measures a lane and against the one setting that marks a - # lane for handoff. `pick --lane` answers about that directory alone: 0 has - # room, 3 is at or below the mark, and 4 is a directory that is no configured - # lane of this harness. Every other exit, and a read that passes the ceiling, + # one script that measures a lane and judges its handoff marks. + # `pick --lane` answers about that directory alone: 0 has room, 3 reaches + # the headroom mark or overseer seat reserve, and 4 is a directory that is + # no configured lane of this harness. Every other exit, and a read that passes the ceiling, # is an account nothing measured: reported and passed, never read as room and # never held, because a setup with no usage endpoint must still end its turns. # `lanes` keeps an inventory for claude, codex and copilot, and a Pi lane is @@ -3465,9 +3471,9 @@ handoff_check() { ${PICK_MODEL[@]+"${PICK_MODEL[@]}"} --min-headroom-pct "$PCT" --json 2>"$WORK_DIR/lanes.err") || PICK_RC=$? # `lanes` keeps a status-only contract where `workflow-state handoff-standing` # could not, and one reservation is what makes that safe here: every status - # with an arm of its own below — 3 for a lane at its mark, 4 for one this - # harness keeps no inventory for, 124 for a read the ceiling abandoned — is - # one no death before the verb can produce. `lanes` loads the same + # with an arm of its own below (3 for a lane at its mark or seat reserve, + # 4 for one this harness keeps no inventory for, 124 for a read the ceiling + # abandoned) is one no death before the verb can produce. `lanes` loads the same # `.env.local` through the same loader, and a file bash 3.2 cannot parse # kills it with 1 or 2; both fall to `*` and are reported as an account # nothing measured, which is as true of a script that died in its loader as @@ -3479,10 +3485,22 @@ handoff_check() { 3) # pick's wall is the binding bucket's used percent, including a scoped # model window. Account-wide headroom can still show room at that wall. - BINDING=$(jq -r '[.binding_bucket // "unknown", + # Only seat-reserve keeps its verdict in pick's public record; the + # ordinary wall omits it. Exit 3 alone cannot name the reached mark. + BINDING=$(jq -r '[.verdict // "walled", .binding_bucket // "unknown", (if .wall == null then "unknown" else 100 - .wall end)] | @tsv' <<<"$PICK" 2>/dev/null) || - BINDING=$'unknown\tunknown' - IFS=$'\t' read -r BINDING_BUCKET HEADROOM <<<"$BINDING" + BINDING=$'unknown\tunknown\tunknown' + IFS=$'\t' read -r PICK_VERDICT BINDING_BUCKET HEADROOM <<<"$BINDING" + case "$PICK_VERDICT" in + seat-reserve) + PCT=$("$SCRIPTS/orch-env" ORCH_OVERSEER_SEAT_RESERVE_PCT 50 2>"$WORK_DIR/env.err") || + refuse_handoff setting ORCH_OVERSEER_SEAT_RESERVE_PCT "$(cat -- "$WORK_DIR/env.err")" + percent_in_range "$PCT" || refuse_handoff setting-range "ORCH_OVERSEER_SEAT_RESERVE_PCT=$PCT" + refuse_handoff seat-reserve "$HEADROOM" + ;; + walled) ;; + *) message account unmeasured "lanes pick returned an unreadable refusal record"; return 0 ;; + esac refuse_handoff headroom "$HEADROOM" ;; 4) message account unlisted "$(cat -- "$WORK_DIR/lanes.err")" ;; diff --git a/.kendex-lock.json b/.kendex-lock.json index 01d77e6d..15105e88 100644 --- a/.kendex-lock.json +++ b/.kendex-lock.json @@ -8,7 +8,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f61907f3d571a02cf2a775ebb0034f787a1d5ffe2d68e52585124f28badd368", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -43,7 +43,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f61907f3d571a02cf2a775ebb0034f787a1d5ffe2d68e52585124f28badd368", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -78,7 +78,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f61907f3d571a02cf2a775ebb0034f787a1d5ffe2d68e52585124f28badd368", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -113,7 +113,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f61907f3d571a02cf2a775ebb0034f787a1d5ffe2d68e52585124f28badd368", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -148,7 +148,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "5d2ba692c5b40abe71c7af38392e2ee2aecc2a3b07d256d9b44a4cb4d6c06090", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -185,7 +185,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "5d2ba692c5b40abe71c7af38392e2ee2aecc2a3b07d256d9b44a4cb4d6c06090", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -222,7 +222,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "5d2ba692c5b40abe71c7af38392e2ee2aecc2a3b07d256d9b44a4cb4d6c06090", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -259,7 +259,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "5d2ba692c5b40abe71c7af38392e2ee2aecc2a3b07d256d9b44a4cb4d6c06090", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -296,7 +296,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4a25e8a4c3e339bdf1890993e437e938feed7baa0a565bbe09e873ec62a75c64", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -327,7 +327,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4a25e8a4c3e339bdf1890993e437e938feed7baa0a565bbe09e873ec62a75c64", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -358,7 +358,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4a25e8a4c3e339bdf1890993e437e938feed7baa0a565bbe09e873ec62a75c64", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -389,7 +389,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4a25e8a4c3e339bdf1890993e437e938feed7baa0a565bbe09e873ec62a75c64", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -420,7 +420,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "a1802df17bd986fd550df5df1d70792098e98f5b2e518364a51337835cab6bb7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -453,7 +453,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "a1802df17bd986fd550df5df1d70792098e98f5b2e518364a51337835cab6bb7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -486,7 +486,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "a1802df17bd986fd550df5df1d70792098e98f5b2e518364a51337835cab6bb7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -519,7 +519,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "a1802df17bd986fd550df5df1d70792098e98f5b2e518364a51337835cab6bb7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -552,7 +552,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3002276f894146f3c381e406e2c14d3ef3f75e64e0d7a51c1a8be30486bfa79e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -582,7 +582,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3002276f894146f3c381e406e2c14d3ef3f75e64e0d7a51c1a8be30486bfa79e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -612,7 +612,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3002276f894146f3c381e406e2c14d3ef3f75e64e0d7a51c1a8be30486bfa79e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -642,7 +642,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3002276f894146f3c381e406e2c14d3ef3f75e64e0d7a51c1a8be30486bfa79e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -672,7 +672,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "64f1a2e0e2bb4c4bac776f8c489c4fbaa17f149f955092737e47c72cc31bb7b2", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -702,7 +702,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "64f1a2e0e2bb4c4bac776f8c489c4fbaa17f149f955092737e47c72cc31bb7b2", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -732,7 +732,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "64f1a2e0e2bb4c4bac776f8c489c4fbaa17f149f955092737e47c72cc31bb7b2", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -762,7 +762,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "64f1a2e0e2bb4c4bac776f8c489c4fbaa17f149f955092737e47c72cc31bb7b2", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -792,7 +792,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c29a9dd689ce336a07824eb0fb8d518191124b6be0c5ca037a65ca618cd07106", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -822,7 +822,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c29a9dd689ce336a07824eb0fb8d518191124b6be0c5ca037a65ca618cd07106", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -852,7 +852,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c29a9dd689ce336a07824eb0fb8d518191124b6be0c5ca037a65ca618cd07106", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -882,7 +882,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c29a9dd689ce336a07824eb0fb8d518191124b6be0c5ca037a65ca618cd07106", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -912,7 +912,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e0a3a3a908ecfb00b4e9ae083e0ce2a2db55183f0ab878a38d8092eaaee6d8ad", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -942,7 +942,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e0a3a3a908ecfb00b4e9ae083e0ce2a2db55183f0ab878a38d8092eaaee6d8ad", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -972,7 +972,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e0a3a3a908ecfb00b4e9ae083e0ce2a2db55183f0ab878a38d8092eaaee6d8ad", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1002,7 +1002,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e0a3a3a908ecfb00b4e9ae083e0ce2a2db55183f0ab878a38d8092eaaee6d8ad", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1032,7 +1032,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "954fde6a7332eac489845daa35b7413e7a216823cba8bcf73aaeecf180d73f3d", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1062,7 +1062,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "954fde6a7332eac489845daa35b7413e7a216823cba8bcf73aaeecf180d73f3d", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1092,7 +1092,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "954fde6a7332eac489845daa35b7413e7a216823cba8bcf73aaeecf180d73f3d", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1122,7 +1122,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "954fde6a7332eac489845daa35b7413e7a216823cba8bcf73aaeecf180d73f3d", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1152,7 +1152,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ac74145015e2575770fdaa3f2730ef7672b1cc72c0159a5a4f390e1b1f474f2f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1182,7 +1182,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ac74145015e2575770fdaa3f2730ef7672b1cc72c0159a5a4f390e1b1f474f2f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1212,7 +1212,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ac74145015e2575770fdaa3f2730ef7672b1cc72c0159a5a4f390e1b1f474f2f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1242,7 +1242,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ac74145015e2575770fdaa3f2730ef7672b1cc72c0159a5a4f390e1b1f474f2f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1272,7 +1272,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5bba5231d21a1ecf327af004dbcc34c36fe074fa2ce01fc855848017d7ccd8a", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1302,7 +1302,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5bba5231d21a1ecf327af004dbcc34c36fe074fa2ce01fc855848017d7ccd8a", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1332,7 +1332,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5bba5231d21a1ecf327af004dbcc34c36fe074fa2ce01fc855848017d7ccd8a", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1362,7 +1362,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5bba5231d21a1ecf327af004dbcc34c36fe074fa2ce01fc855848017d7ccd8a", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1392,7 +1392,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5c7aad291389053ed6aae2b30ced684b9818e83d3faf332c316bc80d8b126f6", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1422,7 +1422,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5c7aad291389053ed6aae2b30ced684b9818e83d3faf332c316bc80d8b126f6", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1452,7 +1452,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5c7aad291389053ed6aae2b30ced684b9818e83d3faf332c316bc80d8b126f6", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1482,7 +1482,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b5c7aad291389053ed6aae2b30ced684b9818e83d3faf332c316bc80d8b126f6", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1512,7 +1512,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e9b4d7ef81ad5f5439354dee4ce7f41a9a5b02e4e2c196a202b649bfbb489342", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1542,7 +1542,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e9b4d7ef81ad5f5439354dee4ce7f41a9a5b02e4e2c196a202b649bfbb489342", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1572,7 +1572,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e9b4d7ef81ad5f5439354dee4ce7f41a9a5b02e4e2c196a202b649bfbb489342", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1602,7 +1602,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e9b4d7ef81ad5f5439354dee4ce7f41a9a5b02e4e2c196a202b649bfbb489342", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1632,7 +1632,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "23ac64c27be9ea4619067d5facaa78f01edf2d37e986ec0a6f023eb51c61dc01", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1667,7 +1667,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "23ac64c27be9ea4619067d5facaa78f01edf2d37e986ec0a6f023eb51c61dc01", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1702,7 +1702,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "23ac64c27be9ea4619067d5facaa78f01edf2d37e986ec0a6f023eb51c61dc01", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1737,7 +1737,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "23ac64c27be9ea4619067d5facaa78f01edf2d37e986ec0a6f023eb51c61dc01", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1772,7 +1772,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b264e304113e038b3eb1fd220e50a7122ac11b270fbd4e6bc145e95f4bc9bd65", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1807,7 +1807,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b264e304113e038b3eb1fd220e50a7122ac11b270fbd4e6bc145e95f4bc9bd65", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1842,7 +1842,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b264e304113e038b3eb1fd220e50a7122ac11b270fbd4e6bc145e95f4bc9bd65", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1877,7 +1877,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b264e304113e038b3eb1fd220e50a7122ac11b270fbd4e6bc145e95f4bc9bd65", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1912,7 +1912,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1510d851b6a09b92fc0c50f142733a8273e0fdc85e87a0bbde43dd9fbee280f9", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1943,7 +1943,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1510d851b6a09b92fc0c50f142733a8273e0fdc85e87a0bbde43dd9fbee280f9", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -1974,7 +1974,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1510d851b6a09b92fc0c50f142733a8273e0fdc85e87a0bbde43dd9fbee280f9", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2005,7 +2005,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1510d851b6a09b92fc0c50f142733a8273e0fdc85e87a0bbde43dd9fbee280f9", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2036,7 +2036,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f04b302951c4fe6adc0e0dc7124417a847b00ea2902666c8f8a869bc79895d88", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2070,7 +2070,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f04b302951c4fe6adc0e0dc7124417a847b00ea2902666c8f8a869bc79895d88", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2104,7 +2104,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f04b302951c4fe6adc0e0dc7124417a847b00ea2902666c8f8a869bc79895d88", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2138,7 +2138,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f04b302951c4fe6adc0e0dc7124417a847b00ea2902666c8f8a869bc79895d88", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2172,7 +2172,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d2dac90f8f53f19ae855924d27b53c54d2b28871a4f84b068d6a2bad0c4f6c36", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2199,7 +2199,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d2dac90f8f53f19ae855924d27b53c54d2b28871a4f84b068d6a2bad0c4f6c36", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2226,7 +2226,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d2dac90f8f53f19ae855924d27b53c54d2b28871a4f84b068d6a2bad0c4f6c36", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2253,7 +2253,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b733e4ad323748222e30134660417d1de58727dbdaee690b9b9f27f5d23f12a7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2285,7 +2285,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b733e4ad323748222e30134660417d1de58727dbdaee690b9b9f27f5d23f12a7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2317,7 +2317,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b733e4ad323748222e30134660417d1de58727dbdaee690b9b9f27f5d23f12a7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2349,7 +2349,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b733e4ad323748222e30134660417d1de58727dbdaee690b9b9f27f5d23f12a7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2381,7 +2381,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "47bf5378331d6d82cf860c3c38150cb95b21f6b7d12841f7ee056c55622799e8", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2413,7 +2413,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "47bf5378331d6d82cf860c3c38150cb95b21f6b7d12841f7ee056c55622799e8", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2445,7 +2445,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "056014489bdf17897fb9de308ecc1ea22c3ffdf83c3894382b08f0e94b2dbcdb", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2477,7 +2477,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "056014489bdf17897fb9de308ecc1ea22c3ffdf83c3894382b08f0e94b2dbcdb", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2509,7 +2509,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "056014489bdf17897fb9de308ecc1ea22c3ffdf83c3894382b08f0e94b2dbcdb", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2541,7 +2541,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "056014489bdf17897fb9de308ecc1ea22c3ffdf83c3894382b08f0e94b2dbcdb", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2573,7 +2573,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "8d06d8ae1faf86625add070a7a6dca48c5be41a600e7cecfbd71e6e151f5e769", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2605,7 +2605,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "8d06d8ae1faf86625add070a7a6dca48c5be41a600e7cecfbd71e6e151f5e769", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2637,7 +2637,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "8d06d8ae1faf86625add070a7a6dca48c5be41a600e7cecfbd71e6e151f5e769", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2669,7 +2669,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "8d06d8ae1faf86625add070a7a6dca48c5be41a600e7cecfbd71e6e151f5e769", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2701,7 +2701,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ec0e477e5664f963929581df503d093d4ae21da6b76d6f3d542f7980c3a9a08a", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2733,7 +2733,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ec0e477e5664f963929581df503d093d4ae21da6b76d6f3d542f7980c3a9a08a", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2765,7 +2765,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ec0e477e5664f963929581df503d093d4ae21da6b76d6f3d542f7980c3a9a08a", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2797,7 +2797,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "ec0e477e5664f963929581df503d093d4ae21da6b76d6f3d542f7980c3a9a08a", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2829,7 +2829,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4cca63d27e717911ce6dff804126511f8611fea1dd170d913defcfea15bdf2c7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2870,7 +2870,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4cca63d27e717911ce6dff804126511f8611fea1dd170d913defcfea15bdf2c7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2911,7 +2911,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4cca63d27e717911ce6dff804126511f8611fea1dd170d913defcfea15bdf2c7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2952,7 +2952,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4cca63d27e717911ce6dff804126511f8611fea1dd170d913defcfea15bdf2c7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -2993,7 +2993,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "9246462997cb2e9e8166226f651f7598ea6c81bd0e025f9861e7366ffca2d699", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3031,7 +3031,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "158045e0bc3594e6b18d6cb77032b9ef98aad34cee1b35a0f556684c76a09fc9", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3063,7 +3063,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "158045e0bc3594e6b18d6cb77032b9ef98aad34cee1b35a0f556684c76a09fc9", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3094,13 +3094,13 @@ "harness": "claude", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "aa8ec9e210f6385308d6a824177a1cc7e5e88460918a904a5519836428824444", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "c4b885e3233ccc3bd14acee271ac9674285c391f67001c9ab1fc735bd61a52bd", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "e46120fc2b89e3ebcf688bc46d8bfa0f4732b3338a1538987958b72060b4a096", + "renderedHash": "27d48aa7aa708189b683f050e92ffa5711cfa6a59b0f2f5eb4d9607e387da588", "enabled": true, "emitted": { "kind": "hook", @@ -3189,13 +3189,13 @@ "harness": "codex", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "aa8ec9e210f6385308d6a824177a1cc7e5e88460918a904a5519836428824444", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "c4b885e3233ccc3bd14acee271ac9674285c391f67001c9ab1fc735bd61a52bd", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "e46120fc2b89e3ebcf688bc46d8bfa0f4732b3338a1538987958b72060b4a096", + "renderedHash": "27d48aa7aa708189b683f050e92ffa5711cfa6a59b0f2f5eb4d9607e387da588", "enabled": true, "emitted": { "kind": "hook", @@ -3257,13 +3257,13 @@ "harness": "copilot", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "aa8ec9e210f6385308d6a824177a1cc7e5e88460918a904a5519836428824444", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "c4b885e3233ccc3bd14acee271ac9674285c391f67001c9ab1fc735bd61a52bd", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "e46120fc2b89e3ebcf688bc46d8bfa0f4732b3338a1538987958b72060b4a096", + "renderedHash": "27d48aa7aa708189b683f050e92ffa5711cfa6a59b0f2f5eb4d9607e387da588", "enabled": true, "emitted": { "kind": "hook", @@ -3352,13 +3352,13 @@ "harness": "pi", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "aa8ec9e210f6385308d6a824177a1cc7e5e88460918a904a5519836428824444", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "c4b885e3233ccc3bd14acee271ac9674285c391f67001c9ab1fc735bd61a52bd", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "e46120fc2b89e3ebcf688bc46d8bfa0f4732b3338a1538987958b72060b4a096", + "renderedHash": "27d48aa7aa708189b683f050e92ffa5711cfa6a59b0f2f5eb4d9607e387da588", "enabled": true, "emitted": { "kind": "hook", @@ -3430,7 +3430,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1bfbcb2c43e6fab13888956bdc98691ec72d4eadf293187f4867af817d60bdbe", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3462,7 +3462,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7a99ebbd12769b351b8656699134c0f93d7ab06af43b4cb4ea8ac410fcaf64aa", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3503,7 +3503,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7a99ebbd12769b351b8656699134c0f93d7ab06af43b4cb4ea8ac410fcaf64aa", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3544,7 +3544,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7a99ebbd12769b351b8656699134c0f93d7ab06af43b4cb4ea8ac410fcaf64aa", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3585,7 +3585,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7a99ebbd12769b351b8656699134c0f93d7ab06af43b4cb4ea8ac410fcaf64aa", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3626,7 +3626,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4fa45a9fc7c4f7a5bb5ff5bb66e392460442ac8ed4ef14832d17832a2a4515eb", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3667,7 +3667,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4fa45a9fc7c4f7a5bb5ff5bb66e392460442ac8ed4ef14832d17832a2a4515eb", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3708,7 +3708,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4fa45a9fc7c4f7a5bb5ff5bb66e392460442ac8ed4ef14832d17832a2a4515eb", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3749,7 +3749,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "4fa45a9fc7c4f7a5bb5ff5bb66e392460442ac8ed4ef14832d17832a2a4515eb", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3790,7 +3790,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "eef427b33e0fbbfbb8b807dd0986ffa66ce350033aac9bb23255988b03925024", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3828,7 +3828,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b128f266b3d67697e7ac128f8aabc97b472a03cc7fe6f05e4fc9b145cc315442", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3860,7 +3860,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c7905659a294ec88a2b38b9bfbf071d0160a45689ece954a0f9564e3c5791ba2", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3901,7 +3901,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d8a11a3b614b97c3b0c304cae7494a16510c998f1f325f0ad10874957c43b917", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3933,7 +3933,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d8a11a3b614b97c3b0c304cae7494a16510c998f1f325f0ad10874957c43b917", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3965,7 +3965,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d8a11a3b614b97c3b0c304cae7494a16510c998f1f325f0ad10874957c43b917", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -3997,7 +3997,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d8a11a3b614b97c3b0c304cae7494a16510c998f1f325f0ad10874957c43b917", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4029,7 +4029,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "87dd5148fca28408dab96f6a6819bb3d43cf6da54ad02c4cf60fc953e50bbc43", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4061,7 +4061,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "87dd5148fca28408dab96f6a6819bb3d43cf6da54ad02c4cf60fc953e50bbc43", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4093,7 +4093,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "26090ae471accc49d86a2b1c10fd364b72df1ce4f6a767fd10e82318770d3105", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4125,7 +4125,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "26090ae471accc49d86a2b1c10fd364b72df1ce4f6a767fd10e82318770d3105", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4157,7 +4157,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "26090ae471accc49d86a2b1c10fd364b72df1ce4f6a767fd10e82318770d3105", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4189,7 +4189,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d7dad268fbd914b6517b1afe088558166c009cd0ac221ce83fed82de7e8488e3", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4221,7 +4221,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d7dad268fbd914b6517b1afe088558166c009cd0ac221ce83fed82de7e8488e3", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4253,7 +4253,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "d7dad268fbd914b6517b1afe088558166c009cd0ac221ce83fed82de7e8488e3", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4285,7 +4285,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f8fa08d86e3482b5f30034dd7522ce3236f6e6a5000b8f64d6009093dccc5577", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4326,7 +4326,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f8fa08d86e3482b5f30034dd7522ce3236f6e6a5000b8f64d6009093dccc5577", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4367,7 +4367,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f8fa08d86e3482b5f30034dd7522ce3236f6e6a5000b8f64d6009093dccc5577", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4408,7 +4408,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f8fa08d86e3482b5f30034dd7522ce3236f6e6a5000b8f64d6009093dccc5577", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4449,7 +4449,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fb43be6b7dee642b200268fbe71e14cc96282ea06a1554012ab80ce52a92ba79", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4490,7 +4490,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fb43be6b7dee642b200268fbe71e14cc96282ea06a1554012ab80ce52a92ba79", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4531,7 +4531,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fb43be6b7dee642b200268fbe71e14cc96282ea06a1554012ab80ce52a92ba79", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4572,7 +4572,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fb43be6b7dee642b200268fbe71e14cc96282ea06a1554012ab80ce52a92ba79", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4613,7 +4613,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "101caf97829906294354478ca77d288f5311a70a3c6ba90ae2babf9e3bf34624", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4654,7 +4654,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "101caf97829906294354478ca77d288f5311a70a3c6ba90ae2babf9e3bf34624", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4695,7 +4695,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "a334bd710c5b926e24b2dd2a066d3b4dcd6747030a111bf7cabcc545ea242ad7", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4727,7 +4727,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "9425ae12b1eb7229702d033513e1758ae9a092db8f561b912e74c6740bbfa2ef", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4768,7 +4768,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3e981ce407351f70b1e2dbc8e46840b64be2ecd8b17fe16ccdff0960edf2f7ad", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4809,7 +4809,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3e981ce407351f70b1e2dbc8e46840b64be2ecd8b17fe16ccdff0960edf2f7ad", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4841,7 +4841,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3e981ce407351f70b1e2dbc8e46840b64be2ecd8b17fe16ccdff0960edf2f7ad", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4873,7 +4873,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3e981ce407351f70b1e2dbc8e46840b64be2ecd8b17fe16ccdff0960edf2f7ad", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -4904,13 +4904,13 @@ "harness": "claude", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "17acbaa3d814c683f04c45b904c6aeba02c20bcc0fe529e2333031077abdac6f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "4acc2d11305cd9023a912f3aacf6101a06361d22843e19209f26483be8bc5529", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "02a9c8016a92f2e75fe3d7d35213e0b24e19f70d5963d79fb8557e5f82bc46fd", + "renderedHash": "3cbea8a333fd6e9b76fd8d98af6a796758af3909a0b8eda464de96c5a7791320", "enabled": true, "emitted": { "kind": "skill", @@ -4941,13 +4941,13 @@ "harness": "codex", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "17acbaa3d814c683f04c45b904c6aeba02c20bcc0fe529e2333031077abdac6f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "4acc2d11305cd9023a912f3aacf6101a06361d22843e19209f26483be8bc5529", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "02a9c8016a92f2e75fe3d7d35213e0b24e19f70d5963d79fb8557e5f82bc46fd", + "renderedHash": "3cbea8a333fd6e9b76fd8d98af6a796758af3909a0b8eda464de96c5a7791320", "enabled": true, "emitted": { "kind": "skill", @@ -4977,13 +4977,13 @@ "harness": "copilot", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "17acbaa3d814c683f04c45b904c6aeba02c20bcc0fe529e2333031077abdac6f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "4acc2d11305cd9023a912f3aacf6101a06361d22843e19209f26483be8bc5529", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "02a9c8016a92f2e75fe3d7d35213e0b24e19f70d5963d79fb8557e5f82bc46fd", + "renderedHash": "3cbea8a333fd6e9b76fd8d98af6a796758af3909a0b8eda464de96c5a7791320", "enabled": true, "emitted": { "kind": "skill", @@ -5013,13 +5013,13 @@ "harness": "pi", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "17acbaa3d814c683f04c45b904c6aeba02c20bcc0fe529e2333031077abdac6f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "4acc2d11305cd9023a912f3aacf6101a06361d22843e19209f26483be8bc5529", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "02a9c8016a92f2e75fe3d7d35213e0b24e19f70d5963d79fb8557e5f82bc46fd", + "renderedHash": "3cbea8a333fd6e9b76fd8d98af6a796758af3909a0b8eda464de96c5a7791320", "enabled": true, "emitted": { "kind": "skill", @@ -5050,7 +5050,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "bed7626f1d7e1f047a4f3f49ff2d2b83167d03ea2610d85e0c4cddd892353157", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5105,7 +5105,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "bed7626f1d7e1f047a4f3f49ff2d2b83167d03ea2610d85e0c4cddd892353157", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5159,7 +5159,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "bed7626f1d7e1f047a4f3f49ff2d2b83167d03ea2610d85e0c4cddd892353157", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5213,7 +5213,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "bed7626f1d7e1f047a4f3f49ff2d2b83167d03ea2610d85e0c4cddd892353157", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5267,7 +5267,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "98fc478b875c8c5b7d831bce38f1eb2665925e6c5c76eeba6184e80d1b5554ac", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5322,7 +5322,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "98fc478b875c8c5b7d831bce38f1eb2665925e6c5c76eeba6184e80d1b5554ac", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5376,7 +5376,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "98fc478b875c8c5b7d831bce38f1eb2665925e6c5c76eeba6184e80d1b5554ac", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5430,7 +5430,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "98fc478b875c8c5b7d831bce38f1eb2665925e6c5c76eeba6184e80d1b5554ac", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5483,13 +5483,13 @@ "harness": "claude", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "02cfb4aeb93eee375890032cc3eaaf0d896ced7d85619dfd636eb37c08611aae", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "a80792441ba91a1fb0c14148a5bc2b4b9ee440a3ca5a588f4d5acc14ee9eef72", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "ae5b6c36a5920f095847eea18d59c11350a268a4f335dcef1e2fa65e00251e2f", + "renderedHash": "3cc2418c6a34482fe406585a7a29d5ce9be93c56ffb6ba25421a9bbbe1007253", "enabled": true, "emitted": { "kind": "skill", @@ -5517,13 +5517,13 @@ "harness": "codex", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "02cfb4aeb93eee375890032cc3eaaf0d896ced7d85619dfd636eb37c08611aae", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "a80792441ba91a1fb0c14148a5bc2b4b9ee440a3ca5a588f4d5acc14ee9eef72", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "ae5b6c36a5920f095847eea18d59c11350a268a4f335dcef1e2fa65e00251e2f", + "renderedHash": "3cc2418c6a34482fe406585a7a29d5ce9be93c56ffb6ba25421a9bbbe1007253", "enabled": true, "emitted": { "kind": "skill", @@ -5550,13 +5550,13 @@ "harness": "copilot", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "02cfb4aeb93eee375890032cc3eaaf0d896ced7d85619dfd636eb37c08611aae", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "a80792441ba91a1fb0c14148a5bc2b4b9ee440a3ca5a588f4d5acc14ee9eef72", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "ae5b6c36a5920f095847eea18d59c11350a268a4f335dcef1e2fa65e00251e2f", + "renderedHash": "3cc2418c6a34482fe406585a7a29d5ce9be93c56ffb6ba25421a9bbbe1007253", "enabled": true, "emitted": { "kind": "skill", @@ -5583,13 +5583,13 @@ "harness": "pi", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "02cfb4aeb93eee375890032cc3eaaf0d896ced7d85619dfd636eb37c08611aae", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "a80792441ba91a1fb0c14148a5bc2b4b9ee440a3ca5a588f4d5acc14ee9eef72", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "ae5b6c36a5920f095847eea18d59c11350a268a4f335dcef1e2fa65e00251e2f", + "renderedHash": "3cc2418c6a34482fe406585a7a29d5ce9be93c56ffb6ba25421a9bbbe1007253", "enabled": true, "emitted": { "kind": "skill", @@ -5617,7 +5617,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b4a75dca09bb20bb042bde9f3998d836b981a5b8030ec9690ca01e6836a2f752", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5672,7 +5672,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b4a75dca09bb20bb042bde9f3998d836b981a5b8030ec9690ca01e6836a2f752", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5726,7 +5726,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b4a75dca09bb20bb042bde9f3998d836b981a5b8030ec9690ca01e6836a2f752", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5780,7 +5780,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "b4a75dca09bb20bb042bde9f3998d836b981a5b8030ec9690ca01e6836a2f752", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5834,7 +5834,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f07de0df87cd6a53de4d68f1098c408db4e8d73fa88822426de3cad6875f04e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5862,7 +5862,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f07de0df87cd6a53de4d68f1098c408db4e8d73fa88822426de3cad6875f04e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5889,7 +5889,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f07de0df87cd6a53de4d68f1098c408db4e8d73fa88822426de3cad6875f04e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5916,7 +5916,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7f07de0df87cd6a53de4d68f1098c408db4e8d73fa88822426de3cad6875f04e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5943,7 +5943,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f2bca9bc82c0e18f23e61cc013e521dd5b6867f5038845a1163ee1effa83abed", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5971,7 +5971,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f2bca9bc82c0e18f23e61cc013e521dd5b6867f5038845a1163ee1effa83abed", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -5998,7 +5998,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f2bca9bc82c0e18f23e61cc013e521dd5b6867f5038845a1163ee1effa83abed", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6025,7 +6025,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "f2bca9bc82c0e18f23e61cc013e521dd5b6867f5038845a1163ee1effa83abed", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6052,7 +6052,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "2b4fb8a2e6cee53ac5340737a5b71cd26ff88276766ac78fcc45c7f28769822c", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6089,7 +6089,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "2b4fb8a2e6cee53ac5340737a5b71cd26ff88276766ac78fcc45c7f28769822c", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6125,7 +6125,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "2b4fb8a2e6cee53ac5340737a5b71cd26ff88276766ac78fcc45c7f28769822c", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6161,7 +6161,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "2b4fb8a2e6cee53ac5340737a5b71cd26ff88276766ac78fcc45c7f28769822c", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6197,7 +6197,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fd88aed4b9211e14a8250139ebedd785f139c9e508101465548c06a6571fec46", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6225,7 +6225,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fd88aed4b9211e14a8250139ebedd785f139c9e508101465548c06a6571fec46", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6252,7 +6252,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fd88aed4b9211e14a8250139ebedd785f139c9e508101465548c06a6571fec46", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6279,7 +6279,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "fd88aed4b9211e14a8250139ebedd785f139c9e508101465548c06a6571fec46", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6306,7 +6306,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "0a859081ace51943009f81b7748b1f08a236bb886fe50495e2d26518524ec195", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6352,7 +6352,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "0a859081ace51943009f81b7748b1f08a236bb886fe50495e2d26518524ec195", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6397,7 +6397,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "0a859081ace51943009f81b7748b1f08a236bb886fe50495e2d26518524ec195", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6442,7 +6442,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "0a859081ace51943009f81b7748b1f08a236bb886fe50495e2d26518524ec195", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6487,7 +6487,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "831b57913311d8fd3bcdd376b7da7ef3344ab22702865bcb731393dc7580662b", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6569,7 +6569,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "831b57913311d8fd3bcdd376b7da7ef3344ab22702865bcb731393dc7580662b", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6650,7 +6650,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "831b57913311d8fd3bcdd376b7da7ef3344ab22702865bcb731393dc7580662b", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6731,7 +6731,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "831b57913311d8fd3bcdd376b7da7ef3344ab22702865bcb731393dc7580662b", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6812,7 +6812,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3168f92b017a42bfd272b4be616ab39c22c1b3f5640f8087e1740b3f8be99666", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6858,7 +6858,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3168f92b017a42bfd272b4be616ab39c22c1b3f5640f8087e1740b3f8be99666", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6903,7 +6903,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3168f92b017a42bfd272b4be616ab39c22c1b3f5640f8087e1740b3f8be99666", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6948,7 +6948,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3168f92b017a42bfd272b4be616ab39c22c1b3f5640f8087e1740b3f8be99666", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -6993,7 +6993,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3ba41c08e765a62757dfa60e6c5c182e18491c2f94223824957cc50187ffc823", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7030,7 +7030,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3ba41c08e765a62757dfa60e6c5c182e18491c2f94223824957cc50187ffc823", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7066,7 +7066,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3ba41c08e765a62757dfa60e6c5c182e18491c2f94223824957cc50187ffc823", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7102,7 +7102,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "3ba41c08e765a62757dfa60e6c5c182e18491c2f94223824957cc50187ffc823", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7137,13 +7137,13 @@ "harness": "claude", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "65b880f56f31d134b2e2cb53b693f434825143b9c5b7022a89b11fa733f4ee2e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "a535f6d275d711b1676f0e7787841918808f6a12fd1e60b279aebeaa824960bd", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "467899aaa45d594d5a647ec656ff851f6fe49c2a60b8d582458fcb4f2735c268", + "renderedHash": "6492e89b3863f6754d5e72f46031d60f0871f949f4f5c6ce967ad433671c2bbc", "enabled": true, "emitted": { "kind": "skill", @@ -7180,13 +7180,13 @@ "harness": "codex", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "65b880f56f31d134b2e2cb53b693f434825143b9c5b7022a89b11fa733f4ee2e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "a535f6d275d711b1676f0e7787841918808f6a12fd1e60b279aebeaa824960bd", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "467899aaa45d594d5a647ec656ff851f6fe49c2a60b8d582458fcb4f2735c268", + "renderedHash": "6492e89b3863f6754d5e72f46031d60f0871f949f4f5c6ce967ad433671c2bbc", "enabled": true, "emitted": { "kind": "skill", @@ -7222,13 +7222,13 @@ "harness": "copilot", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "65b880f56f31d134b2e2cb53b693f434825143b9c5b7022a89b11fa733f4ee2e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "a535f6d275d711b1676f0e7787841918808f6a12fd1e60b279aebeaa824960bd", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "467899aaa45d594d5a647ec656ff851f6fe49c2a60b8d582458fcb4f2735c268", + "renderedHash": "6492e89b3863f6754d5e72f46031d60f0871f949f4f5c6ce967ad433671c2bbc", "enabled": true, "emitted": { "kind": "skill", @@ -7264,13 +7264,13 @@ "harness": "pi", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "65b880f56f31d134b2e2cb53b693f434825143b9c5b7022a89b11fa733f4ee2e", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "a535f6d275d711b1676f0e7787841918808f6a12fd1e60b279aebeaa824960bd", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "467899aaa45d594d5a647ec656ff851f6fe49c2a60b8d582458fcb4f2735c268", + "renderedHash": "6492e89b3863f6754d5e72f46031d60f0871f949f4f5c6ce967ad433671c2bbc", "enabled": true, "emitted": { "kind": "skill", @@ -7306,13 +7306,13 @@ "harness": "claude", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "555518b41740a2d1e50708d8c0f586633773bdb15794bce752c8cfd2fafa2daa", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "4686944c783a208cf802e0ac99b69965ce73e21cc021b94048c6cf69eb9937d1", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "f06541ec1f671c27d52b6d75fb3f7926f0c7545256e60ff2b6f49d9be32b8109", + "renderedHash": "123a56e85e21e818da78374dd73638650ec7570e0b2f56682a9b6cda9f0b3b92", "enabled": true, "emitted": { "kind": "skill", @@ -7388,13 +7388,13 @@ "harness": "codex", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "555518b41740a2d1e50708d8c0f586633773bdb15794bce752c8cfd2fafa2daa", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "4686944c783a208cf802e0ac99b69965ce73e21cc021b94048c6cf69eb9937d1", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "f06541ec1f671c27d52b6d75fb3f7926f0c7545256e60ff2b6f49d9be32b8109", + "renderedHash": "123a56e85e21e818da78374dd73638650ec7570e0b2f56682a9b6cda9f0b3b92", "enabled": true, "emitted": { "kind": "skill", @@ -7469,13 +7469,13 @@ "harness": "copilot", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "555518b41740a2d1e50708d8c0f586633773bdb15794bce752c8cfd2fafa2daa", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "4686944c783a208cf802e0ac99b69965ce73e21cc021b94048c6cf69eb9937d1", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "f06541ec1f671c27d52b6d75fb3f7926f0c7545256e60ff2b6f49d9be32b8109", + "renderedHash": "123a56e85e21e818da78374dd73638650ec7570e0b2f56682a9b6cda9f0b3b92", "enabled": true, "emitted": { "kind": "skill", @@ -7541,13 +7541,13 @@ "harness": "pi", "source": "kendex", "sourceRepo": "vanillagreencom/kendex", - "sourceHash": "555518b41740a2d1e50708d8c0f586633773bdb15794bce752c8cfd2fafa2daa", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceHash": "4686944c783a208cf802e0ac99b69965ce73e21cc021b94048c6cf69eb9937d1", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null }, - "renderedHash": "f06541ec1f671c27d52b6d75fb3f7926f0c7545256e60ff2b6f49d9be32b8109", + "renderedHash": "123a56e85e21e818da78374dd73638650ec7570e0b2f56682a9b6cda9f0b3b92", "enabled": true, "emitted": { "kind": "skill", @@ -7614,7 +7614,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e967f26a25614f2028d62a3d0a9a4ae1a45d5e15d438f27f32006afa4de3dc7f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7642,7 +7642,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e967f26a25614f2028d62a3d0a9a4ae1a45d5e15d438f27f32006afa4de3dc7f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7669,7 +7669,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e967f26a25614f2028d62a3d0a9a4ae1a45d5e15d438f27f32006afa4de3dc7f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7696,7 +7696,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "e967f26a25614f2028d62a3d0a9a4ae1a45d5e15d438f27f32006afa4de3dc7f", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7723,7 +7723,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "457ba4b0812f431f86d0b5c4ed21e8f9b2f39ecbf49cfcf1f2e0172797e7d1fe", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7769,7 +7769,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "457ba4b0812f431f86d0b5c4ed21e8f9b2f39ecbf49cfcf1f2e0172797e7d1fe", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7814,7 +7814,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "457ba4b0812f431f86d0b5c4ed21e8f9b2f39ecbf49cfcf1f2e0172797e7d1fe", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7859,7 +7859,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "457ba4b0812f431f86d0b5c4ed21e8f9b2f39ecbf49cfcf1f2e0172797e7d1fe", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7904,7 +7904,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1bbf866e0a8475b09892ab440195b61e3c1ea252497ff568de02bfa921c203f8", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7950,7 +7950,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1bbf866e0a8475b09892ab440195b61e3c1ea252497ff568de02bfa921c203f8", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -7995,7 +7995,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1bbf866e0a8475b09892ab440195b61e3c1ea252497ff568de02bfa921c203f8", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8040,7 +8040,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "1bbf866e0a8475b09892ab440195b61e3c1ea252497ff568de02bfa921c203f8", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8085,7 +8085,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "88fff5eb5e09dd6ed63d56799b56af08853870b9215d7be54285d52cde241980", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8149,7 +8149,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "88fff5eb5e09dd6ed63d56799b56af08853870b9215d7be54285d52cde241980", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8212,7 +8212,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "88fff5eb5e09dd6ed63d56799b56af08853870b9215d7be54285d52cde241980", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8275,7 +8275,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "88fff5eb5e09dd6ed63d56799b56af08853870b9215d7be54285d52cde241980", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8338,7 +8338,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c4c87f61d4b51c532387d32daa24f0eda5fb1433ca6fe50d3261473410ec8ae4", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8366,7 +8366,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c4c87f61d4b51c532387d32daa24f0eda5fb1433ca6fe50d3261473410ec8ae4", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8393,7 +8393,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c4c87f61d4b51c532387d32daa24f0eda5fb1433ca6fe50d3261473410ec8ae4", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8420,7 +8420,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "c4c87f61d4b51c532387d32daa24f0eda5fb1433ca6fe50d3261473410ec8ae4", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8447,7 +8447,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7fef40dd6cf911411a9c4a340ddc550d73a8f0e3c9d7c4ff0b8280d4a139c3df", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8493,7 +8493,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7fef40dd6cf911411a9c4a340ddc550d73a8f0e3c9d7c4ff0b8280d4a139c3df", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8538,7 +8538,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7fef40dd6cf911411a9c4a340ddc550d73a8f0e3c9d7c4ff0b8280d4a139c3df", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8583,7 +8583,7 @@ "source": "kendex", "sourceRepo": "vanillagreencom/kendex", "sourceHash": "7fef40dd6cf911411a9c4a340ddc550d73a8f0e3c9d7c4ff0b8280d4a139c3df", - "sourceCommit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34", + "sourceCommit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e", "selector": { "sourceRev": null, "rev": null @@ -8625,7 +8625,7 @@ "sources": { "kendex": { "repo": "vanillagreencom/kendex", - "commit": "d83b22a37b4e52ee2d27e9bee9d094a97d563e34" + "commit": "95b4fb9c7cf44f38c608f23ca1458b42d287575e" } }, "claudeProjectDefault": "owned" diff --git a/.pi/kendex/hooks/lane-mail-check.sh b/.pi/kendex/hooks/lane-mail-check.sh index 73306ecc..ba719e94 100644 --- a/.pi/kendex/hooks/lane-mail-check.sh +++ b/.pi/kendex/hooks/lane-mail-check.sh @@ -3,7 +3,7 @@ # name: lane-mail-check # event: Stop # matcher: -# description: Blocks a lane's turn end while its overseer mailbox holds unread lines, so a directive or a ruling reaches the lane without a keystroke, a pane or a question tool. The lane is the work item `LANE_MAIL_ITEM` names, or the one directory under `/tmp/lane-mail/` whose name lowercases to the current branch; a session with neither is not a lane; a lane whose mailbox holds no unread line passes silently, as does a directory git reports no repository for and that holds no mailbox of its own. The checkout's overseer mailbox, `/tmp/lane-mail/overseer`, has one reader: the session whose tmux server and pane the checkout's oversee workflow state names under `.overseer`, the pair every writer the orch `schemas/workflow-state.md` `overseer` row names writes, `oversee register` among them for a session opened by hand, and the one the fleet's OVERSEER is established by below, so a record naming a dead pane names no reader. The native session must also match the recorded harness, readable caller home and payload session id; `ol_record_heal` binds the first matching native id from the recorded pane, and `oversee register` clears that binding after a resume. Pi and any harness whose `lane_context_caller_home` reports no home compare the harness and native session id only. The pair names a session only on the tmux server started at the record's `server_start`, so a server a tmux restart handed the recorded pid and pane id names no reader either; a record carrying no start at all names the session in that pane, which writes its server's start into it. Where a file stands there, that session is handed the notes `lane-mail peer send --repo` wrote there at its turn end and after its tool calls, under the same `unread=` line, unless a live watch holds the fleet state: the `oversee-watch.pid` record a repeat `oversee-watch` writes beside the fleet state on every surface and removes on exit, judged by the orch `lib/watch-pid.sh` library's `watch_pid_live`, which reads the mailbox itself, so the named session is handed nothing from it beside that watch. A fleet watched in single passes writes no watch record, so its named overseer is handed the notes as `unread=` lines and the next pass does not report them. A Jarvis session's wake, the process `ORCH_WAKE_PROCESS` matches, is no such watch: it moves no cursor, so that session is handed each note in full here once and acknowledges it here, and its wake carries no note's body, at most the count and read command `lane-mail watch` prints. Where the payload's `kendex_ack` is `caller`, which the pi-hooks lane mail wake sends, the context carries the reader's `--ack` command as `kendex_ack` and nothing is acknowledged here: the wake runs it once its send returns, so a send that throws leaves the lines unread. Every other session in the checkout, one the owner opened there for other work included, is handed nothing from that mailbox, and so is a session whose install has no reader beside this hook. For the named session, where the install's `workflow-state path oversee` prints no path, or the library cannot be sourced or answers neither way, the hook refuses, opening `lane-mail-check: fleet-state=` with that file's own words under it; the halt arm never reads that mailbox, a subagent's turn end is handed nothing from it, and a session in a checkout with no overseer mailbox pays two file tests for the question. `` is the lane's root, resolved in this order: `CLAUDE_PROJECT_DIR`, the directory Claude Code started the session in; else the root the launch marker for `LANE_MAIL_ITEM` binds, where that root exists; else the directory the hook runs in, which on Codex and Pi is the session's start directory and on Claude Code without the variable is the call's own. A Claude Code lane working from the main clone is therefore still judged on its own mailbox. A root its launch marker binds that has no `tmp/lane-mail` directory is refused at a turn end, before any tool call and after the lead's finished one, opening `lane-mail-check: mailbox-missing=` with the marker and the one `mkdir` command that restores the directory, and that command alone passes a tool call. Before a tool call a subagent is refused whatever it runs, and a call whose caller is unknown may run that command; after one a subagent is handed nothing and refused nothing, as with any mail, and its next call meets the refusal. The marker is looked up for the item `LANE_MAIL_ITEM` names or else the branch names, so that check costs one stat in a repository whose common git directory holds no `lane-mail` directory, and one branch read and one marker stat in one that does. A mailbox belongs to a lane only where a launch recorded one: `open-terminal` and `lane-host create` write the lane's root to `lane-mail/` under the repository's common git directory and create the lane's own `tmp/lane-mail/`, and a mailbox with no marker bound to this root passes silently. Unread lines are peeked through the orch skill's own `lane-mail inbox --peek`, the one reader of the mailbox and its cursor, and acknowledged with `inbox --ack` only once the refusal is written, so a hook killed at its budget leaves them unread and a line acknowledged here is never handed over twice. That reader is resolved from this hook's own install, walking up to the home directory for `skills/mailbox/scripts/lane-mail` or the shared `.agents/skills/mailbox/scripts/lane-mail` beside it, then the home's own shared tree for a harness root relocated out of it; the open repository's `.agents/skills/mailbox/scripts/lane-mail` is used only where this hook is installed in that repository, and a reader outside that containment is refused rather than run. The refusal opens with `lane-mail-check: unread=` and carries one JSON envelope per line under it, and for the lead, where a halt is among them, the one `lane-mail inbox` command that reads it; the turn then continues with them. Run with the argument `deliver` by the lane-mail-deliver hook after a tool call, it exits 0 with the harness's JSON on stdout, whose `additionalContext` carries the same lines. That run first judges the context mark of the fleet's OVERSEER, below, for a lead's call in tmux in a checkout whose `tmp/lane-mail/overseer` directory stands, so a mark crossed mid-turn is read at the next tool call: the context is read and recorded as the overseer's turn end reads it and judged at `ORCH_HANDOFF_CONTEXT_PCT` by the rule the orch `references/oversee-events.md` § Judgement rules states for the overseer's context mark. On Pi the window is the payload's own `context_window`, which the pi-hooks carrier puts on the PostToolUse payload of every tool call; a Pi payload naming none, the lane mail wake's run or a tool call from an older carrier, takes no reading, writes no record and hands nothing over, so the turn end's reading and judgement stand. A reached mark, or a setting it cannot be judged on, is handed over as that `additionalContext`, opening `lane-mail-check: context=` with the succession and the handoff record as the route, at every tool call until that record stands. Every other line that judgement writes, a judgement that could not run, a transcript it could not read or an `orch-env` this install has not got, is handed over the same way once per session and first line, the last told kept in `tmp/lane-mail/overseer/context-told`, written only once the run's output carrying it is written and cleared by a clean reading; only the bound native session the fleet record names, or the overseer it lost whose native identity still matches a nonempty recorded binding, writes or clears that file. Either opens the same context as any mail the call hands over, above its `unread=` line, and a refusal the mailbox check makes on the same call, above its keyed line, whether that refusal is Copilot's `additionalContext` or stderr at exit 2. The judgement itself refuses no call, and no account is read there. Run with `start` by the lane-mail-start hook at a session start, or with `prompt` by the lane-mail-prompt hook at a prompt, both on Copilot alone, it hands the same lines over the same way. A session start acknowledges them only once that context is written. A prompt leaves the lines unread because Copilot can discard its output, so a later inbox read or hook delivery can repeat them. Neither arm refuses anything: every refusal this description names is its keyed line on stderr at exit 0, with nothing on stdout and nothing acknowledged. Before an attached agent launch, the halt arm also judges the lead of a launched lane or the identified fleet overseer at the context mark, refusing missing context with the orch job runner or a separate session as the route. While an attached agent of the session may still be out, the mark is less ORCH_HANDOFF_AGENT_RESERVE_TOKENS, default 150000 tokens, equality refused: Claude Code reads that roster from its task registry where the payload carries one, else from the transcript's Agent-call results, task notifications, teammate idle notifications and sends, and reads an unreadable roster or an entry neither read classifies as unknown; Codex reads ordered collaboration snapshots, launches and followups from its rollout. Idle, completed, errored, shutdown and not-found children release the reserve; initializing, running and interrupted children keep it. A full unfiltered snapshot replaces earlier unknown observations only when its call does not overlap a launch or followup; pending calls and unreadable current observations keep the roster unknown. After waiting, Codex must call list_agents with no path filter to observe returns. Other harnesses read none, so their rosters are unknown. With none out the launch meets the plain mark. A launch the reserve alone refuses with an agent out is keyed `agent-reserve` and names waiting for those agents, the job runner or a separate session, never a handoff, since the turn end and every succession judge the plain mark. With the roster unknown no wait can be observed, so the refusal is keyed `agent-unobserved` and names the job runner or a separate session, and for a lane its handoff record. On Pi the lead launches through subagent; delegate_subagent carries child identity and is outside this lead-only reserve rule. At a context hold, a live session waits for attached agent returns in this turn; Claude Stop background_tasks is preferred, with the transcript's measured Agent-call results, async launch and teammate spawn records, task notifications, teammate idle notifications and sends as the fallback when absent. Other harnesses name known unfinished children and known output paths, or unknown paths, in the emergency handoff. A standing handoff retains its escape, and the successor reads existing output before repeating work. Run with `halt` by the lane-mail-halt hook before one, it acknowledges nothing and refuses the call while an unread directive sent with `lane-mail send --halt` stands, opening `lane-mail-check: halt=` with the directive and the one `lane-mail inbox` command that reads it, which names the lane's root with `--root` so it reads the same mailbox from any checkout; that command alone passes. Run with `row` and the event by the session-start-row, session-end-row and stop-failure-row hooks, it writes the event row of a session with no lane of its own, only for the pane's top-level harness and, on Copilot, only for a session the caller rule names the lead, through the orch skill's `lib/session-rows.sh`, the file those hooks describe, and refuses nothing: every gap below its payload read is reported and passed; the overseer's own turn end writes a Stop row there through the same library at every turn end, compact, its time, event, harness and session alone, except over a standing StopFailure row, which it lifts and where it keeps the turn's last message. Run with `lane` by the critical-path-deny hook, it prints `lane` where the launch marker for the session's item binds the session's root and its mailbox directory stands, else `none`, records and judges nothing else, and exits 0; a gap past its payload read is reported on stderr and passed with nothing on stdout. On a Pi install a launched lane's lead writes its own turn rows through that library into its mailbox directory, `session-rows.jsonl`: a Stop row at each turn end, carrying the `stopReason` of the turn's last assistant message in the transcript and Pi's `errorMessage` where that reason is `error`, and a PreToolUse row at the first tool call of each turn, after a turn end or on an empty file, written ahead of the mailbox check; oversee-watch and `lanes state` judge a Pi lane idle, working or walled from those rows in place of its pane, and a gap in the write is reported under `lane-rows-skipped` or `lane-rows-unwritten` and passed. The Pi install is the hook directory under `.pi` or `.pi/agent`, or under the user root `PI_CODING_AGENT_DIR` names; an install naming no harness writes no row, which a launched lane's turn end reports under `harness-unlisted`. Who made a call is answered once for every arm: the lead, a subagent, or unknown. A SubagentStop payload or one carrying a non-empty `agent_id` or `agent_type` is a subagent's on every harness, handed no mail and acknowledging none, and while a halt stands refused without that command. On Copilot, whose payloads name no agent, a preToolUse or postToolUse call, a preCompact and a context reading the usage arm is handed are the lead's where the session id they carry is a lead session this install recorded, the one rule for all four: one empty file per session under `~/.cache/lane-mail/copilot-leads`, written at the session's sessionStart, which Copilot fires for the lead alone, and at each turn end the transcript rule below proves the lead's, and pruned at a start once untouched for 30 days. A custom subagent's call was measured on Copilot CLI 1.0.88 carrying its own session id, which nothing recorded; whether a built-in task-tool subagent's calls carry their own session id or the lead's is a pending live-lane proof, and one whose calls carry the lead's is read as the lead, handed the lead's mail after its calls, which marks it read, and under a halt shown the read that clears it. A call whose session is no recorded lead, a custom subagent's among them, is unknown: the deliver arm hands it nothing and acknowledges nothing, writing `lane-mail-check: session-unrecorded=` to stderr, the compact arm flags nothing and writes the same line at exit 0, the usage arm records nothing and refuses under that key at exit 2, so the lead's turn end hands the lines over and acknowledges them, and the halt arm refuses it without showing that command yet passes the command, because the reader's `--ack` stops short of an unread halt and a lead whose record could not be written would otherwise be refused for good; the lead is shown the command by every notice and refusal that hands it the halt, its turn end's included. A record that cannot be written is reported on stderr under `lane-mail-check: lead-unrecorded=`, or `=none` for a session start naming no session id, and never refused. A Copilot sessionStart or userPromptSubmitted is the lead's, and an agentStop is ruled by its transcript, below; a prompt records no lead, since that a subagent's prompt fires no userPromptSubmitted is unmeasured. `stop_hook_active` true skips the mailbox check whole on the turn-end run. The flag is in the payload, so nothing above the payload read knows a turn was continued, and `arm`, the `missing-tools` refusal for `jq` or `cat`, `payload=unreadable` and `payload=invalid-json` are refused on every turn, the continued one included. Below that read one rule holds and every refusal is on one side of it: a refusal the lane itself can clear is still made, and a refusal it cannot is reported on stderr and passed. The lane clears the two handoff marks, and `script`, `setting`, `setting-range` and both `transcript` refusals, by writing its handoff record, and `mailbox-missing` by running the command it names, so those are refused on a continued turn as on any other. It clears `idle` by sending a lane-mail ask or notice, or by updating `tmp/lane-status-.md` under its launch root, so `idle` is refused on a turn another stop hook continued, except on Pi, as the idle rule below states. It clears none of `workdir`, `git`, `item`, `marker` or the `missing-tools` refusal for `git`, `tr`, `awk`, `mktemp` or `tail`, so each of those is reported and the turn ends, where a fresh turn refuses it. The halt arm reports and passes that same set at every tool call: a lane whose tool calls are refused can clear nothing, since clearing it takes a tool call, so there only the payload refusals and the mailbox's own, `reader`, `inbox`, `halt` and `mailbox-missing`, are refused, the last two each passing the one command that clears it. The same turn-end run hands the lane off before it runs out, so the handoff never waits on an overseer reading a pane. It reads this session's context use from the `transcript_path` the payload names, through the orch adapter for the harness this hook's install directory names, `.claude/hooks`, `.codex/hooks` or Pi's `kendex/hooks`: the tokens the last response left in context and effective capacity, with Pi reading the payload's own `context_window`. It records that reading as `context.json` in the lane's mailbox directory, where `lanes context` reads it, and refuses the turn end when `lane_context_handoff_due` requires handoff under the shared context rule in orch `references/oversee-events.md`, Judgement rules. It reads the account the credential this session runs on still has through the orch skill's own `lanes pick --lane`, judging a Claude lane on its own model, and refuses at or below `ORCH_HANDOFF_HEADROOM_PCT` (default 3). A Pi session's account is the one its model's provider bills, by the orch `lane_pick_harness` rule on the `/` its transcript names: a `pi-claude/` model spends the Claude seat `CLAUDE_CONFIG_DIR` names and is judged there on that model, a `github-copilot/` model spends the Copilot pool on Pi's own root, and any other provider, or a reading naming none, is left unjudged under `account=unmeasured`. Either refusal opens `lane-mail-check: context=` or `lane-mail-check: headroom=` and carries one instruction: reach the next safe point, write the record with `workflow-state set handoff`, send a `handoff` notice, and exit. The record is read where `workflow-state --help` § Handoff record says, a launched lane naming the root its launch marker binds as the worktree, and the instruction names the state directory the read found, so a record written as told ends both refusals. The instruction opens with the `workflow-state init ` that `set` needs where the item has no state file yet, so it is enough on its own. It repeats at every turn end, `stop_hook_active` included, until the item's workflow state carries a `.handoff` object no relaunch has resumed; only the lane can write that record, so a single refusal it declines to act on would end the session with nothing recorded. That record is judged before every mark, before every read they rest on and before `orch-env` and `lanes` are looked for, so no failure but the record's own writer can hold a lane that has already done what it was asked. `orch-env` or `lanes` missing from this hook's install, a mark setting that is not a whole number in range, and a transcript the payload names and nothing can read are refusals too, each on the lane path alone and each carrying the same instruction. What the marks cannot judge is reported and passed, never refused: a payload naming no transcript leaves the context unread, and so does a transcript whose last usage line is an object carrying none of the field names its adapter reads, which is reported under `usage-unread=` rather than summed to a figure of zero and read as room, a reading below the independent token limit whose capacity the adapter could not name, reported under `window-unread=`, and an install directory naming no harness, reported under `harness-unlisted=`; a reading that could not be recorded is reported under `context-unrecorded=` and still judged; an account `lanes` keeps no inventory for, one it could not measure and a read that passed this hook's own ceiling each leave the account unjudged under `account=unlisted`, `account=unmeasured` or `account=timeout`, never read as room, so a setup with no usage endpoint still ends its turns; and a lane whose handoff record cannot be judged leaves both marks unjudged under one of four keys, `handoff-skipped=` for a reader or a script this install has not got, or `handoff-skipped=unlocatable` where this hook's own directory could not be resolved and none of them could be looked for, `handoff-outside=` for one only the open repository supplies, `handoff-unanswered=` for one that is there and answered nothing this hook can read, and `handoff-unreadable=` for a state file the install's own `workflow-state` could not read. Passing the turn is the answer for all four. For the first three it is because an install whose orch scripts cannot answer cannot run `workflow-state set` either, so a lane told to record a handoff with them could never end a turn again; for `handoff-unreadable` the install answers and the fault is the item's own state file, which is the file the record would be written into, so that write could not land either and the refusal would be as uncloseable. A subagent's turn end is judged on neither mark. The fleet's OVERSEER meets four triggers of its own on its turn end: a session with no lane of its own whose tmux server and pane are the pair the oversee workflow state records under `.overseer` is that overseer, and nothing weaker establishes one, so an ordinary session in a fleet checkout is judged on nothing. A session whose native identity matches a nonempty binding in the fleet record but whose pane only the overseer's `context.json` names, the overseer the record lost, is judged on nothing either, and reports `pane-unrecorded=` with the recorded key under it and writes that record with no reading and the gap `pane-unrecorded`; any other session the record does not name writes nothing, so the real overseer's reading stands. A fleet record naming this session's pane that lacks its server start, its harness, its launch home or its native session id is healed from an authorized native session first, at a turn end and at a tool call alike: the start of this session's own tmux server, the harness this install names and the launch home the harness variable of this session's own environment carries, `CLAUDE_CONFIG_DIR`, `CODEX_HOME` or `COPILOT_HOME` or that harness's default where it is unset, are written into it through the orch `lib/overseer-launch.sh` `ol_record_heal`, which writes only a fact the record lacks, and the transcript is bound to that home on the same run; a write that fails is reported under `record-unhealed=` with the writer's words, and the caller remains unbound until a later binding write succeeds. Before it reads that transcript for the overseer it binds it to the current session: the `transcript_path` the payload names is read only where it is this session's own native file, held to the `session_id` the payload carries and the launch home the fleet record names under `.overseer.home`, through the orch adapter for a claude, codex or copilot install; a Pi install states no transcript shape and reads the payload's own window as a Pi lane does. If `lane_context_transcript_owned` refuses an admitted overseer's transcript binding, the hook reports `transcript-unowned=` with the reason the library returns. Nothing is read then, and the context record is written with a null token count and that reason as its `gap` (orch `workflow-state.md`, `context.json` row), so it still advances at every turn end and oversee-watch reports the gap, and the judge is handed this install's harness and no context figure, so it judges the account triggers alone, the `transcript-unowned` line is this hook's one report that the context went unmeasured, and a session is never judged on a file it does not own. Every overseer turn end whose orch context library loads writes that record, a reading or a null token count with a `gap` naming why none was taken: the binding library's reason, `transcript-unnamed` for a payload naming no transcript, `usage-absent` for a transcript holding no usage line, `usage-unread` for a usage object its adapter does not read, which is also reported under `usage-unread=`, `session-record` for a Copilot session with no extension reading whose statusLine session record does not answer either, which is also reported under `session-record=`, or `pane-unrecorded` below. A Copilot statusLine record reporting allow_all_enabled false, read whether or not an extension reading stands, in a session whose `COPILOT_ALLOW_ALL` is true (a launch line granting `--allow-all` or `--yolo`), is reported under `stop-cause=allow-all-blocked-by-policy`, and the turn end judged as usual. An install naming no harness an adapter reads writes no gap, since its context is never read, and leaves the record as it was, and a Copilot one names none where the reading its usage arm wrote for this session stands, its turn end reading that record rather than taking a reading of its own; a gap record that cannot be written is reported under `context-gap-unrecorded=`, the record keeping its earlier entry. This hook records the overseer's own context reading as `context.json` in the overseer mailbox directory at the main checkout, naming the session and its pane, and hands that reading to `oversee-succeed --check-marks --context :` from this hook's own install, which judges those marks on it and on no stored figure, and nothing at the turn end here judges them, under the same ceiling the account read runs under, so the turn-end refusal and the `overseer-mark` watch event cannot describe one overseer differently. Its refusal opens with the `context=`, `headroom=`, `rate=` or `qualifying=` key, carrying the figure that judgement read, and names `oversee-succeed`, handed the same reading, as the route, with `workflow-state set oversee handoff` under it for a succession that refuses, so the refusal always has an escape the overseer can reach. That record names the session that wrote it, in the native `session_id` the payload gives. A payload with no native session id is refused and cannot read mail or write overseer context or gaps. `overseer_identify` owns its native refusal diagnostics. One other refusal stands on that path, `script` for an `oversee-succeed` this install has not got, and the record clears it as it clears the marks. `ORCH_OVERSEER_SUCCESSION=off`, read off the judgement's own line and never here, turns the account-mark refusals off with the succession they name, the watch's `overseer-mark` event still reporting those marks; the context mark is refused whatever the setting, since no watch event reports it, and the handoff record ends that refusal. An answer this hook cannot act on, one the ceiling abandoned, and one whose own reading was unmeasured are reported under `marks=unjudged`, `marks=timeout` and `marks=unmeasured` and the turn ends, never held. A lane asks its overseer only through lane mail. Before a tool call in a launched lane, the halt arm refuses the harness question tool by its name, whichever of the four names the payload's `tool_name` carries, Claude Code's `AskUserQuestion` and `EnterPlanMode`, Codex's `request_user_input` and Pi's `question`, opening `lane-mail-check: question-tool=` and naming the `lane-mail ask --item --file ` send and the `lane-mail wait` on its printed id as the route, because a dialog on the pane reaches no overseer; an unread halt is refused ahead of it, a subagent's call is refused and told to report its question to the lead, and a session that is no launched lane passes the call silently, a committed mailbox and status file included. At a launched lane lead's turn end, once the handoff marks pass, the lane is judged idle on lane-mail sends and its lane status file update state, never on words in its pane, on Claude Code, Codex, Pi and Copilot; OpenCode and Cursor run no kendex hooks, and Gemini and Antigravity do not run this one, so a lane there is never judged idle. The reader's own `lane-mail events` listing, which moves no cursor, counts the asks and notices in the lane's outbound file against the count this hook recorded at the lane's last judged turn end, `sent-count` in the lane's mailbox directory: a line holding the count, the word `held` where this judge refused that turn end, and an optional encoded status file update state; no record is a count of zero with no status state. A status file update since that record, including a rewrite of the same text, passes without a notice. A count other than the recorded one is a send this turn and passes, a standing handoff record ends the run before this judge, the newest directive the overseer sent carrying `halt` passes, and a lane whose launch marker no longer binds its root, the close-out's state, is no lane. With none of these the turn is refused and the hold recorded, opening `lane-mail-check: idle=` with one continuation, the lane's `lane-mail inbox` read and then its workflow, beside the ask route and the `lane-mail notice` send, which follows the orch Coordination notice rule: changed work sends a notice, and a continuing wait on a dispatched agent or an armed wake updates the lane status file only. On a turn the harness continued for this judge's own recorded hold it refuses nothing and sends the overseer a lane notice stating what it checked, opening `lane-mail-check: idle-notice=`, or `idle-notice-unsent=` with the sender's words where the send fails, so an idle lane is reported and never looped. A turn another stop hook's refusal continued is held as a fresh one, except on Pi, whose pi-hooks carrier runs no further request after a continued turn, so there the notice is sent with no hold before it. The record counts that notice, so the lane's next turn is judged on what the lane itself sends. An `events` listing that fails, or whose envelopes jq cannot read, is reported under `events=` or `events=envelope`, and a record that is not a plain file holding a whole number, an optional `held` mark and an optional encoded status state under `idle-record=` and rewritten. A record that cannot be written is reported under `idle-unrecorded=`; under `idle-hold-unrecorded=` where it was to take a hold, which is then not made, since one with no record would be made again on every continued turn; and under `idle-notice-unrecorded=` where it was to count the notice, which the next turn end then reads as the lane's own send. Each of these ends the turn, because nothing a lane does at its turn end repairs its mailbox; an install with no reader leaves the turn unjudged under the marks' own `handoff-skipped` line. On Copilot the event is `agentStop`, registered in Copilot's own hook file under its camelCase name, so the payload spells its fields `sessionId`, `transcriptPath` and `toolArgs`, which this hook reads beside the snake_case spellings; its reference spells `stop_hook_active` so on both, and `toolName` identifies an attached launch. The `lane-mail-halt` description owns the Copilot preToolUse decision and deadline contract. Copilot also runs the hooks `.claude/settings.json` registers, under their PascalCase names, but the registration kendex writes there exits 0 before its script in a Copilot hook process, so a Copilot call reaches an install that is not Copilot's, the claude copy of this hook among them, only through a registration made there by hand or one kendex wrote before that skip and no refresh has rewritten. Whether Copilot made the call is read from the call, never from the install: a payload carrying `timestamp`, which both of Copilot's payload formats carry and no Claude, Codex or Pi payload does, or naming the session `sessionId`, is Copilot's, and any install but Copilot's own passes it silently, exit 0 with nothing written and nothing acknowledged, so the Copilot install is the one reader of the mailbox for a Copilot call. A Copilot agentStop names no agent: the stop whose `transcriptPath` sits in the directory named for the `sessionId`, Copilot's `session-state//events.jsonl`, is the lead's and records it, a stop naming a transcript under another directory is read as a subagent's, handed nothing and judged on nothing, and a payload naming no transcript, or no session, is the lead's and records nothing. Copilot CLI 1.0.88 was measured firing agentStop at a custom subagent's end too, with the subagent's own `sessionId` and the lead's `transcriptPath`, which this rule reads as a subagent's. A refusal on Copilot is the documented answer for its event, on stdout beside the keyed stderr line: at a turn end `{"decision":"block","reason":}` with exit 0, which Copilot stops honouring after 8 consecutive blocks, ending that turn unheld, so a handoff refusal holds a Copilot session for 8 continued turns and then returns at its next turn end, and after a tool call `{"additionalContext":}` with exit 0, since Copilot reads a postToolUse answer only at exit 0. A Copilot session's context is read through Copilot's own SDK event `session.usage_info`: the orch `copilot-lane-context` extension, which `open-terminal` installs in a Copilot fleet lane's `COPILOT_HOME` with the EXTENSIONS feature on, runs this hook with the argument `usage` at each reading of the session's root agent, handing it `{session_id, cwd, current_tokens, token_limit}` on stdin, and for a recorded lead session that is a launched lane's lead or the fleet's overseer, named by the same gate every arm that judges the marks asks, it records `current_tokens` as the tokens and, as the capacity, the limit Copilot compacts at: 80 percent of `token_limit`, the SDK's documented `backgroundCompactionThreshold` default, named in the record's `capacity_source`. It writes nothing on stdout; a gap is refused on stderr at exit 2, which the extension writes to the session timeline: `payload=invalid-json`, an orch install it cannot use under the key its turn end reports that gap under, `handoff-skipped=`, `handoff-outside=` or `handoff-unanswered=`, or `context-unrecorded=` for a reading that could not be written, where the session's earlier reading is removed too so its turn end reports the context unmeasured rather than judging an older figure as room. Any other session passes silently. The Copilot turn end judges this session's record under the shared context rule exactly as it judges a transcript reading, the capacity putting the handoff before Copilot's own compaction; no reading of this session, no record or a gap record, is read from the fallback below; where the pending marker the extension leaves at `~/.cache/lane-mail/copilot-usage/` for a reading it handed on and no run has recorded yet still stands after a wait of 5 seconds, the turn end reports `reading-pending=` and passes with the context unmeasured, reading no fallback, since the extension runs for that session, and never judging the earlier record as room, since nothing orders the extension's run before the turn end; and a record that stands and cannot be read is refused under `record=`. Where no pending marker stands and no reading of the extension's stands for this session, no record, one naming another session, a gap record or one the fallback below wrote, which its `capacity_source` tells apart, the turn end reads the fallback: the session record the orch `copilot-statusline` command writes as the account's `statusLine`, under `/lane-status/.json`, through the orch adapter for copilot, which holds the record to the payload's `sessionId`, its `transcriptPath` where one is named, the account directory and a freshness bound, and hands the shared judge the same compaction point of the window as the capacity; that reading is judged and recorded as any other harness's, and a record that does not answer leaves the context unmeasured under `reading-unrecorded=` and `session-record=`, reported and passed, never read as room. An extension reading below the mark is never overridden by a statusLine record past it. Run with `compact` by the lane-mail-compact hook at a preCompact whose `trigger` is `auto`, from a recorded lead session that gate names, it flags that compaction as `compaction.json` beside the reading, the backstop for a turn that crossed into the compaction before a reading past the mark reached a turn end, and the turn end then refuses under `compacted=auto` until the handoff record stands, the overseer's whatever its succession setting; a gap there is refused under `compaction-unrecorded=` on stderr at exit 2, which Copilot shows the operator without holding the compaction. A Copilot account is judged through `lanes pick --lane` like any other. A session the Jarvis runtime launched, which carries `JARVIS_RECORD`, has its lead's tool calls, on Copilot any call under the session id the record's start bound, and on Claude Code its turn ends, stamp that runtime record's launch row once as its Start brief taken, the fact the Jarvis launch worker reads beside the pane; another harness's turn end is no stamp, since Pi's carrier also dispatches it on a run that ended on an error and Codex and Copilot have no turn-failure event to tell one apart; a stamp that cannot be written is reported under `jarvis-rows-unwritten=` and passed, and the next such call writes it. Not run on gemini: it has no Stop event. Not run on antigravity: its Stop payload carries no `stop_hook_active`. +# description: Blocks a lane's turn end while its overseer mailbox holds unread lines, so a directive or a ruling reaches the lane without a keystroke, a pane or a question tool. The lane is the work item `LANE_MAIL_ITEM` names, or the one directory under `/tmp/lane-mail/` whose name lowercases to the current branch; a session with neither is not a lane; a lane whose mailbox holds no unread line passes silently, as does a directory git reports no repository for and that holds no mailbox of its own. The checkout's overseer mailbox, `/tmp/lane-mail/overseer`, has one reader: the session whose tmux server and pane the checkout's oversee workflow state names under `.overseer`, the pair every writer the orch `schemas/workflow-state.md` `overseer` row names writes, `oversee register` among them for a session opened by hand, and the one the fleet's OVERSEER is established by below, so a record naming a dead pane names no reader. The native session must also match the recorded harness, readable caller home and payload session id; `ol_record_heal` binds the first matching native id from the recorded pane, and `oversee register` clears that binding after a resume. Pi and any harness whose `lane_context_caller_home` reports no home compare the harness and native session id only. The pair names a session only on the tmux server started at the record's `server_start`, so a server a tmux restart handed the recorded pid and pane id names no reader either; a record carrying no start at all names the session in that pane, which writes its server's start into it. Where a file stands there, that session is handed the notes `lane-mail peer send --repo` wrote there at its turn end and after its tool calls, under the same `unread=` line, unless a live watch holds the fleet state: the `oversee-watch.pid` record a repeat `oversee-watch` writes beside the fleet state on every surface and removes on exit, judged by the orch `lib/watch-pid.sh` library's `watch_pid_live`, which reads the mailbox itself, so the named session is handed nothing from it beside that watch. A fleet watched in single passes writes no watch record, so its named overseer is handed the notes as `unread=` lines and the next pass does not report them. A Jarvis session's wake, the process `ORCH_WAKE_PROCESS` matches, is no such watch: it moves no cursor, so that session is handed each note in full here once and acknowledges it here, and its wake carries no note's body, at most the count and read command `lane-mail watch` prints. Where the payload's `kendex_ack` is `caller`, which the pi-hooks lane mail wake sends, the context carries the reader's `--ack` command as `kendex_ack` and nothing is acknowledged here: the wake runs it once its send returns, so a send that throws leaves the lines unread. Every other session in the checkout, one the owner opened there for other work included, is handed nothing from that mailbox, and so is a session whose install has no reader beside this hook. For the named session, where the install's `workflow-state path oversee` prints no path, or the library cannot be sourced or answers neither way, the hook refuses, opening `lane-mail-check: fleet-state=` with that file's own words under it; the halt arm never reads that mailbox, a subagent's turn end is handed nothing from it, and a session in a checkout with no overseer mailbox pays two file tests for the question. `` is the lane's root, resolved in this order: `CLAUDE_PROJECT_DIR`, the directory Claude Code started the session in; else the root the launch marker for `LANE_MAIL_ITEM` binds, where that root exists; else the directory the hook runs in, which on Codex and Pi is the session's start directory and on Claude Code without the variable is the call's own. A Claude Code lane working from the main clone is therefore still judged on its own mailbox. A root its launch marker binds that has no `tmp/lane-mail` directory is refused at a turn end, before any tool call and after the lead's finished one, opening `lane-mail-check: mailbox-missing=` with the marker and the one `mkdir` command that restores the directory, and that command alone passes a tool call. Before a tool call a subagent is refused whatever it runs, and a call whose caller is unknown may run that command; after one a subagent is handed nothing and refused nothing, as with any mail, and its next call meets the refusal. The marker is looked up for the item `LANE_MAIL_ITEM` names or else the branch names, so that check costs one stat in a repository whose common git directory holds no `lane-mail` directory, and one branch read and one marker stat in one that does. A mailbox belongs to a lane only where a launch recorded one: `open-terminal` and `lane-host create` write the lane's root to `lane-mail/` under the repository's common git directory and create the lane's own `tmp/lane-mail/`, and a mailbox with no marker bound to this root passes silently. Unread lines are peeked through the orch skill's own `lane-mail inbox --peek`, the one reader of the mailbox and its cursor, and acknowledged with `inbox --ack` only once the refusal is written, so a hook killed at its budget leaves them unread and a line acknowledged here is never handed over twice. That reader is resolved from this hook's own install, walking up to the home directory for `skills/mailbox/scripts/lane-mail` or the shared `.agents/skills/mailbox/scripts/lane-mail` beside it, then the home's own shared tree for a harness root relocated out of it; the open repository's `.agents/skills/mailbox/scripts/lane-mail` is used only where this hook is installed in that repository, and a reader outside that containment is refused rather than run. The refusal opens with `lane-mail-check: unread=` and carries one JSON envelope per line under it, and for the lead, where a halt is among them, the one `lane-mail inbox` command that reads it; the turn then continues with them. Run with the argument `deliver` by the lane-mail-deliver hook after a tool call, it exits 0 with the harness's JSON on stdout, whose `additionalContext` carries the same lines. That run first judges the context mark of the fleet's OVERSEER, below, for a lead's call in tmux in a checkout whose `tmp/lane-mail/overseer` directory stands, so a mark crossed mid-turn is read at the next tool call: the context is read and recorded as the overseer's turn end reads it and judged at `ORCH_HANDOFF_CONTEXT_PCT` by the rule the orch `references/oversee-events.md` § Judgement rules states for the overseer's context mark. On Pi the window is the payload's own `context_window`, which the pi-hooks carrier puts on the PostToolUse payload of every tool call; a Pi payload naming none, the lane mail wake's run or a tool call from an older carrier, takes no reading, writes no record and hands nothing over, so the turn end's reading and judgement stand. A reached mark, or a setting it cannot be judged on, is handed over as that `additionalContext`, opening `lane-mail-check: context=` with the succession and the handoff record as the route, at every tool call until that record stands. Every other line that judgement writes, a judgement that could not run, a transcript it could not read or an `orch-env` this install has not got, is handed over the same way once per session and first line, the last told kept in `tmp/lane-mail/overseer/context-told`, written only once the run's output carrying it is written and cleared by a clean reading; only the bound native session the fleet record names, or the overseer it lost whose native identity still matches a nonempty recorded binding, writes or clears that file. Either opens the same context as any mail the call hands over, above its `unread=` line, and a refusal the mailbox check makes on the same call, above its keyed line, whether that refusal is Copilot's `additionalContext` or stderr at exit 2. The judgement itself refuses no call, and no account is read there. Run with `start` by the lane-mail-start hook at a session start, or with `prompt` by the lane-mail-prompt hook at a prompt, both on Copilot alone, it hands the same lines over the same way. A session start acknowledges them only once that context is written. A prompt leaves the lines unread because Copilot can discard its output, so a later inbox read or hook delivery can repeat them. Neither arm refuses anything: every refusal this description names is its keyed line on stderr at exit 0, with nothing on stdout and nothing acknowledged. Before an attached agent launch, the halt arm also judges the lead of a launched lane or the identified fleet overseer at the context mark, refusing missing context with the orch job runner or a separate session as the route. While an attached agent of the session may still be out, the mark is less ORCH_HANDOFF_AGENT_RESERVE_TOKENS, default 150000 tokens, equality refused: Claude Code reads that roster from its task registry where the payload carries one, else from the transcript's Agent-call results, task notifications, teammate idle notifications and sends, and reads an unreadable roster or an entry neither read classifies as unknown; Codex reads ordered collaboration snapshots, launches and followups from its rollout. Idle, completed, errored, shutdown and not-found children release the reserve; initializing, running and interrupted children keep it. A full unfiltered snapshot replaces earlier unknown observations only when its call does not overlap a launch or followup; pending calls and unreadable current observations keep the roster unknown. After waiting, Codex must call list_agents with no path filter to observe returns. Other harnesses read none, so their rosters are unknown. With none out the launch meets the plain mark. A launch the reserve alone refuses with an agent out is keyed `agent-reserve` and names waiting for those agents, the job runner or a separate session, never a handoff, since the turn end and every succession judge the plain mark. With the roster unknown no wait can be observed, so the refusal is keyed `agent-unobserved` and names the job runner or a separate session, and for a lane its handoff record. On Pi the lead launches through subagent; delegate_subagent carries child identity and is outside this lead-only reserve rule. At a context hold, a live session waits for attached agent returns in this turn; Claude Stop background_tasks is preferred, with the transcript's measured Agent-call results, async launch and teammate spawn records, task notifications, teammate idle notifications and sends as the fallback when absent. Other harnesses name known unfinished children and known output paths, or unknown paths, in the emergency handoff. A standing handoff retains its escape, and the successor reads existing output before repeating work. Run with `halt` by the lane-mail-halt hook before one, it acknowledges nothing and refuses the call while an unread directive sent with `lane-mail send --halt` stands, opening `lane-mail-check: halt=` with the directive and the one `lane-mail inbox` command that reads it, which names the lane's root with `--root` so it reads the same mailbox from any checkout; that command alone passes. Run with `row` and the event by the session-start-row, session-end-row and stop-failure-row hooks, it writes the event row of a session with no lane of its own, only for the pane's top-level harness and, on Copilot, only for a session the caller rule names the lead, through the orch skill's `lib/session-rows.sh`, the file those hooks describe, and refuses nothing: every gap below its payload read is reported and passed; the overseer's own turn end writes a Stop row there through the same library at every turn end, compact, its time, event, harness and session alone, except over a standing StopFailure row, which it lifts and where it keeps the turn's last message. Run with `lane` by the critical-path-deny hook, it prints `lane` where the launch marker for the session's item binds the session's root and its mailbox directory stands, else `none`, records and judges nothing else, and exits 0; a gap past its payload read is reported on stderr and passed with nothing on stdout. On a Pi install a launched lane's lead writes its own turn rows through that library into its mailbox directory, `session-rows.jsonl`: a Stop row at each turn end, carrying the `stopReason` of the turn's last assistant message in the transcript and Pi's `errorMessage` where that reason is `error`, and a PreToolUse row at the first tool call of each turn, after a turn end or on an empty file, written ahead of the mailbox check; oversee-watch and `lanes state` judge a Pi lane idle, working or walled from those rows in place of its pane, and a gap in the write is reported under `lane-rows-skipped` or `lane-rows-unwritten` and passed. The Pi install is the hook directory under `.pi` or `.pi/agent`, or under the user root `PI_CODING_AGENT_DIR` names; an install naming no harness writes no row, which a launched lane's turn end reports under `harness-unlisted`. Who made a call is answered once for every arm: the lead, a subagent, or unknown. A SubagentStop payload or one carrying a non-empty `agent_id` or `agent_type` is a subagent's on every harness, handed no mail and acknowledging none, and while a halt stands refused without that command. On Copilot, whose payloads name no agent, a preToolUse or postToolUse call, a preCompact and a context reading the usage arm is handed are the lead's where the session id they carry is a lead session this install recorded, the one rule for all four: one empty file per session under `~/.cache/lane-mail/copilot-leads`, written at the session's sessionStart, which Copilot fires for the lead alone, and at each turn end the transcript rule below proves the lead's, and pruned at a start once untouched for 30 days. A custom subagent's call was measured on Copilot CLI 1.0.88 carrying its own session id, which nothing recorded; whether a built-in task-tool subagent's calls carry their own session id or the lead's is a pending live-lane proof, and one whose calls carry the lead's is read as the lead, handed the lead's mail after its calls, which marks it read, and under a halt shown the read that clears it. A call whose session is no recorded lead, a custom subagent's among them, is unknown: the deliver arm hands it nothing and acknowledges nothing, writing `lane-mail-check: session-unrecorded=` to stderr, the compact arm flags nothing and writes the same line at exit 0, the usage arm records nothing and refuses under that key at exit 2, so the lead's turn end hands the lines over and acknowledges them, and the halt arm refuses it without showing that command yet passes the command, because the reader's `--ack` stops short of an unread halt and a lead whose record could not be written would otherwise be refused for good; the lead is shown the command by every notice and refusal that hands it the halt, its turn end's included. A record that cannot be written is reported on stderr under `lane-mail-check: lead-unrecorded=`, or `=none` for a session start naming no session id, and never refused. A Copilot sessionStart or userPromptSubmitted is the lead's, and an agentStop is ruled by its transcript, below; a prompt records no lead, since that a subagent's prompt fires no userPromptSubmitted is unmeasured. `stop_hook_active` true skips the mailbox check whole on the turn-end run. The flag is in the payload, so nothing above the payload read knows a turn was continued, and `arm`, the `missing-tools` refusal for `jq` or `cat`, `payload=unreadable` and `payload=invalid-json` are refused on every turn, the continued one included. Below that read one rule holds and every refusal is on one side of it: a refusal the lane itself can clear is still made, and a refusal it cannot is reported on stderr and passed. The lane clears the handoff refusals, and `script`, `setting`, `setting-range` and both `transcript` refusals, by writing its handoff record, and `mailbox-missing` by running the command it names, so those are refused on a continued turn as on any other. It clears `idle` by sending a lane-mail ask or notice, or by updating `tmp/lane-status-.md` under its launch root, so `idle` is refused on a turn another stop hook continued, except on Pi, as the idle rule below states. It clears none of `workdir`, `git`, `item`, `marker` or the `missing-tools` refusal for `git`, `tr`, `awk`, `mktemp` or `tail`, so each of those is reported and the turn ends, where a fresh turn refuses it. The halt arm reports and passes that same set at every tool call: a lane whose tool calls are refused can clear nothing, since clearing it takes a tool call, so there only the payload refusals and the mailbox's own, `reader`, `inbox`, `halt` and `mailbox-missing`, are refused, the last two each passing the one command that clears it. The same turn-end run hands the lane off before it runs out, so the handoff never waits on an overseer reading a pane. It reads this session's context use from the `transcript_path` the payload names, through the orch adapter for the harness this hook's install directory names, `.claude/hooks`, `.codex/hooks` or Pi's `kendex/hooks`: the tokens the last response left in context and effective capacity, with Pi reading the payload's own `context_window`. It records that reading as `context.json` in the lane's mailbox directory, where `lanes context` reads it, and refuses the turn end when `lane_context_handoff_due` requires handoff under the shared context rule in orch `references/oversee-events.md`, Judgement rules. It reads the account the credential this session runs on still has through the orch skill's own `lanes pick --lane`, judging a Claude lane on its own model. The picker owns the account handoff decision. For an ordinary account wall, the hook refuses the turn end and names the binding bucket's headroom against `ORCH_HANDOFF_HEADROOM_PCT` (default 3). When that picker reports `seat-reserve` for an overseer seat, the hook refuses the turn end. That refusal names the binding bucket's headroom and the configured `ORCH_OVERSEER_SEAT_RESERVE_PCT` (default 50) as independent facts. A Pi session's account is the one its model's provider bills, by the orch `lane_pick_harness` rule on the `/` its transcript names: a `pi-claude/` model spends the Claude seat `CLAUDE_CONFIG_DIR` names and is judged there on that model, a `github-copilot/` model spends the Copilot pool on Pi's own root, and any other provider, or a reading naming none, is left unjudged under `account=unmeasured`. A lane's context and account mark refusals open `lane-mail-check: context=`, `lane-mail-check: headroom= bucket= mark=` or `lane-mail-check: seat-reserve= bucket= reserve=`. Each carries one instruction: reach the next safe point, write the record with `workflow-state set handoff`, send a `handoff` notice, and exit. The record is read where `workflow-state --help` § Handoff record says, a launched lane naming the root its launch marker binds as the worktree, and the instruction names the state directory the read found, so a record written as told ends both refusals. The instruction opens with the `workflow-state init ` that `set` needs where the item has no state file yet, so it is enough on its own. It repeats at every turn end, `stop_hook_active` included, until the item's workflow state carries a `.handoff` object no relaunch has resumed; only the lane can write that record, so a single refusal it declines to act on would end the session with nothing recorded. That record is judged before every mark, before every read they rest on and before `orch-env` and `lanes` are looked for, so no failure but the record's own writer can hold a lane that has already done what it was asked. `orch-env` or `lanes` missing from this hook's install, a mark setting that is not a whole number in range, and a transcript the payload names and nothing can read are refusals too, each on the lane path alone and each carrying the same instruction. What the marks cannot judge is reported and passed, never refused: a payload naming no transcript leaves the context unread, and so does a transcript whose last usage line is an object carrying none of the field names its adapter reads, which is reported under `usage-unread=` rather than summed to a figure of zero and read as room, a reading below the independent token limit whose capacity the adapter could not name, reported under `window-unread=`, and an install directory naming no harness, reported under `harness-unlisted=`; a reading that could not be recorded is reported under `context-unrecorded=` and still judged; an account `lanes` keeps no inventory for, one it could not measure and a read that passed this hook's own ceiling each leave the account unjudged under `account=unlisted`, `account=unmeasured` or `account=timeout`, never read as room, so a setup with no usage endpoint still ends its turns; and a lane whose handoff record cannot be judged leaves both marks unjudged under one of four keys, `handoff-skipped=` for a reader or a script this install has not got, or `handoff-skipped=unlocatable` where this hook's own directory could not be resolved and none of them could be looked for, `handoff-outside=` for one only the open repository supplies, `handoff-unanswered=` for one that is there and answered nothing this hook can read, and `handoff-unreadable=` for a state file the install's own `workflow-state` could not read. Passing the turn is the answer for all four. For the first three it is because an install whose orch scripts cannot answer cannot run `workflow-state set` either, so a lane told to record a handoff with them could never end a turn again; for `handoff-unreadable` the install answers and the fault is the item's own state file, which is the file the record would be written into, so that write could not land either and the refusal would be as uncloseable. A subagent's turn end is judged on neither mark. The fleet's OVERSEER meets four triggers of its own on its turn end: a session with no lane of its own whose tmux server and pane are the pair the oversee workflow state records under `.overseer` is that overseer, and nothing weaker establishes one, so an ordinary session in a fleet checkout is judged on nothing. A session whose native identity matches a nonempty binding in the fleet record but whose pane only the overseer's `context.json` names, the overseer the record lost, is judged on nothing either, and reports `pane-unrecorded=` with the recorded key under it and writes that record with no reading and the gap `pane-unrecorded`; any other session the record does not name writes nothing, so the real overseer's reading stands. A fleet record naming this session's pane that lacks its server start, its harness, its launch home or its native session id is healed from an authorized native session first, at a turn end and at a tool call alike: the start of this session's own tmux server, the harness this install names and the launch home the harness variable of this session's own environment carries, `CLAUDE_CONFIG_DIR`, `CODEX_HOME` or `COPILOT_HOME` or that harness's default where it is unset, are written into it through the orch `lib/overseer-launch.sh` `ol_record_heal`, which writes only a fact the record lacks, and the transcript is bound to that home on the same run; a write that fails is reported under `record-unhealed=` with the writer's words, and the caller remains unbound until a later binding write succeeds. Before it reads that transcript for the overseer it binds it to the current session: the `transcript_path` the payload names is read only where it is this session's own native file, held to the `session_id` the payload carries and the launch home the fleet record names under `.overseer.home`, through the orch adapter for a claude, codex or copilot install; a Pi install states no transcript shape and reads the payload's own window as a Pi lane does. If `lane_context_transcript_owned` refuses an admitted overseer's transcript binding, the hook reports `transcript-unowned=` with the reason the library returns. Nothing is read then, and the context record is written with a null token count and that reason as its `gap` (orch `workflow-state.md`, `context.json` row), so it still advances at every turn end and oversee-watch reports the gap, and the judge is handed this install's harness and no context figure, so it judges the account triggers alone, the `transcript-unowned` line is this hook's one report that the context went unmeasured, and a session is never judged on a file it does not own. Every overseer turn end whose orch context library loads writes that record, a reading or a null token count with a `gap` naming why none was taken: the binding library's reason, `transcript-unnamed` for a payload naming no transcript, `usage-absent` for a transcript holding no usage line, `usage-unread` for a usage object its adapter does not read, which is also reported under `usage-unread=`, `session-record` for a Copilot session with no extension reading whose statusLine session record does not answer either, which is also reported under `session-record=`, or `pane-unrecorded` below. A Copilot statusLine record reporting allow_all_enabled false, read whether or not an extension reading stands, in a session whose `COPILOT_ALLOW_ALL` is true (a launch line granting `--allow-all` or `--yolo`), is reported under `stop-cause=allow-all-blocked-by-policy`, and the turn end judged as usual. An install naming no harness an adapter reads writes no gap, since its context is never read, and leaves the record as it was, and a Copilot one names none where the reading its usage arm wrote for this session stands, its turn end reading that record rather than taking a reading of its own; a gap record that cannot be written is reported under `context-gap-unrecorded=`, the record keeping its earlier entry. This hook records the overseer's own context reading as `context.json` in the overseer mailbox directory at the main checkout, naming the session and its pane, and hands that reading to `oversee-succeed --check-marks --context :` from this hook's own install, which judges those marks on it and on no stored figure, and nothing at the turn end here judges them, under the same ceiling the account read runs under, so the turn-end refusal and the `overseer-mark` watch event cannot describe one overseer differently. Its refusal opens with the `context=`, `headroom=`, `rate=` or `qualifying=` key, carrying the figure that judgement read, and names `oversee-succeed`, handed the same reading, as the route, with `workflow-state set oversee handoff` under it for a succession that refuses, so the refusal always has an escape the overseer can reach. That record names the session that wrote it, in the native `session_id` the payload gives. A payload with no native session id is refused and cannot read mail or write overseer context or gaps. `overseer_identify` owns its native refusal diagnostics. One other refusal stands on that path, `script` for an `oversee-succeed` this install has not got, and the record clears it as it clears the marks. `ORCH_OVERSEER_SUCCESSION=off`, read off the judgement's own line and never here, turns the account-mark refusals off with the succession they name, the watch's `overseer-mark` event still reporting those marks; the context mark is refused whatever the setting, since no watch event reports it, and the handoff record ends that refusal. An answer this hook cannot act on, one the ceiling abandoned, and one whose own reading was unmeasured are reported under `marks=unjudged`, `marks=timeout` and `marks=unmeasured` and the turn ends, never held. A lane asks its overseer only through lane mail. Before a tool call in a launched lane, the halt arm refuses the harness question tool by its name, whichever of the four names the payload's `tool_name` carries, Claude Code's `AskUserQuestion` and `EnterPlanMode`, Codex's `request_user_input` and Pi's `question`, opening `lane-mail-check: question-tool=` and naming the `lane-mail ask --item --file ` send and the `lane-mail wait` on its printed id as the route, because a dialog on the pane reaches no overseer; an unread halt is refused ahead of it, a subagent's call is refused and told to report its question to the lead, and a session that is no launched lane passes the call silently, a committed mailbox and status file included. At a launched lane lead's turn end, once the handoff marks pass, the lane is judged idle on lane-mail sends and its lane status file update state, never on words in its pane, on Claude Code, Codex, Pi and Copilot; OpenCode and Cursor run no kendex hooks, and Gemini and Antigravity do not run this one, so a lane there is never judged idle. The reader's own `lane-mail events` listing, which moves no cursor, counts the asks and notices in the lane's outbound file against the count this hook recorded at the lane's last judged turn end, `sent-count` in the lane's mailbox directory: a line holding the count, the word `held` where this judge refused that turn end, and an optional encoded status file update state; no record is a count of zero with no status state. A status file update since that record, including a rewrite of the same text, passes without a notice. A count other than the recorded one is a send this turn and passes, a standing handoff record ends the run before this judge, the newest directive the overseer sent carrying `halt` passes, and a lane whose launch marker no longer binds its root, the close-out's state, is no lane. With none of these the turn is refused and the hold recorded, opening `lane-mail-check: idle=` with one continuation, the lane's `lane-mail inbox` read and then its workflow, beside the ask route and the `lane-mail notice` send, which follows the orch Coordination notice rule: changed work sends a notice, and a continuing wait on a dispatched agent or an armed wake updates the lane status file only. On a turn the harness continued for this judge's own recorded hold it refuses nothing and sends the overseer a lane notice stating what it checked, opening `lane-mail-check: idle-notice=`, or `idle-notice-unsent=` with the sender's words where the send fails, so an idle lane is reported and never looped. A turn another stop hook's refusal continued is held as a fresh one, except on Pi, whose pi-hooks carrier runs no further request after a continued turn, so there the notice is sent with no hold before it. The record counts that notice, so the lane's next turn is judged on what the lane itself sends. An `events` listing that fails, or whose envelopes jq cannot read, is reported under `events=` or `events=envelope`, and a record that is not a plain file holding a whole number, an optional `held` mark and an optional encoded status state under `idle-record=` and rewritten. A record that cannot be written is reported under `idle-unrecorded=`; under `idle-hold-unrecorded=` where it was to take a hold, which is then not made, since one with no record would be made again on every continued turn; and under `idle-notice-unrecorded=` where it was to count the notice, which the next turn end then reads as the lane's own send. Each of these ends the turn, because nothing a lane does at its turn end repairs its mailbox; an install with no reader leaves the turn unjudged under the marks' own `handoff-skipped` line. On Copilot the event is `agentStop`, registered in Copilot's own hook file under its camelCase name, so the payload spells its fields `sessionId`, `transcriptPath` and `toolArgs`, which this hook reads beside the snake_case spellings; its reference spells `stop_hook_active` so on both, and `toolName` identifies an attached launch. The `lane-mail-halt` description owns the Copilot preToolUse decision and deadline contract. Copilot also runs the hooks `.claude/settings.json` registers, under their PascalCase names, but the registration kendex writes there exits 0 before its script in a Copilot hook process, so a Copilot call reaches an install that is not Copilot's, the claude copy of this hook among them, only through a registration made there by hand or one kendex wrote before that skip and no refresh has rewritten. Whether Copilot made the call is read from the call, never from the install: a payload carrying `timestamp`, which both of Copilot's payload formats carry and no Claude, Codex or Pi payload does, or naming the session `sessionId`, is Copilot's, and any install but Copilot's own passes it silently, exit 0 with nothing written and nothing acknowledged, so the Copilot install is the one reader of the mailbox for a Copilot call. A Copilot agentStop names no agent: the stop whose `transcriptPath` sits in the directory named for the `sessionId`, Copilot's `session-state//events.jsonl`, is the lead's and records it, a stop naming a transcript under another directory is read as a subagent's, handed nothing and judged on nothing, and a payload naming no transcript, or no session, is the lead's and records nothing. Copilot CLI 1.0.88 was measured firing agentStop at a custom subagent's end too, with the subagent's own `sessionId` and the lead's `transcriptPath`, which this rule reads as a subagent's. A refusal on Copilot is the documented answer for its event, on stdout beside the keyed stderr line: at a turn end `{"decision":"block","reason":}` with exit 0, which Copilot stops honouring after 8 consecutive blocks, ending that turn unheld, so a handoff refusal holds a Copilot session for 8 continued turns and then returns at its next turn end, and after a tool call `{"additionalContext":}` with exit 0, since Copilot reads a postToolUse answer only at exit 0. A Copilot session's context is read through Copilot's own SDK event `session.usage_info`: the orch `copilot-lane-context` extension, which `open-terminal` installs in a Copilot fleet lane's `COPILOT_HOME` with the EXTENSIONS feature on, runs this hook with the argument `usage` at each reading of the session's root agent, handing it `{session_id, cwd, current_tokens, token_limit}` on stdin, and for a recorded lead session that is a launched lane's lead or the fleet's overseer, named by the same gate every arm that judges the marks asks, it records `current_tokens` as the tokens and, as the capacity, the limit Copilot compacts at: 80 percent of `token_limit`, the SDK's documented `backgroundCompactionThreshold` default, named in the record's `capacity_source`. It writes nothing on stdout; a gap is refused on stderr at exit 2, which the extension writes to the session timeline: `payload=invalid-json`, an orch install it cannot use under the key its turn end reports that gap under, `handoff-skipped=`, `handoff-outside=` or `handoff-unanswered=`, or `context-unrecorded=` for a reading that could not be written, where the session's earlier reading is removed too so its turn end reports the context unmeasured rather than judging an older figure as room. Any other session passes silently. The Copilot turn end judges this session's record under the shared context rule exactly as it judges a transcript reading, the capacity putting the handoff before Copilot's own compaction; no reading of this session, no record or a gap record, is read from the fallback below; where the pending marker the extension leaves at `~/.cache/lane-mail/copilot-usage/` for a reading it handed on and no run has recorded yet still stands after a wait of 5 seconds, the turn end reports `reading-pending=` and passes with the context unmeasured, reading no fallback, since the extension runs for that session, and never judging the earlier record as room, since nothing orders the extension's run before the turn end; and a record that stands and cannot be read is refused under `record=`. Where no pending marker stands and no reading of the extension's stands for this session, no record, one naming another session, a gap record or one the fallback below wrote, which its `capacity_source` tells apart, the turn end reads the fallback: the session record the orch `copilot-statusline` command writes as the account's `statusLine`, under `/lane-status/.json`, through the orch adapter for copilot, which holds the record to the payload's `sessionId`, its `transcriptPath` where one is named, the account directory and a freshness bound, and hands the shared judge the same compaction point of the window as the capacity; that reading is judged and recorded as any other harness's, and a record that does not answer leaves the context unmeasured under `reading-unrecorded=` and `session-record=`, reported and passed, never read as room. An extension reading below the mark is never overridden by a statusLine record past it. Run with `compact` by the lane-mail-compact hook at a preCompact whose `trigger` is `auto`, from a recorded lead session that gate names, it flags that compaction as `compaction.json` beside the reading, the backstop for a turn that crossed into the compaction before a reading past the mark reached a turn end, and the turn end then refuses under `compacted=auto` until the handoff record stands, the overseer's whatever its succession setting; a gap there is refused under `compaction-unrecorded=` on stderr at exit 2, which Copilot shows the operator without holding the compaction. A Copilot account is judged through `lanes pick --lane` like any other. A session the Jarvis runtime launched, which carries `JARVIS_RECORD`, has its lead's tool calls, on Copilot any call under the session id the record's start bound, and on Claude Code its turn ends, stamp that runtime record's launch row once as its Start brief taken, the fact the Jarvis launch worker reads beside the pane; another harness's turn end is no stamp, since Pi's carrier also dispatches it on a run that ended on an error and Codex and Copilot have no turn-failure event to tell one apart; a stamp that cannot be written is reported under `jarvis-rows-unwritten=` and passed, and the next such call writes it. Not run on gemini: it has no Stop event. Not run on antigravity: its Stop payload carries no `stop_hook_active`. # summary: Uses orch and mailbox to hand lanes their overseer's mail and hold turn ends for handoff or idle checks, plus a `wake=unarmed` refusal for the registered overseer without its repeat follow or the Jarvis session whose `ORCH_WAKE_PROCESS` does not match, printing `ORCH_WAKE_START`; empty Jarvis session keys with no watch claim disable the check, and a running single pass is its own wake. Pi's wake check is partial; a continued turn or an unavailable check only warns. # safety: Reads the payload, the repository's branch, the lane's launch marker, read with the shell's own `read`, and the lane mailbox directory, and for a session that is no lane the checkout's overseer mailbox and, where a file stands there and the fleet record names this session's pane, the fleet state's path from the identity read, with `workflow-state path oversee` as its fallback and the watch record beside it, read by the orch watch record library `lib/watch-pid.sh` sourced in a child shell from the same install as the mailbox reader, which checks the record's pid with `kill -0` and `ps`; the writes are the mailbox cursor the orch reader advances, the session's context reading, `context.json`, and a Copilot session's compaction flag, `compaction.json`, each renamed into its mailbox directory, and on a Pi lane its turn rows, `session-rows.jsonl`, appended there under that file's own lock at a turn end and at the first tool call of each turn, and for the overseer one row appended to its rows file, `session--.jsonl` in the overseer mailbox directory, under that file's own lock, a compact Stop at every overseer turn end, the overseer's directory made where the fleet has not made it yet, the fleet record's `.overseer` server start, harness, launch home and native session id where a record naming this session's pane lacks one, through `workflow-state update oversee`, and after each overseer tool call its `context.json` and, where a gap is told, `tmp/lane-mail/overseer/context-told`, and on Copilot a lead session's empty record under `~/.cache/lane-mail/copilot-leads`, touched at its session start and at each turn end its transcript proves the lead's, with records untouched for 30 days removed by one `find` at each start, as are the extension's pending markers under `~/.cache/lane-mail/copilot-usage`, which a Copilot turn end reads and polls for 5 seconds. For a session the Jarvis runtime launched it also reads, at its lead's tool calls and Claude Code, Codex and Copilot CLI turn ends, the runtime record `JARVIS_RECORD` names, in one child shell sourcing the orch session rows library from the same install, and where that launch is starting and unstamped, reads it again under that record's `.lock` and renames a new record over it once: at a tool call or Claude Code turn end with its brief delivered, stamping its launch row's `brief_taken`; at a Codex or Copilot CLI turn end before the brief, stamping its `kickoff_ended`. Exit 2 names the unread count and the messages, and asks for them to be acted on, never bypassed. The reader it runs comes from its own install, never from the repository a session has open, so a repository that tracks a mailbox and an executable at that path cannot have it run. jq and cat read the payload; a payload it cannot read is refused on every turn, the continued one included, because the flag that marks a continued turn is in the payload none of those refusals reached. A mailbox whose reader is missing or fails is refused on the turns the mailbox check runs, which is every turn end but a continued one; on a continued turn that check is skipped whole, and the same missing reader is reported under `handoff-skipped` or `handoff-outside` and the turn is passed. An item name outside the alphabet a work item is spelled in, a branch that matches more than one mailbox, and a repository state git cannot report where a mailbox sits under the working directory are refused on a fresh turn and reported on a continued one and before a tool call, by the one rule the description states; none of them is ever passed in silence. For a lane's handoff marks it also reads the transcript the payload names and runs `orch-env`, `lanes` and `workflow-state` and sources the orch context library from the same install as the mailbox reader, never the open repository's, and on Pi one child shell sourcing that install's `lib/lane-launch.sh` to name the account the session's provider bills; the context reading is the one thing it writes for them. A session that names no lane costs two file tests of the checkout's overseer mailbox; where a file stands there it adds that install's resolution and, inside tmux, the overseer test below, and for the session the record names the identity read's fleet path, one child shell sourcing the watch record library, and the reader's peek where no live watch stands. Outside tmux it costs nothing more, where the overseer test stops at its first condition. After a tool call a lead session with no lane of its own, in tmux, in a checkout with no `tmp/lane-mail/overseer` directory costs one stat more; where that directory stands it pays the overseer test below, and for the overseer one transcript read, one `workflow-state handoff-standing`, one `orch-env` read and one record write, the reads the turn end makes but for the account judgement; the overseer test runs once per call, and the mailbox check takes its answer. Inside tmux the overseer test resolves that install and reads the caller's pane key, the fleet record and the server start in a child shell loading the orch context and overseer launch libraries and their dependencies. A required heal loads `lib/overseer-launch.sh` and its dependencies in a child shell and rechecks the recorded native identity before the state update; a session whose native identity matches a nonempty recorded binding but whose pane the state does not name adds one child shell loading the orch context library, one `git-context` call and one read of the overseer's `context.json`; where that record names this session's pane, it reports `pane-unrecorded` and rewrites that record. Any other unbound caller stops before those context reads and writes. The overseer's own marks are then judged by `oversee-succeed --check-marks` from that same install, under the same 20 second ceiling the lane's account read runs under. That judgement measures the one account the overseer session runs on, through the same `lanes pick --lane` this hook asks about a lane, renewing an expired token in that account's credential file and refreshing that account's usage cache, the writes `lanes` states in its own contract; it opens no window and launches nothing. The context-usage reader first parses the last 1 MiB, and reads the whole file only when that window carries no usage line. When native Claude Stop background_tasks is absent, the transcript roster fallback reads complete ordered history; its work grows with transcript size. It runs only under the remaining hook deadline, with three seconds reserved for refusal emission and a one-second kill grace. An unavailable bound, exhausted budget, timeout or failed parse reports agents=unknown and discards partial rows. `lanes pick --lane` judges a Claude lane on its own model, measures one account and renews that account's expired token, the write its own contract states; it can wait on a credentials lock and two network calls, and on a cache miss on the host-wide usage refresh lock for up to 10 seconds and, after a 429 with nothing cached, one sleep of up to 5 seconds and one more usage request, so it runs under a 20 second ceiling that leaves the rest of the run inside this hook's 30 second budget, and a read that reaches the ceiling is reported as a gap rather than refused. Where `timeout` is not installed that read runs unbounded, and a hook the harness then kills at its budget leaves the account unjudged, the same outcome the reported gap gives without the line. Before a tool call it reads `tool_name` or Copilot `toolName`; the question-tool rule and attached-launch check consume that normalized name. For the idle judge at a lane lead's turn end it runs the reader's `events` listing, which moves no cursor, and reads the kind, the box and the halt flag of each envelope, never its text and never the transcript; it reads stat metadata for the fixed regular `tmp/lane-status-.md` file under the lane's launch root, with no symbolic link at the status file itself, and writes that update state beside the count in the lane's `sent-count` record, renamed into its mailbox directory, and the one idle notice the description names, through the reader's `notice`. Every refusal opens with `lane-mail-check: =`; what a command this hook runs writes is captured at the site and replayed under that line, so nothing precedes the key. For a launched lane or the bound fleet overseer, PostModelSwitch reads its to_model target and the recorded launch identity. It writes model checks and switch history through workflow-state. A lane replacement that reaches its first Stop without a mismatch writes one model-recovery-reset row and a passed model check in the same fleet state. Lane recovery preserves the standing handoff and checks the recorded arguments before stopping the verified predecessor through the existing lane stop owner. Account selection and launch follow that stop. Overseer recovery passes a durable handoff to oversee-succeed. That owner preserves the executable model selector and account, verifies the successor, then stops its predecessor. Unreadable PostModelSwitch dependencies reach the model as once-only unavailable context. A failed first-turn reset reports a keyed Stop warning on stderr and leaves later checks active. # timeout: 30 @@ -50,7 +50,7 @@ UNREAD="" HALT_TEXT="" ACK_COMMAND="" MAILBOX_COMMAND="" -# The handoff marks: the two settings judged and the commands that end the +# The handoff marks: the settings judged and the commands that end the # refusal, and the window the context mark is judged against. Empty until each # is known. MARK="" @@ -218,6 +218,8 @@ message() { # KEY VALUE [CAUSE] { if [ "$1" = headroom ] && [ "$ROLE" = lane ]; then printf 'lane-mail-check: headroom=%s bucket=%s mark=%s\n' "$2" "$BINDING_BUCKET" "$PCT" + elif [ "$1" = seat-reserve ]; then + printf 'lane-mail-check: seat-reserve=%s bucket=%s reserve=%s\n' "$2" "$BINDING_BUCKET" "$PCT" else printf 'lane-mail-check: %s=%s\n' "$1" "$2" fi @@ -456,6 +458,10 @@ message() { # KEY VALUE [CAUSE] "$BINDING_BUCKET" "$2" "$PCT" "$HANDOFF_INSTRUCTION" fi ;; + seat-reserve=*) + printf 'The account picker requires handoff from this overseer seat. The binding bucket %s has %s percent headroom left. ORCH_OVERSEER_SEAT_RESERVE_PCT is %s. No handoff record stands. Hand this lane off at the next safe point.\n%s\n' \ + "$BINDING_BUCKET" "$2" "$PCT" "$HANDOFF_INSTRUCTION" + ;; rate=*) printf 'oversee-succeed projects that this overseer account will reach its wall in %s minutes, at or before the ORCH_OVERSEER_WALL_MINUTES mark of %s. Succeed this session yourself before the account walls.\n%s\n' \ "$2" "$MARK" "$HANDOFF_INSTRUCTION" @@ -3427,10 +3433,10 @@ handoff_check() { fi # The account the credential THIS session runs on still has, judged by the - # one script that measures a lane and against the one setting that marks a - # lane for handoff. `pick --lane` answers about that directory alone: 0 has - # room, 3 is at or below the mark, and 4 is a directory that is no configured - # lane of this harness. Every other exit, and a read that passes the ceiling, + # one script that measures a lane and judges its handoff marks. + # `pick --lane` answers about that directory alone: 0 has room, 3 reaches + # the headroom mark or overseer seat reserve, and 4 is a directory that is + # no configured lane of this harness. Every other exit, and a read that passes the ceiling, # is an account nothing measured: reported and passed, never read as room and # never held, because a setup with no usage endpoint must still end its turns. # `lanes` keeps an inventory for claude, codex and copilot, and a Pi lane is @@ -3465,9 +3471,9 @@ handoff_check() { ${PICK_MODEL[@]+"${PICK_MODEL[@]}"} --min-headroom-pct "$PCT" --json 2>"$WORK_DIR/lanes.err") || PICK_RC=$? # `lanes` keeps a status-only contract where `workflow-state handoff-standing` # could not, and one reservation is what makes that safe here: every status - # with an arm of its own below — 3 for a lane at its mark, 4 for one this - # harness keeps no inventory for, 124 for a read the ceiling abandoned — is - # one no death before the verb can produce. `lanes` loads the same + # with an arm of its own below (3 for a lane at its mark or seat reserve, + # 4 for one this harness keeps no inventory for, 124 for a read the ceiling + # abandoned) is one no death before the verb can produce. `lanes` loads the same # `.env.local` through the same loader, and a file bash 3.2 cannot parse # kills it with 1 or 2; both fall to `*` and are reported as an account # nothing measured, which is as true of a script that died in its loader as @@ -3479,10 +3485,22 @@ handoff_check() { 3) # pick's wall is the binding bucket's used percent, including a scoped # model window. Account-wide headroom can still show room at that wall. - BINDING=$(jq -r '[.binding_bucket // "unknown", + # Only seat-reserve keeps its verdict in pick's public record; the + # ordinary wall omits it. Exit 3 alone cannot name the reached mark. + BINDING=$(jq -r '[.verdict // "walled", .binding_bucket // "unknown", (if .wall == null then "unknown" else 100 - .wall end)] | @tsv' <<<"$PICK" 2>/dev/null) || - BINDING=$'unknown\tunknown' - IFS=$'\t' read -r BINDING_BUCKET HEADROOM <<<"$BINDING" + BINDING=$'unknown\tunknown\tunknown' + IFS=$'\t' read -r PICK_VERDICT BINDING_BUCKET HEADROOM <<<"$BINDING" + case "$PICK_VERDICT" in + seat-reserve) + PCT=$("$SCRIPTS/orch-env" ORCH_OVERSEER_SEAT_RESERVE_PCT 50 2>"$WORK_DIR/env.err") || + refuse_handoff setting ORCH_OVERSEER_SEAT_RESERVE_PCT "$(cat -- "$WORK_DIR/env.err")" + percent_in_range "$PCT" || refuse_handoff setting-range "ORCH_OVERSEER_SEAT_RESERVE_PCT=$PCT" + refuse_handoff seat-reserve "$HEADROOM" + ;; + walled) ;; + *) message account unmeasured "lanes pick returned an unreadable refusal record"; return 0 ;; + esac refuse_handoff headroom "$HEADROOM" ;; 4) message account unlisted "$(cat -- "$WORK_DIR/lanes.err")" ;;