@evoclock/pi-agentic-driver 0.9.1 → 0.9.3
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/.agentic-driver/router.defaults.json +64 -0
- package/LICENSE +11 -8
- package/README.md +116 -32
- package/extensions/attended-authority-guard.ts +1 -1
- package/extensions/code-phage.js +1 -1
- package/extensions/herdr-communication.ts +1 -1
- package/extensions/herdr-dispatch.ts +1 -1
- package/extensions/herdr-lifecycle.ts +1 -1
- package/extensions/linux-microvm.ts +1 -1
- package/extensions/pulse.ts +33 -2
- package/extensions/task-board.ts +1 -1
- package/janus/README.draft.md +210 -0
- package/janus/README.md +196 -0
- package/janus/janus/audit.ts +213 -0
- package/janus/janus/budget.ts +101 -0
- package/janus/janus/budget_breaker.ts +105 -0
- package/janus/janus/config.ts +332 -0
- package/janus/janus/errors.ts +90 -0
- package/janus/janus/evaluate.ts +230 -0
- package/janus/janus/keychain.ts +119 -0
- package/janus/janus/providers.ts +544 -0
- package/janus/janus/schema.ts +344 -0
- package/janus/janus/server.ts +267 -0
- package/janus/janus/single_flight.ts +99 -0
- package/janus/janus/verdict.ts +192 -0
- package/janus/package-lock.json +616 -0
- package/janus/package.json +29 -0
- package/janus/tests/accounting.test.ts +229 -0
- package/janus/tests/allowlist.test.ts +97 -0
- package/janus/tests/config.test.ts +151 -0
- package/janus/tests/errors.test.ts +147 -0
- package/janus/tests/evaluate_pipeline.test.ts +358 -0
- package/janus/tests/helpers.ts +217 -0
- package/janus/tests/providers.test.ts +292 -0
- package/janus/tests/redaction_budget.test.ts +227 -0
- package/janus/tests/schema.test.ts +356 -0
- package/janus/tests/server.test.ts +288 -0
- package/janus/tests/single_flight.test.ts +84 -0
- package/janus/tsconfig.json +19 -0
- package/janus/user.janus.plist +51 -0
- package/lib/adapters/diff-scope.mjs +1 -1
- package/lib/adapters/evidence.mjs +1 -1
- package/lib/adapters/narrative.mjs +1 -1
- package/lib/adapters/review-feedback.mjs +1 -1
- package/lib/adapters/visualization.mjs +1 -1
- package/lib/code-phage-core.mjs +1 -1
- package/lib/python_ast_metrics.py +1 -1
- package/lib/typescript_ast_metrics.mjs +1 -1
- package/package.json +14 -3
- package/scripts/aidr_writing_review.js +1 -1
- package/scripts/enforcement/attended_authority_guard.js +1 -1
- package/scripts/enforcement/guest_containment_taxonomy.v1.json +1 -1
- package/scripts/enforcement/herdr_async_dispatch_pi.js +1 -1
- package/scripts/enforcement/herdr_communication_pi.js +13 -8
- package/scripts/enforcement/herdr_lifecycle_pi.js +3 -3
- package/scripts/enforcement/linux_microvm_cutover_pi.js +1 -1
- package/scripts/enforcement/native_tui_context.js +1 -1
- package/scripts/enforcement/pulse_core_pi.js +38 -14
- package/scripts/enforcement/pulse_scheduler_pi.js +188 -25
- package/scripts/enforcement/router_engine_pi.js +483 -0
- package/scripts/enforcement/router_ranking_pi.js +146 -0
- package/scripts/enforcement/router_replacement_pi.js +98 -0
- package/scripts/enforcement/router_runtime_pi.js +299 -0
- package/scripts/enforcement/router_schemas_pi.js +654 -0
- package/scripts/enforcement/router_store_pi.js +438 -0
- package/scripts/enforcement/task_board_core_pi.js +255 -44
- package/skills/pulse/SKILL.md +1 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "agentic-driver.router-config.v1",
|
|
3
|
+
"revision": 1,
|
|
4
|
+
"endpoints": {
|
|
5
|
+
"local-default": {
|
|
6
|
+
"url": "http://127.0.0.1:8080",
|
|
7
|
+
"kind": "llama-server"
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"seats": [
|
|
11
|
+
{
|
|
12
|
+
"schema": "agentic-driver.seat.v1",
|
|
13
|
+
"seatId": "local-default",
|
|
14
|
+
"kind": "local",
|
|
15
|
+
"provider": "llama-server",
|
|
16
|
+
"accountId": null,
|
|
17
|
+
"endpointRef": "local-default",
|
|
18
|
+
"model": "replace-with-installed-model",
|
|
19
|
+
"capabilities": ["implement", "review"],
|
|
20
|
+
"containmentTier": "none",
|
|
21
|
+
"maxConcurrency": 1,
|
|
22
|
+
"costClass": "free",
|
|
23
|
+
"quotaCollector": null,
|
|
24
|
+
"clusterMembership": null,
|
|
25
|
+
"enabled": false,
|
|
26
|
+
"deprecated": null
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"models": {
|
|
30
|
+
"replace-with-installed-model": {
|
|
31
|
+
"aliases": [],
|
|
32
|
+
"contextWindow": 32768,
|
|
33
|
+
"capabilities": ["implement", "review"]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"collectors": {},
|
|
37
|
+
"eligibility": {
|
|
38
|
+
"rules": [],
|
|
39
|
+
"reserve": {
|
|
40
|
+
"floorPercent": 40,
|
|
41
|
+
"scope": "account-window",
|
|
42
|
+
"coldStartFraction": 0.25,
|
|
43
|
+
"estimateSamples": 20,
|
|
44
|
+
"estimateMinSamples": 5,
|
|
45
|
+
"estimateOutlierSigma": 3,
|
|
46
|
+
"ownerInteractiveOverride": false
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"preferences": {
|
|
50
|
+
"order": [{ "seatId": "local-default" }],
|
|
51
|
+
"costPolicy": "free-first"
|
|
52
|
+
},
|
|
53
|
+
"ranking": {
|
|
54
|
+
"enabled": false,
|
|
55
|
+
"janusUrl": "http://127.0.0.1:7431",
|
|
56
|
+
"maxCandidates": 8,
|
|
57
|
+
"fallback": "preference-order"
|
|
58
|
+
},
|
|
59
|
+
"localHealth": {
|
|
60
|
+
"probeSeconds": 60,
|
|
61
|
+
"warmStateTracking": true
|
|
62
|
+
},
|
|
63
|
+
"secrets": {}
|
|
64
|
+
}
|
package/LICENSE
CHANGED
|
@@ -723,14 +723,17 @@ on the Software.
|
|
|
723
723
|
COMMERCIAL LICENCE OPTION
|
|
724
724
|
================================================================================
|
|
725
725
|
|
|
726
|
-
|
|
727
|
-
General Public License
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
726
|
+
Commercial use, modification, and distribution are permitted under
|
|
727
|
+
the GNU Affero General Public License when all AGPL obligations and
|
|
728
|
+
the additional terms of Section 7(b) above are followed. This includes
|
|
729
|
+
the network-use source-disclosure obligation of Section 13 and the
|
|
730
|
+
required preservation of attribution.
|
|
731
|
+
|
|
732
|
+
A separate commercial licence is available for organisations that
|
|
733
|
+
require proprietary modifications, do not wish to disclose covered
|
|
734
|
+
source as required by the AGPL, need alternative attribution terms, or
|
|
735
|
+
otherwise cannot or do not wish to comply with the AGPL. Contact the
|
|
736
|
+
author for details.
|
|
734
737
|
|
|
735
738
|
When published, the commercial licence template will be available at
|
|
736
739
|
COMMERCIAL.md in this repository.
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# pi-agentic-driver
|
|
1
|
+
# pi-agentic-driver
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
4
|
<img src="assets/Yamagane-origami.png" alt="pi-agentic-driver, Yamagane origami mark" width="140"/>
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-AGPL%20v3-blue?style=flat" alt="License: AGPL v3"/></a>
|
|
9
9
|
<a href="https://www.npmjs.com/package/@evoclock/pi-agentic-driver"><img src="https://img.shields.io/npm/v/@evoclock/pi-agentic-driver?style=flat" alt="npm version"/></a>
|
|
10
|
-
<img src="https://img.shields.io/badge/version-0.9.0-blue?style=flat" alt="Version 0.9.0"/>
|
|
11
10
|
<img src="https://img.shields.io/badge/status-active%20development%20%26%20testing-orange?style=flat" alt="Status"/>
|
|
12
11
|
<img src="https://img.shields.io/badge/JavaScript-F7DF1E?style=flat&logo=javascript&logoColor=black" alt="JavaScript"/>
|
|
13
12
|
<img src="https://img.shields.io/badge/TypeScript-3178C6?style=flat&logo=typescript&logoColor=white" alt="TypeScript"/>
|
|
@@ -53,6 +52,9 @@ proofs for agentic workflows.
|
|
|
53
52
|
| `agentic_kanban_board_write` | Adds cards to the board through the trusted writer, which records who authorized the work. | shipped |
|
|
54
53
|
| `agentic_kanban_board_update` | Moves, closes, flags, edits, or removes cards on the board, always recording who authorized the change. | shipped |
|
|
55
54
|
| `agentic_kanban_board_dispatch` | Claims an eligible board card for automated contained work and creates its assignment envelope. | shipped |
|
|
55
|
+
| `agentic_kanban_pulse` | Checks for ready work and available capacity, then starts assignments under the board policy. | shipped |
|
|
56
|
+
| Router | Capacity/policy routing for Board Pulse: seats with scope statements, tunable policy values, and a binding dispatch gate. | shipped |
|
|
57
|
+
| Janus (bundled service) | Local Jev evaluation service on loopback: semantic ranking, the dispatch-gate judgment, redaction before every external call. See `janus/README.md`. | shipped |
|
|
56
58
|
|
|
57
59
|
**Status: active development and testing.** Each extension ships only after
|
|
58
60
|
it passes fixture-based acceptance, native tests, live-session checks, and
|
|
@@ -66,7 +68,7 @@ components are listed here for transparency and are not packaged.
|
|
|
66
68
|
<details>
|
|
67
69
|
<summary><strong>code-phage, advisory code review</strong> <em>(released, 0.1.1)</em></summary>
|
|
68
70
|
|
|
69
|
-
`code_phage` reviews a proposed change against a stated goal before the agent
|
|
71
|
+
The `code_phage` tool reviews a proposed change against a stated goal before the agent
|
|
70
72
|
writes or commits code. Give it a goal, candidate files, accepted
|
|
71
73
|
requirements, and test paths. It will:
|
|
72
74
|
|
|
@@ -102,6 +104,82 @@ only, not a runtime dependency).
|
|
|
102
104
|
- **inventory refresh.** Git-aware codebase inventory regeneration with
|
|
103
105
|
verification receipts, so prior-art matching stays honest.
|
|
104
106
|
|
|
107
|
+
<details>
|
|
108
|
+
<summary><strong>router, capacity/policy routing with a binding dispatch gate</strong> <em>(released, 0.9.2)</em></summary>
|
|
109
|
+
|
|
110
|
+
Board Pulse selects a route seat through the capacity/policy router. The
|
|
111
|
+
router reads a closed configuration file and a local-first SQLite file for
|
|
112
|
+
operational state (reservations, observations, route-decision audit).
|
|
113
|
+
|
|
114
|
+
Two router features call **Janus** — a separate local service, bundled under
|
|
115
|
+
`janus/`, that is the only component allowed to talk to the TypeSafe Jev
|
|
116
|
+
models:
|
|
117
|
+
|
|
118
|
+
- **Semantic ranking** (optional): Janus ranks up to eight eligible seats;
|
|
119
|
+
on any Janus failure the router falls back to preference order.
|
|
120
|
+
- **The binding dispatch gate**: before a task is claimed, Janus judges
|
|
121
|
+
whether the task fits the selected seat. No verdict, no dispatch — the
|
|
122
|
+
gate fails closed when Janus is unreachable.
|
|
123
|
+
|
|
124
|
+
Janus binds loopback only (`127.0.0.1:8787`), reads its API key from the
|
|
125
|
+
macOS Keychain at runtime, redacts state before every external call, and
|
|
126
|
+
coalesces identical requests. See `janus/README.md` for the endpoint
|
|
127
|
+
contract, Keychain provisioning, and configuration.
|
|
128
|
+
|
|
129
|
+
- **Repository defaults** ship at `.agentic-driver/router.defaults.json`. The
|
|
130
|
+
template contains no accounts and one disabled placeholder seat, so it loads
|
|
131
|
+
out of the box and schedules nothing until you enable a real seat.
|
|
132
|
+
- **User profile (precedence over defaults):**
|
|
133
|
+
`~/.config/agentic-driver/router/profile.json`, or the path in the
|
|
134
|
+
`AGENTIC_DRIVER_ROUTER_PROFILE` environment variable. A profile section
|
|
135
|
+
replaces the matching defaults section wholesale; the merged config must
|
|
136
|
+
validate or the router refuses to produce decisions (fails closed).
|
|
137
|
+
- **Operational state:** `~/.local/share/agentic-driver/router/state.db`, or
|
|
138
|
+
`AGENTIC_DRIVER_ROUTER_DB`. This store is operational state only. The
|
|
139
|
+
authenticated claims file and the board writer remain the only dispatch
|
|
140
|
+
authority; the system repairs SQLite from them, never the reverse.
|
|
141
|
+
- **Runtime requirement:** the operational store uses the built-in
|
|
142
|
+
`node:sqlite` module. You need Node.js 22.5 or newer.
|
|
143
|
+
|
|
144
|
+
<details>
|
|
145
|
+
<summary><strong>Tunable configuration values</strong> <em>(all keys required, defaults are conservative starting values)</em></summary>
|
|
146
|
+
|
|
147
|
+
Every numeric policy in the router is a configuration key — never a
|
|
148
|
+
constant in code. All keys are **required**. The repository defaults below
|
|
149
|
+
are conservative starting values. Your profile overrides them. A missing key
|
|
150
|
+
is a configuration validation failure: the router fails closed rather than
|
|
151
|
+
guess. Changing a value participates in the configuration digest, so cached
|
|
152
|
+
routing decisions computed under the old values no longer apply.
|
|
153
|
+
|
|
154
|
+
| Section | Key | Default | What it controls |
|
|
155
|
+
|---|---|---|---|
|
|
156
|
+
| `eligibility.reserve` | `floorPercent` | 40 | Share of every quota window kept in reserve (per account, per window). Headroom for an unexpected burst and your next interactive session, without idling the account. |
|
|
157
|
+
| `eligibility.reserve` | `scope` | `account-window` | How widely the reserve floor applies (per account per window at launch). |
|
|
158
|
+
| `eligibility.reserve` | `coldStartFraction` | 0.25 | Consumption assumed for a seat with too little history: deliberately generous, so a mis-estimate fails eligibility instead of draining the account. |
|
|
159
|
+
| `eligibility.reserve` | `estimateSamples` | 20 | How many recent dispatches the consumption estimate averages: enough to smooth outliers, quick enough to track a model change. |
|
|
160
|
+
| `eligibility.reserve` | `estimateMinSamples` | 5 | Below this many observations, the estimator treats the average as noise and uses the cold-start value instead. |
|
|
161
|
+
| `eligibility.reserve` | `estimateOutlierSigma` | 3 | Outlier cut for the estimate: one unusually slow dispatch cannot inflate the average, real tail latency is kept. |
|
|
162
|
+
| `eligibility.reserve` | `ownerInteractiveOverride` | false | Whether your own interactive dispatches bypass the reserve rule (they do not, at launch). |
|
|
163
|
+
| `ranking` | `janusUrl` | `http://127.0.0.1:8787` | The local Janus evaluation service endpoint used for semantic ranking. |
|
|
164
|
+
| `ranking` | `maxCandidates` | 8 | The router ranks at most eight eligible seats per request; preference order trims the list first. |
|
|
165
|
+
| `ranking` | `fallback` | `preference-order` | What happens when ranking is unavailable: dispatch falls back to your preference order and never blocks. |
|
|
166
|
+
| `gate` | `threshold` | 0.9 | The dispatch gate's confidence threshold. A task is only dispatched when the evaluation clears it. Lower it only with evidence from your own audit log. |
|
|
167
|
+
| `gate` | `timeoutMs` | 8000 | How long the gate waits for an evaluation. On timeout there is no verdict, and the gate blocks dispatch (fail closed). |
|
|
168
|
+
| `gate` | `requestBudgetTokens` | 30000 | Maximum size of a gate evaluation request. Normal evaluations use under a thousand tokens. |
|
|
169
|
+
| seat record | `maxConcurrency` | 4 | How many workers one seat may run at once. The default suits a typical single machine or hosted seat. Tune it per seat: a cluster takes more, a constrained subscription endpoint may take less. |
|
|
170
|
+
| automation policy | `maxConcurrent` | 4 | How many workers may run at once across all seats. The default is a conservative start. Tune it to the capacity you actually have, and raise it when you add seats or hardware. |
|
|
171
|
+
|
|
172
|
+
Seats are named for infrastructure, not models: `dgx-spark`,
|
|
173
|
+
`dgx-spark-cluster`, `mac-studio`, `mac-studio-cluster`, `strix-halo`,
|
|
174
|
+
`strix-halo-cluster`, `merge-gateway-worker`. The model is a mutable field on
|
|
175
|
+
the seat, so changing models never renumbers your configuration. Each seat
|
|
176
|
+
also carries `scopeStatements`: plain-language descriptions of what the seat
|
|
177
|
+
is for. The dispatch gate reads them when judging whether a task fits.
|
|
178
|
+
|
|
179
|
+
</details>
|
|
180
|
+
|
|
181
|
+
</details>
|
|
182
|
+
|
|
105
183
|
## Multi-agent communication
|
|
106
184
|
|
|
107
185
|
*Extensions for controlled coordination between agents.*
|
|
@@ -109,8 +187,10 @@ only, not a runtime dependency).
|
|
|
109
187
|
<details>
|
|
110
188
|
<summary><strong>herdr-communication, controlled role communication</strong> <em>(released, 0.2.1)</em></summary>
|
|
111
189
|
|
|
112
|
-
`agentic_herdr_communication` exchanges controlled, marked reports with
|
|
113
|
-
configured Pi worker roles running under [Herdr](https://herdr.dev/)
|
|
190
|
+
The `agentic_herdr_communication` tool exchanges controlled, marked reports with
|
|
191
|
+
configured Pi worker roles running under [Herdr](https://herdr.dev/) (validated
|
|
192
|
+
against Herdr 0.9.1; the trust seam accepts the Homebrew-managed herdr binary
|
|
193
|
+
across versions rather than pinning one).
|
|
114
194
|
|
|
115
195
|
- **List and observe.** Worker roles are filtered to trusted repositories: a
|
|
116
196
|
checked-in registry plus canonical-path validation. Unlisted or
|
|
@@ -133,7 +213,7 @@ configured Pi worker roles running under [Herdr](https://herdr.dev/) 0.8.2.
|
|
|
133
213
|
<details>
|
|
134
214
|
<summary><strong>herdr-lifecycle, role-labelled worker dispatch</strong> <em>(released, 0.2.1)</em></summary>
|
|
135
215
|
|
|
136
|
-
`agentic_herdr_spawn_worker` turns one natural-language request into Herdr's
|
|
216
|
+
The `agentic_herdr_spawn_worker` tool turns one natural-language request into Herdr's
|
|
137
217
|
native lifecycle. Choose a placement (`right`, `below`, or `tab`), a safe role
|
|
138
218
|
label, a model from the active Pi model roster, and a trusted repository. The
|
|
139
219
|
extension:
|
|
@@ -165,7 +245,7 @@ for the wider task and model-routing workflow.
|
|
|
165
245
|
<details>
|
|
166
246
|
<summary><strong>herdr-dispatch, continuous worker journeys</strong> <em>(released, 0.5.0)</em></summary>
|
|
167
247
|
|
|
168
|
-
`agentic_worker_dispatch` runs controlled worker journeys and observes worker
|
|
248
|
+
The `agentic_worker_dispatch` tool runs controlled worker journeys and observes worker
|
|
169
249
|
liveness. Two actions:
|
|
170
250
|
|
|
171
251
|
- **pulse** reports whether a worker role is alive, its current state, and
|
|
@@ -192,7 +272,7 @@ silently, and return results as untrusted evidence.
|
|
|
192
272
|
|
|
193
273
|
|
|
194
274
|
<details>
|
|
195
|
-
<summary><strong>task board, planned and automated work you can see</strong> <em>(released, 0.9.
|
|
275
|
+
<summary><strong>task board and Pulse, planned and automated work you can see</strong> <em>(released, 0.9.1)</em></summary>
|
|
196
276
|
|
|
197
277
|
Keep planned work in canonical `TASKS.md`. You can read it directly or use
|
|
198
278
|
the generated `board.md` view in Obsidian. Agents use the same canonical
|
|
@@ -216,10 +296,10 @@ For automated work, you set an explicit policy for the board. It defines:
|
|
|
216
296
|
|
|
217
297
|
Without a valid policy, automated dispatch is refused.
|
|
218
298
|
|
|
219
|
-
`agentic_kanban_board_dispatch` claims the highest-priority eligible card
|
|
220
|
-
creates a single-attempt assignment envelope
|
|
221
|
-
|
|
222
|
-
|
|
299
|
+
The `agentic_kanban_board_dispatch` tool claims the highest-priority eligible card. It
|
|
300
|
+
creates a single-attempt assignment envelope that binds the card, repository,
|
|
301
|
+
starting revision, assigned branch, allowed paths, stopping point, expiry, and
|
|
302
|
+
interaction profile.
|
|
223
303
|
|
|
224
304
|
Blocked, altered, expired, reused, or unauthorized assignments fail closed.
|
|
225
305
|
The journey validates the authenticated envelope before each consequential
|
|
@@ -232,10 +312,12 @@ Claims and envelopes are kept in authenticated state beside `TASKS.md`. The
|
|
|
232
312
|
derived `board.md` view shows active claims but never becomes an authority
|
|
233
313
|
source.
|
|
234
314
|
|
|
235
|
-
`agentic_kanban_pulse` checks the board for ready work and available capacity.
|
|
236
|
-
A check only reports which work is ready to run. It does not claim cards.
|
|
237
|
-
|
|
238
|
-
work
|
|
315
|
+
The `agentic_kanban_pulse` tool checks the board for ready work and available capacity.
|
|
316
|
+
A check only reports which work is ready to run. It does not claim cards.
|
|
317
|
+
|
|
318
|
+
Interactive host work needs explicit policy and one native confirmation for
|
|
319
|
+
the batch. Automated work requires containment and never falls back to the
|
|
320
|
+
host.
|
|
239
321
|
|
|
240
322
|
Coming next:
|
|
241
323
|
|
|
@@ -264,7 +346,7 @@ writer's voice.*
|
|
|
264
346
|
<details>
|
|
265
347
|
<summary><strong>AI;DR, writing review</strong> <em>(released, 0.4.2)</em></summary>
|
|
266
348
|
|
|
267
|
-
`agentic_aidr` reviews the last assistant response, supplied prose, or a
|
|
349
|
+
The `agentic_aidr` tool reviews the last assistant response, supplied prose, or a
|
|
268
350
|
Markdown file. It checks four principles:
|
|
269
351
|
|
|
270
352
|
- **Clarity.** Each sentence carries one useful idea.
|
|
@@ -304,8 +386,8 @@ QEMU/KVM virtual machine on a Linux host. The job cannot reach the host, the
|
|
|
304
386
|
network, or anything else outside the machine. The system deletes the machine
|
|
305
387
|
after the job ends.
|
|
306
388
|
|
|
307
|
-
Isolation is off at the start of every session.
|
|
308
|
-
|
|
389
|
+
Isolation is off at the start of every session. Use the `/agentic-isolation-enable`
|
|
390
|
+
command in the Pi TUI, and confirm. The model cannot run
|
|
309
391
|
that command. Every cutover run asks for its own confirmation too. Nothing is
|
|
310
392
|
saved to settings, and headless sessions stay blocked.
|
|
311
393
|
|
|
@@ -532,10 +614,9 @@ acceptance with all prohibited effects absent.
|
|
|
532
614
|
|
|
533
615
|
### Portable repository contract
|
|
534
616
|
|
|
535
|
-
`templates/AGENTS.md` is a starting contract you can copy into any
|
|
536
|
-
that uses Pi agents. It asks for controlled tasks and realistic tests, and
|
|
537
|
-
treats agent reports as untrusted evidence. It never overwrites an existing
|
|
538
|
-
`AGENTS.md`; add your project rules below it.
|
|
617
|
+
The `templates/AGENTS.md` file is a starting contract you can copy into any
|
|
618
|
+
repository that uses Pi agents. It asks for controlled tasks and realistic tests, and
|
|
619
|
+
treats agent reports as untrusted evidence. It never overwrites an existing `AGENTS.md`. Add your project rules below it.
|
|
539
620
|
|
|
540
621
|
## Install
|
|
541
622
|
|
|
@@ -545,24 +626,24 @@ From npm:
|
|
|
545
626
|
pi install npm:@evoclock/pi-agentic-driver
|
|
546
627
|
```
|
|
547
628
|
|
|
548
|
-
Or from Git at
|
|
629
|
+
Or from Git at the latest release tag (see the repo's tags for the current one; the npm badge above shows the live version):
|
|
549
630
|
|
|
550
631
|
```sh
|
|
551
|
-
pi install git:github.com/evoclock/pi-agentic-driver
|
|
632
|
+
pi install git:github.com/evoclock/pi-agentic-driver@<latest-tag>
|
|
552
633
|
```
|
|
553
634
|
|
|
554
|
-
Released extensions load
|
|
635
|
+
Released extensions load independently.
|
|
555
636
|
|
|
556
637
|
### Choose which extensions load
|
|
557
638
|
|
|
558
|
-
A normal install loads all
|
|
639
|
+
A normal install loads all packaged extensions by default. You can load only the
|
|
559
640
|
extensions you want with the object form in your Pi settings:
|
|
560
641
|
|
|
561
642
|
```json
|
|
562
643
|
{
|
|
563
644
|
"packages": [
|
|
564
645
|
{
|
|
565
|
-
"source": "npm:@evoclock/pi-agentic-driver
|
|
646
|
+
"source": "npm:@evoclock/pi-agentic-driver",
|
|
566
647
|
"extensions": [
|
|
567
648
|
"extensions/aidr.ts",
|
|
568
649
|
"extensions/code-phage.js"
|
|
@@ -572,12 +653,15 @@ extensions you want with the object form in your Pi settings:
|
|
|
572
653
|
}
|
|
573
654
|
```
|
|
574
655
|
|
|
575
|
-
The package
|
|
576
|
-
`herdr-dispatch.ts
|
|
656
|
+
The package includes the `herdr-communication.ts`, `herdr-lifecycle.ts`, and
|
|
657
|
+
`herdr-dispatch.ts` extensions. It also includes `linux-microvm.ts`. Use `pi config` to enable or
|
|
577
658
|
disable individual resources from an installed package. You are not required
|
|
578
659
|
to use every extension.
|
|
579
660
|
|
|
580
661
|
## License
|
|
581
662
|
|
|
582
|
-
AGPL-3.0-
|
|
583
|
-
see [LICENSE](LICENSE).
|
|
663
|
+
AGPL-3.0-only with author-attribution additional terms (Section 7(b));
|
|
664
|
+
see [LICENSE](LICENSE). Commercial use, forks, and substantial modifications
|
|
665
|
+
are permitted when all AGPL and attribution obligations are followed. A
|
|
666
|
+
separate commercial licence is available for organisations requiring
|
|
667
|
+
proprietary modifications or other terms incompatible with the AGPL.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Julen Gamboa <j.a.r.gamboa@gmail.com>
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
3
|
|
|
4
4
|
export default async function attendedAuthorityGuard(pi) {
|
|
5
5
|
const module = await import(new URL("../scripts/enforcement/attended_authority_guard.js", import.meta.url).href);
|
package/extensions/code-phage.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Julen Gamboa <j.a.r.gamboa@gmail.com>
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
3
|
|
|
4
4
|
export default async function herdrDispatchPi(pi) {
|
|
5
5
|
const dispatch = await import(new URL("../scripts/enforcement/herdr_async_dispatch_pi.js", import.meta.url).href);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Julen Gamboa <j.a.r.gamboa@gmail.com>
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
3
|
|
|
4
4
|
import { registerLinuxMicroVMCutoverInterface, registerIsolationSwitchCommands, createIsolationSwitch } from "../scripts/enforcement/linux_microvm_cutover_pi.js";
|
|
5
5
|
|
package/extensions/pulse.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Julen Gamboa <j.a.r.gamboa@gmail.com>
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
3
|
|
|
4
4
|
// Board Pulse provider extension. Registers the deterministic
|
|
5
5
|
// agentic_kanban_pulse tool and owns the optional fixed-interval timer. The
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { executeHerdrSpawnWorker } from "../scripts/enforcement/herdr_lifecycle_pi.js";
|
|
18
18
|
import { resolveBoardPath, registerPulseTools, createPulseTimer, pulseTick, pulseWorkerSpawnSeam } from "../scripts/enforcement/pulse_scheduler_pi.js";
|
|
19
|
+
import { prepareRouterRuntimeWithHealth, closeCachedRouterStores } from "../scripts/enforcement/router_runtime_pi.js";
|
|
19
20
|
|
|
20
21
|
export default function pulsePi(pi) {
|
|
21
22
|
|
|
@@ -26,9 +27,31 @@ export default function pulsePi(pi) {
|
|
|
26
27
|
// worker is ever started. No other creation path exists.
|
|
27
28
|
const spawnWorker = pulseWorkerSpawnSeam({ executeHerdrSpawnWorker });
|
|
28
29
|
|
|
30
|
+
// The runtime is rebuilt per tool call and per automated tick (W3): a
|
|
31
|
+
// snapshot frozen at session setup would leave every subscription seat
|
|
32
|
+
// stale after the first observation expiry and freeze the prior-reservation
|
|
33
|
+
// term. The localHealth probe adapter (W2) is attached here, producing
|
|
34
|
+
// endpoint-keyed fresh health observations for local seats. `check`
|
|
35
|
+
// assembles the runtime read-only (W4): no store writes, no store creation.
|
|
36
|
+
const routerRuntimeFor = async (ctx, boardPath, { readOnly = false } = {}) => {
|
|
37
|
+
const runtime = await prepareRouterRuntimeWithHealth({
|
|
38
|
+
repoRoot: ctx?.cwd || process.cwd(), boardPath,
|
|
39
|
+
defaultsPath: ctx?.routerDefaultsPath ?? null, profilePath: ctx?.routerProfilePath ?? null,
|
|
40
|
+
dbPath: ctx?.routerDbPath ?? null, cacheRoot: ctx?.routerCacheRoot ?? null,
|
|
41
|
+
consumptionReceipts: ctx?.consumptionReceipts ?? [], readOnly,
|
|
42
|
+
fetchFn: ctx?.routerHealthFetch ?? null,
|
|
43
|
+
});
|
|
44
|
+
const installed = new Set(runtime.routerConfig.seats.map((seat) => seat.model).filter((model) => {
|
|
45
|
+
try { return ctx?.modelRegistry?.get?.(model) != null; } catch { return false; }
|
|
46
|
+
}));
|
|
47
|
+
runtime.routerSnapshot.modelInstalled = installed;
|
|
48
|
+
return { ...runtime, activeSessions: ctx?.activeSessions ?? [], providerLimit: ctx?.providerLimit ?? null };
|
|
49
|
+
};
|
|
50
|
+
|
|
29
51
|
const result = registerPulseTools(pi, {
|
|
30
52
|
resolveBoardPath: (ctx) => resolveBoardPath(typeof ctx === "string" ? ctx : ctx?.cwd || process.cwd()),
|
|
31
53
|
spawnWorker,
|
|
54
|
+
routerRuntimeFor,
|
|
32
55
|
});
|
|
33
56
|
|
|
34
57
|
// Optional timer (§8): created only after session_start, only when the
|
|
@@ -43,6 +66,9 @@ export default function pulsePi(pi) {
|
|
|
43
66
|
timer.clear();
|
|
44
67
|
timer = null;
|
|
45
68
|
}
|
|
69
|
+
// Release the cached per-dbPath store handles with the session so the
|
|
70
|
+
// runtime never accumulates DatabaseSync handles (W5).
|
|
71
|
+
closeCachedRouterStores();
|
|
46
72
|
};
|
|
47
73
|
const setupTimer = async (_event, ctx) => {
|
|
48
74
|
clearTimer();
|
|
@@ -54,10 +80,15 @@ export default function pulsePi(pi) {
|
|
|
54
80
|
const check = checkAutomationPolicy(policy, { boardPath });
|
|
55
81
|
const pulse = check.ok ? check.policy.pulse : null;
|
|
56
82
|
if (!pulse || pulse.enabled !== true || pulse.mode !== "automated") return;
|
|
83
|
+
// W3: the tick asks for a FRESH runtime every tick instead of reusing a
|
|
84
|
+
// setup-time snapshot. The factory re-reads collector caches, health
|
|
85
|
+
// probes, and the prior-reservation term under the read-time freshness
|
|
86
|
+
// rules; a factory failure fails that tick closed.
|
|
57
87
|
timer = createPulseTimer({
|
|
58
88
|
intervalSeconds: pulse.intervalSeconds,
|
|
59
89
|
fillOnStart: pulse.fillOnStart === true,
|
|
60
|
-
tick: () => pulseTick({ boardPath, spawnWorker, context: ctx
|
|
90
|
+
tick: () => pulseTick({ boardPath, spawnWorker, context: ctx,
|
|
91
|
+
routerRuntimeFor: () => routerRuntimeFor(ctx, boardPath, { readOnly: false }) }),
|
|
61
92
|
});
|
|
62
93
|
timer.start();
|
|
63
94
|
} catch {
|
package/extensions/task-board.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Julen Gamboa <j.a.r.gamboa@gmail.com>
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
3
|
|
|
4
4
|
// BOARD-1 provider extension. Both tools register at startup; the board is
|
|
5
5
|
// resolved per tool call from the calling session's working directory. A
|