@tryinget/pi-autonomous-session-control
pi extension package for autonomy-control workflows in pi
Package details
Install @tryinget/pi-autonomous-session-control from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@tryinget/pi-autonomous-session-control- Package
@tryinget/pi-autonomous-session-control- Version
0.7.0- Published
- Sep 2, 2026
- Downloads
- 1,923/mo · 451/wk
- Author
- tryinget
- License
- MIT
- Types
- extension, prompt
- Size
- 1.2 MB
- Dependencies
- 0 dependencies · 3 peers
Pi manifest JSON
{
"extensions": [
"./extensions/self.ts"
],
"prompts": [
"./prompts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
summary: "Overview and quickstart for pi-autonomous-session-control." read_when:
- "Starting work in this repository." system4d: container: "Repository scaffold for a pi extension package." compass: "Ship small, safe, testable extension iterations." engine: "Plan -> implement -> verify with docs and hooks in sync." fog: "Unknown runtime integration edge cases until first live sync."
pi-autonomous-session-control
Monorepo-home package for subagent lifecycle hardening, failure recovery, and operator visibility in pi.
Canonical package path: packages/pi-autonomous-session-control
Workspace placement
For workspace-level placement and ownership boundaries, read:
~/ai-society/holdingco/governance-kernel/docs/core/definitions/ai-society-stack-map.md~/ai-society/softwareco/owned/agent-kernel/docs/project/ai-society-convergence-architecture.md~/ai-society/softwareco/owned/pi-extensions/packages/pi-society-orchestrator/docs/project/subagent-execution-boundary-map.md~/ai-society/softwareco/owned/pi-extensions/packages/pi-society-orchestrator/docs/adr/2026-03-11-control-plane-boundaries.md
Short version:
- this package is the strongest current Pi-side execution/runtime owner
- it is not the canonical society-state authority (
ak/AK own that) - it is not the workspace-wide control board (FCOS/governance-kernel own that)
- package-local control-plane coordination belongs in
pi-society-orchestrator
Cross-package execution-boundary packet
If the work is about how ASC should expose its runtime to pi-society-orchestrator, start with the orchestrator-owned packet docs:
../pi-society-orchestrator/docs/project/subagent-execution-boundary-map.md../pi-society-orchestrator/docs/adr/2026-03-11-control-plane-boundaries.md../pi-society-orchestrator/docs/project/2026-03-10-rfc-asc-public-execution-contract.md../pi-society-orchestrator/docs/project/2026-03-10-architecture-convergence-backlog.md
Interpretation:
- the ADR decides that ASC remains the execution-plane owner
- the RFC describes the first public runtime seam ASC should expose
- the backlog / AK tasks describe the implementation order
- this package README describes the current runtime owner reality, not the seam design by itself
Quickstart
Install dependencies:
npm installTest with pi (one-off, doesn't persist):
pi -e ./extensions/self.tsFor active development, rely on auto-discovery:
When you're in this project directory, pi automatically discovers the
package.jsonand loads extensions defined inpi.extensions. No manual install needed.
Local Development vs Global Install
Important: Avoid double-loading by understanding pi's package identity:
| Source | Identity |
|---|---|
| npm package | Package name (@tryinget/pi-autonomous-session-control) |
| git source | Repository URL |
| Local path | Resolved absolute path |
During local development:
- Do NOT add this package to global
~/.pi/agent/settings.json - Rely on project auto-discovery when working in this directory
- Use
pi -e /path/to/packageif you need the extension in another project temporarily
After publishing to npm:
pi install npm:@tryinget/pi-autonomous-session-control
When both exist:
- Local path and npm package are DIFFERENT identities → both load → conflicts
- Solution: During active development, remove the npm entry from global settings
To temporarily disable a global package while developing locally:
# Remove from global settings
pi remove npm:@tryinget/pi-autonomous-session-control
# Or manually edit ~/.pi/agent/settings.json and remove from packages array
To quickly test the extension in another project without installing:
pi -e /path/to/pi-autonomous-session-control
Runtime dependencies and packaged files
This extension expects pi host runtime APIs and declares them as peerDependencies:
@earendil-works/pi-coding-agent@earendil-works/pi-ai
For npm publishing, package.json uses a files whitelist so required runtime artifacts are explicit:
extensions/self.tsextensions/self/dist/— precompiled JavaScript public execution graph and transport helper executed throughnodefrom installed packagesprompts/examples/policy/security-policy.json
If your extension also needs extra runtime assets, add them to files intentionally.
Shared engineering policy now stays root-owned rather than shipping a package-local stack metadata file.
Prompt surfaces and provenance
ASC owns two distinct prompt-related surfaces:
- package-owned prompt assets in
prompts/, exposed throughpackage.json#pi.promptsand shipped with the package install - runtime prompt-envelope provenance returned by
dispatch_subagentresult details when callers provideprompt_name,prompt_content,prompt_tags, andprompt_source
Keep those surfaces separate from repo-root .pi/prompts/* operator prompts in the monorepo root.
Mock/unit prompt-vault contract tests run in the default package check. Live prompt-vault files use the non-default .live.mjs suffix, so npm run check does not discover them and reports zero live prompt-vault skips. The live cross-extension harness is host-dependent and opt-in; run npm run test:live:prompt-vault (or set ASC_RUN_LIVE_PROMPT_VAULT_TESTS=1) to prove the vault_query -> vault_retrieve -> dispatch_subagent chain preserves prompt provenance coherently, including the vault-client-live source label. When no PI_VAULT_CLIENT_DIR / VAULT_CLIENT_DIR override is set, the harness tries the legacy installed extension path and then the monorepo sibling ../pi-vault-client package.
Prompt-vault compatibility self-check
The self-prompt-vault-compat command reports the ASC package version, vault-client version, and prompt-vault schema version. Its ASC floor now comes from a safer feature/manifest policy: source manifests that declare the ASC package name, the public ./execution export, and shipped extensions/self runtime files may use the package source floor (0.1.0), while missing/unparseable or feature-incomplete manifests fall back to the historical prompt-envelope floor (0.1.3). This avoids certifying arbitrary low manifests (for example 0.0.1) solely because their checked package version is low. The Dolt schema probe is timeout-bounded and reports schema unavailable instead of hanging when the prompt-vault DB is slow or wedged.
Capability discovery surfaces
The self tool accepts operational handoff queries such as controller handoff summary and closeout summary. These summaries are mirror-only: they aggregate tracked file touches, recent commands, errors, progress/stall state, loop state, file-budget advisories for touched files, context-pressure heuristics, and handoff cues for the caller to decide what to report. Context-pressure cues are deliberately heuristic: they can notice many turns, repeated install/reload/commit lifecycle commands, or multiple AK task-completion commands and suggest preparing a handoff, but they do not claim exact context-window/token budget or remaining capacity. They are not durable evidence, AK/KES authority, validation authority, or a controller. For proactive compaction/reload handoffs, canonical fresh-session prompt shape now belongs to pi-session-compaction (/compact-handoff and the session_compaction_handoff tool). self({ query: "create self-contained handoff prompt" }) remains only an ASC mirror/convenience bridge when ASC has useful session-local cues; it must not become the canonical compaction engine. The prompt remains mirror-only and explicitly points fresh sessions back to git/AK/session evidence when ASC evidence is sparse after reload. When a handoff includes nextMove, self({ query: "prefill suggested next move" }) copies that exact operator-facing suggestion into the Pi editor. For agent-actionable low-risk continuations, self({ query: "continue suggested next move" }), self({ query: "continue safely" }), and self({ query: "next autonomous step" }) send a follow-up user message through pi.sendUserMessage; harness/peer/compaction/high-severity moves remain editor-prefilled for operator review instead of being advanced silently. controller handoff summary, explicit record continuation candidate: <text>, and the guarded continuation actions record a fresh same-cwd self.continuation_candidate.v1 when they can see or are given a nextMove. Explicit recording stores a mirror-only hint only; it does not send, execute, launch peers, or write owner truth. When the current operation mirror is sparse after reload, guarded continuation queries may reuse scoped ASC memory; stale, cross-cwd, peer/harness/compaction/campaign/commit/evidence/release-like candidates still fail closed or prefill for review. For explicit low-risk operator notifications, self({ query: "notify operator: <message>" }) and self({ query: "send user message: <message>" }) route through the same pi.sendUserMessage follow-up seam; missing text and likely secret material fail closed, while action-directive text such as commands, peer launches, commits, durable records, or compaction is editor-prefilled for operator review rather than sent. Slash-command-looking text at the start of a message/line or embedded as a command token is never injected through pi.sendUserMessage; ASC reports whether editor prefill actually happened (operator_submit_required) or, when no UI is available, returns operator_manual_submit_required copy/submit instructions because extension-originated follow-up messages do not invoke Pi slash-command expansion and ASC must not become a hidden loop/campaign launcher.
The self tool also accepts self memory status / memory lifecycle status as a mirror-only status surface for its own scoped memory persistence. It reports the last persisted-memory load status plus counts for patterns, semantic-pressure annotations, traps, checkpoints, follow-ups, and continuation candidates; it does not promote ontology candidates, write evidence, record vents, launch loops, or create durable owner truth.
self({ query: "action summary" }) reports checkpoint/followup totals plus mirror-only continuation candidate counts/previews, separating current-cwd fresh candidates from cross-cwd or expired candidates so agents can inspect whether a same-cwd continuation hint exists before asking the operator to restate context.
Follow-up send policy (self-driving budget)
Every extension-originated pi.sendUserMessage follow-up in ASC goes through one canonical policy kernel (extensions/self/follow-up-policy.ts):
- Fail-closed continuation posture. Continuation-class sends (
agent_continuation) require the action line to affirmatively match a narrow low-risk local-validation command allowlist (npm/pnpm/yarn/bun ... test|check|lint|build|verify,just check-family,npx tsc,node --test). Everything else degrades to editor prefill withoperator_review_required; the old denylist (requiresOperatorReview) remains as a second layer. - Self-driving budget. At most 3 consecutive continuation-class and 8 consecutive notification-class follow-ups may be delivered without an intervening operator-authored user message (
message_startwith roleuserthat is not one of our own pending follow-up texts resets both counters). Over-budget sends are blocked to prefill withself_driving_budget_exhausted. Env overrides:PI_SELF_MAX_CONSECUTIVE_FOLLOW_UPS,PI_SELF_MAX_CONSECUTIVE_NOTIFICATIONS. - Dedup cooldown. Identical follow-up text inside a 10-minute cooldown is suppressed to prefill (
self_driving_dedup_suppressed) instead of re-sent. - Autonomy-mode gate.
PI_SELF_SEND_USER_MESSAGE_MODEbinds the runtime to the autonomy ladder:notifications_only<bounded_continuation<owner_bridge(default ceiling, preserving the established allowlisted/visible-loopowner-bridge route). Lower modes block higher classes to prefill withself_driving_mode_gate. - Guarded send seam. The
pi.sendUserMessagecall is wrapped; a runtime failure reportsuserMessageSendFailed, falls back to editor prefill when a UI exists, and is tracked as an error instead of surfacing as an opaque tool error. - Effect linkage. A delivered continuation send marks its
self.continuation_candidate.v1consumed (consumedByFollowUpId); consumed candidates are never re-selected for later sends. - Telemetry. Send outcomes are recorded as
self.follow_up_send.v1records and surfaced inaction summary(data.followUpPolicyplus afollow-up sends sent=... blocked=...sentence) so the operator can audit how much self-driving actually happened. - Declared kinds.
send user message/notify operatoracceptscontext.kind(notification|status|continuation); a declaredcontinuationmust still contain an affirmative low-risk action line or it fails closed to prefill. Declarations select the policy tier and never bypass validation.
The owner-bridge allowlist is a versioned registry (OWNER_BRIDGE_SEND_ALLOWLIST) instead of an inline hard-coded triple, so a /visible-loop flag-set change in pi-little-helpers updates one reviewed entry.
The self tool accepts autonomy status / what level of autonomy is needed? as a mirror-only explanation of the self-driving envelope. It makes the autonomy ladder explicit: Level 3 for supervised multi-session discovery/review, Level 4 for visible-loop campaigns, Level 5 for measured campaigns, and Level 6 only for explicitly gated durable owner-surface mutation. This status is not permission by itself and does not authorize hidden infinite loops, unbounded peer launch, candidate merge, owner writes, releases, or publication.
self({ query: "cache-aware delegation: tree or fork?" }) returns typed mirror-only routing advice for /tree, /tree then /clone, /fork, and clean dispatch_subagent. It reads current provider/model/context pressure when available, explains that only in-place /tree preserves the Pi session identity, and refuses to claim that any branch operation clones provider KV-cache state. Session replacement remains command-context-only: a model-callable tool may advise or prefill /tree, but must not navigate or replace its own active session during a tool turn.
The self tool also accepts diagnostic-review queries such as dogfood self, self-evolution, evolve self, how can self improve?, and what friction just happened?. Diagnostic review is still mirror-only: it can name moment-level friction, return a typed self.diagnostic_candidate.v1 payload, and suggest toolbox/agent_vent follow-up, but it does not write agent_vent records, create AK tasks/evidence, open issues, declare incidents, or persist diagnostic recurrence truth inside ASC. When callers provide explicit correction/focus context, diagnostic review prefers that context over recent mirror error evidence so a stale failed command does not hijack a package-specific self-evolution request. self({ query: "continue diagnostic review" }) may send a low-risk pi.sendUserMessage follow-up that keeps working on the mirror-only diagnostic candidate; durable local diagnostic writes such as self({ query: "prefill agent_vent record" }) remain editor-prefilled for operator review and now prefill agent_vent action=preview before any record write. The cross-package handoff contract is documented in Self, toolbox, and agent_vent diagnostic boundary.
Loop/stall responses from self are mirror-only advisories. Repeated successful validation, provenance-helper, VCS, or AK-completion commands may indicate productive workflow rather than stuckness; stall signals may coexist with recent command evidence when the mirror has not seen a recent file change. The caller decides what the session-local evidence means in task context.
The self tool accepts capability meta-queries such as What can you do?, capability discovery, and capability routing. Its response intentionally distinguishes five surfaces:
selfquery domains: perception, direction, crystallization, protection, and action queries understood by the ASC self mirror. Action-domain checkpoints and follow-ups are restart-persistent and can be reviewed withaction summarybefore Level-4 handoff or dogfood closeout.- Toolbox/bundle discovery: use the Pi
toolboxtool to search, explain, activate, deactivate, or inspect extension bundles. ASC does not add or replace that tool. Recurring agent frustration diagnostics belong to the separatepi-agent-ventpackage and same-namedagent_venttoolbox bundle/tool, not ASC/self state. - Parallel work routing: use ASC-owned
dispatch_subagentfor bounded investigation, review, or testing when parallel cognition reduces risk or latency. Use visible candidate peers only when the controller/operator explicitly wants an isolated worktree mutation lane; candidates propose patches and do not merge, push, or promote themselves. - Repo/lane capability-map routing: use documentation surfaces such as
repo-capability-map.mdandpi-extensions/docs/project/root-capabilities.mdto choose owning repos/packages and read-first docs. These maps are routing guidance, not runtime authority. - Durable authority boundaries: use AK/KES/evidence systems for canonical work-item, knowledge, and evidence state.
selfmemory remains a session mirror/candidate scratchpad, not canonical AK/KES/evidence authority.
Public execution contract
ASC now exposes a supported package-level execution seam for non-tool consumers:
import { createAscExecutionRuntime } from "@tryinget/pi-autonomous-session-control/execution";
const runtime = createAscExecutionRuntime({
sessionsDir: "/tmp/pi-subagent-sessions",
modelProvider: () => "openai-codex/gpt-5.4",
});
const controller = new AbortController();
const result = await runtime.execute(
{
profile: "reviewer",
objective: "Review the staged changes for risk and missing tests.",
},
{ cwd: process.cwd() },
undefined,
controller.signal,
);
modelProvider may also inspect the execution context (for example ctx?.model) when you want public-runtime consumers to mirror the active session model instead of hard-coding one.
What this seam guarantees:
- the same core execution logic now backs both
dispatch_subagentand public runtime consumers - prompt-envelope application, request env policy, lifecycle invariants, runtime-owned concurrency reservation, session-name reservation, result shaping, assistant protocol classification, and abort propagation stay ASC-owned
- runtime options and caller-supplied session/capacity identity are captured and hardened at construction, so retained caller references cannot inject a later spawner/model resolver or redirect capacity/receipt storage
resolveSubagentSessionsDir,getPiNativeSessionDirForCwd, andresolvePiAgentDirexpose ASC-owned path resolution without importing Pi host APIs into the compiled headless graph- raw
spawnSubagentandspawnSubagentWithSpawnvalues are intentionally absent from the public execution entrypoint; usecreateAscExecutionRuntimerather than bypassing its admission/capacity contract - result surfaces now use one normalized failure taxonomy: canonical
result.details.status(done,aborted,timed_out,error) plusresult.details.failureKindfor the specific failure branch - a dedicated parity harness now proves those shared semantics stay aligned across the public runtime and the tool path
- downstream consumers should prefer
@tryinget/pi-autonomous-session-control/executionover privateextensions/self/*imports
Current verification split:
- ASC package-local tests prove seam semantics and transport-safety invariants
- ASC packed transport smoke imports the installed execution artifact, requires the path resolver, and proves raw spawn value exports remain absent
packages/pi-society-orchestrator/tests/runtime-shared-paths.test.mjsproves the narrow consumer-side adapter still preserves those semantics in repo-local sourcepackages/pi-society-orchestrator/tests/execution-seam-guardrails.test.mjsfail-closes drift back to private ASC imports or a revived orchestrator-local execution pathnpm run test:live:prompt-vaultopts into host-dependent live prompt-vault validation; it runstests/prompt-vault-db-integration.live.mjsandtests/prompt-vault-cross-extension.live.mjsto prove real DB/vault-client coherence with ASC-owned prompt provenance ondispatch_subagent; defaultnpm run checkdoes not discover live prompt-vault filescd packages/pi-society-orchestrator && npm run release:checkproves installed-package/import-graph truth for the packaged orchestrator artifact, including the current bundled ASC bridge while the temporary lifecycle defined in bundled ASC bridge lifecycle remains in force- the first time-boxed execution seam review still counts only one real external runtime consumer today (
pi-society-orchestrator), so no seam widening is justified
Companion package doc:
When using UI APIs (ctx.ui), guard interactive-only behavior with ctx.hasUI so pi -p non-interactive runs stay stable.
Repository checks
Run:
npm run check
check routes to quality:ci via scripts/quality-gate.sh.
It enforces structure validation, Biome lint checks, optional TypeScript typechecks, default unit/mock tests, and npm pack dry-run. Host-dependent live prompt-vault DB / vault-client tests are not discovered by default because they use .live.mjs filenames; run them explicitly when the host has the vault DB, Dolt, and vault-client runtime available:
npm run test:live:prompt-vault
# equivalent env gate for focused node --test runs:
ASC_RUN_LIVE_PROMPT_VAULT_TESTS=1 node --test tests/prompt-vault-db-integration.live.mjs tests/prompt-vault-cross-extension.live.mjs
Quality gate lane (TS)
- formatter/lint baseline:
- biome.jsonc
- .vscode/settings.json (Biome formatter + code actions on save for JS/TS/JSON)
- pinned local binary via
@biomejs/biomeindevDependencies
- scripts/quality-gate.sh stages:
pre-commitpre-pushci
- npm script entry points:
npm run quality:pre-commitnpm run quality:pre-pushnpm run quality:ci
- helper scripts:
npm run fix(auto-fix)npm run lint(check-only)npm run typecheck
- root-owned stack review surface:
Release + security baseline
This package now uses the root-owned monorepo release control plane in component mode. It keeps its own independent release cadence, but the workflows/config live at monorepo root.
Relevant root-owned files:
- CI workflow
- release-check workflow
- release-please workflow
- publish workflow
- release-please config
- release-please manifest
- root component helper
- release-check script
- Security policy
Trusted-publishing defaults now relevant to this package:
- release tags are component-scoped (
pi-autonomous-session-control-vX.Y.Z) - root release-please action is pinned to an immutable v4.4.0 SHA
- root publish and release-check workflows both upgrade npm (
>=11.5.1) for consistent trusted publishing behavior - setup-node uses
package-manager-cache: falseto avoid implicit caching behavior changes from setup-node v5+ - package metadata must include
repository.urlmatching the GitHub repo for npm provenance verification
Recommended before release:
npm run release:check
# quick mode for CI / no local pi smoke
npm run release:check:quick
Optional: add an executable scripts/release-smoke.sh for extension-specific smoke checks.
release-check.sh will run it with isolated PI_CODING_AGENT_DIR and PACKAGE_SPEC env vars.
Before first production release under root automation:
- Confirm/adjust owners in ../../.github/CODEOWNERS.
- Enable branch protection on
main. - Confirm GitHub Actions repo settings:
- workflow permissions:
Read and write - allow GitHub Actions to create/approve PRs
- allowed actions policy permits marketplace actions used by workflows
- workflow permissions:
- Configure npm Trusted Publishing for the monorepo repo + root publish workflow.
- If this is a brand-new npm package, perform one bootstrap token publish first, then add the trusted publisher in npm package settings.
- Let root release-please open the component release PR, then publish from the GitHub release.
Issue + PR intake baseline
Included files:
- Bug report form
- Feature request form
- Docs request form
- Issue template config
- PR template
- Code of conduct
- Support guide
- Top-level contributing guide
Vouch trust gate baseline
Included files:
Default behavior:
- PR workflow runs on
pull_request_target(opened,reopened). require-vouch: trueandauto-close: trueare enabled by default.- Maintainers can comment
vouch,denounce, orunvouchon issues to update trust state. - Vouch actions are SHA pinned for reproducibility and supply-chain review.
Bootstrap step:
- Confirm/adjust entries in .github/VOUCHED.td before enforcing production policy.
Docs discovery
Run:
npm run docs:list
npm run docs:list:workspace
npm run docs:list:json
Canonical implementation: node ~/ai-society/core/agent-scripts/scripts/docs-list.mjs
Resolution order:
DOCS_LIST_SCRIPT./scripts/docs-list.mjs(if vendored)~/ai-society/core/agent-scripts/scripts/docs-list.mjs
TypeScript lane reference for pi extensions:
uv tool run --from ~/ai-society/core/engineering-core engineering-core show pi-ts --prefer-repo
Shared lane stance for this monorepo now lives at root in ../../docs/engineering.local.md.
Copier lifecycle policy
- Keep
.copier-answers.ymlcommitted. - Do not edit
.copier-answers.ymlmanually. - Run from a clean destination repo (commit or stash pending changes first).
- Use
copier update --trustwhen.copier-answers.ymlincludes_commitand update is supported. - In non-interactive shells/CI, append
--defaultsto update/recopy. - Use
copier recopy --trustwhen update is unavailable (for example local non-VCS source) or cannot reconcile cleanly. - After recopy, re-apply local deltas intentionally and run
npm run check.
Hook behavior
- Git hooks path is configured to
.githooksby scripts/install-hooks.sh. - .githooks/pre-commit runs:
scripts/quality-gate.sh pre-commit- check-only (auto-fix with
npm run fix)
- .githooks/pre-push runs:
scripts/quality-gate.sh pre-push
- Repo-local commit workflow prompt:
Subagent Configuration
The dispatch_subagent tool spawns subagents with configurable model selection:
Model selection priority:
PI_SUBAGENT_MODELenvironment variable (override)- Current session model (
<provider>/<model-id>) when available - Fixed fallback:
openai-codex/gpt-5.4
The child still launches with --no-extensions, but ASC supports explicit and narrowly inherited child-only extension bootstrap on top of that minimal base. Empty or whitespace-only requested/effective model selections fail before spawn as structured model_selection_failed results and do not expose internal concurrency counters. When the current model uses a numeric-suffix provider alias such as openai-codex-2, ASC auto-loads pi-multi-pass into the child so the same subscription-backed provider alias remains valid instead of being collapsed to the base provider. When pi-better-openai publishes its versioned fast-state event, ASC loads that package's minimal fast-child.ts request hook and passes the parent's exact desired on/off mode through an ASC-owned environment key; it does not load the full Pro/image extension surface. ASC also launches the raw child against an isolated copy of the Pi agent dir with a sanitized settings.json, so extensionless child runs do not inherit unrelated global default-model warnings from the parent's configured provider aliases.
Dispatch contract and lifecycle policy:
- Legacy
{ profile, objective }requests remain supported. Optional structured fields adddeliverable,acceptanceCriteria,constraints,evidenceRequired,mutationPolicy,stopConditions,allowedPaths, andforbiddenPaths; path fields are advisory task scope, not a filesystem sandbox. - Pi's host prompt, loaded project context, and child tool schema form the stable request prefix. ASC places profile instructions, prompt-envelope content, and the typed task contract once in the initial user message after that prefix; it does not duplicate the objective as a separate user message or insert task variation ahead of project context.
- The compatibility request field
systemPromptnow means custom child instructions in that initial task message. Prompt-envelope provenance fields are unchanged, butprompt_contentis likewise task-message content rather than an early system-prefix mutation. objectivemust be a non-empty string. ASC imposes no objective character-count ceiling and does not truncate the normalized objective; available host/model context remains the natural capacity boundary.- When
thinkingis omitted, the tool path inherits the current parent session's effective thinking level. An explicit request value wins; profile defaults remain the fallback for headless/public-runtime callers that provide no parent thinking level. startupTimeoutis separately bounded from the execution deadman. Startup defaults to 30 seconds; execution defaults to a 4-hour emergency deadman so healthy modern-agent work is not killed by the former five-minute default.timeout=0is unlimited only whenallowUnlimited=trueand the host setsPI_SUBAGENT_ALLOW_UNLIMITED_TIMEOUT=true.- Each new dispatch gets a stable
dispatchIdand per-runattemptId. The canonical dispatch ID is printed in model-visible result content before child output so callers can copy it exactly even when child output is truncated. Only an exact repository- and parent-session-checkedresumeDispatchIdresumes an existing canonical JSONL; current and legacy token formats are accepted only when persisted status metadata matches exactly, missing ownership metadata fails closed, and repeated names keep collision-safe new-session behavior. /subagent-cancel <dispatchId> [reason]and publicruntime.cancel(...)target one live child with verified process-start identity. Unsupported identity fails closed, failed signals roll back cancellation intent, and custom-spawner sidecars are observable but cannot signal the parent Pi process.- Progress updates expose bounded phase/sequence, latest-tool, activity, and usage metadata. Completed owned runs add first-turn and aggregate prompt-cache samples (
promptTokens, fresh input, cache read/write, uncached tokens, cache-read ratio, output tokens, and provider cost) plus wall time. The model-visible result includes a compact measurement line. These are observed provider-usage measurements, not proof of reasoning cost, result quality/overlap, or a provider KV-cache clone. The extension adapter also emits a sanitizedasc.execution_observation.v1host event containing no objective, prompt, output, stderr, session path, environment value, or receipt path.pi-little-helpersmay render that event in a read-only Ghostty observer, but listener/launch failure is swallowed and never changes ASC execution or effect truth. The helper probespi --versionand declares settlement capability intransport_ready: Pi >=0.80 requires exactly one authoritativeagent_settledafter the final terminal assistant outcome. The retained Pi 0.76 mode instead requires clean foreground JSON-mode exit plus finalagent_end.willRetry=falseafter that outcome; undeclared streams cannot select this fallback, and unclassified versions fail closed. - The public runtime returns structured failure results. The
dispatch_subagenttool adapter throws those failures so Pi records the tool invocation as an error rather than a successful tool call containing{ status: "error" }. - An owned helper exit before its synchronous
raw_child_spawn_intentmarker is classified assubagent_helper_bootstrap_failedand may carryconfirmed_no_effectsonly when the parent observed an otherwise unambiguous protocol stream. Missing intent after malformed, oversized, or out-of-order protocol data stays effect-indeterminate. Once intent is observed, a nonzero exit before a valid terminal assistant outcome and settlement istransport_exited_before_settlementand also remains effect-indeterminate. Both paths preserve bounded transport stderr, exit code, and exit signal when present; partial child work never becomes success.
Request env policy:
DispatchSubagentRequest.envis a per-dispatch child environment overlay for provenance sidecars only.- Allowed keys must match
PI_PROVENANCE_*(for examplePI_PROVENANCE_REVIEW_LANE_IDorPI_PROVENANCE_OUTPUT_FILE). - All other request env keys, including
PATH,NODE_OPTIONS, andPI_CODING_AGENT_DIR, fail before spawn as structuredenv_policy_failedresults; there is no privileged passthrough escape hatch. - Allowed request env values reach the spawned helper/child process but are not echoed in result details.
Child skill profile policy:
- Clean children default to
--no-skills, keeping ambient skill discovery out of the prompt and making sibling prompt prefixes more stable. DispatchSubagentRequest.skillProfileresolves a named profile through the ai-society skill registry, keeps--no-skills, and passes a temporary materialized--skill <dir>.noSkills: falseis an explicit compatibility opt-out that restores ordinary child skill discovery when no named profile is selected.- Raw
skills[]path requests are reserved and rejected fail-closed; use named profiles rather than caller-supplied paths. - ASC reports
skillProfile,loadedSkills,librarySkills,skillWarnings, andskillRegistryin result/update details, but does not install, promote, or mutate skill-library sources.
Session storage:
- Default storage now uses an ASC-owned subdirectory inside Pi's native session tree for the current cwd:
~/.pi/agent/sessions/--<encoded-cwd>--/asc-subagents/. PI_CODING_AGENT_SESSION_DIRis respected when Pi is configured to use a custom native session directory.PI_SUBAGENT_SESSIONS_DIRremains an escape hatch for a separate ASC-owned directory.PI_SUBAGENT_CLEAR_ON_SESSION_START— legacy startup cleanup flag; retained as a no-op compatibility knob because ASC preserves subagent traces by defaultPI_SUBAGENT_ALLOW_DESTRUCTIVE_CLEANUP— legacy compatibility knob; startup cleanup no longer deletes traces, use/subagent-clear --deleteor/subagent-cleanup --delete ...for explicit destructive pruningPI_SUBAGENT_RESERVE_SESSION_NAMES— set tofalseto disable in-memory + file-lock reservation for rollback/debugging (default: enabled); owned status sidecars still occupy recorded session names to prevent trace reusePI_SUBAGENT_FILE_LOCK_SESSION_NAMES— set tofalseto disable only cross-process file-lock reservation while keeping in-memory reservation (default: enabled; ignored whenPI_SUBAGENT_RESERVE_SESSION_NAMES=false)PI_SUBAGENT_LOCK_STALE_AFTER_MS— stale-lock reclamation threshold in milliseconds for orphaned subagent locks that no longer have a live owning PID (default:3600000)PI_SUBAGENT_EVENT_BUFFER_BYTES— buffer for the filtered assistant-only subagent protocol consumed by ASC (default:262144)PI_SUBAGENT_DEFAULT_TIMEOUT_MS— positive default emergency execution deadman in milliseconds (default:14400000, four hours); explicit request timeouts still override it, while zero/unlimited remains separately gatedPI_SUBAGENT_STDERR_CHARS— maximum retained transport stderr characters for model-visible failure diagnostics and bounded status previews (default:16000)PI_SUBAGENT_RAW_PI_EVENT_BUFFER_BYTES— raw upstreampi --mode jsonline buffer inside the filter helper before aggregate events are dropped (default:8388608)
Session artifact notes:
- Subagent child runs are stored as
.jsonlPi session files so Pi-native session tooling, export/share workflows, and future dataset pipelines can discover the raw LLM trace. - ASC keeps its lifecycle metadata in sidecars next to the child session (
<session>.status.jsonand transient<session>.lock) rather than creating a separate hidden session world by default. - Human Pi sessions in the same native directory are ignored by ASC statistics and by any explicitly destructive ASC cleanup unless they have an ASC status sidecar.
/subagent-clearand/subagent-cleanuppreserve traces by default; they delete only when passed--delete. Startup cleanup does not delete traces.- Destructive pruning only deletes expected ASC trace names (
<session>.jsonl/ legacy<session>.json) plus matching ASC sidecars; a status sidecar cannot point deletion at an arbitrary contained trace. - Unless
PI_SUBAGENT_MODELoverrides it, subagents inherit the current session model when Pi exposes one; the fixed fallbackopenai-codex/gpt-5.4is only used when no current model is available. - When that requested model points at a numeric-suffix provider alias supplied by an extension (for example
openai-codex-2from multi-pass), ASC preserves that exact requested/effective model and auto-loadspi-multi-passinto the child runtime. - When the parent has
pi-better-openailoaded, each dispatch inherits the parent's current/fastdesired state, including non-persisted toggles. The child receives only the minimal priority-request hook; later parent toggles do not retroactively change an already-running child. dispatch_subagentalso acceptsextensions: ["vault-client", "/abs/path/to/ext.ts", ...]so a subagent can opt into specific extension-provided tools without inheriting the full parent extension surface.dispatch_subagentacceptsskillProfile: "minimal" | "ak" | "governance" | "dspx-skill-authoring"when the child should load an allowlisted skill profile without inheriting all parent skills.- Result details expose the selected model (
requestedModel/effectiveModel),configuredThinking, optionalinheritedFastMode, and explicit child bootstrap metadata (loadedExtensions,extensionWarnings,skillProfile,loadedSkills,librarySkills,skillWarnings,skillRegistry). - Subagent transport now runs through a precompiled package-local JavaScript assistant-only JSON filter helper, so installed packages do not depend on Node TypeScript stripping or an ambient loader and large aggregate Pi payloads are removed before ASC parses the stream:
agent_endis reduced to boundedagent_run_end.willRetrymetadata for audited Pi 0.76 finality, whileturn_endandtool_execution_endare dropped. - ASC now treats the helper protocol as authoritative: raw Pi JSON events on the parent seam fail closed instead of being accepted as a compatibility fallback.
- Before spawning raw Pi, the current versioned helper (
subagent-pi-json-filter-v2) starts a dormant detached raw supervisor, acquires the same per-slot transition fence used by stale takeover, revalidates the exact lease, immutably publishes supervisor/process-group custody and the exact-token spawn marker, synchronously emitsraw_child_spawn_intent, and only then opens the supervisor start gate. Takeover and helper start are therefore mutually exclusive even when the parent dies inside that handoff. The parent still requires intent before readiness or lifecycle events; once intent is observed, later failures remain effect-indeterminate unless another owned attestation proves otherwise. - Helper protocol generations use additive producer and parser filenames because a long-lived parent keeps its parser in memory while a source-path package checkout can change underneath it. Newly loaded parents bind to the paired
subagent-pi-json-filter-v2/subagent-protocol-v2graph, and any future incompatible ordering must use a new generation rather than rewritingv2. - The unversioned helper remains intent-v2 compatible for parents already loaded during the original
8852cbf7transition. A stricter pre-8852cbf7parent cannot share that same mutable filename because it requirestransport_readyfirst; those already-running sessions require one/reloadafter this fix lands. This transition limit is explicit rather than weakening either parser. - Custody-mode compatibility is deliberately fail-closed rather than bidirectionally transparent: an old parent can run the additive new helper, but a newly loaded
helper_ownedparent paired with an older helper cannot obtain custody and returnscapacity_release_deferred. Source-path update or rollback therefore requires parent/helper version coherence through/reloador a fresh Pi process. - Parent-side startup remains independently bounded; execution timeouts arm only after the helper emits one complete
transport_readyhandshake with the probed Pi version and settlement mode. The parent independently reclassifies that version, rejects missing/mismatched handshakes and pre-handshake lifecycle events, and does not let stdout noise or malformed startup output consume the execution budget. - The helper mirrors startup/execution deadlines independently, pauses the corresponding raw stream when filtered protocol stdout or forwarded stderr is backpressured, and tears down the managed raw process group on deadline/signal or foreground-supervisor close. One positive backpressure watchdog covers both streams and remains active even for explicitly unlimited execution. The helper cooperatively monitors the exact parent PID/start identity, while the dormant supervisor's custody pipe makes the live group leader terminate the complete managed process group after helper death, including helper
SIGKILL; no post-reap numeric PGID signal is used. - Shared capacity leases are scoped to the current repository session root and store bounded dispatch/attempt/session identity, an explicit
helper_ownedorparent_ownedcustody mode, and an exact-token spawn-commit marker. The first reservation atomically fixes that root'smaxConcurrentin.asc-subagent-capacity-limit.v1; later runtimes must match it and cannot create higher-numbered slots to route around holders. The limit record is deliberately persistent and malformed/mismatched records fail closed. Helper custody is single-writer/no-replace and exists before the raw Pi start gate, so recovery does not depend on the parent draining or parsing the same transport whose loss is under investigation. - Post-spawn release and recovery are safe for the managed raw process group: helper-owned release cannot remove a spawn-committed lease until exact helper/supervisor identity is stale and the kernel reports group absence. Only
killpg(..., 0)ESRCHproves absence, so zombies remain conservative holders until reaped. A failed exact release becomescapacity_release_deferred, terminalerror, and effect-indeterminate instead of coexisting with reported success. - Custom runtime spawners must explicitly set
customSpawnerCapacityOwnership: "parent_owned"; their returned promise defines the capacity lifetime and they receive no helper custody binding. This is an execution-test/integration seam, not permission to infer that arbitrary detached effects have settled. - The managed boundary is the detached raw supervisor process group, not an OS sandbox or cgroup. A descendant that deliberately escapes with
setsidis outside ASC's containment proof; callers that require complete descendant confinement need a stronger external sandbox/cgroup and must not reinterpret the capacity lease as that proof. - Helper-owned shared-capacity recovery currently requires Linux
/procPID start identity plus Linux process-group signaling. Other platforms fail closed instead of claiming recovery; the package's unrelated non-recovery surfaces remain portable. - Malformed effect-bearing capacity leases never become reclaimable by age alone and appear as bounded
lease=unreadableholders. Lease metadata is canonicalized before atomic publication, and spawn markers/custody records are removed only after exact-token lease deletion succeeds, so a concurrent hard-link claimant cannot erase fencing evidence while leaving the lease behind. - Cross-process rate-limit failures report bounded token-free holder metadata (session/candidates, age, and parent/helper/raw PID state) and name the repository-session-root scope instead of presenting an opaque global Pi-process limit.
- Status sidecars (
<session>.status.json) are atomically replaced and recordrunning|done|error|timeout|aborted|abandonedplus dispatch/attempt identity, helper/raw-child custody, resumability/cancellation metadata, timeout phase, session file path, profile, model, tools, parent session key, parent repo root, bounded result/stderr previews, and pre-settlement transport failure classification; dead running sessions are reconciled toabandonedon next startup. - Status sidecars now also keep a bounded
resultPreviewplus the originating liveparentSessionKeywhen available so dashboard/inspection views can stay session-aware without parsing the whole session log. /subagent-statusreports terminal/runtime counts plus bounded shared-capacity holder identities and process states, so operators can inspect repository-scoped capacity before another dispatch fails. It remains read-only; malformed or uncertain leases require owner investigation rather than blind deletion.- A read-only widget surfaces recent subagent sessions for the current live session only, appears only after this session dispatches a subagent, and auto-clears once entries age past 1 hour.
- If you want to keep subagent traces outside Pi's native session tree, set
PI_SUBAGENT_SESSIONS_DIRto a durable external path (for example~/.pi/subagent-sessions). The default favors native Pi session storage because subagent traces are useful operator/eval data rather than disposable repo-local clutter.
Dashboard commands:
/subagent-dashboard— open a read-only summary of recent subagent sessions, including current-session scope and bounded result previews/subagent-inspect <session-name>— open a derived inspection summary with lifecycle metadata, session scope, bounded replay notes, artifact paths, safety notes, and the raw status sidecar for a specific session
Example:
# Use a different model for subagents
PI_SUBAGENT_MODEL=github-copilot/gpt-4o pi
# Force extra child-only extensions for every subagent
PI_SUBAGENT_EXTENSIONS=vault-client,/abs/path/to/custom-extension.ts pi
# Optional separate ASC session directory instead of Pi-native sessions
PI_SUBAGENT_SESSIONS_DIR=/tmp/pi-sessions pi
Self memory persistence
self now persists scoped memory domains across sessions:
- Crystallization (
remember/recallpatterns) - Protection (
mark trap/ trap registry)
Retrieval behavior:
- Pattern recall accepts
context.topicand natural filters such asRecall patterns about peer protocol. - Pattern recall result details include a non-canonical
topicSummaryfor quick topic counts. - Trap listing accepts
context.topicand natural filters such asList traps about validation. - Trap listing result details include
topicSummary; a trap's explicitcontext.topicis stored separately from proximitytriggers, so retrieval categories cannot create warnings.
Persistence behavior:
PI_SELF_MEMORY_PATH— explicit memory snapshot file path override- Default path: sibling of the sessions directory, named
<sessionsDirBase>.self-memory.json- default Pi-native sessions dir
~/.pi/agent/sessions/--<encoded-cwd>--⇒ default memory file~/.pi/agent/sessions/--<encoded-cwd>--.self-memory.json
- default Pi-native sessions dir
- Snapshot format is schema-versioned (
schemaVersion: 1) and validated on load - Malformed snapshots fail safe (tool remains usable; snapshot is repaired on next successful scoped persistence)
- Self memory remains runtime-local mirror state, not canonical AK/KES/evidence authority.
Current runtime reality
dispatch_subagentis wired, bounded, and backed by session/status artifacts plus the read-only dashboard and inspection commands.- The package-level
pi-autonomous-session-control/executionentrypoint now exposes the supported public execution contract for non-tool consumers. - ASC now carries an owned rewind runtime slice that captures exact rewind points on turn boundaries, integrates with Pi's built-in
/forkand/treelifecycle hooks, and can project bounded restore milestones into Replay Fabric whenASC_REWIND_REPLAY_FABRIC_URLis configured. - Rewind retention now runs after session reconstruction and rewind-state lifecycle changes. Each active session publishes a shared
refs/pi-rewind/active-sessions/*lease commit that directly protects its current/undo parents across linked worktrees; aggregate store rewrites verify the active-session epoch, collected lease heads, and old store OID in one Git ref transaction, then recollect/retry on drift. Historical op/turn snapshots are bounded to 128 snapshots and 30 days by default. Override with non-negative integers inPI_ASC_REWIND_MAX_SNAPSHOTSandPI_ASC_REWIND_MAX_AGE_DAYS; supply comma-separated full lowercase SHA-1 pins withPI_ASC_REWIND_PINNED_COMMITS./asc-rewind-statusreports the last retention result, live/pinned/ordinary snapshot and active-session counts, store head, policy, and any fail-closed error.refs/pi-rewind/storeis never deleted for an empty live set. - Prompt-envelope application, runtime compatibility checks, invariant summaries, failure-memory canary coverage, and Edge Contract Kernel adoption are all live.
- Scoped self-memory persistence is in place for crystallization, protection, and action-domain checkpoint/follow-up state; remaining forward-looking work should live in
README.md+next_session_prompt.md, not a separatestatus.mdmirror.
Live package activation
Install the package into Pi from its local package path:
pi install /home/tryinget/ai-society/softwareco/owned/pi-extensions/packages/pi-autonomous-session-control
Then in Pi:
- run
/reload - verify with a real command or tool call from this package
Docs map
- Organization operating model
- Project foundation model
- Project vision
- Project incentives
- Project resources
- Project skills
- ASC public execution contract
- ASC capacity recovery runbook
- Subagent cache locality evidence and tree/fork interpretation
- Self continuation harness suggestions
- Self
/scoutpeercontinuation dogfood - Rewind salvage and integration plan
- Strategic goals
- Tactical goals
- Contributor guide
- Extension SOP
- Trusted publishing runbook
- Next session prompt