@osolmaz/pi-workflows 0.6.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,119 @@
1
+ # Durable job progress
2
+
3
+ `@osolmaz/pi-workflows/job-progress` lets a remote job publish progress that a Pi Workflows monitor can validate and measure. It uses the existing `pi-workflows.progress.v1` track contract and ETA estimator.
4
+
5
+ ## Report progress
6
+
7
+ Create one reporter for one physical job. Inject the storage write so the package remains independent of a cloud provider.
8
+
9
+ ```ts
10
+ import { createJobProgressReporter } from "@osolmaz/pi-workflows/job-progress";
11
+
12
+ const reporter = createJobProgressReporter({
13
+ application: "example",
14
+ component: "batch-worker",
15
+ jobId: process.env.JOB_ID ?? "local",
16
+ sourceRevision: "abc123",
17
+ contractHash: "def456",
18
+ startedAt: new Date().toISOString(),
19
+ initialTracks: [
20
+ {
21
+ key: "overall",
22
+ data: {
23
+ schema: "pi-workflows.progress.v1",
24
+ status: "running",
25
+ phase: "starting",
26
+ },
27
+ },
28
+ ],
29
+ minimumIntervalMs: 30_000,
30
+ publishTimeoutMs: 15_000,
31
+ publish: async (snapshot, signal) => {
32
+ await bucket.writeText(progressPath, JSON.stringify(snapshot), { signal });
33
+ },
34
+ });
35
+
36
+ await reporter.report({
37
+ phase: "processing",
38
+ tracks: [
39
+ {
40
+ key: "records",
41
+ data: {
42
+ schema: "pi-workflows.progress.v1",
43
+ status: "running",
44
+ phase: "processing",
45
+ completed: 400,
46
+ total: 1_000,
47
+ unit: "records",
48
+ },
49
+ },
50
+ ],
51
+ });
52
+ ```
53
+
54
+ The first update, each phase change, and each terminal update publishes immediately. Other updates are coalesced until `minimumIntervalMs` has passed. Call `flush()` at a durable checkpoint or before exit when the current snapshot has not been published.
55
+
56
+ On process restart, read and validate the existing snapshot and pass it as `previousSnapshot`. The reporter continues its sequence number and rejects an identity, deadline, or terminal-state mismatch.
57
+
58
+ The reporter keeps the latest snapshot after a write failure. The application decides when to log and retry that failure. A timed-out storage write remains serialized until the underlying write settles, so an older write cannot overwrite a newer snapshot. Storage adapters must honor the abort signal and settle after cancellation. A progress failure must not replace receipt or checkpoint validation.
59
+
60
+ ## Finish a job
61
+
62
+ A terminal update gets a finish timestamp and publishes immediately:
63
+
64
+ ```ts
65
+ await reporter.report({
66
+ state: "completed",
67
+ phase: "complete",
68
+ tracks: [
69
+ {
70
+ key: "records",
71
+ data: {
72
+ schema: "pi-workflows.progress.v1",
73
+ status: "completed",
74
+ phase: "complete",
75
+ completed: 1_000,
76
+ total: 1_000,
77
+ unit: "records",
78
+ },
79
+ },
80
+ ],
81
+ });
82
+ ```
83
+
84
+ A terminal snapshot is not a receipt. Receipts, manifests, hashes, and durable application outputs remain authoritative.
85
+
86
+ ## Store and discover snapshots
87
+
88
+ Write one mutable snapshot per physical job:
89
+
90
+ ```text
91
+ <existing-bucket>/<application-prefix>/runs/<job-id>/progress.json
92
+ ```
93
+
94
+ Add these immutable labels to the job or schedule:
95
+
96
+ ```text
97
+ progress_schema=pi-workflows.job-progress.v1
98
+ progress_bucket=<existing-bucket>
99
+ progress_prefix=<application-prefix>/runs
100
+ ```
101
+
102
+ A monitor reads the labels, forms `<progress_prefix>/<job-id>/progress.json`, validates the snapshot with `validateJobProgressSnapshot`, and publishes its tracks with stable keys. It should retain consecutive snapshots so Pi Workflows can estimate a conservative ETA from measured rates.
103
+
104
+ ## Estimate from snapshots
105
+
106
+ ```ts
107
+ import { estimateJobProgress } from "@osolmaz/pi-workflows/job-progress";
108
+
109
+ const result = estimateJobProgress(previousSnapshots);
110
+ for (const estimate of result.estimates) {
111
+ console.log(estimate.key, estimate.remainingMedianMs);
112
+ }
113
+ ```
114
+
115
+ The estimator returns no measured ETA until a track has a known total and enough positive progress samples. A source-provided `sourceEstimatedFinishAt` remains available through the normal progress contract.
116
+
117
+ ## Data boundary
118
+
119
+ Snapshots may contain identifiers, phases, counters, totals, timestamps, and cost totals. Do not put credentials, environment values, input records, model responses, logs, or private content in a snapshot. The strict validator rejects unknown fields and limits the encoded snapshot to 64 KiB.
package/docs/MONITOR.md CHANGED
@@ -242,6 +242,11 @@ One monitor can track several processes. Each uses a stable progress key. A miss
242
242
 
243
243
  The progress estimator treats each key independently. A phase, unit, total, or counter reset in one track does not reset another track.
244
244
 
245
+ Remote Jobs can publish the same tracks in a strict
246
+ [`pi-workflows.job-progress.v1` snapshot](JOB_PROGRESS.md). A monitor discovers
247
+ the snapshot from immutable Job labels, validates its identity, and submits its
248
+ tracks without copying log-derived guesses into progress fields.
249
+
245
250
  ## Interval and lifetime
246
251
 
247
252
  The normal workflow engine remains finite. The built-in monitor therefore retains the 1,000-check safety ceiling and must not claim to be mathematically unbounded.
@@ -0,0 +1,104 @@
1
+ ---
2
+ title: Bundle Pi Workflows skills with the extension
3
+ author: Onur Solmaz <2453968+osolmaz@users.noreply.github.com>
4
+ date: 2026-08-17
5
+ ---
6
+
7
+ # Bundle Pi Workflows skills with the extension
8
+
9
+ Pi Workflows should be the single source of truth for instructions that teach an agent how to use its extension and built-in workflows. Installing the Pi package should discover those skills with the extension, while Pi's normal package filters let users disable either resource type or an individual skill.
10
+
11
+ ## Outcome
12
+
13
+ The npm package will include two optional Pi skills:
14
+
15
+ - `pi-workflows` explains when and how to use the `workflow` tool, control runs, complete step contracts, publish progress, and author workflow files.
16
+ - `monitor` starts and operates the built-in monitor workflow with the established 30-minute default, inferred finish rule, status report on every check, and structured progress guidance.
17
+
18
+ The existing monitor skill in `osolmaz/tools` will move here and be removed from that repository. OnurPi will expose the upstream extension and skills from one reviewed package version.
19
+
20
+ ## Scope
21
+
22
+ - Add stable skill paths under `skills/`.
23
+ - Declare both the extension and skills in the Pi package manifest.
24
+ - Include the skill files in npm artifacts.
25
+ - Document bundled resources and independent disable controls.
26
+ - Add automated checks for manifest paths, skill metadata, package contents, and duplicate skill names.
27
+ - Test discovery from a packed package with the real Pi runtime.
28
+ - Release the compatible feature as `0.7.0`, following the repository's pre-1.0 minor-release convention.
29
+ - Update the OnurPi pin and package resource forwarding.
30
+ - Delete the Tools copy and sync local skill mirrors so no duplicate remains.
31
+
32
+ ## Non-goals
33
+
34
+ - Do not add a new workflow node, workflow schema field, or Pi core API.
35
+ - Do not load skills only while a workflow step is active.
36
+ - Do not create a general workflow-to-skill attachment system.
37
+ - Do not copy unrelated operating-policy skills such as `autoimplement` or `autoresearch-loop`.
38
+
39
+ ## Public contract
40
+
41
+ The package uses Pi's documented package resource contract:
42
+
43
+ - `pi.extensions` exposes the existing extension.
44
+ - `pi.skills` exposes `skills/`.
45
+ - Pi package filters and `pi config` can disable all skills, one skill, or the extension independently.
46
+
47
+ The `workflow` tool description remains the small always-available call contract. The `pi-workflows` skill contains detailed guidance that Pi loads only when a matching task requires it. Workflow step messages remain compact and authoritative for `submit` and `update` attempt identifiers.
48
+
49
+ ## Contract impact
50
+
51
+ - **Session state:** no new session entry or change to normal Pi session behavior.
52
+ - **Other persistent data:** none.
53
+ - **Pi internals:** none.
54
+ - **Public Pi API:** package `pi.skills` discovery and existing package resource filters. The extension continues to use its current public APIs.
55
+
56
+ ## Implementation
57
+
58
+ 1. Add `skills/pi-workflows/SKILL.md` with concise tool and authoring guidance linked to the bundled reference docs.
59
+ 2. Move the current monitor skill to `skills/monitor/SKILL.md` and align repository-relative references with the package layout.
60
+ 3. Add `skills` to the npm package files and Pi manifest.
61
+ 4. Add tests that validate declared paths, required frontmatter, unique skill names, and packed files.
62
+ 5. Update README installation and configuration examples, including independent resource filtering.
63
+ 6. Pack the package and start the real Pi runtime from that artifact. Verify that `/skill:pi-workflows` and `/skill:monitor` are discovered with the extension, then verify that package filtering can hide the monitor skill without hiding the extension.
64
+ 7. Run all repository checks and Pi Reviewer, merge, release `0.7.0`, and verify npm contents.
65
+ 8. Pin `0.7.0` in OnurPi, forward the dependency's skills, and run OnurPi checks.
66
+ 9. Remove `agents/skills/monitor` from Tools, run the sync script, and verify that the installed skill now comes from the Pi Workflows package only.
67
+
68
+ ## Acceptance criteria
69
+
70
+ - A direct Pi installation of `@osolmaz/pi-workflows` discovers the extension and both skills.
71
+ - The OnurPi wrapper discovers the same two upstream skills.
72
+ - Users can disable bundled skills or the extension with standard Pi package settings.
73
+ - The model can use the `workflow` tool from the new skill without larger workflow step messages.
74
+ - npm contains the two `SKILL.md` files and their referenced documentation.
75
+ - Tools contains no monitor skill source or synced duplicate.
76
+ - Local checks, real-Pi end-to-end tests, Pi Reviewer, and CI pass.
77
+
78
+ ## Verification
79
+
80
+ Run in `pi-workflows`:
81
+
82
+ ```bash
83
+ npm run check
84
+ npm run test:e2e
85
+ npx slophammer-ts@latest dry .
86
+ npx slophammer-ts@latest check . --only ts.dependency-boundaries-required
87
+ npx -y @simpledoc/simpledoc check
88
+ npm pack --dry-run
89
+ ```
90
+
91
+ Run the packed-package Pi discovery smoke test documented by the implementation, then run in OnurPi:
92
+
93
+ ```bash
94
+ npm run check
95
+ npm run slophammer
96
+ git diff --check
97
+ ```
98
+
99
+ Run in Tools after deletion:
100
+
101
+ ```bash
102
+ python3 agents/sync-skills.py
103
+ npx -y @simpledoc/simpledoc check
104
+ ```
@@ -0,0 +1,176 @@
1
+ # Durable job progress
2
+
3
+ ## Problem
4
+
5
+ Long-running remote jobs can expose state only through logs and final receipts. A monitor can confirm that a job is running, but it cannot give a reliable progress value or remaining time when the job does not publish a completed count, a total, and source timestamps.
6
+
7
+ xTap Pool and OurModels need the same durable progress contract. The contract must work with their existing Hugging Face Buckets, survive worker restarts, and use the ETA estimator that Pi Workflows already uses for `pi-workflows.progress.v1` tracks.
8
+
9
+ ## Requirements
10
+
11
+ The implementation must:
12
+
13
+ - add one storage-neutral job progress API to `@osolmaz/pi-workflows`
14
+ - reuse `pi-workflows.progress.v1` for progress tracks
15
+ - write one mutable snapshot for each physical job in the application's existing Bucket
16
+ - let monitors discover the snapshot from immutable job labels
17
+ - let Pi Workflows validate the snapshot and estimate remaining time from repeated samples
18
+ - let xTap Pool report restore, review, recovery, and publication progress
19
+ - let OurModels report discovery, processing, cache, and publication progress
20
+ - keep receipts, content hashes, manifests, and databases authoritative
21
+ - avoid secrets, post text, model output, and other private content in progress snapshots
22
+ - preserve one physical enrichment job at a time during the xTap Pool change
23
+ - leave the OurModels replacement schedule suspended until a paid run is separately approved
24
+
25
+ ## Non-goals
26
+
27
+ This work does not add:
28
+
29
+ - a new remote store
30
+ - a metrics database
31
+ - a second ETA protocol
32
+ - a Pi core change
33
+ - a service or daemon
34
+ - a compatibility path for an older snapshot schema
35
+ - automatic authority to retry, deploy, publish, or spend money
36
+
37
+ ## Public contract
38
+
39
+ The npm package exports a new subpath:
40
+
41
+ ```ts
42
+ import {
43
+ createJobProgressReporter,
44
+ estimateJobProgress,
45
+ validateJobProgressSnapshot,
46
+ type JobProgressSnapshot,
47
+ } from "@osolmaz/pi-workflows/job-progress";
48
+ ```
49
+
50
+ A snapshot has schema `pi-workflows.job-progress.v1` and contains:
51
+
52
+ - stable application and component names
53
+ - the physical job identifier
54
+ - source and work-contract identifiers
55
+ - a monotonic sequence number
56
+ - job state and current phase
57
+ - start, update, optional deadline, and optional finish timestamps
58
+ - one or more keyed `pi-workflows.progress.v1` tracks
59
+ - optional settled cost and active reservation facts
60
+
61
+ The validator is strict. It rejects unknown fields, duplicate track keys, invalid timestamps, non-finite values, invalid progress tracks, and oversized snapshots.
62
+
63
+ The reporter accepts an injected asynchronous `publish(snapshot)` callback. Pi Workflows does not import a Hugging Face client. The reporter:
64
+
65
+ - keeps sequence numbers monotonic within the process
66
+ - rejects regressions within one phase and epoch
67
+ - coalesces frequent updates with a configurable minimum interval
68
+ - flushes phase changes and terminal states immediately
69
+ - bounds publication time with an abort deadline
70
+ - preserves the most recent unsent snapshot after a transient publication failure
71
+ - never includes arbitrary metadata or environment values
72
+
73
+ A terminal snapshot is operational evidence only. The application's receipt and durable output validation still decide whether work succeeded.
74
+
75
+ ## Storage and discovery
76
+
77
+ Each application writes snapshots to its existing Bucket.
78
+
79
+ xTap Pool uses:
80
+
81
+ ```text
82
+ osolmaz/xtap-pool-bucket/operations/enrichment/runs/<job-id>/progress.json
83
+ ```
84
+
85
+ OurModels uses:
86
+
87
+ ```text
88
+ osolmaz/ourmodels-data/<prefix>/operations/community-posts/runs/<job-id>/progress.json
89
+ ```
90
+
91
+ Each schedule supplies these immutable labels:
92
+
93
+ ```text
94
+ progress_schema=pi-workflows.job-progress.v1
95
+ progress_bucket=<bucket>
96
+ progress_prefix=<path-before-job-id>
97
+ ```
98
+
99
+ A monitor reads the labels, appends the physical job identifier and `progress.json`, reads the snapshot with existing local Hugging Face authentication, validates it, and publishes each track under a stable workflow progress key. The monitor does not trust an ETA string from logs. It uses source finish time when the snapshot provides one, or the existing conservative estimator after enough measured samples.
100
+
101
+ ## xTap Pool tracks
102
+
103
+ The enrichment worker reports these stable tracks when facts are measurable:
104
+
105
+ | Key | Unit | Source |
106
+ | ------------------ | ---------- | -------------------------------------------------- |
107
+ | `database-restore` | bytes | downloaded database bytes and expected object size |
108
+ | `registry-replay` | events | replayed registry events and discovered total |
109
+ | `registry-scan` | candidates | durable scan cursor and fixed candidate total |
110
+ | `queue` | records | terminal records and durable queue total |
111
+ | `publication` | bytes | uploaded and verified database bytes |
112
+ | `overall` | phases | completed phases and fixed phase count |
113
+
114
+ Phase-only states remain valid when a total is not yet known. The worker must not invent totals.
115
+
116
+ The existing three unresolved records must receive durable outcomes under the fixed full-response deadline or become exactly validated blocked records. The worker then publishes and verifies the index before its final receipt is accepted.
117
+
118
+ ## OurModels tracks
119
+
120
+ The community-posts worker reports these stable tracks when facts are measurable:
121
+
122
+ | Key | Unit | Source |
123
+ | ----------------- | ------- | ----------------------------------------------- |
124
+ | `model-discovery` | models | discovered and inspected model count |
125
+ | `community-posts` | models | processed models and fixed discovered total |
126
+ | `cache` | records | durable cached model results and expected total |
127
+ | `publication` | bytes | uploaded and verified artifact bytes |
128
+ | `overall` | phases | completed phases and fixed phase count |
129
+
130
+ The worker continues to use its existing receipt and manifest rules. A progress write failure must not corrupt a useful checkpoint or published result.
131
+
132
+ ## Delivery sequence
133
+
134
+ 1. Add and release `@osolmaz/pi-workflows/job-progress` as version `0.8.0`.
135
+ 2. Add snapshot discovery guidance to the bundled monitor skill.
136
+ 3. Update xTap Pool to use `0.8.0`, add measured callbacks, and add schedule labels.
137
+ 4. Merge and deploy xTap Pool, then replace the old suspended schedule.
138
+ 5. End the old physical job only when the replacement source is ready and the one-job rule can be preserved.
139
+ 6. Start one instrumented xTap Pool recovery job under the existing restoration budget.
140
+ 7. Update OurModels to use `0.8.0`, add measured callbacks, and replace old schedules with one suspended instrumented schedule.
141
+ 8. Do not start a paid OurModels run until its measured cost range and ceiling receive the required approval.
142
+ 9. Start a Pi monitor that reads both progress surfaces and displays current progress and ETA.
143
+
144
+ ## Acceptance checks
145
+
146
+ Pi Workflows must pass:
147
+
148
+ ```bash
149
+ npm run check
150
+ npm run test:e2e
151
+ npx slophammer-ts@latest dry .
152
+ npx slophammer-ts@latest check . --only ts.dependency-boundaries-required
153
+ ```
154
+
155
+ Tests must cover strict validation, unknown fields, duplicate keys, monotonic updates, phase resets, coalescing, transient publication failure, deadline abort, terminal flush, and ETA estimation from snapshots.
156
+
157
+ xTap Pool must pass its repository checks, including mutation testing. A live recovery must show a valid snapshot in the existing index Bucket, and repeated monitor samples must produce a measured ETA when a track has a known total and positive progress.
158
+
159
+ OurModels must pass:
160
+
161
+ ```bash
162
+ npm run check
163
+ npm run coverage
164
+ npm run dry
165
+ npm run mutate
166
+ node scripts/test-bounds-engine.mjs
167
+ node scripts/validate-model-data.mjs
168
+ ```
169
+
170
+ Its replacement schedule must remain suspended with only the approved two secrets until a paid run is authorized.
171
+
172
+ ## Recovery
173
+
174
+ If a progress publication fails, the worker keeps useful work and retries only the latest snapshot at the next bounded update. If the job ends before that succeeds, the receipt and durable outputs remain authoritative and the monitor marks progress stale.
175
+
176
+ If a repeated deterministic worker defect appears, stop the affected job and schedule. Preserve all existing Bucket objects and return the exact failing phase, source revision, snapshot, receipt state, and last valid durable outputs.
package/docs/workflows.md CHANGED
@@ -369,6 +369,16 @@ and resume later by running that wait again from the beginning.
369
369
  A monitor uses the session's single active workflow slot. It does not provide
370
370
  cron syntax, calendar scheduling, OS notifications, or a background service.
371
371
 
372
+ ### Durable remote Job progress
373
+
374
+ Remote workers can publish the same progress tracks through
375
+ `@osolmaz/pi-workflows/job-progress`. The storage-neutral reporter writes a
376
+ strict, versioned snapshot through an application-supplied callback. A monitor
377
+ can read consecutive snapshots from an existing remote store and use the normal
378
+ progress estimator without treating logs as durable state. See
379
+ [JOB_PROGRESS.md](JOB_PROGRESS.md) for the API, snapshot schema, restart rules,
380
+ and discovery labels.
381
+
372
382
  ## The step contract
373
383
 
374
384
  Every `agent` prompt ends with a step contract block naming the workflow, the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osolmaz/pi-workflows",
3
- "version": "0.6.1",
3
+ "version": "0.8.0",
4
4
  "description": "Workflow and controller runtime with a live terminal viewer for the pi coding agent",
5
5
  "keywords": [
6
6
  "pi-package"
@@ -20,6 +20,7 @@
20
20
  "files": [
21
21
  "dist",
22
22
  "src",
23
+ "skills",
23
24
  "examples",
24
25
  "docs",
25
26
  "README.md",
@@ -38,6 +39,10 @@
38
39
  "./controllers": {
39
40
  "types": "./dist/controllers/index.d.ts",
40
41
  "default": "./dist/controllers/index.js"
42
+ },
43
+ "./job-progress": {
44
+ "types": "./dist/job-progress/index.d.ts",
45
+ "default": "./dist/job-progress/index.js"
41
46
  }
42
47
  },
43
48
  "publishConfig": {
@@ -86,6 +91,9 @@
86
91
  "pi": {
87
92
  "extensions": [
88
93
  "./src/extension/index.ts"
94
+ ],
95
+ "skills": [
96
+ "./skills"
89
97
  ]
90
98
  }
91
99
  }
@@ -0,0 +1,170 @@
1
+ ---
2
+ name: monitor
3
+ description: Use when the user asks to monitor, watch, track, or periodically check a running command, remote Job, CI run, deployment, publication, or other long-running objective. Starts the built-in Pi monitor workflow immediately in the current session and drives the objective autonomously, including routine recovery, until verified completion or a material blocker.
4
+ compatibility: Requires Pi Workflows and the built-in monitor workflow.
5
+ ---
6
+
7
+ # Monitor
8
+
9
+ Use the built-in Pi `monitor` workflow as an autopilot for the requested objective. Monitoring is not passive status polling. The agent must maintain nominal operation, repair recoverable failures, resume durable work, and continue until the complete objective is verified or a material blocker makes safe continuation impossible.
10
+
11
+ A monitor request authorizes routine operational actions that are necessary to preserve and finish the stated objective, subject to the conversation and repository approval boundaries. These actions can include restarting or resuming the same non-paid Job or process, repairing an exact operational configuration or storage-path error, retrying transient infrastructure failures, restoring a verified checkpoint, and replacing a failed physical attempt with the same immutable execution contract. Paid launches, resumes, retries, or replacements require the explicit approval described below. Monitoring does not authorize changing the objective, method, model, data source, production selection, or other consequential contract.
12
+
13
+ ## Prepare and start without delay
14
+
15
+ As soon as the user invokes this skill:
16
+
17
+ 1. Read the current conversation, active plan, repository instructions, and applicable compute, runtime, credential, deployment, or publication skills.
18
+ 2. Preserve the exact objective, immutable execution contract, current identifiers, durable progress, cost already spent, approval ceilings, finish criteria, and known recovery rules in the workflow input. Write or update a durable plan or incident note first only when the work needs one for safe continuation.
19
+ 3. Make the workflow instructions faithful to what the user requested. Do not reduce an implementation or recovery objective to observation-only monitoring.
20
+ 4. Call `workflow` with `action: "start"` in the current Pi session without asking for another confirmation or waiting for a later turn.
21
+ 5. Let the first workflow check run immediately. Do not use Unified Exec sleeps, manual polling loops, a second scheduler, or a separate Pi session as a substitute.
22
+
23
+ Do not finish the initiating turn before the workflow start call. If a safe contract cannot yet be written because a critical identifier or boundary is missing, gather it immediately when possible. Ask the user only when the missing decision is consequential and cannot be inferred safely.
24
+
25
+ ## Build the monitor contract
26
+
27
+ Derive the workflow input from the full conversation:
28
+
29
+ - `task`: State the complete objective, the exact current target and stable identifiers, authoritative status sources, durable progress and final-output surfaces, approved recovery actions, immutable boundaries, cost and credential rules, and required validation or downstream operations.
30
+ - `everyMinutes`: Use the user's interval when present. Use `30` when the user gives no interval. The built-in workflow accepts intervals from 1 minute through 24 hours.
31
+ - `stopWhen`: Infer verified completion from the full conversation. Describe completion of the complete objective, not only the end of one physical process. Also name material blockers that require human intervention.
32
+
33
+ When the conversation gives no clear finish criterion, set `stopWhen` to `Stop only when the user explicitly asks to stop.` Do not use that fallback when a broader implementation, repair, publication, or deployment objective is clear from context.
34
+
35
+ Do not invent a finite check count. Omit `maxChecks` unless the user explicitly requests one. The workflow host can apply its own safety upper bound. Disclose that bound if it appears.
36
+
37
+ ## Paid infrastructure authority
38
+
39
+ A monitoring request does not grant spending approval or create a default spending ceiling. Before launching, resuming, retrying, or replacing paid work, load and follow the paid-compute, provider, Job-control, and runtime skills that apply. Present the required estimate and obtain explicit approval when those policies require it.
40
+
41
+ After approval, preserve the exact method, hardware, concurrency, cumulative cost ceiling, and recovery assumptions in the monitor task. Continue only within that approved contract. Stop for a decision before new paid work when there is no applicable approval, when the ceiling would be exceeded, or when evidence invalidates an approved assumption.
42
+
43
+ The monitor may use a credential only when the conversation or repository has already authorized that credential's source, destination, and purpose. It may reuse that authorization for retries and replacement attempts under the same objective. It must not discover unrelated credentials, broaden scopes, copy credentials to a new store, or print secret values.
44
+
45
+ ## Start the workflow
46
+
47
+ Start the built-in workflow in the current session with this shape:
48
+
49
+ ```text
50
+ workflow({
51
+ action: "start",
52
+ workflow: "monitor",
53
+ input: {
54
+ task: "<complete objective, contract, recovery authority, and verification task>",
55
+ everyMinutes: 30,
56
+ stopWhen: "<derived finish criterion or explicit-user-stop fallback>"
57
+ }
58
+ })
59
+ ```
60
+
61
+ Use the user-supplied interval instead of `30` when present. Add `maxChecks` only when the user explicitly supplies that limit. Do not send `reportWhen`; the current monitor reports every accepted check.
62
+
63
+ Do not start a second monitor for the same objective while one is active. Update or replace the run only when the objective or contract changes. A replacement must preserve the previous accepted observation and durable recovery state.
64
+
65
+ ## Complete workflow checks
66
+
67
+ Each workflow check arrives with an exact step contract. Apply only the operational authority recorded in `task`. The default monitor contract is recovery-capable autopilot within recorded approval boundaries, not authority to create new spending or change the objective.
68
+
69
+ For each check:
70
+
71
+ 1. Query the target's authoritative status.
72
+ 2. Query durable progress and final-output surfaces. Run independent reads in parallel when useful.
73
+ 3. Compare the current values with the previous accepted observation.
74
+ 4. If operation is not nominal, preserve evidence, diagnose the issue, apply the smallest authorized repair, and verify that durable progress resumes. Fix issues and restart Jobs or processes when that is necessary to keep the same objective moving.
75
+ 5. Include a concise report for every accepted check. Report absolute totals and meaningful deltas when counters matter.
76
+ 6. Select `continue` or `stop` as required by the step contract.
77
+ 7. Call `workflow` with `action: "submit"` exactly once, using the supplied step and attempt IDs and the required output shape.
78
+
79
+ The workflow sends each report as a Pi notification. Notifications do not start a new assistant turn. Do not add a separate assistant reply to a workflow notification.
80
+
81
+ ## Publish progress when measurable
82
+
83
+ Progress is optional. Do not invent it for work that has no factual count, total, rate, or source estimate.
84
+
85
+ When the target exposes measurable progress, include one or more tracks in the check output. Use a stable key for each independent process or workstream. Use `overall` for a real aggregate only; do not add unrelated tracks together.
86
+
87
+ Each track uses `pi-workflows.progress.v1` and can include:
88
+
89
+ - `status`: `pending`, `running`, `waiting`, `blocked`, `completed`, `failed`, `cancelled`, or `unknown`;
90
+ - `label` and `phase` for short display text and estimation epochs;
91
+ - `completed`, `total`, and `unit` for factual counts;
92
+ - `sourceUpdatedAt` and `sourceEstimatedFinishAt` when the target provides its own fresh estimate.
93
+
94
+ Submit observed facts. The workflow computes rates, confidence, remaining work, and measured ETA from durable samples. Do not guess a count, rate, or ETA. A changed phase, total, unit, or lower completed count starts a new estimation epoch.
95
+
96
+ For several concurrent processes, publish one stable track per process. The Pi widget and viewers show them separately and keep each ETA independent.
97
+
98
+ ### Read durable job snapshots
99
+
100
+ A remote job can advertise a `pi-workflows.job-progress.v1` snapshot with these immutable labels:
101
+
102
+ - `progress_schema=pi-workflows.job-progress.v1`
103
+ - `progress_bucket=<existing-bucket>`
104
+ - `progress_prefix=<path-before-job-id>`
105
+
106
+ When these labels exist, form `<progress_prefix>/<physical-job-id>/progress.json`, read it from the named existing store with an already authorized credential, and validate it with the installed `@osolmaz/pi-workflows/job-progress` API. Reject a snapshot whose job ID, source revision, or work-contract identity does not match the observed Job. Do not follow a path or credential named inside unvalidated data.
107
+
108
+ Publish the snapshot tracks under stable keys. Preserve consecutive samples so the workflow can estimate ETA from measured progress. Treat a stale or missing snapshot as unavailable progress, not as proof that the Job stopped. Receipts, hashes, manifests, and final outputs remain the completion evidence.
109
+
110
+ ## Apply finish rules
111
+
112
+ ### Still active
113
+
114
+ Continue. Keep reports short unless the state changed materially.
115
+
116
+ ### Completed
117
+
118
+ Stop only after the inferred finish criterion is true. Verify required final artifacts, checksums, receipts, publication state, or downstream health before selecting `stop`.
119
+
120
+ ### Failed, stopped, or blocked
121
+
122
+ Do not disarm the monitor for a superficial reason. One failed physical Job, command, CI run, deployment attempt, upload, or status read is not the end of the objective. Treat it as an operational event, preserve evidence and durable state, diagnose it, apply the smallest safe repair, restart or resume the same immutable contract, restore nominal operation, and keep monitoring.
123
+
124
+ Examples of recoverable conditions include transient provider or network errors, platform eviction, rate limits, expired physical attempts, safe checkpoint reconciliation, exact path or configuration mistakes, bounded storage failures, and a stalled deployment that has a documented recovery action.
125
+
126
+ Stop only for a material blocker, such as:
127
+
128
+ - a deterministic shared code or data defect that makes further attempts unsafe;
129
+ - an invalid, missing, or unverifiable checkpoint when useful state would be lost;
130
+ - a required credential that has no prior source-and-destination authorization;
131
+ - a changed model, method, source, hardware class, objective, or production decision;
132
+ - a destructive or security-sensitive action outside the recorded authority;
133
+ - a cost, time, or resource ceiling that cannot safely contain the remaining work;
134
+ - evidence that the requested result cannot be made truthful or valid under the current contract.
135
+
136
+ Never keep paid workers retrying a deterministic shared failure. Contain affected work, report the evidence and ETA impact, and stop for a decision.
137
+
138
+ ### Status unavailable
139
+
140
+ Retry only a cheap, bounded status read. If the source remains unavailable, report the gap. Continue only when observation remains safe and the finish criterion is not met.
141
+
142
+ ## Check the right surfaces
143
+
144
+ Depending on the target, inspect:
145
+
146
+ - Process, Job, workflow, CI, or deployment status.
147
+ - Durable receipts and counters.
148
+ - Checkpoints or partial outputs.
149
+ - Final manifests, databases, publications, or release artifacts.
150
+ - Error state and the freshness of the last durable update.
151
+
152
+ Logs and progress counters alone do not prove saved work or completion. Prefer durable artifacts and authoritative remote state.
153
+
154
+ ## Stop on user request
155
+
156
+ When the user asks to stop, cancel the active monitor workflow with `workflow({ action: "cancel" })` and confirm that monitoring stopped. Do not wait for the next scheduled check.
157
+
158
+ ## Status format
159
+
160
+ For an unchanged active target, prefer a compact report:
161
+
162
+ ```text
163
+ Target remains running:
164
+ - Progress: <absolute total> (<delta since last report>)
165
+ - Cost or resource use: <total>
166
+ - Durable output: <state>
167
+ - Next check: <interval>
168
+ ```
169
+
170
+ Explain anomalies, failures, or approval boundaries when they occur. Avoid repeating the full history at every check.