# Miner preparation and analysis workflow

## Status and purpose

This document defines Miner's product contract. The Pi 1.5 alignment and lifecycle changes were released for bounded TestLater implementation on 8 November 2026; implementation and runtime acceptance remain separate from this target contract. Historical tests and runs alone do not establish current conformity.

Miner prepares historical Pi sessions as self-contained, ordered work packets. The current Pi LLM coordinates analysis by passing task-directory paths to subworkers without loading each task's source into its own context. After every task has a real result, a separate LLM summary pass synthesizes those results and discusses the findings with the user. Miner performs deterministic preparation and persistence, not model reasoning, semantic classification, worker dispatch, or certification of analysis quality.

## Conversation and preparation

A direct request to start Miner in ordinary language or `/miner` begins the same guided conversation in the current Pi session. Pi's native model tool selection routes natural-language requests through `miner_begin`; the command and tool use one shared instruction builder and the same saved-workdir suggestion. Miner does not add a keyword listener or intercept ordinary input, and merely mentioning Miner does not commission an investigation. Entry does not record intake answers or prepare sources; `miner_start` remains the separate operation after the first four explicit interview answers. The LLM uses the user's language throughout the user-facing Miner conversation. It translates the agreed analysis goal and task assignment into English before recording them for the run. Generated run/task instructions, task analyses, and the final summary are in English for an international audience; source excerpts and quotations retain their original language. It greets the user, first explains Miner's purpose—evidence-based investigation of historical Pi sessions for problems and insights about work, behavior, skills, prompts and extensions, with non-binding proposals but no automatic changes—and then briefly explains the five stages (interactive project brief, autonomous tool preparation, autonomous LLM/tool task analysis, autonomous LLM synthesis, interactive evaluation), and immediately asks only the first question. Before later tool use it explains the next action briefly in that language. The entry instruction describes boundaries and available Miner tools; it refers only to actually available and authorized delegation capabilities. Miner must function as the only installed extension. Missing or declined delegation uses the current-session analysis and synthesis path with an honest context warning, not a required third-party installation. The durable run `README.md` repeats the procedure and boundaries for a later session.

Miner tool operations use Pi's native sequential execution. Additionally, at most one complete investigation is active per user-facing Pi session, spanning entry, intake, preparation, analysis and every synthesis round. Reserve its Run ID before asynchronous entry work; the first metadata submission attaches to that reservation. Reject a second start with a clear message rather than queueing it or overwriting intake. A busy Pi session with no Miner run likewise receives a refusal, not an automatic later start. Preparation completion, an idle turn or `agent_end` alone never releases the active run. Actual completion, cancellation or terminal failure plus safe own cleanup frees the slot so a new run with a new ID may start in the same session. Other Pi sessions and authorized technical/analysis worker concurrency remain independent.

Bind intake and coverage confirmation to the originating session, current branch and execution revision. An actual branch switch or rewind aborts the run and invalidates its approval; merely opening/canceling tree navigation or ordinary compaction does not. Shutdown/reload reconciles durable progress as interrupted, without auto-resume. Old results and callbacks must not change a newer run. Native session entries store small state/references, not copied source bodies or analysis prose.

Manual abort is available through both a native command/TUI path and an LLM operation. Miner signals its own technical work and awaits real cleanup before claiming it stopped. The coordinating LLM stops further dispatch and handles any delegated work using its own available authorized capabilities, then reports completion or uncertainty through a generic Miner contract. Miner neither inspects nor controls another extension's tasks, roles or cancellation APIs. Unknown external outcomes stay explicit and cannot certify stopped workers or authorize unsafe redispatch. Existing artifacts remain intact after interruption.

Header inventory and later full-source preparation use the same bounded internal Node-worker mechanism and the intake's chosen technical worker count. Each thread handles one session at a time from its assigned batch. Before coverage confirmation, inventory returns only header metadata; it does not normalize full sources or create snippets. Internal inventory-library calls without an explicit worker count use one thread. Missing, non-file, permission-inaccessible or invalid-header candidates remain excluded; resource failures such as exhausted file descriptors fail visibly rather than silently shrinking the inventory. Only session format v3 is supported. Plausible unsupported-version headers contribute visible supported/unsupported aggregate counts, dates and bytes before confirmation; a requested selection containing unsupported sources cannot be confirmed or prepared. Never silently discard these sources or migrate original v1/v2 files.

The following source-selection interview applies when a new source cut is requested. Searching or reusing an existing cut follows the separate procedure below.

1. Ask one question at a time; after each answer, put the brief acknowledgement or answer in its own paragraph, followed by a blank line and the next question in a separate paragraph. Ask in this order: working directory, nonempty human run name, permission/method/maximum concurrent analysis subagents, maximum concurrent technical tool workers, project, timeframe, then analysis goal with LLM assistance. Suggest the last workdir actually used by a plan-ready run of this workflow from its separate Miner preference if one is saved; otherwise suggest `~/llm_session_analyze`. Neither a suggestion nor a workdir in the former `config.json` is a current choice. Await the user's explicit answer before recording the workdir; the user may choose another directory. Expand `~` to the current user's home directory. Obtain permission before creating a missing directory outside the project. Recommend only available authorized delegation rather than a particular provider or invented capacity; if unavailable or declined, warn clearly before analysis about current-session context consumption, then proceed there or report a concrete capacity blocker. Suggest 4 concurrent technical tool workers by default, separately from analysis subagent concurrency. The technical workers perform deterministic header inventory and, after confirmation, source preparation only; they do not perform analysis.
2. After the first four interview topics, record their answers with the Miner start tool. Use a Miner tool to list historical projects, with full roots and bounded pagination. The user chooses one exact project. Equal directory names are distinguished by root path; no project is inferred from the current directory without the user's choice.
3. Call `miner_list_sessions` for aggregate date/count orientation of the chosen project. Miner consumes bounded inventory pages internally and returns only the project, candidate count, earliest/latest dates and approximate bytes, not individual session lists, IDs, paths or cursors. The user chooses a timeframe using these aggregates. `miner_set_timeframe` computes the complete selection internally and returns aggregate coverage. Only then ask for and record the analysis goal and LLM-formulated task assignment.
4. Show the chosen project, requested timeframe, actual source coverage (session count, earliest/latest dates and approximate bytes), technical worker limit and analysis concurrency. Miner owns deterministic inventory, selection, stable ordering and cutting; the LLM facilitates project/timeframe choice and aggregate confirmation. The user does not inspect session IDs/paths or select individual sessions. Include all matching sessions except the current Pi session, which Miner excludes using Pi's public current-session file, and extra ongoing session IDs expressly identified by the user. Store these explicit exclusions in intake and durable run metadata, show the applied set at confirmation, and retain it through timeframe adjustments unless the user deliberately changes it. Compute coverage extrema from chronological instants, not lexical ISO timestamp order. Pi provides no reliable global live-session flag; neither modification time nor a guessed inactivity threshold proves a session is finished. If the user adjusts the timeframe, call Miner again to recompute counts, clear the old confirmation and obtain fresh aggregate confirmation. Exact task count is known only after cutting; do not invent task counts, synthesis iteration counts or runtime estimates.
5. After `miner_confirm_coverage` succeeds, invoke `miner_prepare_sessions` with an empty object and no IDs/list argument. Preparation uses the internally stored confirmed selection; no caller sorting or comparison is needed. The stable internal order remains in run provenance. Previously captured metadata, project, timeframe, and explicit ongoing-session exclusions are scoped to this intake, not passed again as invented source paths. Re-inventory and validate the IDs and coverage before reading sources. Missing, ambiguous, duplicate, out-of-scope, or newly changed selections fail visibly; do not silently choose a file. If session metadata changed after confirmation, explain that no usable cut was published, retain any reserved Run ID and partial state, and require refreshed timeframe coverage and explicit confirmation before retrying. The final full read must match the approved v3 header ID, project and timestamp; an identity mismatch is a rejection, not a harmless anomaly. Preflight alone owns the full-source preparation and bounded cutting after confirmation; earlier header inventory uses the same bounded technical workers without preparing source bodies. Every running Miner tool is visible in the widget area; preflight labels its widget phases as checking confirmed sessions, preparing source excerpts, creating task snippets, and writing and validating the task plan, then clears it on completion or failure. The LLM makes one awaited preflight call; Pi resumes it when that call returns. It neither launches analysis subagents during preparation nor inserts a separate conversational wait or second preparation call. Preflight creates the run, writes the complete ready-made task tree using the assignment captured with metadata, and reports readiness only after its files are actually present and validated. It does not run analysis.
6. When subagents are authorized, the main LLM creates one subworker assignment per task-directory path in plan order: exactly one task for each subworker invocation, never a bundle of multiple tasks. It does not read the task's `snippet.md` or README into its own context. Several independent one-task assignments may run concurrently up to the approved subagent limit. Pi and the LLM own subagent selection, dispatch, approved concurrency, and collection. Each worker reads only its one assigned task's files and writes its actual analysis result to that task's matching analysis directory. If subagents were declined, the LLM clearly warns beforehand that analyzing the tasks in its current session will probably fail due to context consumption, then does that work itself. The LLM checks technical completion and the resulting file. Ordered task identity and ordered aggregation remain stable.
7. Only after every required task has a real completed result does the LLM launch a distinct analysis-summary pass over the ordered task results. It records an evidence-based synthesis with concrete, non-authoritative solution proposals, reports failures or gaps honestly, and discusses the findings with the user. A present or nonempty result file is technical completion evidence, not proof that its interpretation is correct. No incomplete run is presented as a complete analysis.

The English rendering of the user's goal and the LLM-formulated English operational assignment are recorded after the timeframe, before coverage confirmation and preflight. Miner does not invent, translate, or certify their semantic quality; the coordinating LLM is responsible for faithful translation.

## Reusing and finding prepared cuts

The LLM lists and searches existing runs in the user-selected workdir through `miner_browse_workdir` with `view="runs"`, by run name, project root, Run ID and dates. This single paginated surface serves both listing and search. Bounded listings expose the run name, project, requested timeframe, actual source coverage, creation date, storage root, task count, status and canonical source Run ID. A project root and a human run name are separate metadata, not interchangeable identifiers.

For an explicit search or reuse request, ask for a workdir only if the user has not already selected one, then browse that workdir instead of repeating the source-selection interview. For another analysis, collect a new run name, goal, and current subagent permission/method/concurrency one question at a time; check actual subagent availability, formulate the goal and assignment in English, and obtain confirmation of the new named analysis. `miner_reuse_cut` validates the stored evidence and creates a new sibling run with its own English goal, assignment, current subagent permissions, task READMEs, and separate output locations for analysis results and the final summary. Preparation does not create those results or the summary; the subsequent LLM work writes them. It does not rediscover or recut historical sessions. Every new task README points to exactly its original read-only snippet; no source evidence is copied or altered. Reusing an already reused run resolves directly to the original cut, not a chain of references. Each analysis still assigns one task per worker and completes all synthesis rounds.

Deliberate compatibility: existing runs keep their original plan, initial analysis and summary unchanged and remain searchable and reusable. New analysis runs record `sourceRunId` in `run.json`, retain the same ordered task identities/provenance, and have task instructions but no duplicated `snippet.md`. Inspection validates referenced source snippets and this analysis's own files. Results and summaries are always scoped to the new Run ID. Failed/canceled creation is not readiness. Deleting a cut while other analyses reference it is refused; those dependent analyses must be explicitly deleted first. This supports the current prepared-run format, not the removed legacy intake format.

## Explicit continuation and interrupted-run management

Resume explicitly selects a saved Run ID and keeps that same ID, assignment and valid completed work, including after cancellation. A deliberately new analysis uses cut reuse and receives a new ID. Resume validates actual copied evidence, task outputs and ordered synthesis inputs before reuse; file presence alone is not a completion record. Record finished output identity/digests on an explicit coordinator report and revalidate them on continuation. Preserve conflicting or partial files and report uncertainty rather than overwriting them or rerunning valid results.

Incomplete preparation retains its ID and checkpoints. Finish missing deterministic artifacts from valid copied evidence where possible; remaining original-source reads require current-branch coverage approval and renewed identity validation. A completed investigation returns its existing result rather than rerunning. Resume requires a free active session slot and rejects potentially still-mutating output until its status is resolved.

TUI and LLM management use the same run-store operations for listing interrupted runs/reasons, status, abort, resume and exact-Run-ID-confirmed deletion. Active or still-aborting runs cannot be deleted. Existing source-cut reference protection remains in force for partial, failed and canceled dependent analyses too. A bounded interprocess transaction in the selected workdir protects reference publication and dependency-check/deletion; a process-local native file queue is not an interprocess lock. Fail visibly on occupied or crash-left ownership rather than polling or guessing that a stale lock is safe to steal. No separate reference database or global run lock is introduced.

## Run directory and task contract

If a run directory has no `run.json`, Miner fails visibly with its exact directory and Run ID and explains that this blocks saved-run listing and deletion in that workdir. The coordinating LLM tells the user in their language and asks whether to delete that incomplete run or move it aside, recommending a move to preserve existing files. It waits for an explicit choice naming the affected directory and Run ID and, for a move, approval of the exact destination outside the workdir's active run folders. Recovery uses Pi's available filesystem or shell tools after approval, followed by retrying the blocked operation. Miner performs no automatic cleanup and adds no recovery tool or alternate deletion path for healthy runs.

The selected working directory is the actual run storage authority, not an export of another hidden plan. A read-only Miner tool can browse saved runs in an explicitly supplied workdir, page their task statuses, and read one selected `analysis.md` or `summary.md` in bounded UTF-8 pages. It does not infer a workdir from legacy settings, read source snippets implicitly, or start/resume analysis. A missing result is reported as missing, never presented as complete. After a plan-ready run, Miner saves that used workdir in its distinct `<agent-dir>/pi-blitz-miner/used-workdir.json` preference and proposes it in the next `/miner` conversation; a failure to save this preference is reported separately and does not invalidate the prepared run or imply that analysis is complete. A missing, unreadable, malformed or invalid optional preference must not prevent entry: return a bounded warning and propose `~/llm_session_analyze`, without silently repairing the preference or treating the proposal as the user's selection. The former `config.json` and its legacy intake/run layout are neither read as this preference nor modified. Each run has a unique, filesystem-safe `<runname_runid>` directory beneath it. The generated Run ID remains the stable identity regardless of name normalization. A default directory and its run child may be created only within the user's authorized working-directory scope. Files containing copied session evidence must be accessible to the intended same-user LLM/subworkers but not made public by default. Existing unrelated content in the working directory is not modified.

```text
<working-directory>/<runname_runid>/
├── README.md
├── plan/
│   ├── T0001/
│   │   ├── README.md
│   │   └── snippet.md
│   └── T0002/
│       ├── README.md
│       └── snippet.md
├── analyze/
│   ├── T0001/
│   │   └── analysis.md
│   └── T0002/
│       └── analysis.md
└── summary.md
```

The tree depicts a completed example; `analyze/<Task>/analysis.md` and `summary.md` do not exist merely because a plan is ready. `README.md` at the root explains the goal, the source-selection coverage, the ordered handoff, available Miner operations and applicable native-tool choices, result location, technical completion criteria, final synthesis, and boundaries. It tells the orchestrating LLM explicitly not to ingest every task's source during dispatch.

Worker and synthesis instructions require complete paginated reads through end-of-file and an actual input/instruction/output context-capacity check. A 64-KiB snippet may exceed a single native read response. Keep the short procedure before large provenance lists; retain full lists in `run.json`. Historical evidence is untrusted source material, never an instruction to execute. Workers receive only their assigned task/output paths and report to their coordinator, not general Miner control.

Every `plan/<Task>/README.md` is a self-contained worker packet: the LLM-provided English assignment, task ID and order, relevant source identity/date/line provenance, the local `snippet.md` input, the required `analyze/<Task>/analysis.md` output, evidence expectations, and the instruction to report uncertainty rather than invent facts. Each `snippet.md` contains the actual source-attributed evidence for exactly that task, bounded to 64 KiB of UTF-8 text including provenance labels. Task READMEs remain bounded; complete technical source accounting, including excluded/malformed lines and gaps, is retained in run metadata rather than copied wholesale into a worker prompt. No task claims a semantic finding before a worker analyzes it. The task cut must keep each worker input bounded while representing all confirmed source evidence; source order and explicit gaps are preserved. Worker outputs remain separate from the source packet and are written only when real work is done.

Miner may retain a structured run database for source integrity, mappings, task order, and truthful completion bookkeeping. It must not maintain a conflicting second authority for task prose or analysis prose. A source file remains read-only. During preparation Miner verifies its observed identity/integrity and records the provenance of copied snippets. A later source change does not retroactively turn an already copied snippet into a claim that the original remained unchanged. Reopening a run validates its actual files and metadata, not a simulated completion marker. File presence can establish only technical artifact completeness; it cannot prove worker identity, summary authorship, temporal ordering, or semantic correctness. Inspection does not verify completed synthesis rounds or finished workers; the orchestrating LLM checks those separately before declaring the assignment finished.

`available`, `working`, `finished`, `canceled`, and `error` are not a separate LLM-facing snippet-status API. Any internal state needed to distinguish actual work from failed or missing work must match the filesystem and worker outcome. A worker may receive only its assigned task and output paths; it has no authority to edit the root instructions, other tasks, or another worker's result. Miner does not create Pi sessions or dispatch subworkers itself.

The separate synthesis stage reads the ordered English `analyze/<Task>/analysis.md` files, not all copied snippets in the main LLM context. Group consecutive results so every group fits fully into a synthesis worker's available context, including instructions and output space. Each worker synthesizes one group through a real LLM pass and retains its English intermediate result in the run directory. Repeat this procedure over ordered intermediate results until a final LLM pass can write `summary.md` with the most important findings. Cover every input without sampling or merely concatenating files; preserve source references, important counterexamples and uncertainties through every round. Original analyses remain unchanged. The one-task-per-worker rule governs source analysis; a synthesis worker instead receives one group. No fixed group size or number of rounds is prescribed. The same subagent authorization applies to synthesis. If subagents were declined, synthesize in the current session without dispatching workers and report a concrete blocker if the available context is insufficient. Carry out every required synthesis round autonomously within the approved worker method and concurrency, without asking for renewed approval between rounds. The analysis assignment ends only after coordinator output records validate all task results and the final summary, and `miner_finish` records verified coverage and finished workers; intermediate results or completed rounds are not completion. Report a concrete blocker if continuation is impossible, and never present a blocked or partial run as finished. It checks coverage and evidence references, distinguishes observation from interpretation, groups recurring findings when useful, includes concrete solution proposals, and writes `summary.md` only from actual results. The LLM then presents and discusses the synthesis with the user. Miner ends at that analysis boundary. The user decides what to do with the result; any follow-up change to code, rules, prompts, or external systems is a separate task with its own authorization under `analysis-results.md`. A separate Workbench product is not a Miner dependency or automatic handoff target.

## Technical boundaries

- Historical source discovery is metadata-only until the confirmed preflight. The current session is excluded before listing and coverage. Additional running sessions can be excluded only by IDs supplied by the user; do not pretend to detect every live Pi process from JSONL data.
- Project roots and native session IDs come from Pi's historical session headers. Preparation accepts no arguments and revalidates internally stored IDs, never caller-supplied session lists or arbitrary source paths, SQL, or executable commands. Duplicate native IDs that cannot be resolved unambiguously within the inventory are rejected rather than silently selected.
- Inventory uses bounded internal pages. Project listings remain pageable; routine session intake returns aggregate summaries only. The obsolete `miner_selection_page` tool is removed. No full session bodies or unbounded tool descriptions are returned in project/session listings. Pi's complete-result byte and line limits apply before any outer Codemode filtering. Validate practical UTF-8 input and worst-case response bounds before mutation. Native tool arguments are limited to 24 KiB of UTF-8 JSON for the complete object, including escaping. Each string is limited to 4,096 bytes of its JSON representation, except `analysisGoal` and `taskAssignment`, each limited to 10,000 JSON bytes; `taskAssignment` also has an 8,192-byte unescaped UTF-8 limit to leave room for generated worker instructions. Reject NUL characters before mutation. Expanded workdir paths remain within the 4,096-JSON-byte limit and must be absolute and normalized. Keep successful mutation results constructively small; if a later presentation/preference step fails, retain the created Run ID and actual phase instead of reporting an ambiguous uncommitted failure.
- Cutting respects UTF-8 boundaries, physical source ordering, explicit timestamps and line provenance, malformed records and gaps. It does not infer intent, sentiment, causation, or relevance. Technical worker count may parallelize deterministic normalization/cutting but says nothing about Pi subagent capacity.
- A run may be `preparing`, `plan-ready`, `analyzing`, `complete`, `canceled`, or `failed` only when its actual durable state supports that description. Failures and cancellation preserve truthful partial state. Technical plan readiness does not imply worker results or a final summary. A missing/failed task blocks a complete-summary claim; the user may explicitly decide on a separately labelled partial analysis.
- A proposed workdir becomes the current run workdir only after the user's explicit selection. Exact-run deletion remains user-confirmed. Deletion requires confirmation naming the Run ID; it never follows implicitly from canceled preparation. The default working directory is a suggestion, not authority to overwrite an existing explicitly selected location.
- The implementation uses documented Pi extension and session APIs and Node core facilities. Miner introduces no custom model backend, general session/task controller, hidden script execution, installation mechanism, Workbench adapter, automatic follow-up action, or external publication. Its application-run state uses public native Pi session events and generic coordinator reports only. Optional collaboration tools are discovered and used by the LLM only when actually available and authorized.

## Obsolete workflow removed

This contract replaces the old mandatory timeframe-first intake, numbered-session selection, Basic/Enhanced profile questionnaire, execution/model/collaboration preference questionnaire, virtual-chunk read API, incremental slice/layer plan, per-layer review/endpoint-consent gate, and separate Habit/status persistence workflow. Do not retain those as a parallel path, compatibility shim, or required preliminary ceremony. Analysis patterns may still be described in the final synthesis without a Habit status machine. Existing unsupported unpublished run formats are not silently migrated or presented as conforming runs.

## Verification boundary

Acceptance requires isolated real-filesystem tests for project-first inventory, current and user-named ongoing-session exclusion, aggregate-only intake, coverage confirmation, empty-argument preparation using the complete internal ordering, timeframe changes that recompute coverage and invalidate approval, stale/ambiguous rejection, bounded source-to-snippet fidelity and ordering, run-directory permissions/path containment, plan readiness, worker-result integrity, failed/canceled/partial states, and a summary that cannot claim completion over missing tasks. Packed native Pi dispatch and instruction delivery must be tested. Test doubles for LLM reasoning, user confirmation, or independent subworker execution must be named as simulations; passing them does not prove actual model quality or human consent.
