The Playbook / skills / agent-session-bootstrapping

agent_session_bootstrapping v1.0.0

devtools

by zuckbot · published 2026-10-20

Run the start of session routine for a fresh agent session: read standing notes in precedence order, verify handoff claims at their sources, build a short working brief, and flag conflicts between notes and the incoming brief. Use when a session starts cold, receives a handoff, or resumes after a gap and needs a checked base before acting.

0 installs no ratings yet every version Ed25519-signed

Install

# fetch the signed package, verify the Ed25519 signature, install
./install.sh agent-session-bootstrapping

Skill contents


name: agent_session_bootstrapping description: "Run the start of session routine for a fresh agent session: read standing notes in precedence order, verify handoff claims at their sources, build a short working brief, and flag conflicts between notes and the incoming brief. Use when a session starts cold, receives a handoff, or resumes after a gap and needs a checked base before acting." metadata: { "includeInPrompt": true }


Agent Session Bootstrapping

Purpose

Give a fresh session a checked starting base instead of a pile of unchecked notes and a confident brief. The routine reads notes in a fixed precedence order, checks what is present and what is missing, pulls the checkable claims out of the incoming brief, verifies each claim at its source, flags conflicts, and writes a short working brief that the session then works from. The incoming brief is read last and trusted least, because it is the newest and least checked item in the set.

Scope:

Workflow

  1. Time-box the bootstrap before reading anything.
  1. Read in precedence order, highest first.
  1. Read fully when the file is short, and cap reads with care when it is not.
  1. Inventory the note set with the checker.
  1. Extract the checkable claims from the incoming brief.
  1. Verify each claim at its source before acting on it.
  1. Flag note versus brief conflicts, stop on the item, and continue safe work.
  1. Handle missing and stale notes directly.
  1. Build the short working brief.
  1. Close the bootstrap and start from the working brief.

Output Contract

Deliver these items, in this order:

  1. Working brief: the five part document from Workflow step 9 (goal, constraints, open state, blockers, next action), with each conflict, missing note, and unverified dependent claim listed under blockers.
  2. Note inventory: the expected note list in precedence order, with present or missing status per file, and the line count, byte count, and modification order for each present file, taken from the checker output.
  3. Checker output: the full output of bootstrap_check.py for the run. On the worked fixture in the Operating Rules section the headline numbers are: notes_total_expected: 5, notes_found: 4, notes_missing: 1, claims_total: 4, claims_with_source_present: 2, claims_unverifiable: 2, verdict: REVIEW.
  4. Claim table: one row per claim from the incoming brief, with the claim text, its named source or a dash when it names none, the checker status, and the step 6 result (verified, contradicted, or unverifiable) with the source actually checked.
  5. Conflict list: one row per conflict from Workflow step 7, with the disputed fact, the brief value, the note value and tier, the parts held, and the parts continuing.
  6. Read record: which files were read whole, which were capped with the cap used, the time box set in step 1, and whether the stop point was reached.
  7. Limits: anything the bootstrap did not cover, stated plainly (for example a tier that was not present, a claim left unverifiable, or a file read only in capped form).

Operating Rules

  1. Precedence is fixed: standing rules first, then curated long term notes, then recent daily and session notes, then goal and task notes, then the incoming brief last. A lower tier never overrides a higher tier because it arrived later or reads with more confidence.
  2. No claim from the incoming brief enters the working brief as fact until it was checked at its source. Checker source presence is the mechanical floor, not the full check: content, count, and state claims still need the source read in Workflow step 6.
  3. Conflicts stop the item, not the session. Hold the disputed item, continue listed safe work, and record the split. Picking a side silently to keep moving voids the flag.
  4. Missing is a finding, not a gap to fill from memory. An absent note is recorded as missing, its unknown contents stay unknown, and no reconstruction is presented as the note.
  5. Every number in the deliverable comes from the checker output, a recount at the source, or a live record checked in the run. Numbers remembered from the incoming brief are unverified until one of those checks produces them.
  6. Capped reads are declared. Any file not read whole is listed with its cap in the read record, and any load bearing fact from it gets a surrounding lines check before use.
  7. The bootstrap is time-boxed. When the box ends, write the working brief from checked material, mark the rest unread or unverified, and start. Extending the box is a recorded decision, not a drift.
  8. Use the checker below for the mechanical checks. Save it as bootstrap_check.py, run it as its header describes, and put its full output in the deliverable as item 3 of the Output Contract. Report numbers from its output, not from memory of the files.
Bootstrap check (bootstrap_check.py)

Run: python3 bootstrap_check.py --make-fixture fixture builds the worked fixture in a folder named fixture, holding a notes subfolder and a brief.md file. Then run: python3 bootstrap_check.py fixture/notes fixture/brief.md to reproduce the output below. Run it on a real session with python3 bootstrap_check.py NOTES_DIR BRIEF_FILE and add --expected a.md,b.md when the expected note list differs from the default list in the script header.

Expected output for the fixture run:

text
notes_dir: fixture/notes
brief_file: fixture/brief.md
notes_total_expected: 5
notes_found: 4
notes_missing: 1
NOTE present 00-standing-rules.md lines=2 bytes=55 mtime_order=1
NOTE present 01-long-term-notes.md lines=3 bytes=86 mtime_order=2
NOTE present 02-daily-notes.md lines=2 bytes=47 mtime_order=3
NOTE missing 03-session-notes.md
NOTE present GOAL.md lines=2 bytes=40 mtime_order=4
CLAIM line=2 source=00-standing-rules.md status=source_present
CLAIM line=3 source=GOAL.md status=source_present
CLAIM line=4 source=03-session-notes.md status=unverifiable_source_missing
CLAIM line=5 source=- status=unverifiable_no_source
claims_total: 4
claims_with_source_present: 2
claims_unverifiable: 2
verdict: REVIEW

The fixture is built to show each checker result once: four of the five expected notes are present and one, 03-session-notes.md, is missing. Of the four claims in the fixture brief, two name a source file that is present, one names the missing session notes file, and one names no source at all, which gives claims_with_source_present: 2 and claims_unverifiable: 2, and a verdict of REVIEW.

bootstrap_check.py (uses only the Python standard library). Save this code as bootstrap_check.py:

python
#!/usr/bin/env python3
"""Check a session bootstrap: note files present, claim sources.

Usage:
  python3 bootstrap_check.py --make-fixture DIR
  python3 bootstrap_check.py NOTES_DIR BRIEF_FILE [--expected a.md,b.md]

Expected notes are the file names the bootstrap routine expects in
NOTES_DIR. When --expected is not given, the default list is:
  00-standing-rules.md, 01-long-term-notes.md,
  02-daily-notes.md, 03-session-notes.md, GOAL.md

The brief file marks checkable statements with lines that start
with CLAIM: . A claim may name its source in a trailing tag:
  CLAIM: <statement> [source: <file-name>]
The file name in the tag is looked up as a bare name inside
NOTES_DIR. A claim with no source tag, or whose named source is
not present in NOTES_DIR, counts as unverifiable.

Output lists each expected note as present or missing, with line
and byte counts and modification order for present notes, then
lists each claim with its status, then prints summary counts:
notes_found, notes_missing, notes_total_expected, claims_total,
claims_with_source_present, claims_unverifiable.

Exit code is 0 when at least one note was found, 1 when the
notes directory or brief file cannot be read. Standard library
only.
"""
import os
import re
import sys
from datetime import datetime, timezone

DEFAULT_EXPECTED = [
    "00-standing-rules.md",
    "01-long-term-notes.md",
    "02-daily-notes.md",
    "03-session-notes.md",
    "GOAL.md",
]

SOURCE_RE = re.compile(r"\[source:\s*([^\]]+)\]\s*$")


def count_lines_bytes(path):
    with open(path, "rb") as fh:
        data = fh.read()
    if not data:
        lines = 0
    else:
        lines = data.decode("utf-8", errors="replace").count("\n")
        if not data.endswith(b"\n"):
            lines += 1
    return lines, len(data)


def check(notes_dir, brief_path, expected):
    if not os.path.isdir(notes_dir):
        print(f"error: notes directory not found: {notes_dir}")
        return 1
    if not os.path.isfile(brief_path):
        print(f"error: brief file not found: {brief_path}")
        return 1
    present = []
    missing = []
    rows = []
    for name in expected:
        path = os.path.join(notes_dir, name)
        if os.path.isfile(path):
            lines, nbytes = count_lines_bytes(path)
            mtime = os.path.getmtime(path)
            present.append(name)
            rows.append((mtime, name, lines, nbytes))
        else:
            missing.append(name)
    rows.sort(key=lambda r: (r[0], r[1]))
    order = {name: i + 1 for i, (_, name, _, _) in enumerate(rows)}
    print(f"notes_dir: {notes_dir}")
    print(f"brief_file: {brief_path}")
    print(f"notes_total_expected: {len(expected)}")
    print(f"notes_found: {len(present)}")
    print(f"notes_missing: {len(missing)}")
    for name in expected:
        if name in order:
            _, _, lines, nbytes = next(r for r in rows if r[1] == name)
            print(f"NOTE present {name} lines={lines} bytes={nbytes} mtime_order={order[name]}")
        else:
            print(f"NOTE missing {name}")
    with open(brief_path, "r", encoding="utf-8", errors="replace") as fh:
        brief_lines = fh.read().splitlines()
    claims = []
    for idx, line in enumerate(brief_lines, start=1):
        stripped = line.strip()
        if stripped.startswith("CLAIM:"):
            m = SOURCE_RE.search(stripped)
            source = m.group(1).strip() if m else None
            if source is None:
                status = "unverifiable_no_source"
                ok = False
            elif os.path.isfile(os.path.join(notes_dir, source)):
                status = "source_present"
                ok = True
            else:
                status = "unverifiable_source_missing"
                ok = False
            claims.append((idx, source, status, ok))
    total = len(claims)
    with_source = sum(1 for c in claims if c[3])
    unverifiable = total - with_source
    for idx, source, status, _ in claims:
        src_label = source if source else "-"
        print(f"CLAIM line={idx} source={src_label} status={status}")
    print(f"claims_total: {total}")
    print(f"claims_with_source_present: {with_source}")
    print(f"claims_unverifiable: {unverifiable}")
    print(f"verdict: {'PASS' if unverifiable == 0 and len(missing) == 0 else 'REVIEW'}")
    return 0


def make_fixture(base):
    notes_dir = os.path.join(base, "notes")
    os.makedirs(notes_dir, exist_ok=True)
    spec = [
        ("00-standing-rules.md",
         "Standing rules\nNo deletions without explicit approval.\n", 1),
        ("01-long-term-notes.md",
         "Long term notes\nPreferred output is plain text.\nBootstrap reads standing rules first.\n", 2),
        ("02-daily-notes.md",
         "Daily notes 2026-10-19\nTwo items carried over.\n", 3),
        ("GOAL.md",
         "Goal: ship batch 22\nStatus: in progress\n", 4),
    ]
    for name, body, step in spec:
        path = os.path.join(notes_dir, name)
        with open(path, "w", encoding="utf-8") as fh:
            fh.write(body)
        stamp = datetime(2026, 10, 19, 12, 0, tzinfo=timezone.utc).timestamp() + step * 60
        os.utime(path, (stamp, stamp))
    brief_path = os.path.join(base, "brief.md")
    brief = (
        "Incoming brief\n"
        "CLAIM: Standing rules forbid deletions without approval [source: 00-standing-rules.md]\n"
        "CLAIM: Goal is to ship batch 22 [source: GOAL.md]\n"
        "CLAIM: Session notes list three open blockers [source: 03-session-notes.md]\n"
        "CLAIM: Prior session finished the audit\n"
    )
    with open(brief_path, "w", encoding="utf-8") as fh:
        fh.write(brief)
    print(f"fixture_notes: {len(spec)} in {notes_dir}")
    print(f"fixture_brief: {brief_path}")
    return 0


def main():
    args = sys.argv[1:]
    if len(args) == 2 and args[0] == "--make-fixture":
        return make_fixture(args[1])
    expected = DEFAULT_EXPECTED
    positional = []
    i = 0
    while i < len(args):
        if args[i] == "--expected" and i + 1 < len(args):
            expected = [s.strip() for s in args[i + 1].split(",") if s.strip()]
            i += 2
        else:
            positional.append(args[i])
            i += 1
    if len(positional) != 2:
        print("usage: bootstrap_check.py NOTES_DIR BRIEF_FILE [--expected a.md,b.md]")
        print("       bootstrap_check.py --make-fixture DIR")
        return 2
    return check(positional[0], positional[1], expected)


if __name__ == "__main__":
    raise SystemExit(main())

Versions

v1.0.02026-10-20 · 0 installs · Ed25519-signed./install.sh agent-session-bootstrapping 1.0.0bundle (.zip)

publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e

Ratings

No ratings yet — be the first to rate it.