- autoplan: Auto-review pipeline — reads the full CEO, design, eng, and DX review skills from disk
and runs them sequentially with auto-decisions using 6 decision principles. Surfaces
taste decisions (close approaches, borderline scope, codex disagreements) at a final
approval gate. One command, fully reviewed plan out.
Use when asked to "auto review", "autoplan", "run all reviews", "review this plan
automatically", or "make the decisions for me".
Proactively suggest when the user has a plan file and wants to run the full review
gauntlet without answering 15-30 intermediate questions. (gstack)
- benchmark: Performance regression detection using the browse daemon. Establishes
baselines for page load times, Core Web Vitals, and resource sizes.
Compares before/after on every PR. Tracks performance trends over time.
Use when: "performance", "benchmark", "page speed", "lighthouse", "web vitals",
"bundle size", "load time". (gstack)
- browse: Fast headless browser for QA testing and site dogfooding. Navigate any URL, interact with
elements, verify page state, diff before/after actions, take annotated screenshots, check
responsive layouts, test forms and uploads, handle dialogs, and assert element states.
~100ms per command. Use when you need to test a feature, verify a deployment, dogfood a
user flow, or file a bug with evidence. Use when asked to "open in browser", "test the
site", "take a screenshot", or "dogfood this". (gstack)
- canary: Post-deploy canary monitoring. Watches the live app for console errors,
performance regressions, and page failures using the browse daemon. Takes
periodic screenshots, compares against pre-deploy baselines, and alerts
on anomalies. Use when: "monitor deploy", "canary", "post-deploy check",
"watch production", "verify deploy". (gstack)
- careful: Safety guardrails for destructive commands. Warns before rm -rf, DROP TABLE,
force-push, git reset --hard, kubectl delete, and similar destructive operations.
User can override each warning. Use when touching prod, debugging live systems,
or working in a shared environment. Use when asked to "be careful", "safety mode",
"prod mode", or "careful mode". (gstack)
- caveman: Ultra-compressed communication mode. Cuts token usage ~75% by dropping filler, articles, and pleasantries while keeping full technical accuracy. Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens", "be brief", or invokes /caveman.
- ccs-delegation: Auto-activate CCS CLI delegation for deterministic tasks. Parses user input, auto-selects optimal profile (glm/kimi/custom) from ~/.ccs/config.json, enhances prompts with context, executes via `ccs {profile} -p "task"` or `ccs {profile}:continue`, and reports results. Triggers on "use ccs [task]" patterns, typo/test/refactor keywords. Excludes complex architecture, security-critical code, performance optimization, breaking changes.
- checkpoint: Save and resume working state checkpoints. Captures git state, decisions made,
and remaining work so you can pick up exactly where you left off — even across
Conductor workspace handoffs between branches.
Use when asked to "checkpoint", "save progress", "where was I", "resume",
"what was I working on", or "pick up where I left off".
Proactively suggest when a session is ending, the user is switching context,
or before a long break. (gstack)
- codex: OpenAI Codex CLI wrapper — three modes. Code review: independent diff review via
codex review with pass/fail gate. Challenge: adversarial mode that tries to break
your code. Consult: ask codex anything with session continuity for follow-ups.
The "200 IQ autistic developer" second opinion. Use when asked to "codex review",
"codex challenge", "ask codex", "second opinion", or "consult codex". (gstack)
- connect-chrome: Launch GStack Browser — AI-controlled Chromium with the sidebar extension baked in.
Opens a visible browser window where you can watch every action in real time.
The sidebar shows a live activity feed and chat. Anti-bot stealth built in.
Use when asked to "open gstack browser", "launch browser", "connect chrome",
"open chrome", "real browser", "launch chrome", "side panel", or "control my browser".
- cso: Chief Security Officer mode. Infrastructure-first security audit: secrets archaeology,
dependency supply chain, CI/CD pipeline security, LLM/AI security, skill supply chain
scanning, plus OWASP Top 10, STRIDE threat modeling, and active verification.
Two modes: daily (zero-noise, 8/10 confidence gate) and comprehensive (monthly deep
scan, 2/10 bar). Trend tracking across audit runs.
Use when: "security audit", "threat model", "pentest review", "OWASP", "CSO review". (gstack)
- design-consultation: Design consultation: understands your product, researches the landscape, proposes a
complete design system (aesthetic, typography, color, layout, spacing, motion), and
generates font+color preview pages. Creates DESIGN.md as your project's design source
of truth. For existing sites, use /plan-design-review to infer the system instead.
Use when asked to "design system", "brand guidelines", or "create DESIGN.md".
Proactively suggest when starting a new project's UI with no existing
design system or DESIGN.md. (gstack)
- design-html: Design finalization: generates production-quality Pretext-native HTML/CSS.
Works with approved mockups from /design-shotgun, CEO plans from /plan-ceo-review,
design review context from /plan-design-review, or from scratch with a user
description. Text actually reflows, heights are computed, layouts are dynamic.
30KB overhead, zero deps. Smart API routing: picks the right Pretext patterns
for each design type. Use when: "finalize this design", "turn this into HTML",
"build me a page", "implement this design", or after any planning skill.
Proactively suggest when user has approved a design or has a plan ready. (gstack)
- design-review: Designer's eye QA: finds visual inconsistency, spacing issues, hierarchy problems,
AI slop patterns, and slow interactions — then fixes them. Iteratively fixes issues
in source code, committing each fix atomically and re-verifying with before/after
screenshots. For plan-mode design review (before implementation), use /plan-design-review.
Use when asked to "audit the design", "visual QA", "check if it looks good", or "design polish".
Proactively suggest when the user mentions visual inconsistencies or
wants to polish the look of a live site. (gstack)
- design-shotgun: Design shotgun: generate multiple AI design variants, open a comparison board,
collect structured feedback, and iterate. Standalone design exploration you can
run anytime. Use when: "explore designs", "show me options", "design variants",
"visual brainstorm", or "I don't like how this looks".
Proactively suggest when the user describes a UI feature but hasn't seen
what it could look like. (gstack)
- devex-review: Live developer experience audit. Uses the browse tool to actually TEST the
developer experience: navigates docs, tries the getting started flow, times
TTHW, screenshots error messages, evaluates CLI help text. Produces a DX
scorecard with evidence. Compares against /plan-devex-review scores if they
exist (the boomerang: plan said 3 minutes, reality says 8). Use when asked to
"test the DX", "DX audit", "developer experience test", or "try the
onboarding". Proactively suggest after shipping a developer-facing feature. (gstack)
- diagnose: Disciplined diagnosis loop for hard bugs and performance regressions. Reproduce → minimise → hypothesise → instrument → fix → regression-test. Use when user says "diagnose this" / "debug this", reports a bug, says something is broken/throwing/failing, or describes a performance regression.
- document-release: Post-ship documentation update. Reads all project docs, cross-references the
diff, updates README/ARCHITECTURE/CONTRIBUTING/CLAUDE.md to match what shipped,
polishes CHANGELOG voice, cleans up TODOS, and optionally bumps VERSION. Use when
asked to "update the docs", "sync documentation", or "post-ship docs".
Proactively suggest after a PR is merged or code is shipped. (gstack)
- find-skills: Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
- freeze: Restrict file edits to a specific directory for the session. Blocks Edit and
Write outside the allowed path. Use when debugging to prevent accidentally
"fixing" unrelated code, or when you want to scope changes to one module.
Use when asked to "freeze", "restrict edits", "only edit this folder",
or "lock down edits". (gstack)
- grill-me: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
- grill-with-docs: Grilling session that challenges your plan against the existing domain model, sharpens terminology, and updates documentation (CONTEXT.md, ADRs) inline as decisions crystallise. Use when user wants to stress-test a plan against their project's language and documented decisions.
- gsd-add-tests: Generate tests for a completed phase based on UAT criteria and implementation
- gsd-ai-integration-phase: Generate an AI-SPEC.md design contract for phases that involve building AI systems.
- gsd-audit-fix: Autonomous audit-to-fix pipeline — find issues, classify, fix, test, commit
- gsd-audit-milestone: Audit milestone completion against original intent before archiving
- gsd-audit-uat: Cross-phase audit of all outstanding UAT and verification items
- gsd-autonomous: Run all remaining phases autonomously — discuss→plan→execute per phase
- gsd-capture: Capture ideas, tasks, notes, and seeds to their destination
- gsd-cleanup: Archive accumulated phase directories from completed milestones
- gsd-code-review: Review source files changed during a phase for bugs, security issues, and code quality problems
- gsd-complete-milestone: Archive completed milestone and prepare for next version
- gsd-config: Configure GSD settings — workflow toggles, advanced knobs, integrations, and model profile
- gsd-debug: Systematic debugging with persistent state across context resets
- gsd-discuss-phase: Gather phase context through adaptive questioning before planning.
- gsd-docs-update: Generate or update project documentation verified against the codebase
- gsd-eval-review: Audit an executed AI phase's evaluation coverage and produce an EVAL-REVIEW.md remediation plan.
- gsd-execute-phase: Execute all plans in a phase with wave-based parallelization
- gsd-explore: Socratic ideation and idea routing — think through ideas before committing to plans
- gsd-extract-learnings: Extract decisions, lessons, patterns, and surprises from completed phase artifacts
- gsd-fast: Execute a trivial task inline — no subagents, no planning overhead
- gsd-forensics: Post-mortem investigation for failed GSD workflows — diagnoses what went wrong.
- gsd-graphify: Build, query, and inspect the project knowledge graph in .planning/graphs/
- gsd-health: Diagnose planning directory health and optionally repair issues
- gsd-help: Show available GSD commands and usage guide
- gsd-import: Ingest external plans with conflict detection against project decisions before writing anything.
- gsd-inbox: Triage and review open GitHub issues and PRs against project templates and contribution guidelines.
- gsd-ingest-docs: Bootstrap or merge a .planning/ setup from existing ADRs, PRDs, SPECs, and docs in a repo.
- gsd-manager: Interactive command center for managing multiple phases from one terminal
- gsd-map-codebase: Analyze codebase with parallel mapper agents to produce .planning/codebase/ documents
- gsd-milestone-summary: Generate a comprehensive project summary from milestone artifacts for team onboarding and review
- gsd-mvp-phase: Plan a phase as a vertical MVP slice — user story, SPIDR splitting, then plan-phase
- gsd-new-milestone: Start a new milestone cycle — update PROJECT.md and route to requirements
- gsd-new-project: Initialize a new project with deep context gathering and PROJECT.md
- gsd-ns-context: codebase intelligence | map graphify docs learnings
- gsd-ns-ideate: exploration capture | explore sketch spike spec capture
- gsd-ns-manage: config workspace | workstreams thread update ship inbox
- gsd-ns-project: project lifecycle | milestones audits summary
- gsd-ns-review: quality gates | code review debug audit security eval ui
- gsd-ns-workflow: workflow | discuss plan execute verify phase progress
- gsd-pause-work: Create context handoff when pausing work mid-phase
- gsd-phase: CRUD for phases in ROADMAP.md — add, insert, remove, or edit phases
- gsd-plan-phase: Create detailed phase plan (PLAN.md) with verification loop
- gsd-plan-review-convergence: Cross-AI plan convergence loop — replan with review feedback until no HIGH concerns remain.
- gsd-pr-branch: Create a clean PR branch by filtering out .planning/ commits — ready for code review
- gsd-profile-user: Generate developer behavioral profile and create Claude-discoverable artifacts
- gsd-progress: Check progress, advance workflow, or dispatch freeform intent — the unified GSD situational command
- gsd-quick: Execute a quick task with GSD guarantees (atomic commits, state tracking) but skip optional agents
- gsd-resume-work: Resume work from previous session with full context restoration
- gsd-review: Request cross-AI peer review of phase plans from external AI CLIs
- gsd-review-backlog: Review and promote backlog items to active milestone
- gsd-secure-phase: Retroactively verify threat mitigations for a completed phase
- gsd-settings: Configure GSD workflow toggles and model profile
- gsd-ship: Create PR, run review, and prepare for merge after verification passes
- gsd-sketch: Sketch UI/design ideas with throwaway HTML mockups, or propose what to sketch next (frontier mode)
- gsd-spec-phase: Clarify WHAT a phase delivers with ambiguity scoring; produces a SPEC.md before discuss-phase.
- gsd-spike: Spike an idea through experiential exploration, or propose what to spike next (frontier mode)
- gsd-stats: Display project statistics — phases, plans, requirements, git metrics, and timeline
- gsd-surface: Toggle which skills are surfaced — apply a profile, list, or disable a cluster without reinstall
- gsd-thread: Manage persistent context threads for cross-session work
- gsd-ui-phase: Generate UI design contract (UI-SPEC.md) for frontend phases
- gsd-ui-review: Retroactive 6-pillar visual audit of implemented frontend code
- gsd-ultraplan-phase: [BETA] Offload plan phase to Claude Code's ultraplan cloud; review in browser and import back.
- gsd-undo: Safe git revert. Roll back phase or plan commits using the phase manifest with dependency checks.
- gsd-update: Update GSD to latest version with changelog display
- gsd-validate-phase: Retroactively audit and fill Nyquist validation gaps for a completed phase
- gsd-verify-work: Validate built features through conversational UAT
- gsd-workspace: Manage GSD workspaces — create, list, or remove isolated workspace environments
- gsd-workstreams: Manage parallel workstreams — list, create, switch, status, progress, complete, and resume
- gstack: Fast headless browser for QA testing and site dogfooding. Navigate pages, interact with
elements, verify state, diff before/after, take annotated screenshots, test responsive
layouts, forms, uploads, dialogs, and capture bug evidence. Use when asked to open or
test a site, verify a deployment, dogfood a user flow, or file a bug with screenshots. (gstack)
- gstack-upgrade: Upgrade gstack to the latest version. Detects global vs vendored install,
runs the upgrade, and shows what's new. Use when asked to "upgrade gstack",
"update gstack", or "get latest version".
- guard: Full safety mode: destructive command warnings + directory-scoped edits.
Combines /careful (warns before rm -rf, DROP TABLE, force-push, etc.) with
/freeze (blocks edits outside a specified directory). Use for maximum safety
when touching prod or debugging live systems. Use when asked to "guard mode",
"full safety", "lock it down", or "maximum safety". (gstack)
- handoff: Compact the current conversation into a handoff document for another agent to pick up.
- health: Code quality dashboard. Wraps existing project tools (type checker, linter,
test runner, dead code detector, shell linter), computes a weighted composite
0-10 score, and tracks trends over time. Use when: "health check",
"code quality", "how healthy is the codebase", "run all checks",
"quality score". (gstack)
- improve-codebase-architecture: Find deepening opportunities in a codebase, informed by the domain language in CONTEXT.md and the decisions in docs/adr/. Use when the user wants to improve architecture, find refactoring opportunities, consolidate tightly-coupled modules, or make a codebase more testable and AI-navigable.
- investigate: Systematic debugging with root cause investigation. Four phases: investigate,
analyze, hypothesize, implement. Iron Law: no fixes without root cause.
Use when asked to "debug this", "fix this bug", "why is this broken",
"investigate this error", or "root cause analysis".
Proactively invoke this skill (do NOT debug directly) when the user reports
errors, 500 errors, stack traces, unexpected behavior, "it was working
yesterday", or is troubleshooting why something stopped working. (gstack)
- land-and-deploy: Land and deploy workflow. Merges the PR, waits for CI and deploy,
verifies production health via canary checks. Takes over after /ship
creates the PR. Use when: "merge", "land", "deploy", "merge and verify",
"land it", "ship it to production". (gstack)
- learn: Manage project learnings. Review, search, prune, and export what gstack
has learned across sessions. Use when asked to "what have we learned",
"show learnings", "prune stale learnings", or "export learnings".
Proactively suggest when the user asks about past patterns or wonders
"didn't we fix this before?"
- mux-send: Send keystrokes to a psmux terminal session. Use when the user says "send to",
"type in", "send keys to", "mux send", or wants to send input to another terminal
session by name.
- office-hours: YC Office Hours — two modes. Startup mode: six forcing questions that expose
demand reality, status quo, desperate specificity, narrowest wedge, observation,
and future-fit. Builder mode: design thinking brainstorming for side projects,
hackathons, learning, and open source. Saves a design doc.
Use when asked to "brainstorm this", "I have an idea", "help me think through
this", "office hours", or "is this worth building".
Proactively invoke this skill (do NOT answer directly) when the user describes
a new product idea, asks whether something is worth building, wants to think
through design decisions for something that doesn't exist yet, or is exploring
a concept before any code is written.
Use before /plan-ceo-review or /plan-eng-review. (gstack)
- open-gstack-browser: Launch GStack Browser — AI-controlled Chromium with the sidebar extension baked in.
Opens a visible browser window where you can watch every action in real time.
The sidebar shows a live activity feed and chat. Anti-bot stealth built in.
Use when asked to "open gstack browser", "launch browser", "connect chrome",
"open chrome", "real browser", "launch chrome", "side panel", or "control my browser".
- pair-agent: Pair a remote AI agent with your browser. One command generates a setup key and
prints instructions the other agent can follow to connect. Works with OpenClaw,
Hermes, Codex, Cursor, or any agent that can make HTTP requests. The remote agent
gets its own tab with scoped access (read+write by default, admin on request).
Use when asked to "pair agent", "connect agent", "share browser", "remote browser",
"let another agent use my browser", or "give browser access". (gstack)
- plan-ceo-review: CEO/founder-mode plan review. Rethink the problem, find the 10-star product,
challenge premises, expand scope when it creates a better product. Four modes:
SCOPE EXPANSION (dream big), SELECTIVE EXPANSION (hold scope + cherry-pick
expansions), HOLD SCOPE (maximum rigor), SCOPE REDUCTION (strip to essentials).
Use when asked to "think bigger", "expand scope", "strategy review", "rethink this",
or "is this ambitious enough".
Proactively suggest when the user is questioning scope or ambition of a plan,
or when the plan feels like it could be thinking bigger. (gstack)
- plan-design-review: Designer's eye plan review — interactive, like CEO and Eng review.
Rates each design dimension 0-10, explains what would make it a 10,
then fixes the plan to get there. Works in plan mode. For live site
visual audits, use /design-review. Use when asked to "review the design plan"
or "design critique".
Proactively suggest when the user has a plan with UI/UX components that
should be reviewed before implementation. (gstack)
- plan-devex-review: Interactive developer experience plan review. Explores developer personas,
benchmarks against competitors, designs magical moments, and traces friction
points before scoring. Three modes: DX EXPANSION (competitive advantage),
DX POLISH (bulletproof every touchpoint), DX TRIAGE (critical gaps only).
Use when asked to "DX review", "developer experience audit", "devex review",
or "API design review".
Proactively suggest when the user has a plan for developer-facing products
(APIs, CLIs, SDKs, libraries, platforms, docs). (gstack)
- plan-eng-review: Eng manager-mode plan review. Lock in the execution plan — architecture,
data flow, diagrams, edge cases, test coverage, performance. Walks through
issues interactively with opinionated recommendations. Use when asked to
"review the architecture", "engineering review", or "lock in the plan".
Proactively suggest when the user has a plan or design doc and is about to
start coding — to catch architecture issues before implementation. (gstack)
- propose-issue: Challenge an issue statement before fixing it. Probes scope, root cause, and assumptions
through interactive questioning grounded in the codebase. Use when the user says "propose issue",
"challenge this bug", "question this fix", "is this the right problem", or wants to pressure-test
a problem statement before jumping to implementation.
- qa: Systematically QA test a web application and fix bugs found. Runs QA testing,
then iteratively fixes bugs in source code, committing each fix atomically and
re-verifying. Use when asked to "qa", "QA", "test this site", "find bugs",
"test and fix", or "fix what's broken".
Proactively suggest when the user says a feature is ready for testing
or asks "does this work?". Three tiers: Quick (critical/high only),
Standard (+ medium), Exhaustive (+ cosmetic). Produces before/after health scores,
fix evidence, and a ship-readiness summary. For report-only mode, use /qa-only. (gstack)
- qa-only: Report-only QA testing. Systematically tests a web application and produces a
structured report with health score, screenshots, and repro steps — but never
fixes anything. Use when asked to "just report bugs", "qa report only", or
"test but don't fix". For the full test-fix-verify loop, use /qa instead.
Proactively suggest when the user wants a bug report without any code changes. (gstack)
- retro: Weekly engineering retrospective. Analyzes commit history, work patterns,
and code quality metrics with persistent history and trend tracking.
Team-aware: breaks down per-person contributions with praise and growth areas.
Use when asked to "weekly retro", "what did we ship", or "engineering retrospective".
Proactively suggest at the end of a work week or sprint. (gstack)
- review: Pre-landing PR review. Analyzes diff against the base branch for SQL safety, LLM trust
boundary violations, conditional side effects, and other structural issues. Use when
asked to "review this PR", "code review", "pre-landing review", or "check my diff".
Proactively suggest when the user is about to merge or land code changes. (gstack)
- screenshot-capture: Capture, process, and analyze screenshots of any running application on Windows 10/11. Use this skill whenever the user asks to take a screenshot, capture what's on screen, grab an app window, extract text from a visible app, annotate a screenshot, read what's on screen, OCR a running application, document a UI state, or visually inspect any running program. Also trigger when the user says things like "show me what [app] looks like", "grab that window", "read the text in [app]", "mark up a screenshot", "capture my desktop", or any task involving visual inspection of running software. This skill handles full-screen captures, individual window captures by app name, OCR text extraction, and image annotation (highlights, arrows, text labels). Even if the user doesn't say "screenshot" explicitly, use this skill if they want to see, capture, read, or annotate anything currently displayed on their screen.
- self-clear: Clear the calling agent's own Claude Code context with /clear, then re-seed it with a user note so it wakes and resumes work after the wipe. Use when the user says "self-clear", "/self-clear", "clear myself", "clear and continue", or "reset my context and keep going".
- setup-browser-cookies: Import cookies from your real Chromium browser into the headless browse session.
Opens an interactive picker UI where you select which cookie domains to import.
Use before QA testing authenticated pages. Use when asked to "import cookies",
"login to the site", or "authenticate the browser". (gstack)
- setup-deploy: Configure deployment settings for /land-and-deploy. Detects your deploy
platform (Fly.io, Render, Vercel, Netlify, Heroku, GitHub Actions, custom),
production URL, health check endpoints, and deploy status commands. Writes
the configuration to CLAUDE.md so all future deploys are automatic.
Use when: "setup deploy", "configure deployment", "set up land-and-deploy",
"how do I deploy with gstack", "add deploy config".
- ship: Ship workflow: detect + merge base branch, run tests, review diff, bump VERSION,
update CHANGELOG, commit, push, create PR. Use when asked to "ship", "deploy",
"push to main", "create a PR", "merge and push", or "get it deployed".
Proactively invoke this skill (do NOT push/PR directly) when the user says code
is ready, asks about deploying, wants to push code up, or asks to create a PR. (gstack)
- to-prd: Turn the current conversation context into a PRD and publish it to the project issue tracker. Use when user wants to create a PRD from the current context.
- trace: Find old conversations in Claude Code session history. Use when the user says
"find the conversation where", "when did we discuss", "trace back to", or wants
to locate a past session by topic, command, commit, or keyword.
- traceable-reqs: traceable-reqs
- unfreeze: Clear the freeze boundary set by /freeze, allowing edits to all directories
again. Use when you want to widen edit scope without ending the session.
Use when asked to "unfreeze", "unlock edits", "remove freeze", or
"allow all edits". (gstack)
- win-marketplace-add: Add a plugin marketplace on Windows, bypassing the EBUSY rename bug. Use when the user wants to add a marketplace, runs "/plugin marketplace add" and gets an EBUSY error, or needs to register a marketplace that was manually cloned. Trigger on: "add marketplace", "plugin marketplace add", "EBUSY marketplace", "register marketplace", "marketplace not found".
- write-a-skill: Create new agent skills with proper structure, progressive disclosure, and bundled resources. Use when user wants to create, write, or build a new skill.
- ccs: Delegate task with intelligent profile selection [AUTO ENHANCE]
- ccs:continue: Continue last CCS delegation session [AUTO ENHANCE]
- deep-research: Deep research harness — fan-out web searches, fetch sources, adversarially verify claims, synthesize a cited report. - When the user wants a deep, multi-source, fact-checked research report on any topic. BEFORE invoking, check if the question is specific enough to research directly — if underspecified (e.g., "what car to buy" without budget/use-case/region), ask 2-3 clarifying questions to narrow scope. Then pass the refined question as args, weaving the answers in.
- frontend-design:frontend-design: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
- spt:clear-psyche: Clear stored Psyche context. Use when the user says "clear psyche",
"reset psyche context", or wants to wipe a Psyche's saved state.
- spt:commune: Send a communal update to your Psyche. Use when the user says "commune",
"update psyche", or wants to sync context with their Psyche companion.
- spt:force-stop: Force-stop an SPT agent -- ready agent or live agent (with its
Psyche). Use when the user says "stop listening", "stop owl", "kill live
agent", "force stop", "tear down perch", or "immediately terminate".
Session-aware: a live session (or a target with `live:true` in info.json)
routes through `$LIVE stop` (3-step kill including Psyche teardown); a
ready agent routes through `$OWL stop`.
- spt:list-agents: Unified listing for SPT agents -- ready agents, live agents, and Psyche
processes. Use when the user says "list agents", "who's live", "who's
listening", "show psyches", "show active listeners", or wants a roster of
active perches. Session-aware: defaults to live agents in a live session,
ready agents otherwise. Pass `--psyches` to list Psyche processes
instead.
- spt:live: Run a live agent session. For past sessions, restores a summarized context.

EXPLICIT START phrases (route to /spt:live <id>):
- "live as"
- "start live"
- "go live"
- "start a live agent"

AUTO-RESUME phrases (route to /spt:live --auto, resumes most-recently-active live agent):
- continue live work
- resume live work
- continue live agent
- resume live agent
- live agent continue
- live agent resume
- live work continue
- live work resume

Does NOT route here (too ambiguous — require BOTH "live" AND ("agent" or "work")):
- "keep going"
- "resume work"
- "continue" (bare)
- spt:new-alarm: Schedule a one-shot timed alarm delivered as TIMED PULSE. Use when the user
says "remind me", "check back in", "set an alarm", "wake me when", or wants a
delayed notification.
- spt:psyche-sync-setup: Enable cross-machine Psyche context sync via a private GitHub repo
(spt-agent-storage). Drives install + auth checks for the `gh` CLI,
creates the repo via `gh repo create --private`, wires it as the
`origin` remote for every existing agent/project worktree, and
seeds the remote with `git push --all`. Idempotent — running again
when already enabled reports current status.

Use when the user says "enable cross-machine sync", "set up psyche
sync", "back up my agent context to GitHub", or runs the skill
directly via /spt:psyche-sync-setup.
- spt:ready: Enable inter-agent messaging for the current session.
Use when the user says "listen as", "ready as", or wants to receive inter-agent messages.
- spt:revive: Restart a live agent with new generation. Use when the user says "revive",
"restart live agent", or wants to refresh a live agent's session.
- spt:send: Send a message to another SPT agent. Use when the user says "send to",
"message", "tell <agent>", or wants to communicate with another agent.
- spt:signoff: Graceful live agent shutdown with final context summary. Use when the user
says "sign off", "graceful stop", or wants to cleanly end a live session.
- spt:whoami: Check which owl agent belongs to the current session. Use when the user asks
"which agent am I?", "what's my owl name?", or when you need to discover your
own perch identity.
- caveman:caveman: Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra, wenyan-lite, wenyan-full, wenyan-ultra. Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens", "be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested.
- caveman:caveman-commit: Ultra-compressed commit message generator. Cuts noise from commit messages while preserving intent and reasoning. Conventional Commits format. Subject ≤50 chars, body only when "why" isn't obvious. Use when user says "write a commit", "commit message", "generate commit", "/commit", or invokes /caveman-commit. Auto-triggers when staging changes.
- caveman:caveman-help: Quick-reference card for all caveman modes, skills, and commands. One-shot display, not a persistent mode. Trigger: /caveman-help, "caveman help", "what caveman commands", "how do I use caveman".
- caveman:caveman-review: Ultra-compressed code review comments. Cuts noise from PR feedback while preserving the actionable signal. Each comment is one line: location, problem, fix. Use when user says "review this PR", "code review", "review the diff", "/review", or invokes /caveman-review. Auto-triggers when reviewing pull requests.
- caveman:compress: Compress natural language memory files (CLAUDE.md, todos, preferences) into caveman format to save input tokens. Preserves all technical substance, code, URLs, and structure. Compressed version overwrites the original file. Human-readable backup saved as FILE.original.md. Trigger: /caveman:compress <filepath> or "compress memory file"
- everything:search: Instantly search files and folders on Windows via voidtools Everything 1.5a HTTP JSON API. Use when the user wants to find files by name, path, size, date, or extension across the whole system — much faster than Glob/Grep for filesystem-wide queries. Triggers on "find file", "where is", "locate", "search my drive", "find all .ext files", "everything search".
- update-config: Use this skill to configure the Claude Code harness via settings.json. Automated behaviors ("from now on when X", "each time X", "whenever X", "before/after X") require hooks configured in settings.json - the harness executes these, not Claude, so memory/preferences cannot fulfill them. Also use for: permissions ("allow X", "add permission", "move permission to"), env vars ("set X=Y"), hook troubleshooting, or any changes to settings.json/settings.local.json files. Examples: "allow npm commands", "add bq permission to global settings", "move permission to user settings", "set DEBUG=true", "when claude stops show X". For simple settings like theme/model, suggest the /config command.
- keybindings-help: Use when the user wants to customize keyboard shortcuts, rebind keys, add chord bindings, or modify ~/.claude/keybindings.json. Examples: "rebind ctrl+s", "add a chord shortcut", "change the submit key", "customize keybindings".
- verify: Verify that a code change actually does what it's supposed to by running the app and observing behavior. Use when asked to verify a PR, confirm a fix works, test a change manually, check that a feature works, or validate local changes before pushing.
- code-review: Review the current diff for correctness bugs and reuse/simplification/efficiency cleanups at the given effort level (low/medium: fewer, high-confidence findings; high→max: broader coverage, may include uncertain findings; ultra: deep multi-agent review in the cloud). Pass --comment to post findings as inline PR comments, or --fix to apply the findings to the working tree after the review.
- simplify: Review the changed code for reuse, simplification, efficiency, and altitude cleanups, then apply the fixes. Quality only — it does not hunt for bugs; use /code-review for that.
- fewer-permission-prompts: Scan your transcripts for common read-only Bash and MCP tool calls, then add a prioritized allowlist to project .claude/settings.json to reduce permission prompts.
- loop: Run a prompt or slash command on a recurring interval (e.g. /loop 5m /foo). Omit the interval to let the model self-pace. - When the user wants to set up a recurring task, poll for status, or run something repeatedly on an interval (e.g. "check the deploy every 5 minutes", "keep running /babysit-prs"). Do NOT invoke for one-off tasks.
- schedule: Create, update, list, or run scheduled remote agents (routines) that execute on a cron schedule. - When the user wants to schedule a recurring remote agent, set up automated tasks, create a cron job for Claude Code, or manage their scheduled agents/routines. Also use when the user wants a one-time scheduled run ("run this once at 3pm", "remind me to check X tomorrow").
- claude-api: Build, debug, and optimize Claude API / Anthropic SDK apps. Apps built with this skill should include prompt caching. Also handles migrating existing Claude API code between Claude model versions (4.5 → 4.6, 4.6 → 4.7, retired-model replacements).
TRIGGER when: code imports `anthropic`/`@anthropic-ai/sdk`; user asks for the Claude API, Anthropic SDK, or Managed Agents; user adds/modifies/tunes a Claude feature (caching, thinking, compaction, tool use, batch, files, citations, memory) or model (Opus/Sonnet/Haiku) in a file; questions about prompt caching / cache hit rate in an Anthropic SDK project.
SKIP: file imports `openai`/other-provider SDK, filename like `*-openai.py`/`*-generic.py`, provider-neutral code, general programming/ML.
- run: Launch and drive this project's app to see a change working. Use when asked to run, start, or screenshot the app, or to confirm a change works in the real app (not just tests). First looks for a project skill that already covers launching the app; otherwise falls back to built-in patterns per project type (CLI, server, TUI, Electron, browser-driven, library).
- init: Initialize a new CLAUDE.md file with codebase documentation
- review: Review a pull request
- security-review: Complete a security review of the pending changes on the current branch


<owl_reachability_notice>
You have an active owl perch. When spawning subagents or doing work, use run_in_background: true so you stay reachable for incoming messages.
</owl_reachability_notice>


CAVEMAN MODE ACTIVE (full). Drop articles/filler/pleasantries/hedging. Fragments OK. Code/commits/security: write normal.


Two real candidates. My read:

**1. Push `dev-freeform` first (small, do now).** This session fixed 2 CI-blocking bugs (unix TOML fixtures + SQLite concurrency). I validated cross-OS locally, but the M3a A6 gate says "CI matrix green" — only a real push confirms ubuntu+windows runners + the traceability gate go green. Cheap, closes the loop. 9 commits sitting local since `f03a490`.

**2. Then M3b — the `spt-daemon` broker/brain process.** The real next milestone (ROADMAP: M3a ✅ → **M3b** → M3c → M4). `M3b-PLAN.md` is currently a **stub**; M3b is large (broker/brain split, versioned IPC, daemon-authoritative liveness, idempotent boundary, auto-start, + the digest daemon-half completing REQ-TERM-4 `int`). It needs the stub fleshed into a full just-in-time task table (like M3a-PLAN) before executing — that's a planning pass, not a code pass.

Recommended order: **push → flesh M3b plan → execute M3b A0 (scaffold `spt-daemon`)**.


AskUserQuestion

Question: What next?

Choices:
Push dev-freeform to confirm CI matrix green, then flesh M3b-PLAN.md from stub into a full task table. Stop before writing M3b code for your review.
Push the 9 local commits, confirm CI green, then stop and wait.
Leave commits local; flesh M3b-PLAN.md into a full just-in-time plan for review.
Skip the planning pass; scaffold crates/spt-daemon (M3b A0) and proceed. Higher risk — M3b is large and the plan is only a stub.


Your questions have been answered: "What next?"="Push, then plan M3b". You can now continue with these answers in mind.

Question: What next?

Choices:
Push dev-freeform to confirm CI matrix green, then flesh M3b-PLAN.md from stub into a full task table. Stop before writing M3b code for your review.
Push the 9 local commits, confirm CI green, then stop and wait.
Leave commits local; flesh M3b-PLAN.md into a full just-in-time plan for review.
Skip the planning pass; scaffold crates/spt-daemon (M3b A0) and proceed. Higher risk — M3b is large and the plan is only a stub.


Pushing. Check remote first.


Bash

git remote -v; echo "---branch---"; git rev-parse --abbrev-ref HEAD; git log --oneline origin/dev-freeform..HEAD 2>/dev/null | wc -l; git status -sb | head -3

Check git remote + unpushed commits


origin	https://github.com/SaberMage/spt-core.git (fetch)
origin	https://github.com/SaberMage/spt-core.git (push)
---branch---
dev-freeform
66
## dev-freeform...origin/dev-freeform [ahead 66]


Remote exists (`SaberMage/spt-core`). Branch is ahead **66** commits — origin/dev-freeform is well behind (the M0–M3a history isn't on origin). User authorized push. Pushing the branch (fast-forward, triggers CI).


git push origin dev-freeform 2>&1 | tail -15

Push dev-freeform to origin


To https://github.com/SaberMage/spt-core.git
   905c6b4..a32b071  dev-freeform -> dev-freeform


Pushed `905c6b4..a32b071`. CI triggers on push to dev-freeform. Watch the run.


gh run list --branch dev-freeform --limit 3 2>&1 | head; echo "---"; gh run list --branch dev-freeform --limit 1 --json databaseId,status,workflowName 2>&1 | head

Check CI run started


gh auth status 2>&1 | head -4; echo "---runs any---"; gh run list --limit 3 2>&1 | head; echo "---workflows---"; gh workflow list 2>&1 | head

Check gh auth + workflows enabled


github.com
  ✓ Logged in to github.com account SaberMage (keyring)
  - Active account: true
  - Git operations protocol: https
---runs any---
queued		fix(store): concurrent SQLite openers fail with 'database is locked' …	ci	dev-freeform	push	26813278169	8s	2026-06-02T10:15:08Z
---workflows---
ci	active	287646136


CI run queued (`26813278169`). Watch it to completion — it's the real cross-OS + traceability gate.


gh run watch 26813278169 --exit-status --interval 20 2>&1 | tail -25; echo "WATCH_EXIT=$?"

Watch CI run to completion


  ✓ Run actions/checkout@v4
  ✓ Install Rust (stable + clippy)
  ✓ Cache cargo
  ✓ Build
  ✓ Test
  ✓ Clippy (deny warnings)
  ✓ Post Cache cargo
  ✓ Post Run actions/checkout@v4
  ✓ Complete job
X traceability in 5s (ID 79048539679)
  ✓ Set up job
  ✓ Run actions/checkout@v4
  X Install traceable-reqs
  - Coverage gate (hard — fails PR on uncovered activated req)
  - Quality audit (advisory)
  ✓ Post Run actions/checkout@v4
  ✓ Complete job

ANNOTATIONS
! Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v4. Actions will be forced to run with Node.js 24 by default starting June 16th, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
traceability: .github#2

X Process completed with exit code 1.
traceability: .github#10

WATCH_EXIT=0


**Test matrix (ubuntu + windows: build, test, clippy) all green ✓** — my fixes worked. But the **traceability** job failed at the **"Install traceable-reqs"** step (the binary download), not the coverage gate (which was skipped). That's CI infra, not my code. Get the exact error.


gh run view 26813278169 --log-failed 2>&1 | grep -iE "traceable|release|download|not found|404|error|asset|pattern" | head -20

Get traceability install failure detail


traceability	Install traceable-reqs	2026-06-02T10:15:14.9296042Z ##[group]Run gh release download --repo BigscreenVR/traceable-reqs \
traceability	Install traceable-reqs	2026-06-02T10:15:14.9298396Z gh release download --repo BigscreenVR/traceable-reqs \
traceability	Install traceable-reqs	2026-06-02T10:15:14.9300589Z   --pattern '*linux-x86_64' --output traceable-reqs
traceability	Install traceable-reqs	2026-06-02T10:15:14.9302225Z chmod +x traceable-reqs
traceability	Install traceable-reqs	2026-06-02T10:15:14.9334611Z shell: /usr/bin/bash -e {0}
traceability	Install traceable-reqs	2026-06-02T10:15:14.9335822Z env:
traceability	Install traceable-reqs	2026-06-02T10:15:14.9348412Z   GH_TOKEN: ***
traceability	Install traceable-reqs	2026-06-02T10:15:14.9349437Z ##[endgroup]
traceability	Install traceable-reqs	2026-06-02T10:15:15.3538637Z release not found
traceability	Install traceable-reqs	2026-06-02T10:15:15.3558259Z ##[error]Process completed with exit code 1.


"release not found" — the CI default `GITHUB_TOKEN` can't see a release on `BigscreenVR/traceable-reqs` (private/cross-org or no published release). Pre-existing infra break, not my code. Confirm by checking release access.


echo "=== releases on BigscreenVR/traceable-reqs (as SaberMage) ==="; gh release list --repo BigscreenVR/traceable-reqs 2>&1 | head; echo "=== repo visibility ==="; gh repo view BigscreenVR/traceable-reqs --json visibility,name 2>&1 | head

Check traceable-reqs release availability


=== releases on BigscreenVR/traceable-reqs (as SaberMage) ===
v0.1.0	Latest	v0.1.0	2026-05-04T00:35:33Z
=== repo visibility ===
{"name":"traceable-reqs","visibility":"PRIVATE"}


CI characterized: **test matrix green** (my fixes landed). The traceability job's failure is **pre-existing infra** — it downloads the `traceable-reqs` binary from `BigscreenVR/traceable-reqs`, which is **private/cross-org**; CI's repo-scoped `GITHUB_TOKEN` can't read another org's private release → "release not found". Needs a PAT secret with BigscreenVR access (a one-line `ci.yml` + secret change). Not my code; requirement coverage passes locally (exit 0). I'll flag it but not block M3b on it.

Now to your choice — **planning M3b**. Gathering inputs: ADR-0004 (broker/brain split), CONTEXT daemon model, the M3b reqs.


ls docs/adr/ | grep -i "0004"; echo "=== ADR-0004 ==="; cat docs/adr/*0004* 2>/dev/null

Read ADR-0004 broker/brain split


0004-single-daemon-broker-brain-split-and-self-update.md
=== ADR-0004 ===
# Single consolidated daemon with broker/brain split; peer-propagated gated self-update

## Status

accepted (2026-05-29)

## Context

ADR-0002 collapsed PTY-hosting and network-hosting into one per-machine `spt-daemon`. Two further forces refine its shape:

1. **Consolidation.** The sister project runs poll listeners as ephemeral per-session background tasks and Psyche wrappers as detached per-live-agent supervisor processes. But poll listeners already interact directly with the agent session (capsule/idle), and Psyche wrappers already invoke harness binaries directly. Once the daemon owns every PTY, keeping these as separate processes is unjustified.

2. **Seamless self-update with a hard no-terminate constraint.** Self-update is a day-one pillar. The constraint: *no endpoint process may terminate or suspend during an spt-core update* — we cannot assume every endpoint can safely suspend. The naive "drain + restart the daemon" approach violates this for spt-hosted sessions (the daemon owns their PTY; killing the daemon SIGHUPs the child).

## Decision

**Consolidate all per-machine logic into the one daemon.** Poll-listener logic and Psyche/pulse loops move into the `spt-daemon` — no separate listener or wrapper processes. The only residue is a thin, stateless **in-session relay** for harness-hosted sessions (topology 1), where spt cannot reach into a process tree it doesn't own; the relay just pipes the daemon's events into the session's stdout and is freely killable.

**Split the logical daemon into two implementation layers** to satisfy the no-terminate invariant:
- **broker** (stable kernel) — holds *only* un-transferable, must-not-die resources: PTY master fds, spawned harness child processes, listening network sockets. Minimal, versioned local IPC. Almost never updates.
- **daemon brain** (userspace) — all logic (routing, registry, pulse/psyche loops, manifest parsing, update orchestration). Restarts freely; rehydrates from disk state and re-attaches to broker-held handles.

Routine self-updates replace only the brain → endpoints never notice. The broker updates rarely (IPC-contract change, held-resource-type change, OS PTY/socket API change, or broker bugfix); the IPC is versioned so a newer brain talks to an older broker. Logical addressing is unchanged — still one per-machine `spt-daemon`; the broker is internal, not separately addressable.

Rejected alternatives for the invariant: **drain + restart** (violates no-terminate for spt-hosted sessions); **whole-daemon live FD-passing** (ConPTY handle transfer mid-swap is hard and platform-divergent — pushing that complexity into the rare broker update instead of every routine update is strictly better); **topology-1-only invariant with spt-hosted as fast-follow** (silently breaks the stated hard constraint for the exact new topology spt-core introduces).

**Self-update delivery:** peer-propagated over P2P, layered on self-fetch, out-of-band still supported. All binaries signature-verified before handoff (spt-core's own release key) regardless of source — peer-propagation otherwise lets one compromised node poison the subnet. spt-core conducts updates for the whole stack: self first, then ripple-update each registered adapter via the adapter manifest's update declaration (file-pull or delegated command). The plugin's role shrinks to initial bootstrap only.

**Cadence/consent:** not fully automatic by default; gated on user confirmation delivered to the most-recently-active live session, with an opt-in full-auto choice.

## Consequences

- The daemon is the single brain for a machine; crash-recovery and update logic must cover PTYs, networking, registry, spools, listeners, and psyche loops together.
- A small internal broker process exists beneath the daemon — a deliberate, bounded walk-back of "literally one process," preserving B1's *intent* (one network identity, one supervisor, one firewall prompt) while guaranteeing endpoint survival across updates.
- Peer-propagated updates make release signing mandatory, not optional.
- spt-core becomes the update conductor for adapters too; adapter manifests must declare an update avenue.
- The "deliver to most-recently-active session" mechanism is a v1 building block that the deferred PresenceChannel will later generalize.
- Whole-daemon live FD-passing (zero-interruption even for broker updates) remains a possible future polish but is explicitly not required for v1.

## Validation & amendments (2026-05-31 — Stage A red-team + Spike #1)

Codex adversarial review (`docs/reviews/STAGE-A-codex-redteam.md`) put 4 FATAL findings on this ADR; Spike #1 (`docs/spikes/SPIKE-01-broker-handoff.md`, `spt-spikes/spike-01-broker-handoff`) tested the hardest path. Resulting binding amendments:

### A. Update-class taxonomy (resolves FATAL #1 — R-UPD-3 self-contradiction)
R-UPD-3's "no endpoint terminates during update" is **only** absolute for the *brain-only* class. Three classes, each with its own invariant:
- **brain-only** (the routine case) — endpoints MUST survive untouched. **Spike #1: PROVEN on Windows ConPTY.**
- **broker-compatible** — broker binary swap behind a versioned IPC the running broker can hot-accept; endpoints survive; no spike yet.
- **broker-breaking** — held-resource-type or OS-API change; requires a *planned endpoint-cycle*. R-UPD-3 is explicitly weakened here: this class MAY suspend endpoints, with consent + scheduling. PRD R-UPD-3 must be reworded to scope the absolute guarantee to brain-only.

### B. Ownership table (resolves FATAL #4 — "any live stream owned by brain breaks the invariant")
The boundary is normative, not "broker holds fds, brain holds logic." A resource is broker-owned **iff** a live consumer would lose continuity on brain restart.

| Resource | Owner | Spiked? |
|---|---|---|
| PTY master read+write handle | **broker** | ✅ #1 |
| Spawned harness child process | **broker** | ✅ #1 |
| Accepted local client socket (`api listen`, relay) | **broker** | ✅ #1 (plain TCP) |
| Iroh endpoint + accepted QUIC streams | **broker** | ✅ #3 (loopback shape; impl M4) |
| mDNS socket / relay session | **broker** | ❌ open |
| Listening sockets | **broker** | ✅ #1 |
| Routing, registry state, pulse/psyche loops, manifest parse, update orchestration | brain (rehydrate from disk) | n/a |

Consequence codex forced into the open: pushing live Iroh/QUIC ownership into the broker means networking stream-state lives in the "stable kernel," enlarging it. Accepted as the cost of the invariant; the broker is "stable" in *update cadence*, not in *narrowness*.

### C. ConPTY DSR gotcha (new hazard, discovered by Spike #1)
ConPTY withholds **all** child stdout until the terminal answers its startup cursor-position query (`ESC [ 6 n`). A broker reading a ConPTY master that does not reply `ESC [ <r>;<c> R` sees only the 4-byte query and then nothing — looks like a hung/silent child. Spike got 0 bytes of program output until the reader answered DSR, then full output. → `REQ-HAZARD-CONPTY-DSR`; every ConPTY reader must auto-answer DSR. Added to KNOWN-HAZARDS §5.

### D. Self-update delivery hardening (resolves SERIOUS #5)
Signature-verify alone is insufficient. v1 adds: monotonic version field (rollback rejection), release-metadata expiry, channel pinning, key rotation/revocation list, and **adapter content signing** (adapter file-pull / delegated-command updates were uncovered by "binary signature"). Track as `REQ-HAZARD-UPDATE-ROLLBACK`.

### E. Open spike gaps (must close before M3 builds the daemon)
1. ✅ **CLOSED (Spike #3, 2026-06-01).** Live Iroh + file-transfer stream survival across brain restart (FATAL #2). Spike #1 only proved PTY + plain TCP; Spike #3 stood up a broker-owned Iroh endpoint + uni QUIC transfer and proved a live peer download survives a brain restart gapless + exactly-once. Loopback shape validated; off-node transport + the QUIC-ownership *implementation* defer to M4. (`docs/spikes/SPIKE-03-quic-survival.md`.)
2. ✅ **CLOSED (Spike #4, 2026-06-01).** Linux `forkpty` parity. Spike #1's binary, unchanged, passed all four invariants on `gravity-linux` (Ubuntu 22.04) — `portable-pty` selects `forkpty` on Unix; the ConPTY-DSR branch is inert there. Invariant B passed with the *strict* contiguity check that ConPTY-under-resize fails (Spike #5): `forkpty` is a raw pipe, ConPTY a screen buffer — different stream contracts, promoted into M3a's `SessionSurface` design. (`docs/spikes/SPIKE-04-forkpty-parity.md`.)
3. ✅ **CLOSED (Spike #5, 2026-06-01).** 100× restart + resize-under-load stress (codex #3). The broker survived 100 rapid brain kill/restart cycles + a resize thread racing the reader with no leak (one child, clean reap), no hang (watchdog deadline), no lost byte (full value-set coverage in the client's observation window). Surfaced two binding ConPTY findings for M3a/REQ-TERM-3: resize triggers a repaint that reorders+dups the stream (terminal-stream contract ≠ exactly-once transfer contract); mid-session attach yields the viewport only, not scrollback. (`docs/spikes/SPIKE-05-restart-stress.md`.)
4. ✅ **CLOSED (Spike #6, 2026-06-01).** Idempotent/exactly-once delivery across brain restart (FATAL-adjacent #14). Durable-ID + WAL + dedup-at-effect proven exactly-once across a crash at any protocol point (before-intent / before-effect / after-effect). Two binding design constraints surfaced for `REQ-HAZARD-RESTART-IDEMPOTENT` / M3b-B5: broker-owned recovery anchor; dedup-at-effect keyed by durable ID. (`docs/spikes/SPIKE-06-idempotent-boundary.md`.)

**Gate status (2026-06-01): ALL FOUR §E GAPS CLOSED PASS** (#3, #4, #5, #6) → the M3-PLAN Phase-0 spike-gate is **complete**. The broker/brain split is validated on both OSes (ConPTY + `forkpty`), across QUIC-stream survival, restart+resize churn, and exactly-once idempotency. M3a and M3b are both unblocked; the QUIC-ownership *implementation* and off-node transport remain explicitly deferred to M4 (only the *shape* was spiked).


ADR-0004 gives the full broker/brain contract + the closed spike gaps. Now gather the rest: M3b reqs, CONTEXT daemon model, and the interim hosting the daemon replaces. Batching reconnaissance.


echo "=== M3b reqs ==="; grep -n "REQ-DAEMON\|REQ-START-3\|REQ-HAZARD-DAEMON-HOSTED-LIVENESS\|REQ-HAZARD-RESTART-IDEMPOTENT\|REQ-HAZARD-HANDOFF-ARGV-COMPAT\|REQ-HAZARD-GEN-START-NOW" traceable-reqs.toml; echo; echo "=== their titles ==="; grep -A1 'id = "REQ-DAEMON-1"\|id = "REQ-DAEMON-3"\|id = "REQ-START-3"\|id = "REQ-HAZARD-DAEMON-HOSTED-LIVENESS"\|id = "REQ-HAZARD-RESTART-IDEMPOTENT"\|id = "REQ-HAZARD-HANDOFF-ARGV-COMPAT"\|id = "REQ-HAZARD-GEN-START-NOW"' traceable-reqs.toml | grep title

M3b requirement ids + titles


=== M3b reqs ===
41:id = "REQ-DAEMON-1"
45:id = "REQ-DAEMON-2"
49:id = "REQ-DAEMON-3"
53:id = "REQ-DAEMON-4"
123:id = "REQ-START-3"
417:id = "REQ-HAZARD-HANDOFF-ARGV-COMPAT"
421:id = "REQ-HAZARD-GEN-START-NOW"
514:id = "REQ-HAZARD-RESTART-IDEMPOTENT"
522:id = "REQ-HAZARD-DAEMON-HOSTED-LIVENESS"

=== their titles ===
title = "One per-machine spt-daemon owning all per-machine state"
title = "Any api invocation auto-starts the daemon if absent"
title = "spt-hosted startup: spawn-session then api bind (no file)"
title = "Broker/brain IPC + handoff argv version-tolerant (2.3)"
title = "gen_start = now() on cold-start and handoff (2.4)"
title = "Idempotent/exactly-once delivery across brain restart at every broker boundary (codex #14)"
title = "Daemon-hosted perches (Psyche, spt-hosted Self) derive liveness from the daemon endpoint table + info.json status, never is_process_alive(info.pid) (2.5)"


40	[[requirements]]
41	id = "REQ-DAEMON-1"
42	title = "One per-machine spt-daemon owning all per-machine state"
43	required_stages = []
44	[[requirements]]
45	id = "REQ-DAEMON-2"
46	title = "Broker/brain split for seamless self-update"
47	required_stages = []
48	[[requirements]]
49	id = "REQ-DAEMON-3"
50	title = "Any api invocation auto-starts the daemon if absent"
51	required_stages = []
52	[[requirements]]
53	id = "REQ-DAEMON-4"
54	title = "Honor every KNOWN-HAZARDS invariant"
55	required_stages = []
56
57	# ───────────────────────────── Harness contract — manifest seams ────────────
58	[[requirements]]
59	id = "REQ-MANIFEST-1"

[[requirements]]
id = "REQ-DAEMON-1"
title = "One per-machine spt-daemon owning all per-machine state"
required_stages = []
[[requirements]]
id = "REQ-DAEMON-2"
title = "Broker/brain split for seamless self-update"
required_stages = []
[[requirements]]
id = "REQ-DAEMON-3"
title = "Any api invocation auto-starts the daemon if absent"
required_stages = []
[[requirements]]
id = "REQ-DAEMON-4"
title = "Honor every KNOWN-HAZARDS invariant"
required_stages = []

# ───────────────────────────── Harness contract — manifest seams ────────────
[[requirements]]
id = "REQ-MANIFEST-1"


Launching a recon agent for the interim hosting M3b replaces (background, staying owl-reachable), while I read the CONTEXT daemon model.


Agent

Map interim daemon hosting seams

Prompt:
Read-only recon of the spt-core repo at C:\Users\decid\Documents\projects\spt-core to map what the future `spt-daemon` (M3b) will consolidate and replace. The daemon does NOT exist yet — M1/M2a/M2b run an "interim, no-daemon" model. I need a precise map of the seams so I can write the M3b build plan.

Report concisely (file:line references, no full dumps) on each:

1. **The `api listen` runner** — in crates/spt/src/api/ (look at startup.rs, worker.rs, delivery.rs, cli.rs). What does the long-lived `api listen` process hold and do? How does it hold the perch + relay messages? Where is `api bind`, `api shutdown`, `api session-end`? List the `api` subcommands and which are one-shot vs long-lived.

2. **The pulse loop** — spt-live's interim pulse (crates/spt-live/src/pulse.rs or similar). How is the period set, who drives it, what does a pulse do?

3. **Psyche per-pid liveness** — how liveness is currently determined for hosted perches: crates/spt-store/src/proc.rs (is_process_alive), crates/spt-msg/src/deliver.rs (is_online), crates/spt-store/src/registry.rs (clean_stale_entries). Where does the per-pid assumption live, and where is it gated behind a single resolver (the spot the M3b daemon-authoritative-liveness swap targets)?

4. **The seed-file bridge** — crates/spt-store/src/seed.rs and how `api seed`/startup uses it (the M2a interim that REQ-START-3 replaces with in-memory spawn→bind).

5. **spt-live public surface** — what crates/spt-live/src/lib.rs exports (the lifecycle the daemon brain re-hosts: spawn-psyche, echo-commune, signoff, resume, boundary ordering). One line each.

6. **The mock adapter lifecycle templates** — adapters/mock: what session roles/manifest seams exist that the daemon would drive (psyche_init, psyche_resume, echo_commune, self, etc.).

7. **Workspace layering** — confirm where spt-daemon would slot: the dependency order in Cargo.toml workspace + the layering comment. Confirm spt-live is the current top-of-stack-below-binary and what the `spt` binary crate depends on.

Goal: a seam map an architect can turn into an ordered M3b task plan (scaffold spt-daemon → broker → brain → consolidate listener/pulse/psyche → daemon-authoritative liveness → idempotent boundary → auto-start → spt-hosted startup). Flag anything that looks already-built vs not-yet-built.


<owl_reachability_notice>
You have an active owl perch. Launch this Agent with run_in_background: true so you stay reachable for incoming messages while it works.
</owl_reachability_notice>


Async agent launched successfully.
agentId: a0b6fe9673dd69793 (internal ID - do not mention to user. Use SendMessage with to: 'a0b6fe9673dd69793' to continue this agent.)
The agent is working in the background. You will be notified automatically when it completes.
Do not duplicate this agent's work — avoid working with the same files or topics it is using. Work on non-overlapping tasks, or briefly tell the user what you launched and end your response.
output_file: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\b494f5e6-5b4d-4145-aaaa-5585e1168377\tasks\a0b6fe9673dd69793.output
Do NOT Read or tail this file via the shell tool — it is the full sub-agent JSONL transcript and reading it will overflow your context. If the user asks for progress, say the agent is still running; you'll get a completion notification.

Map interim daemon hosting seams

Prompt:
Read-only recon of the spt-core repo at C:\Users\decid\Documents\projects\spt-core to map what the future `spt-daemon` (M3b) will consolidate and replace. The daemon does NOT exist yet — M1/M2a/M2b run an "interim, no-daemon" model. I need a precise map of the seams so I can write the M3b build plan.

Report concisely (file:line references, no full dumps) on each:

1. **The `api listen` runner** — in crates/spt/src/api/ (look at startup.rs, worker.rs, delivery.rs, cli.rs). What does the long-lived `api listen` process hold and do? How does it hold the perch + relay messages? Where is `api bind`, `api shutdown`, `api session-end`? List the `api` subcommands and which are one-shot vs long-lived.

2. **The pulse loop** — spt-live's interim pulse (crates/spt-live/src/pulse.rs or similar). How is the period set, who drives it, what does a pulse do?

3. **Psyche per-pid liveness** — how liveness is currently determined for hosted perches: crates/spt-store/src/proc.rs (is_process_alive), crates/spt-msg/src/deliver.rs (is_online), crates/spt-store/src/registry.rs (clean_stale_entries). Where does the per-pid assumption live, and where is it gated behind a single resolver (the spot the M3b daemon-authoritative-liveness swap targets)?

4. **The seed-file bridge** — crates/spt-store/src/seed.rs and how `api seed`/startup uses it (the M2a interim that REQ-START-3 replaces with in-memory spawn→bind).

5. **spt-live public surface** — what crates/spt-live/src/lib.rs exports (the lifecycle the daemon brain re-hosts: spawn-psyche, echo-commune, signoff, resume, boundary ordering). One line each.

6. **The mock adapter lifecycle templates** — adapters/mock: what session roles/manifest seams exist that the daemon would drive (psyche_init, psyche_resume, echo_commune, self, etc.).

7. **Workspace layering** — confirm where spt-daemon would slot: the dependency order in Cargo.toml workspace + the layering comment. Confirm spt-live is the current top-of-stack-below-binary and what the `spt` binary crate depends on.

Goal: a seam map an architect can turn into an ordered M3b task plan (scaffold spt-daemon → broker → brain → consolidate listener/pulse/psyche → daemon-authoritative liveness → idempotent boundary → auto-start → spt-hosted startup). Flag anything that looks already-built vs not-yet-built.


Recon agent running in background. Reading the CONTEXT daemon/broker/brain model in parallel.


Bash

grep -n "daemon\|broker\|brain\|topology\|relay\|in-session\|gen_start\|generation\|handoff" CONTEXT.md | head -40

CONTEXT daemon/broker/brain references


<owl_messages>
<owl_message from="doyle-w332" priority="info">[WORKING_PERCH_NOTICE] Subagent working perch created.
Perch: doyle-w332
Agent type: Explore
To message it: $OWL send doyle-w332 doyle</owl_message>
</owl_messages>

[OWL SYSTEM] Informational owl messages above — no acknowledgment needed. Continue your current task.


25:**spt-daemon** (per-machine supervisor):
26:The single always-on, one-per-machine logical supervisor. Owns the PTYs for all hosted sessions, the node's network identity + WAN endpoint, the subnet registry, all spools, **all poll-listener logic, and all Psyche/pulse loops** — everything is consolidated here (no separate poll-listener or Psyche-wrapper processes; listeners already touch sessions directly under capsule/idle, and Psyche wrappers already invoke harness binaries directly, so they belong in the one supervisor). Collapses what the sister project planned as a separate `spt-node` daemon into one process — see Networking. The `spt-node` separate-deliverable concept is retired.
28:Internally the logical daemon is split into two implementation layers for seamless self-update (see Self-update):
29:- **broker** (stable "kernel") — holds *only* the un-transferable, must-not-die resources: PTY master fds, the spawned harness child processes, and listening network sockets. Minimal, dumb, versioned local IPC. Almost never updates.
30:- **daemon brain** ("userspace") — all logic (routing, registry, pulse/psyche loops, manifest parsing, update orchestration). Restarts freely on update; rehydrates from disk state and re-attaches to the broker's held handles.
32:Logical addressing is unchanged — still one per-machine `spt-daemon`; the broker is an internal layer, not separately addressable.
34:**in-session relay**:
35:A thin, stateless `spt.exe` task that exists only in **harness-hosted** sessions (where the agent harness is the parent process and spt cannot reach into its process tree — today's Monitor model). It streams the daemon brain's events into the session's stdout. All *stateful* listener logic lives in the daemon; the relay is a dumb pipe, freely killable and respawnable. **spt-hosted** sessions need no relay — the daemon injects events straight into the PTY.
69:Every manifest declares a unified **`adapter_name`** (e.g. `claude-spt`), carried on every `api` invocation too. It is load-bearing: one daemon hosts endpoints from multiple adapters, so it resolves an endpoint's manifest + seams by `adapter_name`; adapter-update ripples target by it; capability/manifest lookup and telemetry key on it. The header also declares the adapter's own version and a **`min_spt_core_version`** — the minimum spt-core the adapter requires. This declaration must be **readable before an adapter update is applied** (it lives in the manifest header / a small metadata file fetched first), so spt-core can verify compatibility / expected supported features *before* committing the update. If installed spt-core < the adapter's `min_spt_core_version`, surface the incompatibility rather than silently breaking; when spt-core self-updates, re-verify adapters still satisfy (coordinate core + adapter updates when needed). This is a distinct compatibility axis from the node↔node/library wire-protocol version (see Workspace & versioning).
79:Governing principle: **SPT is not a harness.** Model choice, billing shape, harness-internal env, and harness-internal context are entirely the adapter's concern, expressed inside the adapter's own command templates. spt-core owns only the template *mechanism* (substitution keys), the substitution *values* it is responsible for, and the surrounding lifecycle. Env for the *endpoint binary itself* is auto-handled by spt-core/broker; env for the *agent running inside* that binary is the adapter's config (e.g. the CC plugin config).
81:**spawn-session seam** — launch a new agent session on this node. Manifest provides: a command template; `cwd`/project; a `headless` flag (optional, default false — for the GUI's resume-of-compatible-adapters); a `resume` flag (optional); and the `commune` + `signoff` file directories relative to `cwd` (so the daemon knows where to watch). Substitution keys spt-core can supply: `{id}` and, optionally, a spt-core-generated valid session UUID (e.g. injected as `--session-id {uuid}`) so an adapter can skip the post-spawn seam. spt-core does **not** inject: harness-internal env (broker handles binary env; adapter handles in-session env), and **no initial-context handoff** (not needed at start — the agent is prompted for context once its session is up; the first commune populates it).
84:**post-spawn seam** — the just-launched binary calls an spt-core command on boot (via the adapter's SessionStart-equivalent hook) to bind itself. Needed because the harness's own session id usually isn't known until after the binary runs. Payload: the harness `session_id` (when binary-generated rather than spt-core-injected); the `parent_pid` (the stable session-binding anchor — see KNOWN-HAZARDS 2.1); an endpoint identity/type confirmation; optionally a local HTTP port the binary listens on (for HTTP-mode input delivery, below); and a **boot nonce** (a generation/boot discriminator so a respawn-after-crash bind can't be confused with a stale duplicate — guards KNOWN-HAZARDS 2.4). The call flips the perch from skeleton → live.
99:- PTY injection (with or without key/submit sequences) — spt-hosted topology;
101:- an in-adapter-session child relay (à la CC's Monitor tool);
103:Note: even spt-hosted sessions default to hook injection (or the adapter's equivalent) as the non-disruptive path **during activity**; some adapters prefer the in-session relay regardless of topology.
116:- **Hook output capability is declared per harness-event** (`can_inject`). CC's Stop hook cannot inject context — that single fact drives the echo-gate sentinel + relay fallback. The manifest expresses it so spt-core knows when to fall back.
117:- **Env injection is asymmetric** (file-bridge-only-when-not-launcher, applied to env): spt-hosted sessions inherit env from the broker that spawns them; harness-hosted sessions need the harness's declared env channel. With `spt` on PATH the env table is small.
124:All commands below are `api`-prefixed (machinery-facing). Every `api` invocation **and** every manifest carries a unified **`adapter_name`** string (e.g. `claude-spt`) identifying the owning adapter. This is load-bearing: one daemon hosts endpoints from multiple adapters (`claude-spt`, `spt-codex`, `spt-pi`), so the daemon resolves an endpoint's manifest + seams (history normalize-command, inject method, update avenue) by its `adapter_name`; adapter-update ripples target by it; capability lookup and telemetry key on it.
127:- **`api listen`** — *long-running* relay/poll listener that an adapter-owned (harness-hosted) session owns as a child process; streams the daemon's events to the session's stdout. Distinct from the short-lived `api poll`. This is the heir to today's Monitor-bound `$LIVE start` poll loop.
132:- **`api boundary <clear|compact>`** — context-boundary report; **carries the new `session_id`** (it rotates on `/clear` or `/compact`), so the daemon rebinds the perch to the new session id while keeping the stable identity + `parent_pid` anchor. Authors a **Self-resume commune** (resume the Self session → commune file-drop) rather than a background echo — strong live-context signal at the boundary (see `docs/CONTEXT-MEMORY.md`).
135:- **`api presence`** — adapter reports user interaction → updates the presence datum `(last_active_node, last_active_endpoint, ts)`. In the spt-hosted topology, presence is **also** updated by the broker *detecting* (sensing, not watching/logging) user input on a held PTY — privacy-preserving (it notes that input occurred, records no content).
136:- **`api emit --type <sensory_type> <payload>`** — a broker-launched **Shell** binary pushes a sensory payload to its owner agent (owner known from `api bind`; REST-only, never spooled). See the Shell model.
138:**Not `api` commands — file-drop flow:** `commune` and `signoff` are deprecated as commands (modern SPT) in favor of file drops. The agent/adapter writes `<id>-commune.md` / `<id>-signoff.md`; the daemon watches the manifest-declared commune/signoff dirs (the spawn-session seam fields), ingests, and deletes (drop files are daemon-owned single-writer — KNOWN-HAZARDS 6.4). These stay off the `api` surface and the agent surface alike.
142:**Adapters never resolve `$SPT_HOME`.** spt-core install registers its binary directory on the system-wide PATH, so adapters call `spt api …` on any OS without path math. All harness↔daemon bridging goes through `spt api` commands (the daemon is always running, or auto-started — below), so there is **no adapter-written file** in the bind path.
144:**Harness-hosted (e.g. spt-plugin; the harness binary is user-launched, harness is the parent).** Key constraint: the SPT *live agent* does not exist until the agent invokes start — the `live_id` isn't chosen at session boot, and `$LIVE start` is itself invoked *behind the Monitor tool*, so it becomes the long-running relay. So binding cannot happen at SessionStart directly. A **seed record** (daemon-held, in-memory — not a file) bridges the gap:
145:1. The harness's SessionStart hook calls **`spt api seed --pid <parent_pid> [session_id, cwd, adapter_name, …]`**. The daemon records an ephemeral in-memory **seed entry** keyed by `parent_pid` — the session details the spt-hosted topology would share directly, minus the not-yet-chosen `live_id`. In-memory (not a file) avoids drive churn and the `$SPT_HOME` resolution nuisance; seeds are consumed within seconds, so persistence across a daemon restart is unnecessary (re-fired on the next SessionStart if needed).
146:2. The agent runs `/spt:live <id>` → the adapter's `$LIVE start <id>` alias = **`$SPT listen <id>`** (= `spt api listen <id>`), invoked via Monitor. It self-discovers its `parent_pid`, the daemon matches the seed entry by that pid (validated against `session_id` to defeat PID-recycling — KNOWN-HAZARDS 5.1), creates/revives the perch binding `live_id` ↔ session details, then enters the long-running relay loop streaming events to stdout.
147:3. The always-on daemon holds the perch, spool, registry, and daemon-spawns the Psyche (via the spawn-psyche seam) — no separate wrapper. The relay is purely the delivery pipe.
150:**Daemon auto-start:** the daemon is per-machine always-on (OS-service registered), but any `spt api` invocation that needs it will **start it if absent** (fresh boot, crash, never-installed-as-service). `$SPT listen` for the first SPT session on a machine thus transparently spins up the daemon. Ensure-running lives in the `api` layer generally; `listen` is the reliable anchor.
152:**spt-hosted (terminal wrapper / GUI launcher; the daemon launches the binary into a broker PTY):**
153:1. The frontend/CLI launches the agent: the daemon runs the **spawn-session** command template into a broker-held PTY.
154:2. The binary boots and fires **`api bind`** (or skips it under the strict UUID-injection + stable-pid commitment). **No catalyst/seed file** — the daemon is the launcher, already holds a direct channel (it spawned the process and owns the PTY), so a file round-trip would only add drive churn for no benefit.
155:3. The daemon delivers events; method is **manifest-configurable per activity-state** — direct PTY injection, or a relay even here (some adapters prefer a relay over PTY injection for idle delivery), or HTTP. During *activity*, delivery still defaults to the non-disruptive hook-injection path, not raw PTY writes.
156:4. Psyche is daemon-spawned, same as above.
158:So the old `$LIVE start` splits by topology: harness-hosted = SessionStart writes seed → `$SPT listen <id>` consumes seed (by `parent_pid`) + binds + relays; spt-hosted = daemon spawn-session + `api bind` (direct, no file). The asymmetry is the file-bridge-only-when-no-direct-channel principle.
160:**Env-var aliases:** adapters inject clean env-var aliases for in-session invocation (heirs to today's `$OWL`/`$LIVE`), e.g. **`$SPT` = `spt api`** so a Monitor-bound call reads `$SPT listen <id>`. spt-core supplies the subcommands; the adapter supplies the env aliases (manifest philosophy).
173:The Psyche companion's own perch, distinct from its paired LiveAgent's perch. First-class endpoint type so messages addressed to a LiveAgent's Psyche route directly without ambiguity. **Liveness is daemon-held, not PID-based.** Unlike the sister's separate wrapper *process*, the Psyche (under ADR-0004) is a **loop inside the daemon** — it has no dedicated liveness pid, and its summarizer subprocess is ephemeral. Its perch is alive iff the daemon's endpoint table says so, surfaced via a daemon-managed `status` field on `info.json` (the same pattern Shells use), **never** an `is_process_alive(info.pid)` check. The M1/M2a interim (no daemon) keeps it a real process, so per-pid liveness holds *interim*; M3 replaces it with daemon-authoritative liveness (KNOWN-HAZARDS 2.5).
179:A machine's participation in an SPT subnet, identified by an Ed25519 public key generated on first run. First-class so networking primitives can address nodes directly as message targets, not only as transport peers. The node identity and network endpoint are hosted by the machine's `spt-daemon` (see Networking), not a separate process.
181:**PresenceChannel** (broker endpoint — concept locked, impl deferred past v1):
182:A *broker* endpoint, not an interaction surface. Job: (1) **presence resolution** — track which node + endpoint the user most recently interacted with; (2) **shell brokering** — locate/instantiate the right Shell on that node and relay between the agent and the user. An agent "just knows how to reach the user" by firing at its PresenceChannel; the channel figures out the rest. Also a durable, **shell-agnostic 2-way thread**: messages persist in the channel, not in any one Shell, so the user can be sent a message via a phone messaging-Shell and surface/continue that same agent conversation later at a GameRobot Shell. Shells are interchangeable I/O windows onto the channel's thread.


Got the full daemon/broker/brain model from CONTEXT + ADR-0004. The recon agent (`doyle-w332`) is mapping the interim hosting seams (file:line) that M3b consolidates. I'll synthesize `M3b-PLAN.md` once it returns — waiting on it now rather than duplicating its work.

While it runs, the shape I'm planning toward (from ADR-0004 §B ownership table + M3-PLAN §M3b):

- **B0** scaffold `crates/spt-daemon` (above spt-live, below spt) + versioned-IPC skeleton
- **B1** broker kernel — owns PTY masters (from spt-term), harness children, listening/client sockets; minimal versioned IPC (`REQ-HAZARD-HANDOFF-ARGV-COMPAT`)
- **B2** brain — routing/registry/manifest, rehydrate-from-disk + re-attach to broker handles; `gen_start=now()` cold-start **and** handoff (`REQ-HAZARD-GEN-START-NOW`)
- **B3** consolidation — fold the `api listen` poll-loop + pulse + Psyche loops into the brain; thin stateless relay residue (`REQ-DAEMON-1`)
- **B4** daemon-authoritative liveness — `status` field supersedes `is_process_alive(info.pid)` (`REQ-HAZARD-DAEMON-HOSTED-LIVENESS`)
- **B5** idempotent boundary — durable-ID + dedup-at-effect at every broker↔brain side-effect (`REQ-HAZARD-RESTART-IDEMPOTENT`, Spike #6)
- **B6** auto-start (`REQ-DAEMON-3`) + spt-hosted startup spawn→bind, in-memory seed (`REQ-START-3`)
- **B7** digest daemon-half — manifest-sourcing + `spt digest` pull + delta-stream + Path-B persist (completes **REQ-TERM-4 `int`**)
- **B8** activation sweep + verify + docs

That ordering and the seam targets get pinned to real file:line when recon lands. Standing by for the agent.


<task-notification>
<task-id>a0b6fe9673dd69793</task-id>
<tool-use-id>toolu_01VaWr4epQZdWBtcWSAZUqvB</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\b494f5e6-5b4d-4145-aaaa-5585e1168377\tasks\a0b6fe9673dd69793.output</output-file>
<status>completed</status>
<summary>Agent "Map interim daemon hosting seams" completed</summary>
<result>Excellent. Now I have the complete picture. Let me compile the comprehensive seam map report:

---

## **SEAM MAP: spt-daemon (M3b) Consolidation Blueprint**

Precise reference guide for M3b architecture and task order. Goal: **spt-daemon replaces the interim no-daemon model** (seed-files + long-running `api listen` processes + per-pid liveness checks).

---

### **1. THE `api listen` RUNNER — startup.rs + live.rs**

**What it holds + does:**
- **startup.rs:cmd_listen** (L133–230): long-lived relay loop anchored on parent pid → binds perch skeleton→live + runs `PollListener::bind_blocking` (L172, spt-msg).
- **Relay loop**: drains offline spool → emits → runs one pulse tick (ingest+echo) → sleeps → repeat.
- **Live-agent host** (if manifest has `psyche_init`): sweeps stale signoff sentinel on start (L189), spawns Psyche companion (L190), runs `host.pulse_tick()` each cycle (L228).

**Perch + relay seams:**
| Seam | Location | Role |
|------|----------|------|
| `api seed` | startup.rs:39–63 | Ephemeral file keyed by parent pid (REQ-START-1); reads by parent_pid match in `listen` |
| `api listen <id>` | startup.rs:144–230 | Consume seed, bind perch, relay loop; **M3b replaces entire loop with daemon-driven delivery** |
| `api bind <id>` | startup.rs:237–263 | Post-spawn bind (intrinsic auth); establishes live perch without seed |
| `api shutdown <id>` | live.rs:220–243 | Graceful signoff: echo-before-teardown (T6) + soft stop (ready marker removal) |

**Message/pulse flow:**
- Lines 200–202: drain non-deferred spool (offline backlog).
- Lines 204–209: one pulse tick (ingest drops + clear echo-gate).
- Lines 221–230: **infinite relay loop** — the M3b target for consolidation.

**Commands, one-shot vs long-lived:**
| Command | Type | Auth-gated | Notes |
|---------|------|-----------|-------|
| `seed` | one-shot | No (establishes binding) | Interim bridge; M3b replaces with daemon's in-memory map |
| `listen` | **long-lived** | No (consumes seed) | **M3b: CONSOLIDATES entire loop into daemon** |
| `bind` | one-shot | Intrinsic (session_id match) | Post-spawn bind; stays in M3b API (thin wrapper) |
| `shutdown` | one-shot | Yes (token/session_id) | Graceful teardown path; stays thin in M3b (delegate to daemon) |

---

### **2. THE PULSE LOOP — pulse.rs + live.rs:pulse_tick**

**Period and driver:**
- **pulse.rs**: `DEFAULT_PULSE_PERIOD = Duration::from_secs(5)` (L31) — interim constant, **not configurable in M2b**.
- **Driver**: `api listen` loop (startup.rs:228); invokes `host.pulse_tick()` each cycle.
- **No scheduling abstraction** — the relay loop implicitly paces it (poll + receive + tick + sleep).

**What one tick does:**
- `ingest_drops()` (pulse.rs:69): scan commune/signoff drop dirs, fold into perch context.md, delete drops (T4, single-writer guard).
- `take_echo_gate()` (pulse.rs:70): read+clear `.more-done` sentinel, return whether echo is due.
- Return `TickOutcome` (idle, echo_due, ingested items).

**M3b consolidation point:**
- Pulse lives behind a single module boundary (`crate::pulse::tick`).
- **M3b daemon re-hosts**: configurable per-agent + global period, daemon-scheduled loop instead of relay-driven.

**Tick structure** (pulse.rs:62–77):
```
pub fn tick(...) -> TickOutcome {
    ingested = ingest_drops(drop_dir, ...)  // T4: consume mind drops
    echo_due = take_echo_gate(...)          // read+clear gate for T3 echo
    idle = sentinel_exists()                // for capsule idle decisions
    -> TickOutcome { ingested, echo_due, idle }
}
```

---

### **3. PSYCHE PER-PID LIVENESS — proc.rs + deliver.rs + registry.rs**

**Current per-pid liveness assumption:**

| Location | Function | Role |
|----------|----------|------|
| **proc.rs:9–34** | `is_process_alive(pid)` | OS-level probe (Unix: `kill(pid, 0)`; Win: `OpenProcess`) — **single-point resolver for M3b swap** |
| **deliver.rs:76–85** | `is_online(target)` | Checks ready marker + `is_process_alive(pid_from_info.json)` → true = online |
| **registry.rs:97–110** | `clean_stale_entries()` | Before resolution: scan registry, drop rows where `is_process_alive(pid)` → false |
| **registry.rs:119–122** | `resolve_address()` | Clean stale, then lookup TCP address |
| **startup.rs:83–97** | `bind_from_seed()` | Seed anchor liveness check (L91): `is_process_alive(parent_pid)` guards pid-recycle (REQ-HAZARD-WINDOWS-PID-RECYCLE) |

**The per-pid assumption lives here:**
- **proc.rs:is_process_alive** is the **single resolver** — all liveness checks converge here.
- **Ready marker + pid alive** = `is_online` (deliver.rs:76).
- **Dead pid means stale registry row** → clean before lookup (registry.rs:119–122).
- **Anchor pid alive** = seed is valid (startup.rs:91).

**M3b swap target:**
- Replace `proc::is_process_alive(pid)` with **daemon-authoritative liveness** (uptime flag in daemon's in-memory perch record).
- Single edit point: `proc.rs:is_process_alive` returns daemon status instead of OS probe.
- All downstream paths (deliver, registry, startup) automatically inherit daemon authority.

---

### **4. THE SEED-FILE BRIDGE — seed.rs + startup.rs**

**Current flow (interim M2a):**

| Step | Code | Role |
|------|------|------|
| 1. Harness fires `SessionStart` hook | harness-contract | Writes `api seed --pid <parent_pid> --session-id <sid>` |
| 2. **seed.rs:write_seed()** | L49–54 | `<spt_home>/seeds/<parent_pid>.json` keyed by parent pid (atomic write) |
| 3. **startup.rs:cmd_seed()** | L39–63 | Entry point; writes seed file; prints `SEEDED:{parent_pid}` |
| 4. **startup.rs:cmd_listen** | L162–168 | Calls `bind_from_seed(id, parent_pid)` |
| 5. **startup.rs:bind_from_seed()** | L83–97 | Read seed, check parent alive (L91), establish perch, consume seed (L95) |

**The localized swap point:**
- **seed.rs is the bridge** (comment L8–10): "M3b replaces file read/write with daemon's in-memory map."
- M3b: replace `seed::read_seed(parent_pid)` → daemon lookup in in-memory map.
- M3b: replace `seed::write_seed()` → daemon record in memory on SessionStart hook.
- No other startup path changes.

**REQ-START-1/REQ-START-2 loci:**
- `api seed`: establishes the binding material (REQ-START-1).
- `api listen` / `api bind`: consume binding + establish live perch (REQ-START-2).

---

### **5. spt-live PUBLIC SURFACE — lib.rs**

**Exported for daemon re-hosting (one-line lifecycle each):**

| Export | Module | Role |
|--------|--------|------|
| `spawn_psyche` | psyche.rs:94–102 | Spawn fresh Psyche from `psyche_init` template; bind nested perch; return PsycheHandle. |
| `resume_psyche` | resume.rs:83–100 | Re-entry: validate mode (continue-existing or fresh-with-preload) then spawn from `psyche_resume`. |
| `download_psyche_context` | resume.rs:76–78 | Read stored context for preload (fresh-with-preload resume). |
| `run_echo_commune` | echo.rs:~120 | Spawn `echo_commune` template with history on stdin; write drop file. |
| `ingest_drops` | ingest.rs:55–85 | Fold drops into context.md, delete drops (single-writer guard). |
| `fetch_history` | history.rs:~80 | Read history per manifest `[history]` strategy (native, hook, replay). |
| `graceful_signoff` | signoff.rs:62–96 | Execute ordered signoff: echo → grace → recheck → compose (3.3, 1.1). |
| `sweep_stale_signoff` | signoff.rs:98–120 | Remove stale `<id>-signoff.md` on listener start (3.2). |
| `write_resume_commune` | signoff.rs:~160 | Compose resume brief, write drop file (boundary self-commune). |
| `tick` (pulse) | pulse.rs:62–77 | One pulse cycle: ingest drops, check echo-gate, read idle flag. |
| `compose_psyche_prompt` | psyche.rs:70–85 | spt-core-owned prompt: time + incoming event (adapter fills static preamble). |

**Lifecycle boundary ordering** (incarnate in signoff.rs):
1. **REQ-HAZARD-ECHO-BEFORE-SIGNOFF (3.3)**: `graceful_signoff()` fires echo before composing INIT_SIGNOFF.
2. **REQ-HAZARD-GRACE-BEFORE-SIGNOFF (1.1)**: grace wait + recheck bind `still_gone` before signoff write.
3. **REQ-HAZARD-STALE-SIGNOFF-SENTINEL (3.2)**: `sweep_stale_signoff()` on listener start clears prior generation's sentinel.

**M3b daemon re-hosting:**
- All of lib.rs is **daemon-bound** (not public SDK per comment L8–11).
- Daemon spawns Psyche as a loop (not subprocess); calls these seams as unit-testable functions.
- Pulse period becomes daemon-configurable + daemon-scheduled (not relay-driven).

---

### **6. MOCK ADAPTER LIFECYCLE TEMPLATES — manifest.toml**

**Session roles + seams (daemon-driven in M3b):**

| Role | Command | Detach | CWD | Recursion Guard | M3b Note |
|------|---------|--------|-----|-----------------|----------|
| `session.self` | `mock-session --id {id} --session-id {session_id}` | true | — | — | Outbound session role (the agent); keys: id, session_id |
| `session.psyche_init` | `mock-session --mode psyche ...` | true | `{psyche_dir}` | `MOCK_ECHO_COMMUNE` | Fresh Psyche spawn (T2); spt-live spawns this |
| `session.psyche_resume` | `mock-session --mode psyche ...` | true | `{psyche_dir}` | `MOCK_ECHO_COMMUNE` | Resume re-entry (T7); spt-live spawns this |
| `session.echo_commune` | `mock-session --mode echo --id {id}` | — | — | `MOCK_ECHO_COMMUNE` | Cheap-model brief (T3); spt-live feeds history on stdin |
| `session.signoff` | `mock-session --mode echo --id {id}` | — | — | `MOCK_ECHO_COMMUNE` | Final context-save (T6); alias of echo_commune |

**Watched dirs (file-drops, spt-core writes + deletes):**
```
[session]
commune_dir = ".mock"    # <- <id>-commune.md drops (T3/T4)
signoff_dir = ".mock"    # <- <id>-signoff.md drops (T6/T4)
```

**Hooks (inbound, fire `api` commands):**
```
[hooks.SessionStart]
fires = "api seed --pid {parent_pid} --session-id {session_id} ..."   # T4: ephemeral binding
[hooks.Idle]
fires = "api state idle"   # T5: idle sentinel + gate arm
[hooks.SessionEnd]
fires = "api session-end"  # T7: soft teardown
```

**M3b consolidation:**
- Daemon owns the role spawning (currently hosted by relay loop + ManifestRuntime).
- Daemon invokes `spawn_psyche()`, `run_echo_commune()` seams directly (no relay-loop indirection).

---

### **7. WORKSPACE LAYERING — Cargo.toml + dependency order**

**Acyclic stack (R-ARCH-1, Cargo.toml L1–7):**
```
spt-proto
  ↓
spt-store (persistence + proc liveness)
  ↓
spt-msg (local messaging + registry)
  ↓
{spt-runtime, spt-term} (manifest schema + harness contract)
  ↓
spt-live (lifecycle executor — M2b, daemon-bound NOT SDK)
  ↓
spt-daemon (M3b — NOT YET BUILT)
  ↓
spt (binary — thin CLI layer)
```

**Current `spt` binary deps** (crates/spt/Cargo.toml:13–17):
```toml
spt-proto        # wire (endpoint id validation)
spt-store        # perch + registry
spt-msg          # send/ring/deliver
spt-runtime      # manifest parsing + AgentRuntime
spt-live         # lifecycle seams (spawn_psyche, echo, pulse, etc.)
```

**Workspace members** (Cargo.toml:10):
```
spt-proto, spt-store, spt-msg, spt-term, spt-runtime, spt-live, spt, adapters/mock
```

**spt-live is top-of-stack below binary** (L6 comment: "fifth layer, daemon-bound"):
- spt-live exports the M2b seams (psyche, echo, ingest, pulse, signoff).
- **spt-daemon (M3b) will sit above spt-live** in the stack (not yet created).
- Daemon re-hosts spt-live's functions as a persistent process (replaces relay loop + seed-file interim model).

**M3b insertion point:**
```diff
  spt-live (M2b: lifecycle functions)
+ spt-daemon (M3b: persistent broker + brain, re-hosts spt-live)
  spt (M1/M2a: binary CLI)
```

---

### **8. SUMMARY: ALREADY-BUILT vs NOT-YET-BUILT**

**ALREADY-BUILT (ready for daemon to re-host):**

✅ **spt-live lifecycle seams** (lib.rs exports 10+ functions):
- `spawn_psyche`, `resume_psyche`, `run_echo_commune`, `ingest_drops`, `graceful_signoff`, `sweep_stale_signoff`, `tick`, `fetch_history`, `write_resume_commune`, `compose_psyche_prompt`.
- All are **unit-testable, pure-function wiring** (single-writer guard, ordering invariants baked in).
- Daemon can call these directly; no rewrite needed.

✅ **Liveness probe abstraction** (proc.rs:is_process_alive):
- Single edit point; all downstream (deliver, registry, startup) converge here.
- M3b swap: replace OS probe with daemon status flag.

✅ **Seed-file bridge** (seed.rs):
- Localized, documented swap point; M3b replaces file I/O with in-memory daemon map.

✅ **Ordering invariants** (signoff.rs):
- Echo-before-signoff (3.3), grace-before-signoff (1.1), stale-signoff sweep (3.2) are **implemented as pure functions** (graceful_signoff).
- Daemon re-hosts by calling the same function.

✅ **Activity/idle sentinels** (delivery.rs, pulse.rs):
- `.idle`, `.more-done` (echo-gate) are file-based sentinels.
- Daemon can replicate or demote to in-memory (M3b design choice — not critical to move).

✅ **Manifest schema** (spt-runtime):
- Psyche roles, history strategy, inject methods, lifecycle templates are all parsed.
- Daemon directly uses ManifestRuntime to spawn roles.

---

**NOT-YET-BUILT (M3b task list):**

❌ **spt-daemon binary crate** — the persistent broker process.
- Doesn't exist; must be created above spt-live in stack.

❌ **Daemon brain** — in-memory perch + psyche + session state:
- Replaces file-based perch records + seed-files with authoritative in-memory map.
- Maps agent id → perch state (online/offline, session_id, parent_pid, psyche_pid, context).

❌ **Daemon-authoritative liveness**:
- Daemon owns per-agent uptime flag; replaces OS `is_process_alive()` checks for hosted perches.
- Edit point: proc.rs:is_process_alive returns daemon status (for daemon-hosted) or OS probe (for external perches).

❌ **Daemon broker** (message routing):
- Replaces registry TCP lookup + fallback spool with daemon-mediated delivery (already connected, no reconnect).
- spt binary sends to daemon; daemon routes to target perch or spools.

❌ **Daemon listener consolidation**:
- Replaces `api listen` relay loop with daemon-driven delivery.
- spt binary + hooks call daemon endpoints instead of `api listen`.

❌ **Auto-start mechanism**:
- Daemon must auto-spawn on first SPT activity.
- Replace SessionStart → `api seed` → `api listen` with SessionStart → daemon spawn request.

❌ **Idempotent boundary** (T7):
- Daemon re-entry across suspended sessions (boundary rotate + resume).
- REQ-SEAM-RESUME validation + psyche re-spawn (daemon-owned life cycle).

---

### **TASK PLAN ORDERING (M3b scaffold)**

1. **Create spt-daemon crate** (scaffold above spt-live; Cargo.toml member).
2. **Build daemon brain** (in-memory perch map; session state struct).
3. **Implement broker** (message routing; TCP listener to hook into registry/deliver).
4. **Consolidate listener** (replace `api listen` relay loop → daemon delivery loop).
5. **Daemon-authoritative liveness** (edit proc.rs; daemon status flag for hosted perches).
6. **Idempotent boundary** (T7 daemon re-entry; validate + resume keys before spawn).
7. **Auto-start** (daemon spawn on first SessionStart hook).
8. **Integrate spt binary** (thin wrappers → daemon RPC calls).

---

**KEY SEAM REFERENCES FOR ARCHITECT:**

| M3b Task | File:Line | Current | Daemon-bound |
|----------|-----------|---------|--------------|
| Listen loop | startup.rs:221–230 | `api listen` relay | daemon loop |
| Pulse driver | startup.rs:228 | relay-driven 5s | daemon-scheduled period |
| Liveness | proc.rs:9–34 | OS probe | daemon status |
| Perch binding | startup.rs:83–97 | seed-file → perch | in-memory → perch |
| Seed bridge | seed.rs:49–54 | ephemeral file | daemon in-memory |
| Psyche spawn | live.rs:106–119 | relay-hosted | daemon-hosted |
| Echo-commune | live.rs:159–174 | relay-invoked | daemon-invoked |
| Signoff order | signoff.rs:62–96 | graceful_signoff fn | daemon calls same fn |
| Message route | deliver.rs:93–124 | registry TCP + spool | daemon broker |
| Activity idle | delivery.rs:36–61, pulse.rs:70 | file sentinels | daemon state + sentinels |</result>
<usage><subagent_tokens>80061</subagent_tokens><tool_uses>34</tool_uses><duration_ms>107062</duration_ms></usage>
</task-notification>


Recon complete — full seam map in hand. I have everything to author the plan: ADR-0004 (broker/brain contract + closed spikes), CONTEXT model, the M3b reqs, and file:line seams. Writing the full `M3b-PLAN.md` (replacing the stub).