@tryinget/pi-agent-registry 0.3.1 → 0.3.2
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.
- package/README.md +124 -14
- package/docs/engineering.local.md +16 -7
- package/docs/project/2026-08-27-agent-registry.md +86 -12
- package/extensions/pi-agent-registry.ts +3 -0
- package/extensions/standing-agent-spawn.ts +85 -0
- package/package.json +8 -6
- package/src/visible-launch-admission.ts +69 -0
- package/src/visible-launch-bootstrap.ts +100 -0
- package/src/visible-launch-compose.ts +273 -0
- package/src/visible-launch-contract.ts +165 -0
- package/src/visible-launch-inputs.ts +57 -0
- package/src/visible-launch-receipt.ts +276 -0
- package/src/visible-launch-transport.ts +77 -0
- package/src/visible-launch.ts +482 -0
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
summary: "Overview and operator contract for pi-agent-registry manifest inspection, immutable fleet lint, and
|
|
2
|
+
summary: "Overview and operator contract for pi-agent-registry manifest inspection, immutable fleet lint, and Phase-2 dispatch / Phase-3 visible admission contracts."
|
|
3
3
|
read_when:
|
|
4
4
|
- "Starting work in this package workspace."
|
|
5
|
-
- "Using agent_registry, pi-agent-registry-lint, dispatch_agent, or the agent manifest convention."
|
|
5
|
+
- "Using agent_registry, pi-agent-registry-lint, dispatch_agent, standing_agent_spawn, or the agent manifest convention."
|
|
6
6
|
system4d:
|
|
7
|
-
container: "Pi extension and CLI for standing-agent manifest/fleet observation and
|
|
8
|
-
compass: "Make fleet contract drift visible and bind one provable read-only dispatch without owning lifecycle or
|
|
7
|
+
container: "Pi extension and CLI for standing-agent manifest/fleet observation and bounded dispatch/visible admission contracts."
|
|
8
|
+
compass: "Make fleet contract drift visible and bind one provable read-only dispatch without owning lifecycle or transport machinery."
|
|
9
9
|
engine: "Discover every candidate -> capture committed bytes -> lint deterministically -> authorize one exact task -> dispatch read-only through ASC."
|
|
10
10
|
fog: "A green tool run can be mistaken for a healthy or authorized fleet, and one settled dispatch can be mistaken for general standing-agent enablement."
|
|
11
11
|
---
|
|
@@ -14,16 +14,16 @@ system4d:
|
|
|
14
14
|
|
|
15
15
|
Standing-agent registry for Pi: reads `ai-society.agent/1` manifests for
|
|
16
16
|
inspection, emits a bounded, immutable-observation fleet lint report, and owns
|
|
17
|
-
the Fleet Phase-2 dispatch
|
|
18
|
-
lifecycle, role acceptance, or
|
|
19
|
-
|
|
17
|
+
the Fleet Phase-2 dispatch and Phase-3 visible admission contracts. It does not
|
|
18
|
+
own agent creation, lifecycle, role acceptance, or transport machinery. Phase-2
|
|
19
|
+
execution stays ASC-owned; Phase-3 Ghostty transport stays little-helpers-owned.
|
|
20
20
|
|
|
21
|
-
Status: **Fleet Phase
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
Status: **Fleet Phase 3 (AK 5133), locally implemented and live-dogfood verified**.
|
|
22
|
+
Phase-2 (AK 5132) read-only ASC dispatch is unchanged. Phase 3 adds one clean
|
|
23
|
+
visible standing-agent TUI admission for an exact claimed task, not lifecycle
|
|
24
|
+
authority. The real TUI driver → real child TUI proof and passing package/release
|
|
25
|
+
gates are recorded below. AK owns closeout. This is not a published-feature
|
|
26
|
+
claim; AK 5134 remains separate.
|
|
27
27
|
|
|
28
28
|
## Operator surfaces
|
|
29
29
|
|
|
@@ -40,6 +40,9 @@ remain later fleet phases.
|
|
|
40
40
|
- `dispatch_agent` — the Fleet Phase-2 exact-task read-only contract (see
|
|
41
41
|
below); fails closed with `confirmed_no_effects` before any ASC identity,
|
|
42
42
|
capacity, session, or spawn effect exists.
|
|
43
|
+
- `standing_agent_spawn` — Fleet Phase-3 exact-task clean visible admission
|
|
44
|
+
through the little-helpers Ghostty transport; no automatic retry or AK
|
|
45
|
+
evidence recording (see below).
|
|
43
46
|
- `/agents` — concise operator listing.
|
|
44
47
|
|
|
45
48
|
## Fleet layout
|
|
@@ -195,6 +198,110 @@ records AK evidence; an undetectable modify-and-restore interval is not
|
|
|
195
198
|
claimed absent. The dispatch does not authenticate the calling session as the
|
|
196
199
|
AK claimant — lifecycle-v2 permit binding (Fleet Phase 4) tightens that.
|
|
197
200
|
|
|
201
|
+
## Phase-3 clean visible admission (AK 5133)
|
|
202
|
+
|
|
203
|
+
`standing_agent_spawn { agent, task, objective, parentPeerTarget, reportBack?, cwd? }`
|
|
204
|
+
composes one clean Pi TUI session in a Ghostty tab/window. `task` is an exact
|
|
205
|
+
positive AK task id; `objective` is nonblank, bounded to 32 KiB UTF-8, and
|
|
206
|
+
read-only — never an unbound standby brief. `reportBack` defaults to
|
|
207
|
+
`intercom` and requires an exact `session-<UUID>` controller target, not
|
|
208
|
+
`parent`/`active` aliases. `manual` and `none` may omit `parentPeerTarget`.
|
|
209
|
+
`cwd` defaults to the origin repository root and must remain within that
|
|
210
|
+
same Git repository.
|
|
211
|
+
|
|
212
|
+
Admission gates and composition:
|
|
213
|
+
|
|
214
|
+
1. Reject malformed requests, recursive standing-agent children, unavailable
|
|
215
|
+
version-1 transport, unknown agents, mutation tools, and any manifest
|
|
216
|
+
extensions. Declared tools must be a nonempty subset of `read,bash`;
|
|
217
|
+
`intercom` is an explicit added communication instrument, recorded
|
|
218
|
+
separately from declared tools.
|
|
219
|
+
2. Observe the origin Git repository and authorize `ak task show`: the exact
|
|
220
|
+
task must be origin-repo-bound, claimed, and carry a live lease. This does
|
|
221
|
+
not authenticate the caller as the AK claimant.
|
|
222
|
+
3. Require a clean agent repository and agreement between cached, freshly
|
|
223
|
+
parsed, committed, and current manifest/persona inputs. Compose the persona
|
|
224
|
+
plus advisory scope, selected skills, model, and manifest thinking request;
|
|
225
|
+
recheck these inputs and origin/agent stability around transport admission.
|
|
226
|
+
4. Use `--offline --no-extensions --no-skills --no-prompt-templates`, then
|
|
227
|
+
explicit `--extension` paths for approved locally installed
|
|
228
|
+
`@tryinget/pi-peer-messaging` intercom and `@tryinget/pi-little-helpers`
|
|
229
|
+
session-presence entrypoints, and explicit `--skill` selections. No ambient
|
|
230
|
+
extension/skill discovery or controller conversation is inherited. Normal
|
|
231
|
+
cwd-bound AGENTS context is retained; this is not an empty-policy session.
|
|
232
|
+
`--offline` is a Pi startup flag, not network isolation: model/intercom
|
|
233
|
+
communication still occurs. Installed Pi supplies builtin `zai` (including
|
|
234
|
+
the dogfood model `zai/glm-5.3`); no ambient provider extension is needed.
|
|
235
|
+
Unsupported provider/bootstrap shapes fail closed.
|
|
236
|
+
5. Persist an exclusive per-`(agent, task)` reservation before transport,
|
|
237
|
+
then reread the exact task/lease and recheck inputs, bootstrap entry bytes,
|
|
238
|
+
and origin/agent observations immediately before launch. Reservations are
|
|
239
|
+
scoped to the resolved visible-receipts directory, not fleet-global.
|
|
240
|
+
6. Delegate to `@tryinget/pi-little-helpers/sidequest-launch` only when
|
|
241
|
+
`STANDING_AGENT_TRANSPORT_VERSION === 1` and `launchPiQuestSession` exists.
|
|
242
|
+
Registry owns composition/admission/receipts, not Ghostty or session machinery.
|
|
243
|
+
Publish a write-once `pi-agent-registry.visible-launch-receipt/1` receipt
|
|
244
|
+
(`0o400`, canonical self-digest, hard-link publication) after transport
|
|
245
|
+
observation; post-launch drift remains indeterminate rather than clean proof.
|
|
246
|
+
|
|
247
|
+
**Never retry automatically**, including `confirmed_no_effects`, reservation
|
|
248
|
+
failure, cancellation, crash, receipt-publication failure, or indeterminate
|
|
249
|
+
transport. Existing, corrupt, or partial reservations block admission and are
|
|
250
|
+
never automatically released. Supervise the returned run id; any further
|
|
251
|
+
attempt requires explicit owner disposition. Phase-2's three-attempt policy
|
|
252
|
+
is not a Phase-3 retry policy.
|
|
253
|
+
|
|
254
|
+
For intercom mode, the child must send one correlated `PEER_ACK` before any
|
|
255
|
+
file/context work, stop visibly with `ACK_FAILED` if sending fails, and send
|
|
256
|
+
one correlated `PEER_FINAL` when the bounded objective ends, then stop.
|
|
257
|
+
Admission is **not** session-start, ACK, read-only lifetime, task consumption,
|
|
258
|
+
or completion proof. Receipt fields for startup/ACK/completion remain
|
|
259
|
+
`unproven` even when separate live evidence exists. The launcher writes no
|
|
260
|
+
AK evidence; the parent owns reality-test evidence and closeout.
|
|
261
|
+
|
|
262
|
+
Limits: `bash` and scope/read-only instructions are advisory, not a sandbox.
|
|
263
|
+
Launch-window Git observations exclude ignored files, .git internals, external
|
|
264
|
+
surfaces, and modify-and-restore intervals. Bootstrap hashes cover approved
|
|
265
|
+
package manifests and entry files only, not settings/auth/models or transitive
|
|
266
|
+
import integrity. Skill selection/materialization is not whole-runtime
|
|
267
|
+
immutability. Manifest thinking is the **request**, not a guarantee of the
|
|
268
|
+
runtime level: Pi clamps to model-supported levels; live `medium` requested
|
|
269
|
+
became `high` on `zai/glm-5.3`.
|
|
270
|
+
|
|
271
|
+
### Local evidence and release boundary (2026-09-07)
|
|
272
|
+
|
|
273
|
+
Real TUI driver → real child TUI proof, with immutable launch receipt,
|
|
274
|
+
independent runtime assertion output and bounded session observation:
|
|
275
|
+
[Phase-3 dogfood](docs/project/2026-09-07-fleet-phase3-dogfood.md).
|
|
276
|
+
AK evidence/task state remains authoritative.
|
|
277
|
+
|
|
278
|
+
- Run: `standingagent-mtqmbq5w-aeaf6023`; agent revision:
|
|
279
|
+
`dc354723482f0470ad287d1de3e067a72cd99a85`.
|
|
280
|
+
- Receipt: `visible-agent-adoption-steward.20260907T022519Z.8fb48fd0.launch-receipt.json`;
|
|
281
|
+
SHA-256: `6a37b218e3ea7dff14ec0a13e8230920585ddcbf83598d5d949d62828adffd15`.
|
|
282
|
+
- Child session: `01a079af-2ef4-762c-8bfc-228d0b411d4a`; observed PID
|
|
283
|
+
`189076`, `terminalBound` on `/dev/pts/11`, Ghostty surface
|
|
284
|
+
`0x516815b20d7e09a3`.
|
|
285
|
+
- Ghostty build: `origin-main492300cad`, actual version `1.3.2-main`;
|
|
286
|
+
this does **not** prove a literal 1.4 release.
|
|
287
|
+
- Correlated ACK `cce92533-53a7-49d0-bc42-0b808408aafe` and FINAL
|
|
288
|
+
`44cee2a7-9695-42f8-a76e-d4a08b000752` received; no duplicate protocol.
|
|
289
|
+
Child inspected four files read-only; no file or AK writes observed.
|
|
290
|
+
- Registry check: **134/134**; little-helpers check: **430/430**; both full
|
|
291
|
+
release checks pass, including installed-tarball smoke. The stale real-fleet
|
|
292
|
+
baseline was explicitly refreshed after independent HEAD-only reproduction:
|
|
293
|
+
engineering-core docs-only revision `51fc387` → `9225dd6`, unchanged profile
|
|
294
|
+
bytes, fleet revisions, diagnostics and counts. Assertions were not weakened.
|
|
295
|
+
- The new standing-agent reality assertion passes. The broader all-controller
|
|
296
|
+
observer check still detects an unrelated live process naming retired Ghostty
|
|
297
|
+
`9d8fbd15`; this task did not restart other sessions to hide that drift.
|
|
298
|
+
|
|
299
|
+
The version-1 export exists in local little-helpers **0.9.0 source**, not a
|
|
300
|
+
proven published release. Its next release must ship `./sidequest-launch`
|
|
301
|
+
and the version marker before registry publication can claim Phase 3. A packed
|
|
302
|
+
registry resolving older npm helpers fails closed `visible_transport_unavailable`.
|
|
303
|
+
See [dependency posture](docs/engineering.local.md#package-local-deltas-on-the-pi-ts-lane).
|
|
304
|
+
|
|
198
305
|
## Environment
|
|
199
306
|
|
|
200
307
|
| Variable | Meaning |
|
|
@@ -203,6 +310,7 @@ AK claimant — lifecycle-v2 permit binding (Fleet Phase 4) tightens that.
|
|
|
203
310
|
| `PI_AGENT_REGISTRY_EC_PROFILES` | engineering-core `skills/profiles.json` |
|
|
204
311
|
| `PI_AGENT_REGISTRY_USER_SKILLS` | mutable user fallback for runtime extras; fleet lint does not call it immutable |
|
|
205
312
|
| `PI_AGENT_REGISTRY_DISPATCH_RECEIPTS_DIR` | explicit dispatch-receipts directory (default `<pi-agent-dir>/dispatch-receipts`) |
|
|
313
|
+
| `PI_AGENT_REGISTRY_VISIBLE_LAUNCH_RECEIPTS_DIR` | Phase-3 receipts and persistent pair reservations (default `<pi-agent-dir>/visible-launch-receipts`) |
|
|
206
314
|
|
|
207
315
|
## Validation
|
|
208
316
|
|
|
@@ -219,7 +327,9 @@ smoke, and the Phase-2 dispatch contract: AK authorization matrix,
|
|
|
219
327
|
write-once/tamper-evident receipts, settled-pair re-dispatch rejection, the
|
|
220
328
|
three-attempt bound, ledger rename-integrity, read-only violation observation,
|
|
221
329
|
recursion guard, ASC effect-receipt-first disposition derivation, and ASC
|
|
222
|
-
request composition.
|
|
330
|
+
request composition. Phase-3 coverage adds explicit bootstrap/argv composition,
|
|
331
|
+
exact-task rechecks, drift/cancellation gates, durable pair reservation,
|
|
332
|
+
transport capability gating, and immutable admission receipts.
|
|
223
333
|
|
|
224
334
|
Live dogfood (2026-08-31, AK 5132): `agent-adoption-steward` dispatched for
|
|
225
335
|
task 5132 through a fresh one-shot Pi session. Attempt 1 failed closed at child
|
|
@@ -77,13 +77,22 @@ approval, Pi runtime install/reload proof, or monorepo owner authority.
|
|
|
77
77
|
|
|
78
78
|
- Runtime baseline: Node 22+ running TypeScript sources directly; the
|
|
79
79
|
package ships TS sources and has no dist build of its own.
|
|
80
|
-
- Dependency posture: ASC
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
- Dependency posture: ASC and little-helpers are local runtime links in the
|
|
81
|
+
workspace (`file:../pi-autonomous-session-control` and
|
|
82
|
+
`file:../pi-little-helpers`), not the former npm-only ASC `0.5.2` pin.
|
|
83
|
+
The shared `pi-interaction/scripts/prepare-publish-manifest.mjs` prepack /
|
|
84
|
+
postpack hooks temporarily rewrite local runtime dependencies to the linked
|
|
85
|
+
packages' exact versions for publication and restore the workspace manifest.
|
|
86
|
+
Runtime `typebox` is pinned separately; the packed manifest must contain no
|
|
87
|
+
`file:` runtime dependency. The dependencies are not bundled; the existing
|
|
88
|
+
`fast-xml-parser` security override is retained.
|
|
89
|
+
- Publish capability is separate from version rewriting: Phase 2 requires
|
|
90
|
+
ASC's execution exports; Phase 3 requires little-helpers'
|
|
91
|
+
`./sidequest-launch` export with `STANDING_AGENT_TRANSPORT_VERSION === 1`.
|
|
92
|
+
That export is in current local little-helpers `0.9.0` source; the next
|
|
93
|
+
helpers release must ship it. A packed registry with older npm helpers
|
|
94
|
+
fails closed `visible_transport_unavailable`. Do not describe local tests
|
|
95
|
+
or successful packing as a published Phase-3 feature.
|
|
87
96
|
- Tests intentionally read live workspace fixtures (the real steward agent
|
|
88
97
|
repo and the real engineering-core `profiles.json`) to keep the
|
|
89
98
|
convention honest against the fleet, not just against synthetic data.
|
|
@@ -1,29 +1,32 @@
|
|
|
1
1
|
---
|
|
2
|
-
summary: "Design record for pi-agent-registry runtime inspection, Fleet Phase-1 immutable lint, and
|
|
2
|
+
summary: "Design record for pi-agent-registry runtime inspection, Fleet Phase-1 immutable lint, and Phase-2 dispatch / Phase-3 visible admission contracts."
|
|
3
3
|
read_when:
|
|
4
|
-
- "Changing manifest loading, fleet discovery/lint, immutable observations, or dispatch posture."
|
|
4
|
+
- "Changing manifest loading, fleet discovery/lint, immutable observations, or dispatch/visible admission posture."
|
|
5
5
|
- "Onboarding to the standing-agent fleet contract implementation."
|
|
6
6
|
system4d:
|
|
7
7
|
container: "Pi-side read-only registry and fleet observation package."
|
|
8
8
|
compass: "Converge owner interfaces without absorbing lifecycle or execution authority."
|
|
9
|
-
engine: "Capture committed bytes -> lint every candidate -> report stable diagnostics ->
|
|
9
|
+
engine: "Capture committed bytes -> lint every candidate -> report stable diagnostics -> authorize bounded dispatch/admission."
|
|
10
10
|
fog: "Mutable paths and a green process exit can be mistaken for immutable fleet health."
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
# pi-agent-registry —
|
|
13
|
+
# pi-agent-registry — fleet contract design record
|
|
14
14
|
|
|
15
15
|
The monorepo manifest convention is the consumer contract. L0
|
|
16
16
|
`tpl-agent-repo` owns birth/propagation shape, `softwareco-agents` owns
|
|
17
17
|
fleet/role/lifecycle conventions, engineering-core owns profile keys/members,
|
|
18
|
-
AK owns task/evidence/decision truth,
|
|
18
|
+
AK owns task/evidence/decision truth, ASC owns Phase-2 execution, and
|
|
19
|
+
little-helpers owns Phase-3 visible Ghostty transport.
|
|
19
20
|
|
|
20
|
-
This package owns two read-only Pi-side surfaces and
|
|
21
|
-
|
|
21
|
+
This package owns two read-only Pi-side surfaces and two bounded composition
|
|
22
|
+
contracts:
|
|
22
23
|
|
|
23
24
|
1. mutable manifest inspection for already loadable agents;
|
|
24
25
|
2. aggregate immutable-observation fleet lint;
|
|
25
26
|
3. the Fleet Phase-2 exact-task read-only dispatch contract (authorization,
|
|
26
|
-
receipt, evidence) with all spawn/session/capacity machinery ASC-owned
|
|
27
|
+
receipt, evidence) with all Phase-2 spawn/session/capacity machinery ASC-owned;
|
|
28
|
+
4. the Fleet Phase-3 exact-task clean visible admission contract, with
|
|
29
|
+
little-helpers-owned transport and no automatic AK evidence.
|
|
27
30
|
|
|
28
31
|
None of these surfaces grants standing-agent lifecycle authority.
|
|
29
32
|
|
|
@@ -80,6 +83,21 @@ src/dispatch-request.ts
|
|
|
80
83
|
|
|
81
84
|
src/dispatch.ts + src/sessions-dir.ts
|
|
82
85
|
Phase-2 pipeline with fail-closed gates; sessions delegated to ASC
|
|
86
|
+
|
|
87
|
+
extensions/standing-agent-spawn.ts + src/visible-launch.ts
|
|
88
|
+
Phase-3 tool registration and exact-task admission/recheck pipeline
|
|
89
|
+
|
|
90
|
+
src/visible-launch-contract.ts + visible-launch-compose.ts
|
|
91
|
+
clean child argv, manifest persona/model/thinking request, ACK/FINAL brief
|
|
92
|
+
|
|
93
|
+
src/visible-launch-inputs.ts + visible-launch-bootstrap.ts
|
|
94
|
+
clean agent byte agreement and approved installed bootstrap entry checks
|
|
95
|
+
|
|
96
|
+
src/visible-launch-admission.ts + visible-launch-receipt.ts
|
|
97
|
+
persistent exclusive agent/task reservation and write-once launch observation
|
|
98
|
+
|
|
99
|
+
src/visible-launch-transport.ts
|
|
100
|
+
version-1 little-helpers sidequest-launch capability gate, not transport code
|
|
83
101
|
```
|
|
84
102
|
|
|
85
103
|
## Manifest compatibility
|
|
@@ -218,7 +236,7 @@ failure still fails closed with `confirmed_no_effects`:
|
|
|
218
236
|
request and creates the runtime through ASC's exported
|
|
219
237
|
`createAscExecutionRuntime` + `resolveSubagentSessionsDir` + model
|
|
220
238
|
selection; the registry supplies only the `extraSkillProfileResolver` seam
|
|
221
|
-
(`skillProfile = agent name`). No spawn/session/capacity code lives here.
|
|
239
|
+
(`skillProfile = agent name`). No Phase-2 spawn/session/capacity code lives here.
|
|
222
240
|
`src/sessions-dir.ts` now delegates to ASC instead of the Phase-0
|
|
223
241
|
quarantine.
|
|
224
242
|
- **One level deep**: dispatched children carry
|
|
@@ -256,11 +274,65 @@ so dash-led prompts (persona front matter) require the registry's dispatch
|
|
|
256
274
|
header envelope — a pi/ASC transport hardening candidate for a later slice
|
|
257
275
|
(first observed live 2026-08-31 as child exit `Unknown option: ---`).
|
|
258
276
|
|
|
277
|
+
## Phase-3 clean visible admission (AK 5133)
|
|
278
|
+
|
|
279
|
+
**Locally implemented and live-dogfood verified; not published.**
|
|
280
|
+
`standing_agent_spawn { agent, task, objective, parentPeerTarget, reportBack?, cwd? }`
|
|
281
|
+
adds visible TUI admission without changing Phase-2 ASC dispatch. Full operator
|
|
282
|
+
contract and compact evidence identifiers live in the
|
|
283
|
+
[README](../../README.md#phase-3-clean-visible-admission-ak-5133) and the
|
|
284
|
+
[2026-09-07 dogfood evidence](2026-09-07-fleet-phase3-dogfood.md), including
|
|
285
|
+
receipt and real-runtime assertion output. AK owns evidence and closeout.
|
|
286
|
+
|
|
287
|
+
The exact task must be claimed with a live lease in the observed origin repo;
|
|
288
|
+
child cwd cannot cross that repo boundary. Clean committed manifest/persona
|
|
289
|
+
inputs must agree with cached, fresh, and resolved inputs. After exclusive
|
|
290
|
+
persistent pair reservation, task/lease facts and origin/agent/bootstrap inputs
|
|
291
|
+
are rechecked immediately before transport and inputs are observed afterward.
|
|
292
|
+
An unresolved, corrupt, partial, or admitted reservation blocks another
|
|
293
|
+
admission in that receipts directory. Never retry automatically — including
|
|
294
|
+
no-effects, reservation failure, cancellation, crash, or publication failure;
|
|
295
|
+
explicit owner disposition is required. Phase-2 attempt limits do not apply.
|
|
296
|
+
|
|
297
|
+
Composition uses `--offline --no-extensions --no-skills --no-prompt-templates`
|
|
298
|
+
plus approved installed intercom/presence entrypoints and explicitly selected
|
|
299
|
+
skills. Normal cwd-bound AGENTS context remains; controller conversation and
|
|
300
|
+
ambient extension/skill discovery do not. Builtin `zai` is supported without
|
|
301
|
+
an ambient provider extension. Manifest thinking is requested via argv, then
|
|
302
|
+
Pi applies its supported-level clamp (live `medium` → `high` on
|
|
303
|
+
`zai/glm-5.3`). Settings/auth/models, transitive imports, and full skill/runtime
|
|
304
|
+
integrity are not proven by the approved-entry hashes. Offline startup is not
|
|
305
|
+
network isolation; `bash`/scope are advisory, not a sandbox.
|
|
306
|
+
|
|
307
|
+
Registry composes; little-helpers' exported `sidequest-launch` owns visible
|
|
308
|
+
transport and must advertise `STANDING_AGENT_TRANSPORT_VERSION === 1`.
|
|
309
|
+
The export is present in local helpers 0.9.0 source but must ship in its next
|
|
310
|
+
release; older npm helpers make packed registry admission fail closed. No
|
|
311
|
+
claim of published availability follows from local tests.
|
|
312
|
+
|
|
313
|
+
The immutable launch receipt records transport admission and bounded
|
|
314
|
+
launch-window observations, never session-start/ACK/completion proof; those
|
|
315
|
+
fields remain `unproven`. Intercom mode requires an exact controller
|
|
316
|
+
`session-<UUID>`, one first-action `PEER_ACK`, then one closing `PEER_FINAL`
|
|
317
|
+
and stop; manual/none modes may omit the target. No automatic AK evidence is
|
|
318
|
+
written. Verified live proof used a real TUI driver and real child TUI,
|
|
319
|
+
correlated ACK/FINAL without duplicates, and four read-only file inspections
|
|
320
|
+
with no file/AK writes observed. Ghostty was `1.3.2-main`
|
|
321
|
+
(`origin-main492300cad`), not a literal 1.4 release.
|
|
322
|
+
|
|
323
|
+
Final package checks: registry **134/134**, helpers **430/430**, and both full
|
|
324
|
+
release checks pass. The real-fleet pin was explicitly refreshed after independent
|
|
325
|
+
HEAD-only reproduction of engineering-core's docs-only `51fc387` → `9225dd6`
|
|
326
|
+
drift; profile bytes, fleet revisions, diagnostics and assertions are unchanged.
|
|
327
|
+
The new standing-agent reality assertion passes; the broader observer test still
|
|
328
|
+
reports an unrelated process on retired Ghostty `9d8fbd15`. AK5134 remains separate.
|
|
329
|
+
|
|
259
330
|
## Real fleet baseline
|
|
260
331
|
|
|
261
332
|
The real `~/ai-society/agents/agent-*` walk is revision-bound in
|
|
262
|
-
`tests/fixtures/real-fleet-lint-baseline.json`. The
|
|
263
|
-
|
|
333
|
+
`tests/fixtures/real-fleet-lint-baseline.json`. The original Phase-1 unhealthy
|
|
334
|
+
result recorded these historical observations (not a claim about current
|
|
335
|
+
external HEADs):
|
|
264
336
|
|
|
265
337
|
- four canonical repositories observed;
|
|
266
338
|
- three missing manifests;
|
|
@@ -283,5 +355,7 @@ slice rather than silently turning green.
|
|
|
283
355
|
- real fleet test: exact commits, profile bytes, diagnostics, and report digest;
|
|
284
356
|
- extension test: `action=lint` returns observation-only unhealthy baseline;
|
|
285
357
|
- CLI test: JSON and exit taxonomy;
|
|
286
|
-
- packed smoke: shipped CLI/module/action
|
|
358
|
+
- packed smoke: shipped CLI/module/action and fail-closed dependency capability gates;
|
|
359
|
+
- Phase-3 tests: argv/bootstrap composition, exact-task and input rechecks,
|
|
360
|
+
persistent reservation, cancellation/drift, and immutable launch receipts;
|
|
287
361
|
- package check, fresh Pi dogfood, root loop gates, and independent review.
|
|
@@ -10,6 +10,7 @@ import { Type } from "typebox";
|
|
|
10
10
|
import { dispatchAgent } from "../src/dispatch.ts";
|
|
11
11
|
import { lintAgentFleet } from "../src/fleet-lint.ts";
|
|
12
12
|
import { type AgentRegistry, AgentRegistryError, createAgentRegistry } from "../src/registry.ts";
|
|
13
|
+
import { registerStandingAgentSpawnTool } from "./standing-agent-spawn.ts";
|
|
13
14
|
|
|
14
15
|
interface RegistryHandle {
|
|
15
16
|
registry: AgentRegistry;
|
|
@@ -375,4 +376,6 @@ Phase-2 boundaries: standing-agent dispatch is one level deep (children carry PI
|
|
|
375
376
|
};
|
|
376
377
|
},
|
|
377
378
|
});
|
|
379
|
+
|
|
380
|
+
registerStandingAgentSpawnTool({ pi, getRegistry });
|
|
378
381
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// summary: register exact-task visible admission; no transport/session machinery here.
|
|
2
|
+
import { StringEnum } from "@earendil-works/pi-ai";
|
|
3
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import { Type } from "typebox";
|
|
5
|
+
import type { AgentRegistry } from "../src/registry.ts";
|
|
6
|
+
import { spawnStandingAgentVisible } from "../src/visible-launch.ts";
|
|
7
|
+
|
|
8
|
+
export function registerStandingAgentSpawnTool({
|
|
9
|
+
pi,
|
|
10
|
+
getRegistry,
|
|
11
|
+
}: {
|
|
12
|
+
pi: ExtensionAPI;
|
|
13
|
+
getRegistry: () => Promise<AgentRegistry>;
|
|
14
|
+
}): void {
|
|
15
|
+
pi.registerTool({
|
|
16
|
+
name: "standing_agent_spawn",
|
|
17
|
+
label: "Standing Agent Visible Admission (Phase 3)",
|
|
18
|
+
description:
|
|
19
|
+
"Request ONE clean visible Pi TUI session in a Ghostty tab/window (Fleet Phase 3), composed as a read-only standing agent for an exact claimed AK task in this origin repository. Requires a nonblank bounded objective, clean committed agent inputs and trusted explicit ACK/presence/provider bootstrap. Atomically reserves the agent/task pair before transport: unresolved or admitted launches cannot be retried automatically, even after cancellation or crashes. Explicit owner disposition is required. Transport admission does NOT prove session startup, ACK, read-only lifetime behavior, task consumption or completion; no AK evidence is written. Read/bash posture is advisory, not a sandbox.",
|
|
20
|
+
promptSnippet:
|
|
21
|
+
"Request one exact-task read-only visible standing-agent admission, not task completion.",
|
|
22
|
+
promptGuidelines: [
|
|
23
|
+
"standing_agent_spawn requires agent discovery, an exact claimed AK task, a bounded read-only objective and an exact controller session id for intercom report-back.",
|
|
24
|
+
"Never retry standing_agent_spawn automatically for a reserved/admitted or indeterminate agent/task pair; supervise the returned runId.",
|
|
25
|
+
],
|
|
26
|
+
parameters: Type.Object({
|
|
27
|
+
agent: Type.String({ pattern: "^[a-z][a-z0-9-]{0,63}$" }),
|
|
28
|
+
task: Type.Integer({
|
|
29
|
+
minimum: 1,
|
|
30
|
+
description: "Exact claimed AK task in the origin repository.",
|
|
31
|
+
}),
|
|
32
|
+
objective: Type.String({
|
|
33
|
+
minLength: 1,
|
|
34
|
+
maxLength: 32_768,
|
|
35
|
+
description:
|
|
36
|
+
"Bounded read-only inspection/report objective, maximum 32 KiB UTF-8. No standby or mutation.",
|
|
37
|
+
}),
|
|
38
|
+
reportBack: Type.Optional(
|
|
39
|
+
StringEnum(["intercom", "manual", "none"] as const, { description: "Default intercom." }),
|
|
40
|
+
),
|
|
41
|
+
parentPeerTarget: Type.Optional(
|
|
42
|
+
Type.String({ description: "Exact controller session id; required for intercom." }),
|
|
43
|
+
),
|
|
44
|
+
cwd: Type.Optional(
|
|
45
|
+
Type.String({
|
|
46
|
+
description:
|
|
47
|
+
"Existing directory within the exact task's origin repository; defaults to that root.",
|
|
48
|
+
}),
|
|
49
|
+
),
|
|
50
|
+
}),
|
|
51
|
+
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
52
|
+
const registry = await getRegistry();
|
|
53
|
+
const outcome = await spawnStandingAgentVisible(
|
|
54
|
+
params,
|
|
55
|
+
{ registry, pi },
|
|
56
|
+
{
|
|
57
|
+
cwd: ctx.cwd,
|
|
58
|
+
...(ctx.model ? { model: ctx.model as { provider?: string; id?: string } } : {}),
|
|
59
|
+
},
|
|
60
|
+
signal,
|
|
61
|
+
);
|
|
62
|
+
const text = outcome.ok
|
|
63
|
+
? `Transport admitted (${outcome.launchMode}), run ${outcome.runId}. Session start, ACK and task completion remain unproven.\nReceipt: ${outcome.receiptPath}`
|
|
64
|
+
: `${outcome.message}${outcome.runId ? `\nSupervision run: ${outcome.runId}` : ""}`;
|
|
65
|
+
return {
|
|
66
|
+
content: [{ type: "text" as const, text }],
|
|
67
|
+
details: {
|
|
68
|
+
ok: outcome.ok,
|
|
69
|
+
phase: outcome.phase,
|
|
70
|
+
...(outcome.runId ? { runId: outcome.runId } : {}),
|
|
71
|
+
...(outcome.ok
|
|
72
|
+
? { admission: outcome.admission }
|
|
73
|
+
: {
|
|
74
|
+
reason: outcome.reason,
|
|
75
|
+
effectDisposition: outcome.effectDisposition,
|
|
76
|
+
spawnAttempted: outcome.spawnAttempted,
|
|
77
|
+
}),
|
|
78
|
+
...(outcome.receiptPath ? { receiptPath: outcome.receiptPath } : {}),
|
|
79
|
+
...(outcome.receipt ? { receiptSha256: outcome.receipt.receiptSha256 } : {}),
|
|
80
|
+
},
|
|
81
|
+
...(!outcome.ok ? { isError: true } : {}),
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tryinget/pi-agent-registry",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "Pi standing-agent manifest inspection, immutable fleet lint,
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"description": "Pi standing-agent manifest inspection, immutable fleet lint, the Fleet Phase-2 exact-task read-only dispatch contract, and the Fleet Phase-3 clean visible standing-agent launch",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
7
7
|
"repository": {
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
},
|
|
58
58
|
"files": [
|
|
59
59
|
"extensions/pi-agent-registry.ts",
|
|
60
|
+
"extensions/standing-agent-spawn.ts",
|
|
60
61
|
"src",
|
|
61
62
|
"scripts/fleet-lint.mjs",
|
|
62
63
|
"prompts",
|
|
@@ -84,9 +85,9 @@
|
|
|
84
85
|
},
|
|
85
86
|
"devDependencies": {
|
|
86
87
|
"@biomejs/biome": "2.3.14",
|
|
87
|
-
"@earendil-works/pi-agent-core": "0.84.
|
|
88
|
-
"@earendil-works/pi-ai": "0.84.
|
|
89
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
88
|
+
"@earendil-works/pi-agent-core": "0.84.4",
|
|
89
|
+
"@earendil-works/pi-ai": "0.84.4",
|
|
90
|
+
"@earendil-works/pi-coding-agent": "0.84.4",
|
|
90
91
|
"@types/node": "^25.3.3",
|
|
91
92
|
"@typescript/native-preview": "7.0.0-dev.20260417.1"
|
|
92
93
|
},
|
|
@@ -100,6 +101,7 @@
|
|
|
100
101
|
},
|
|
101
102
|
"dependencies": {
|
|
102
103
|
"@tryinget/pi-autonomous-session-control": "0.7.0",
|
|
103
|
-
"typebox": "1.3.7"
|
|
104
|
+
"typebox": "1.3.7",
|
|
105
|
+
"@tryinget/pi-little-helpers": "0.10.0"
|
|
104
106
|
}
|
|
105
107
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// summary: durable exclusive Phase-3 pair reservation; no automatic release or retry, including crashes.
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { mkdir, open, readFile, realpath } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { canonicalJsonString, sha256Hex } from "./dispatch-receipt.ts";
|
|
6
|
+
import {
|
|
7
|
+
resolveVisibleLaunchReceiptsDir,
|
|
8
|
+
validateVisibleLaunchIdentity,
|
|
9
|
+
} from "./visible-launch-receipt.ts";
|
|
10
|
+
|
|
11
|
+
export async function reserveVisibleLaunchPair(
|
|
12
|
+
input: {
|
|
13
|
+
agent: string;
|
|
14
|
+
task: number;
|
|
15
|
+
runId: string;
|
|
16
|
+
requestSha256: string;
|
|
17
|
+
},
|
|
18
|
+
dir?: string,
|
|
19
|
+
): Promise<{ reserved: true; path: string } | { reserved: false; runId?: string }> {
|
|
20
|
+
validateVisibleLaunchIdentity(input.agent, input.runId);
|
|
21
|
+
if (
|
|
22
|
+
!Number.isSafeInteger(input.task) ||
|
|
23
|
+
input.task <= 0 ||
|
|
24
|
+
!/^[a-f0-9]{64}$/u.test(input.requestSha256)
|
|
25
|
+
) {
|
|
26
|
+
throw new Error("Invalid launch reservation identity");
|
|
27
|
+
}
|
|
28
|
+
const home = resolveVisibleLaunchReceiptsDir(dir);
|
|
29
|
+
await mkdir(home, { recursive: true, mode: 0o700 });
|
|
30
|
+
const canonicalHome = await realpath(home);
|
|
31
|
+
const path = join(canonicalHome, `pair-${input.agent}.ak-${input.task}.reservation.json`);
|
|
32
|
+
let handle: Awaited<ReturnType<typeof open>>;
|
|
33
|
+
try {
|
|
34
|
+
handle = await open(path, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY, 0o600);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
|
|
37
|
+
// Corrupt/incomplete reservations also block. Never infer an expired process or retry permission.
|
|
38
|
+
try {
|
|
39
|
+
const previous = JSON.parse(await readFile(path, "utf8"));
|
|
40
|
+
validateVisibleLaunchIdentity(previous.agent, previous.runId);
|
|
41
|
+
if (previous.agent === input.agent && previous.task === input.task)
|
|
42
|
+
return { reserved: false, runId: previous.runId };
|
|
43
|
+
} catch {
|
|
44
|
+
/* fail closed */
|
|
45
|
+
}
|
|
46
|
+
return { reserved: false };
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const facts = {
|
|
50
|
+
schema: "pi-agent-registry.visible-launch-reservation/1",
|
|
51
|
+
...input,
|
|
52
|
+
recordedAt: new Date().toISOString(),
|
|
53
|
+
};
|
|
54
|
+
await handle.writeFile(
|
|
55
|
+
`${canonicalJsonString({ ...facts, sha256: sha256Hex(canonicalJsonString(facts)) })}\n`,
|
|
56
|
+
);
|
|
57
|
+
await handle.sync();
|
|
58
|
+
await handle.chmod(0o400);
|
|
59
|
+
} finally {
|
|
60
|
+
await handle.close();
|
|
61
|
+
}
|
|
62
|
+
const directory = await open(canonicalHome, constants.O_RDONLY);
|
|
63
|
+
try {
|
|
64
|
+
await directory.sync();
|
|
65
|
+
} finally {
|
|
66
|
+
await directory.close();
|
|
67
|
+
}
|
|
68
|
+
return { reserved: true, path };
|
|
69
|
+
}
|