pi-daddy 0.19.0 → 0.20.1
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/CHANGELOG.md +71 -0
- package/README.md +105 -36
- package/contracts/ledger/v3/README.md +36 -0
- package/contracts/ledger/v3/fixtures/capability-decision.json +98 -0
- package/contracts/ledger/v3/fixtures/check-receipt.json +42 -0
- package/contracts/ledger/v3/fixtures/child-lifecycle.json +45 -0
- package/contracts/ledger/v3/fixtures/workflow-fact.json +41 -0
- package/contracts/ledger/v3/fixtures/workspace-lease.json +43 -0
- package/contracts/ledger/v3/ledger-event.schema.json +930 -0
- package/dist/check-runner.d.ts.map +1 -1
- package/dist/check-runner.js +14 -0
- package/dist/check-runner.js.map +1 -1
- package/dist/cli.js +0 -0
- package/dist/correlation.d.ts.map +1 -1
- package/dist/correlation.js +10 -0
- package/dist/correlation.js.map +1 -1
- package/dist/dashboard-cli.d.ts +18 -0
- package/dist/dashboard-cli.d.ts.map +1 -0
- package/dist/dashboard-cli.js +154 -0
- package/dist/dashboard-cli.js.map +1 -0
- package/dist/dashboard-handshake.d.ts +37 -0
- package/dist/dashboard-handshake.d.ts.map +1 -0
- package/dist/dashboard-handshake.js +127 -0
- package/dist/dashboard-handshake.js.map +1 -0
- package/dist/dashboard-herdr.d.ts +54 -0
- package/dist/dashboard-herdr.d.ts.map +1 -0
- package/dist/dashboard-herdr.js +286 -0
- package/dist/dashboard-herdr.js.map +1 -0
- package/dist/dashboard-projection.d.ts +73 -0
- package/dist/dashboard-projection.d.ts.map +1 -0
- package/dist/dashboard-projection.js +294 -0
- package/dist/dashboard-projection.js.map +1 -0
- package/dist/dashboard-render.d.ts +10 -0
- package/dist/dashboard-render.d.ts.map +1 -0
- package/dist/dashboard-render.js +208 -0
- package/dist/dashboard-render.js.map +1 -0
- package/dist/delegate-types.d.ts +6 -2
- package/dist/delegate-types.d.ts.map +1 -1
- package/dist/delegate-types.js.map +1 -1
- package/dist/delegate.d.ts.map +1 -1
- package/dist/delegate.js +4 -1
- package/dist/delegate.js.map +1 -1
- package/dist/execution-id.d.ts +6 -0
- package/dist/execution-id.d.ts.map +1 -0
- package/dist/execution-id.js +13 -0
- package/dist/execution-id.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/ledger-events.d.ts +27 -4
- package/dist/ledger-events.d.ts.map +1 -1
- package/dist/ledger-events.js +30 -9
- package/dist/ledger-events.js.map +1 -1
- package/dist/ledger-identifiers.d.ts +7 -0
- package/dist/ledger-identifiers.d.ts.map +1 -0
- package/dist/ledger-identifiers.js +20 -0
- package/dist/ledger-identifiers.js.map +1 -0
- package/dist/ledger-report.d.ts +5 -2
- package/dist/ledger-report.d.ts.map +1 -1
- package/dist/ledger-report.js +38 -14
- package/dist/ledger-report.js.map +1 -1
- package/dist/ledger-v3-validation.d.ts +11 -0
- package/dist/ledger-v3-validation.d.ts.map +1 -0
- package/dist/ledger-v3-validation.js +265 -0
- package/dist/ledger-v3-validation.js.map +1 -0
- package/dist/ledger.d.ts +18 -5
- package/dist/ledger.d.ts.map +1 -1
- package/dist/ledger.js +29 -7
- package/dist/ledger.js.map +1 -1
- package/dist/propagation.d.ts +3 -1
- package/dist/propagation.d.ts.map +1 -1
- package/dist/propagation.js +3 -0
- package/dist/propagation.js.map +1 -1
- package/dist/run-child.d.ts +3 -1
- package/dist/run-child.d.ts.map +1 -1
- package/dist/run-child.js +30 -2
- package/dist/run-child.js.map +1 -1
- package/dist/run-herdr.d.ts +2 -0
- package/dist/run-herdr.d.ts.map +1 -1
- package/dist/run-herdr.js +8 -0
- package/dist/run-herdr.js.map +1 -1
- package/dist/workflow-fact-id.d.ts +4 -0
- package/dist/workflow-fact-id.d.ts.map +1 -0
- package/dist/workflow-fact-id.js +14 -0
- package/dist/workflow-fact-id.js.map +1 -0
- package/dist/workflow-facts.d.ts +34 -0
- package/dist/workflow-facts.d.ts.map +1 -0
- package/dist/workflow-facts.js +43 -0
- package/dist/workflow-facts.js.map +1 -0
- package/extensions/chain-ledger.ts +4 -0
- package/extensions/chain-plan.ts +98 -0
- package/extensions/delegate-chain.ts +63 -122
- package/extensions/delegation-ledger.ts +60 -0
- package/extensions/delegation.ts +13 -13
- package/extensions/execute-child.ts +85 -21
- package/extensions/execution-occurrence.ts +20 -0
- package/extensions/grants-command.ts +22 -3
- package/extensions/grants.ts +44 -0
- package/extensions/run-delegation.ts +36 -56
- package/extensions/session.ts +7 -2
- package/extensions/workspace-runtime.ts +10 -0
- package/herdr-plugin/herdr-plugin.toml +18 -0
- package/package.json +16 -4
- package/src/check-runner.ts +16 -0
- package/src/correlation.ts +11 -0
- package/src/dashboard-cli.ts +171 -0
- package/src/dashboard-handshake.ts +185 -0
- package/src/dashboard-herdr.ts +355 -0
- package/src/dashboard-projection.ts +390 -0
- package/src/dashboard-render.ts +254 -0
- package/src/delegate-types.ts +6 -2
- package/src/delegate.ts +4 -2
- package/src/execution-id.ts +18 -0
- package/src/index.ts +25 -0
- package/src/ledger-events.ts +54 -10
- package/src/ledger-identifiers.ts +21 -0
- package/src/ledger-report.ts +40 -19
- package/src/ledger-v3-validation.ts +266 -0
- package/src/ledger.ts +49 -10
- package/src/propagation.ts +3 -0
- package/src/run-child.ts +35 -3
- package/src/run-herdr.ts +9 -0
- package/src/workflow-fact-id.ts +16 -0
- package/src/workflow-facts.ts +65 -0
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,77 @@ the record of how the package got here and are worth keeping; they are not worth
|
|
|
12
12
|
> the record of how the package arrived at what it does, and because the reasoning behind each one is
|
|
13
13
|
> usually the clearest statement of why the current behaviour is what it is.
|
|
14
14
|
|
|
15
|
+
## 0.20.1 — open the dashboard with Herdr's split-pane contract (2026-09-01)
|
|
16
|
+
|
|
17
|
+
- Fix `/grants dashboard` on Herdr 0.8+: a split plugin pane targets the verified caller pane and must not
|
|
18
|
+
also carry the mutually exclusive workspace selector. Released 0.20.0 sent both, so Herdr refused every
|
|
19
|
+
first open with `invalid_params`. Host verification and the returned workspace/tab check are unchanged.
|
|
20
|
+
|
|
21
|
+
## 0.20.0 — live governance dashboard and ledger v3 (2026-08-31)
|
|
22
|
+
|
|
23
|
+
- Ship a Herdr 0.8+ plugin inside the trusted pi-daddy package. A Herdr-hosted pi asks once before linking it;
|
|
24
|
+
**Install and open** is the only choice that installs anything. **Not now** and **Never ask** are persisted.
|
|
25
|
+
- Add `/grants dashboard`: verify this exact pi PID is in its declared Herdr pane, require a configured ledger,
|
|
26
|
+
diagnose missing/disabled/incompatible plugin state, then open or reuse a right split with `--no-focus`.
|
|
27
|
+
- Add a pure `ledger -> projection -> terminal renderer` path. Active ancestry stays visible, old completed
|
|
28
|
+
subtrees collapse, durations and Herdr pane identity render live, and corrupt lines are reported without
|
|
29
|
+
showing raw content or modifying the file.
|
|
30
|
+
- **BREAKING — production events now use the closed ledger v3 contract.** Every governed occurrence has a
|
|
31
|
+
globally unique `executionId` and explicit `parentExecutionId`; readable `childId` remains and may repeat.
|
|
32
|
+
Lifecycle/lease joins by `childId` are invalid. Frozen v2 and legacy lines remain readable but v2 lifecycle
|
|
33
|
+
is shown historical/unjoined rather than guessed.
|
|
34
|
+
- Lifecycle adds `running`, `deadlineAt`, and optional `herdrPaneId`/`herdrAgentName`, so an abandoned start
|
|
35
|
+
becomes incomplete and a live Herdr child can be focused by identity.
|
|
36
|
+
- Add identifier-only workflow facts with explicit `planned`, `observed`, or `controller_validated`
|
|
37
|
+
provenance. Enforced children remain a separate event class. Principal runs receive labels through existing
|
|
38
|
+
correlation fields; no workflow prompt prose is parsed.
|
|
39
|
+
- Add packaged v3 schema and generated fixtures while preserving the v2 artifact paths unchanged.
|
|
40
|
+
- **First-review hardening:** keep routed descendants on one absolute ledger; consolidate mixed chain gates
|
|
41
|
+
into one decision per execution; share strict runtime v3 validation across both readers; runtime-check
|
|
42
|
+
workflow vocabularies; isolate display callbacks from child execution; verify plugin provenance before
|
|
43
|
+
enabled state; and persist only literal installation choices.
|
|
44
|
+
- **Second-review hardening:** remove raw corrupt bytes from the canonical `/grants ledger` report; recheck
|
|
45
|
+
workspace/tab on reuse and returned open identity; validate every nested pane-state entry; reject prose in
|
|
46
|
+
v3 display/capability fields and strip all Unicode control/format characters; share one absolute child
|
|
47
|
+
deadline and running-before-terminal append order; and make public builders assert the exact closed wire.
|
|
48
|
+
- **Third-review hardening:** pane reuse keys exactly on workspace/tab/ledger rather than invocation `cwd`, and
|
|
49
|
+
the workflow-fact builder joins every other public v3 builder at the final closed-wire assertion.
|
|
50
|
+
- **Whole-change-review hardening:** reject stored pane entries whose workspace/tab/ledger disagrees with their
|
|
51
|
+
key, and validate explicit v2 against the frozen schema before presenting it as historical/unjoinable.
|
|
52
|
+
- **Critical-retry hardening:** align all seven v3 schema timestamp sites with runtime's seconds `00`–`59`
|
|
53
|
+
profile; reject a running lifecycle event that changes its occurrence deadline; reserve SIGTERM grace inside
|
|
54
|
+
the remaining process budget and enforce the recorded hard deadline with an independent SIGKILL timer.
|
|
55
|
+
- **Deadline race repairs:** soft and hard deadline callbacks allow pending child exit delivery one event-loop
|
|
56
|
+
turn before acting, then refuse to rewrite a completed PID as timed out merely because descendant pipes delay
|
|
57
|
+
`close`. A genuinely live PID remains subject to SIGTERM and absolute-deadline SIGKILL. Soft and hard routes
|
|
58
|
+
each have their own child-synchronized regression and mutation. The soft timer begins after a real ready
|
|
59
|
+
marker; the hard route uses a detached Linux process-state observer to establish OS exit before overdue timer
|
|
60
|
+
delivery. Tests use `Atomics.wait` rather than scheduler assumptions or busy-spinning, while a direct
|
|
61
|
+
request-mutation guard forces production to snapshot the hard deadline before spawn. The Linux observer is
|
|
62
|
+
independently bounded and accepts only zombie state or `ENOENT` as exit. The hard proof requires that exit
|
|
63
|
+
before a future recorded epoch, then delays controller delivery across it; observer status is published by
|
|
64
|
+
newline-terminated complete-status polling. An unexported AsyncLocalStorage test clock establishes the proof
|
|
65
|
+
epoch only after readiness without weakening public `runChild` snapshot semantics; synchronization searches
|
|
66
|
+
across arbitrary output chunk boundaries before retaining a bounded overlap suffix. Dedicated mutations
|
|
67
|
+
force internal-control consultation, cross-chunk matching and complete terminal-status grammar. Deterministic
|
|
68
|
+
status tests cover partial/complete writes, timeout, observer error, transient/permanent reads and expiry;
|
|
69
|
+
same-process control tests use a two-party barrier for real controlled/uncontrolled overlap and also cover
|
|
70
|
+
nesting, rejection and post-settlement cleanup. Polling has an independent attempt ceiling; AsyncLocalStorage
|
|
71
|
+
ownership lives only under `test/`; build cleans stale `dist/` first and installed smoke refuses the former
|
|
72
|
+
artifact, leaving no control module in the published package.
|
|
73
|
+
- **BREAKING — `LedgerReport.corrupt[]` now exposes `{line, reason}` rather than `{line, text}`.** Raw corrupt
|
|
74
|
+
bytes can contain task/output material and are no longer retained by the public integrity result. Consumers
|
|
75
|
+
that need forensic bytes must read the ledger itself at the reported line; pi-daddy never repairs it.
|
|
76
|
+
- **BREAKING — correlation fields rendered as labels/IDs now require the ASCII identifier grammar
|
|
77
|
+
`[A-Za-z0-9@*][A-Za-z0-9@*._:/-]{0,127}`.** Replace spaces with `-` or `_` before delegating. This prevents a
|
|
78
|
+
model-facing `policy_label`/phase/run ID from becoming a free-text task/output channel into the append-only
|
|
79
|
+
ledger and terminal. Other bounded correlation strings remain unchanged. A top-level
|
|
80
|
+
`assurance_scope: null` is normalized away and is not a valid v3 wire value; omit it instead.
|
|
81
|
+
- **BREAKING — named check IDs must use the same ASCII identifier alphabet and be at most 460 characters.**
|
|
82
|
+
Rename prose/whitespace keys before calling `runNamedCheck`; invalid IDs now refuse before the executable
|
|
83
|
+
or lease starts rather than failing only when a v3 receipt is appended.
|
|
84
|
+
|
|
85
|
+
|
|
15
86
|
## 0.19.0 — workspace routing is a capability (2026-08-23)
|
|
16
87
|
|
|
17
88
|
**The four hang fixes below were staged for a 0.18.2 and are released here instead — a decision reversed
|
package/README.md
CHANGED
|
@@ -220,6 +220,39 @@ no `--env` (the grant rides on the pane, which the agent's shell inherits), `age
|
|
|
220
220
|
shell so a multi-line argument must be staged to a file, and `agent wait --until idle` matches the state the
|
|
221
221
|
agent was *already* in, so settling requires a state counter to advance.
|
|
222
222
|
|
|
223
|
+
### Persistent Herdr dashboard
|
|
224
|
+
|
|
225
|
+
When this pi process is itself hosted inside Herdr 0.8+, `/grants dashboard` opens a managed right split:
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
PI-DADDY
|
|
229
|
+
◆ principal-feature · critical · declared
|
|
230
|
+
● plan running 0:42 · pane w7:p13
|
|
231
|
+
└─ ⛔ deploy refused 0:00
|
|
232
|
+
|
|
233
|
+
depth 2 · 1 active
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The plugin ships inside pi-daddy and is linked globally only after an explicit **Install and open** choice.
|
|
237
|
+
Literal **Not now** and **Never ask** choices are persisted; dismissing or losing the dialog stores nothing.
|
|
238
|
+
`/grants dashboard` never installs silently and prints the exact manual command when the plugin is absent. It
|
|
239
|
+
checks the bundled plugin root and protocol before suggesting that a disabled plugin be enabled. Panes and
|
|
240
|
+
ledgers stay workspace/tab-specific: reuse rechecks the pane's current workspace/tab, a wrong-host open is
|
|
241
|
+
closed and rejected, and malformed nested pane state refuses rather than risking a duplicate. A stored entry's
|
|
242
|
+
workspace/tab/ledger must also agree with its hash key before reuse. Invocation `cwd` sets the first pane
|
|
243
|
+
process directory but is not pane identity, so the same workspace/tab/ledger still reuses one pane across caller directories. Opening uses a right split targeted at this pi pane with `--no-focus`.
|
|
244
|
+
|
|
245
|
+
The view is a read-only ledger projection. Yellow is authorised/starting/running, green completed, red failed
|
|
246
|
+
or refused, and grey incomplete/historical. Old completed subtrees collapse; active ancestry stays visible.
|
|
247
|
+
It never displays task text, prompts, tool arguments, child output, or raw corrupt lines. Displayed ledger
|
|
248
|
+
values must satisfy the v3 identifier grammars (unsafe frozen-v2 values are redacted), and Unicode C1/bidi or
|
|
249
|
+
other control/format characters are removed before terminal output.
|
|
250
|
+
|
|
251
|
+
Provenance markers are explicit: **P** planned phase, **O** observed inline activity, **V**
|
|
252
|
+
controller-validated transition, **E** pi-daddy-enforced child, **D** caller-declared correlation. A principal
|
|
253
|
+
run can label itself through `run_id`, `phase`, effective assurance and `policy_label`; pi-daddy does not parse
|
|
254
|
+
principal workflow prose or invent pending/completed phases.
|
|
255
|
+
|
|
223
256
|
## Approving a gated capability
|
|
224
257
|
|
|
225
258
|
`gated` capabilities are ones a session holds but may not pass on without a human saying so.
|
|
@@ -355,9 +388,11 @@ All fields are optional; existing callers behave unchanged.
|
|
|
355
388
|
(`docs/probes/g37-registry-tamper`, tracked as R-137).
|
|
356
389
|
- Refusals retain current prose and add stable codes such as `CAPABILITY_ESCALATION`,
|
|
357
390
|
`GATED_UNAPPROVED`, `APPROVAL_SCOPE_MISMATCH`, and `WORKSPACE_WRITE_CONFLICT`.
|
|
358
|
-
- Ledger
|
|
391
|
+
- Ledger v3 adds unique execution/parent identity, joinable capability/lease/lifecycle/check events, and
|
|
392
|
+
provenance-labelled workflow facts while retaining frozen v2 and legacy readers.
|
|
359
393
|
- `pi-daddy/check-runner` selects an operator-named absolute executable+argv definition, never a shell
|
|
360
|
-
command string.
|
|
394
|
+
command string. Check IDs use the v3 ASCII identifier alphabet and are refused before execution if they do
|
|
395
|
+
not fit their generated receipt identity. It strips sensitive inherited environment, enforces timeout/output caps, executes a
|
|
361
396
|
private copy of the exact executable bytes it hashed, and pre/post-verifies Git head/candidate-tree
|
|
362
397
|
identity under an exclusive coordination lease. The executable remains arbitrary code; no filesystem or
|
|
363
398
|
network sandbox is claimed.
|
|
@@ -365,22 +400,21 @@ All fields are optional; existing callers behave unchanged.
|
|
|
365
400
|
Public subpaths: `pi-daddy/correlation`, `pi-daddy/refusals`, `pi-daddy/workspace`,
|
|
366
401
|
`pi-daddy/check-runner`.
|
|
367
402
|
|
|
368
|
-
### Canonical ledger
|
|
403
|
+
### Canonical ledger v3 contract
|
|
369
404
|
|
|
370
405
|
Machine consumers should import or resolve
|
|
371
|
-
`pi-daddy/contracts/ledger/
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
and compatibility rules.
|
|
406
|
+
`pi-daddy/contracts/ledger/v3/ledger-event.schema.json`, not infer a format from prose. Generated fixtures for
|
|
407
|
+
all five events are adjacent. v3 adds globally unique `executionId`, explicit `parentExecutionId`, bounded
|
|
408
|
+
start deadlines, optional Herdr pane identity, and provenance-labelled workflow facts. `childId` remains the
|
|
409
|
+
readable logical tree position and is never an occurrence join.
|
|
410
|
+
|
|
411
|
+
Dispatch on version before event: no version/discriminator is a legacy 0.17 grant record; explicit v2 uses the
|
|
412
|
+
frozen published v2 contract; explicit v3 uses the new closed contract; every other explicit version fails
|
|
413
|
+
closed and is never read as legacy. `verifyLedger` and the dashboard share exact runtime v3 validation, so a
|
|
414
|
+
lookalike string version, missing join identity or malformed nested correlation cannot be `OK` in one and
|
|
415
|
+
corrupt in the other. Explicit v2 is checked against its exact frozen schema before the dashboard labels it
|
|
416
|
+
historical; malformed v2 never becomes a grey row or orphan count. A field/event/enum/requiredness or semantic change requires another ledger version. See
|
|
417
|
+
`contracts/ledger/v3/README.md`; the v2 path remains available unchanged.
|
|
384
418
|
|
|
385
419
|
## Running it
|
|
386
420
|
|
|
@@ -390,6 +424,8 @@ PI_GRANTS_GRANT="agent:review,tool:read,tool:grep,tool:find,tool:ls,tool:delegat
|
|
|
390
424
|
PI_GRANTS_LEDGER=.pi/grants.jsonl \
|
|
391
425
|
PI_GRANTS_MAX_DEPTH=2 \
|
|
392
426
|
pi
|
|
427
|
+
# The relative ledger is resolved once at session start and inherited as one absolute path,
|
|
428
|
+
# so routed descendants changing cwd still append to this tree.
|
|
393
429
|
```
|
|
394
430
|
|
|
395
431
|
**Plain `pi`, no `-e`, when you installed this from npm** — the package declares `pi.extensions` and pi
|
|
@@ -413,12 +449,15 @@ approval says so:
|
|
|
413
449
|
as NONE, never as everything.
|
|
414
450
|
```
|
|
415
451
|
|
|
416
|
-
`/grants
|
|
417
|
-
|
|
452
|
+
`/grants dashboard` verifies that this exact pi PID is hosted in its declared Herdr pane, verifies the ledger
|
|
453
|
+
and plugin, then opens or reuses a right split without changing focus. `/grants ledger` reads the audit file
|
|
454
|
+
back and reports its integrity — record count, escalation attempts, any unparseable lines with line numbers
|
|
455
|
+
and content-free reasons (never copied ledger bytes), and **which instructions actually ran**: records grouped by definition
|
|
418
456
|
digest, each compared against the file on disk (`current` / `CHANGED since`), which is what makes ADR-0018's
|
|
419
457
|
`definitionDigest` answerable rather than decorative. It exists because nothing in this package had ever read a ledger
|
|
420
458
|
back, so a torn line was indistinguishable from a spawn that never happened. A corrupt line is **evidence**
|
|
421
|
-
and is left alone rather than repaired.
|
|
459
|
+
and is left alone rather than repaired. Session start checks integrity automatically; `/grants ledger` gives
|
|
460
|
+
the full report.
|
|
422
461
|
|
|
423
462
|
## Worked example: governing `principal-pi-skills`
|
|
424
463
|
|
|
@@ -551,7 +590,8 @@ everything below it.
|
|
|
551
590
|
| `PI_GRANTS_WORKSPACE_LEASE_DIR` | under `$PI_CODING_AGENT_DIR/pi-daddy/` | Kernel writer locks and ownership metadata. |
|
|
552
591
|
| `PI_GRANTS_CHILD_TIMEOUT` | `600` (seconds) | Wall-clock limit for a child. Inherited by descendants — an operator preference, deliberately *not* attenuating state. |
|
|
553
592
|
| `PI_GRANTS_FANOUT` | `8` | Per-call width and downward subtree budget; not a session-total counter. Malformed or `0` falls back to the default. |
|
|
554
|
-
| `PI_GRANTS_PARENT_ID` | `d0` |
|
|
593
|
+
| `PI_GRANTS_PARENT_ID` | `d0` | Readable logical tree position; set by the parent and allowed to repeat across calls. |
|
|
594
|
+
| `PI_GRANTS_EXECUTION_ID` | unset at a root | Unique governed execution occurrence; set by the parent. Lifecycle/lease joins use this, never `PI_GRANTS_PARENT_ID`. |
|
|
555
595
|
| `PI_GRANTS_HERDR` | unset ⇒ **probe** | Three-state. Unset probes for a reachable herdr and uses panes if one answers; `1` demands panes and refuses every delegation if herdr is unreachable; `0` demands captured subprocesses. Never detected from `herdr` merely being on `PATH`. |
|
|
556
596
|
| `PI_GRANTS_HERDR_WORKSPACE` | the parent's `HERDR_WORKSPACE_ID` | herdr workspace for spawned panes. Defaults to the workspace this session is in, so a child is a tab away rather than a workspace away. |
|
|
557
597
|
| `PI_GRANTS_HERDR_KEEP_PANE` | unset | `1` keeps each child's pane for inspection, and no sweep closes it. Off by default: a fan-out would flood the workspace. |
|
|
@@ -572,21 +612,32 @@ is broken after 10s.
|
|
|
572
612
|
|
|
573
613
|
## The ledger
|
|
574
614
|
|
|
575
|
-
Append-only JSONL. Version
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
615
|
+
Append-only JSONL. Version 3 records capability decisions, workspace leases, child lifecycle, check receipts
|
|
616
|
+
and workflow facts. Every per-child capability decision is present, **including refusals**. The reader still
|
|
617
|
+
accepts frozen v2 and legacy grant-only lines.
|
|
618
|
+
|
|
619
|
+
`childId` is hierarchical and readable (`d0.1`, `d0.1.2`) but repeated/parallel calls may reuse it. v3 adds a
|
|
620
|
+
random `executionId` and explicit `parentExecutionId`; those are the only lifecycle/lease occurrence join.
|
|
621
|
+
A v2 lifecycle is therefore shown historical/unjoined rather than guessed. A v3 starting deadline and the
|
|
622
|
+
executor timer share one absolute budget — waiting for the strict starting append consumes it, a later running
|
|
623
|
+
event cannot replace it, and process SIGTERM grace stays inside it under an independent hard-kill timer. That
|
|
624
|
+
timer bounds the governed PID while live. Soft and hard deadline callbacks first allow one event-loop turn for
|
|
625
|
+
pending child exit delivery; retained descendant pipes cannot rewrite a PID that already exited successfully as
|
|
626
|
+
timed out. A pending running append always lands before a terminal event. `denied` non-empty remains the designated escalation signal — **an agent asking for what it does not hold is an escalation attempt, and it
|
|
627
|
+
is invisible without a record.**
|
|
579
628
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
hold is an escalation attempt, and it is invisible without a record.**
|
|
629
|
+
Workflow facts are identifier-only and mark `planned`, `observed`, or `controller_validated`; they can never
|
|
630
|
+
claim pi-daddy enforcement. Capability/lifecycle records are the enforced class. Correlation remains a
|
|
631
|
+
caller-declared label; fields eligible for display must use the v3 ASCII identifier grammar rather than prose.
|
|
584
632
|
|
|
585
633
|
**Privacy is a property of this file, and the boundary is exact: capability ids, counts and identifiers only
|
|
586
634
|
— never prompts, task text, tool arguments or results.** Trusted `definitionDigest` and `taskDigest` values
|
|
587
635
|
identify the exact operator body and task. A predictable task can be guessed from SHA-256, so its digest is
|
|
588
636
|
sensitive/linkable metadata, not anonymization. Caller-supplied digest-looking values remain under
|
|
589
|
-
`correlation` and never authorize.
|
|
637
|
+
`correlation` and never authorize. Public v3 builders validate their serialized wire form against the same
|
|
638
|
+
closed runtime contract the readers use; `deadlineAt` therefore cannot be a `Date.parse` lookalike. Schema and
|
|
639
|
+
runtime share the seconds `00`–`59` timestamp profile because JavaScript deadline arithmetic cannot represent
|
|
640
|
+
leap seconds, and a normalized-away top-level null assurance scope is not schema-valid.
|
|
590
641
|
|
|
591
642
|
## Propagation is race-free by construction
|
|
592
643
|
|
|
@@ -664,7 +715,7 @@ The resolver, ledger, spawn planner and the whole approval model are pure functi
|
|
|
664
715
|
without pi:
|
|
665
716
|
|
|
666
717
|
```ts
|
|
667
|
-
import { resolve, assertNarrowing, planSpawn, buildRecord, appendRecord } from "pi-daddy";
|
|
718
|
+
import { resolve, assertNarrowing, planSpawn, buildRecord, appendRecord, digestTask, newExecutionId } from "pi-daddy";
|
|
668
719
|
|
|
669
720
|
const result = resolve({
|
|
670
721
|
requested: ["tool:read", "tool:grep"],
|
|
@@ -678,12 +729,15 @@ const plan = planSpawn({ effective: result.effective, prompt: task });
|
|
|
678
729
|
// -> ["--print","--no-session","--no-extensions","--no-skills","--no-context-files",
|
|
679
730
|
// "--no-prompt-templates","--tools","grep,read"," summarise src/"]
|
|
680
731
|
|
|
681
|
-
await appendRecord({ path: ".pi/grants.jsonl" }, buildRecord({
|
|
732
|
+
await appendRecord({ path: ".pi/grants.jsonl" }, buildRecord({
|
|
733
|
+
/* capability fields … */ result, blocked: false, executor: "process",
|
|
734
|
+
executionId: newExecutionId(), parentExecutionId: null, taskDigest: digestTask(task), now: new Date(),
|
|
735
|
+
}));
|
|
682
736
|
```
|
|
683
737
|
|
|
684
738
|
Subpaths are exported individually (`pi-daddy/resolve`, `/ledger`, `/spawn`, `/delegate`, `/catalog`,
|
|
685
739
|
`/propagation`, `/definitions`, `/fanout`, `/pi-tools`, `/approval`, `/approval-store`, `/approval-prompt`,
|
|
686
|
-
`/run-child`, `/run-herdr`).
|
|
740
|
+
`/run-child`, `/run-herdr`, `/dashboard-projection`, `/dashboard-render`).
|
|
687
741
|
|
|
688
742
|
## Design decisions worth knowing
|
|
689
743
|
|
|
@@ -713,7 +767,9 @@ npx pi-daddy init # as a command: scaffold .pi/skills/ and .pi/grants.
|
|
|
713
767
|
# skill packages — see the worked example above
|
|
714
768
|
```
|
|
715
769
|
|
|
716
|
-
The package is
|
|
770
|
+
The package is also the source of the optional Herdr plugin: the extension offers to link the trusted
|
|
771
|
+
`herdr-plugin/` directory explicitly, and `pi-daddy-dashboard` is the terminal renderer binary. pi loads
|
|
772
|
+
`extensions/grants.ts` through its own transpiling loader, which reads
|
|
717
773
|
TypeScript from `node_modules` quite happily; **Node does not** — it refuses to strip types under
|
|
718
774
|
`node_modules` — so the library entry points are compiled to `dist/`. Until 0.6.0 `exports` pointed at
|
|
719
775
|
`./src/*.ts`, and every consumer import failed with `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING` while
|
|
@@ -723,11 +779,11 @@ every in-repo test passed. `npm run test:smoke` packs a tarball, installs it int
|
|
|
723
779
|
## Testing
|
|
724
780
|
|
|
725
781
|
```bash
|
|
726
|
-
npm test #
|
|
782
|
+
npm test # 719 unit tests. Fast, pure, no pi, no network.
|
|
727
783
|
npm run typecheck # src + extensions + tests + integration tests
|
|
728
784
|
npm run test:integration # 45 tests against a REAL pi process. ~55s, no model tokens.
|
|
729
|
-
npm run test:smoke # pack
|
|
730
|
-
#
|
|
785
|
+
npm run test:smoke # pack/install; exercise library exports, both bins, the v2/v3 contracts,
|
|
786
|
+
# bundled Herdr plugin, dashboard, and `pi-daddy init`
|
|
731
787
|
PI_GRANTS_IT_MODEL=1 npm run test:integration # + 10 end-to-end tests with a real model. Costs money.
|
|
732
788
|
```
|
|
733
789
|
|
|
@@ -753,6 +809,13 @@ its own author the day after it was added: rather than raise the cap, `delegatio
|
|
|
753
809
|
|
|
754
810
|
## Status
|
|
755
811
|
|
|
812
|
+
**0.20.0 — live Herdr dashboard and ledger v3.** Adds the explicit installation handshake,
|
|
813
|
+
`/grants dashboard`, duplicate-safe right split, pure live projection, unique execution/parent identity,
|
|
814
|
+
workflow provenance facts and principal correlation labels. Enforcement is unchanged.
|
|
815
|
+
|
|
816
|
+
**0.19.0 — workspace routing is a capability.** Routing now attenuates through `workspace:<id>`; see the
|
|
817
|
+
changelog for the breaking migration.
|
|
818
|
+
|
|
756
819
|
**0.18.1 — security fix for malformed capability IDs.** Capability IDs containing comma, CR, LF, NUL or
|
|
757
820
|
surrounding whitespace are refused before resolution and again before grant serialization, preventing a
|
|
758
821
|
wildcard-covered string from splitting into authority the parent never held.
|
|
@@ -781,6 +844,12 @@ Known gaps, stated because a gap nobody wrote down is the one that surprises som
|
|
|
781
844
|
- **A running delegation is visible.** One status block per call — per child: its definition, its herdr agent, its
|
|
782
845
|
pane id, its state, elapsed time, and the last three lines it printed. Bounded in height and width, so a fan-out
|
|
783
846
|
cannot flood your screen. It is a **display, never the result**.
|
|
847
|
+
- **The dashboard whole-file polls.** The MVP is sized for 10 MiB; 50 MiB or 100 ms p95 projection is the
|
|
848
|
+
switch point for incremental replay.
|
|
849
|
+
- **v2 is historical in the dashboard.** It has no unique occurrence ID, so lifecycle is reported unjoined
|
|
850
|
+
rather than matched by reusable `childId`.
|
|
851
|
+
- **principal-pi-skills does not yet publish a generated graph declaration.** Explicit correlation and
|
|
852
|
+
provenance facts render; prompt prose is never parsed into a graph.
|
|
784
853
|
- **A definition's *instructions* are governed only by identity.** `agent:<name>` says which file may be
|
|
785
854
|
spawned and the digest says which version ran, but nothing reads a body and judges what it says — the
|
|
786
855
|
operator authorises a file, and its contents are their responsibility.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# pi-daddy ledger contract — version 3
|
|
2
|
+
|
|
3
|
+
Canonical machine contract for one `ledgerVersion: 3` JSONL line:
|
|
4
|
+
|
|
5
|
+
- `ledger-event.schema.json` — closed JSON Schema draft 2020-12 event union.
|
|
6
|
+
- `fixtures/*.json` — deterministic examples generated through the production builders by
|
|
7
|
+
`scripts/generate-ledger-v3-contract.ts`.
|
|
8
|
+
|
|
9
|
+
## Dispatch and compatibility
|
|
10
|
+
|
|
11
|
+
1. No `ledgerVersion` and no `event` is a legacy 0.17 grant record.
|
|
12
|
+
2. `ledgerVersion: 2` is validated against the frozen v2 contract.
|
|
13
|
+
3. `ledgerVersion: 3` requires one known event and validation against this schema.
|
|
14
|
+
4. Any unsupported explicit version, missing discriminator, unknown event, or malformed required identity is corrupt. It is never reinterpreted as legacy.
|
|
15
|
+
|
|
16
|
+
The schema is closed. Adding/removing a field, event or enum member, changing requiredness, or changing meaning requires a new ledger version and versioned path. V3 is still unreleased, so its review repairs are folded into this one initial contract rather than creating a public v4.
|
|
17
|
+
|
|
18
|
+
## Execution identity
|
|
19
|
+
|
|
20
|
+
Every v3 **execution** event carries:
|
|
21
|
+
|
|
22
|
+
- `executionId`: globally unique identity of one execution occurrence.
|
|
23
|
+
- `parentExecutionId`: the unique governed execution that delegated it, or explicit `null` at a root.
|
|
24
|
+
- `childId`: the readable logical tree position, retained for operators and deterministic comparisons.
|
|
25
|
+
|
|
26
|
+
`workflow_fact` is not an execution event; it carries its own `factId` and explicit provenance instead.
|
|
27
|
+
|
|
28
|
+
Consumers join lifecycle and lease events by `executionId`, never by `childId`. Repeated or concurrent calls may reuse a logical position such as `d0.1`; they may never reuse an execution id.
|
|
29
|
+
|
|
30
|
+
A lifecycle `running` event may include `herdrPaneId` and `herdrAgentName` for navigation. These are runtime observations, not enforcement boundaries. `deadlineAt` is immutable within one occurrence and bounds how long a non-terminal start can be rendered as live; after it, the truthful state is incomplete.
|
|
31
|
+
|
|
32
|
+
All timestamp fields share one schema/runtime profile: JSON Schema `date-time` with seconds restricted to `00`–`59`. Leap-second strings are excluded because JavaScript deadline and duration arithmetic cannot represent them.
|
|
33
|
+
|
|
34
|
+
## Privacy and provenance
|
|
35
|
+
|
|
36
|
+
The privacy boundary is unchanged: no task text, prompts, tool arguments, child output, or tool results. Fields displayed as identities and every capability use explicit ASCII identifier grammars in both schema and runtime; public builders assert that their serialized event passes the same exact reader. Correlation display fields use the identifier grammar rather than free-form prose, and a top-level null `assurance_scope` is omitted/rejected consistently. Trusted task/definition digests remain outside `correlation`. Correlation is caller-declared join metadata and never becomes proof that a workflow transition was validated or that an inline skill executed.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ledgerVersion": 3,
|
|
3
|
+
"event": "capability_decision",
|
|
4
|
+
"executionId": "exec:00000000-0000-4000-8000-000000000001",
|
|
5
|
+
"parentExecutionId": null,
|
|
6
|
+
"ts": "2026-08-20T12:00:01.000Z",
|
|
7
|
+
"parentId": "d0",
|
|
8
|
+
"childId": "d0.1",
|
|
9
|
+
"depth": 1,
|
|
10
|
+
"agentType": "build",
|
|
11
|
+
"executor": "process",
|
|
12
|
+
"taskFrom": "d0.0",
|
|
13
|
+
"taskFromExecutionId": "exec:00000000-0000-4000-8000-000000000000",
|
|
14
|
+
"taskDigest": "9999999999999999999999999999999999999999999999999999999999999999",
|
|
15
|
+
"correlation": {
|
|
16
|
+
"schema_version": "1.0",
|
|
17
|
+
"run_id": "run-contract-001",
|
|
18
|
+
"task_id": "task-contract-001",
|
|
19
|
+
"workspace_id": "workspace-contract",
|
|
20
|
+
"context_id": "context-contract",
|
|
21
|
+
"phase": "verify",
|
|
22
|
+
"assurance": "critical",
|
|
23
|
+
"assurance_effective": "critical",
|
|
24
|
+
"policy_label": "policy-contract",
|
|
25
|
+
"assurance_source": "policy",
|
|
26
|
+
"assurance_scope": {
|
|
27
|
+
"kind": "changed-files",
|
|
28
|
+
"paths": [
|
|
29
|
+
"src/**"
|
|
30
|
+
],
|
|
31
|
+
"include_untracked": true
|
|
32
|
+
},
|
|
33
|
+
"activated_at": "2026-08-20T12:00:00.000Z",
|
|
34
|
+
"plan_digest": "1111111111111111111111111111111111111111111111111111111111111111",
|
|
35
|
+
"definition_digest": "2222222222222222222222222222222222222222222222222222222222222222",
|
|
36
|
+
"task_digest": "3333333333333333333333333333333333333333333333333333333333333333",
|
|
37
|
+
"base_sha": "4444444444444444444444444444444444444444",
|
|
38
|
+
"head_sha": "5555555555555555555555555555555555555555",
|
|
39
|
+
"tree_sha": "6666666666666666666666666666666666666666",
|
|
40
|
+
"event_seq": 21,
|
|
41
|
+
"last_change_seq": 18,
|
|
42
|
+
"last_authority_seq": 20,
|
|
43
|
+
"check_receipt_id": "7777777777777777777777777777777777777777777777777777777777777777"
|
|
44
|
+
},
|
|
45
|
+
"refusal": {
|
|
46
|
+
"code": "WORKSPACE_WRITE_CONFLICT",
|
|
47
|
+
"message": "workspace-contract already has a governed writer",
|
|
48
|
+
"details": {
|
|
49
|
+
"workspace_id": "workspace-contract",
|
|
50
|
+
"retryable": true,
|
|
51
|
+
"holder_depth": 1
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"requested": [
|
|
55
|
+
"tool:bash",
|
|
56
|
+
"tool:read"
|
|
57
|
+
],
|
|
58
|
+
"parentGrant": [
|
|
59
|
+
"agent:build",
|
|
60
|
+
"tool:bash",
|
|
61
|
+
"tool:read"
|
|
62
|
+
],
|
|
63
|
+
"effective": [
|
|
64
|
+
"tool:bash",
|
|
65
|
+
"tool:read"
|
|
66
|
+
],
|
|
67
|
+
"denied": [],
|
|
68
|
+
"clipped": [],
|
|
69
|
+
"gatedBlocked": [],
|
|
70
|
+
"blocked": true,
|
|
71
|
+
"reason": "workspace-contract already has a governed writer",
|
|
72
|
+
"approved": [
|
|
73
|
+
"tool:bash",
|
|
74
|
+
"tool:read"
|
|
75
|
+
],
|
|
76
|
+
"approvalSources": {
|
|
77
|
+
"tool:bash": "persisted",
|
|
78
|
+
"tool:read": "prompt"
|
|
79
|
+
},
|
|
80
|
+
"approvalScopes": {
|
|
81
|
+
"tool:bash": "always",
|
|
82
|
+
"tool:read": "once"
|
|
83
|
+
},
|
|
84
|
+
"approvalExpiresAt": {
|
|
85
|
+
"tool:bash": "2026-09-19T12:00:00.000Z"
|
|
86
|
+
},
|
|
87
|
+
"approvalUses": {
|
|
88
|
+
"tool:read": {
|
|
89
|
+
"max": 1,
|
|
90
|
+
"remaining": 0
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"definitionDigest": {
|
|
94
|
+
"name": "build",
|
|
95
|
+
"source": "/operator/skills/build/SKILL.md",
|
|
96
|
+
"sha256": "8888888888888888888888888888888888888888888888888888888888888888"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ledgerVersion": 3,
|
|
3
|
+
"event": "check_receipt",
|
|
4
|
+
"ts": "2026-08-20T12:00:04.000Z",
|
|
5
|
+
"executionId": "exec:00000000-0000-4000-8000-000000000002",
|
|
6
|
+
"parentExecutionId": null,
|
|
7
|
+
"childId": "check:spec-lint:00000000-0000-4000-8000-000000000000",
|
|
8
|
+
"receiptId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
9
|
+
"workspaceId": "workspace-contract",
|
|
10
|
+
"checkId": "spec-lint",
|
|
11
|
+
"treeSha": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
12
|
+
"correlation": {
|
|
13
|
+
"schema_version": "1.0",
|
|
14
|
+
"run_id": "run-contract-001",
|
|
15
|
+
"task_id": "task-contract-001",
|
|
16
|
+
"workspace_id": "workspace-contract",
|
|
17
|
+
"context_id": "context-contract",
|
|
18
|
+
"phase": "verify",
|
|
19
|
+
"assurance": "critical",
|
|
20
|
+
"assurance_effective": "critical",
|
|
21
|
+
"policy_label": "policy-contract",
|
|
22
|
+
"assurance_source": "policy",
|
|
23
|
+
"assurance_scope": {
|
|
24
|
+
"kind": "changed-files",
|
|
25
|
+
"paths": [
|
|
26
|
+
"src/**"
|
|
27
|
+
],
|
|
28
|
+
"include_untracked": true
|
|
29
|
+
},
|
|
30
|
+
"activated_at": "2026-08-20T12:00:00.000Z",
|
|
31
|
+
"plan_digest": "1111111111111111111111111111111111111111111111111111111111111111",
|
|
32
|
+
"definition_digest": "2222222222222222222222222222222222222222222222222222222222222222",
|
|
33
|
+
"task_digest": "3333333333333333333333333333333333333333333333333333333333333333",
|
|
34
|
+
"base_sha": "4444444444444444444444444444444444444444",
|
|
35
|
+
"head_sha": "5555555555555555555555555555555555555555",
|
|
36
|
+
"tree_sha": "6666666666666666666666666666666666666666",
|
|
37
|
+
"event_seq": 21,
|
|
38
|
+
"last_change_seq": 18,
|
|
39
|
+
"last_authority_seq": 20,
|
|
40
|
+
"check_receipt_id": "7777777777777777777777777777777777777777777777777777777777777777"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ledgerVersion": 3,
|
|
3
|
+
"event": "child_lifecycle",
|
|
4
|
+
"ts": "2026-08-20T12:00:03.000Z",
|
|
5
|
+
"executionId": "exec:00000000-0000-4000-8000-000000000001",
|
|
6
|
+
"parentExecutionId": null,
|
|
7
|
+
"childId": "d0.1",
|
|
8
|
+
"state": "failed",
|
|
9
|
+
"executor": "process",
|
|
10
|
+
"deadlineAt": "2026-08-20T12:10:00.000Z",
|
|
11
|
+
"exitCode": null,
|
|
12
|
+
"signal": null,
|
|
13
|
+
"aborted": true,
|
|
14
|
+
"reason": "child did not start",
|
|
15
|
+
"correlation": {
|
|
16
|
+
"schema_version": "1.0",
|
|
17
|
+
"run_id": "run-contract-001",
|
|
18
|
+
"task_id": "task-contract-001",
|
|
19
|
+
"workspace_id": "workspace-contract",
|
|
20
|
+
"context_id": "context-contract",
|
|
21
|
+
"phase": "verify",
|
|
22
|
+
"assurance": "critical",
|
|
23
|
+
"assurance_effective": "critical",
|
|
24
|
+
"policy_label": "policy-contract",
|
|
25
|
+
"assurance_source": "policy",
|
|
26
|
+
"assurance_scope": {
|
|
27
|
+
"kind": "changed-files",
|
|
28
|
+
"paths": [
|
|
29
|
+
"src/**"
|
|
30
|
+
],
|
|
31
|
+
"include_untracked": true
|
|
32
|
+
},
|
|
33
|
+
"activated_at": "2026-08-20T12:00:00.000Z",
|
|
34
|
+
"plan_digest": "1111111111111111111111111111111111111111111111111111111111111111",
|
|
35
|
+
"definition_digest": "2222222222222222222222222222222222222222222222222222222222222222",
|
|
36
|
+
"task_digest": "3333333333333333333333333333333333333333333333333333333333333333",
|
|
37
|
+
"base_sha": "4444444444444444444444444444444444444444",
|
|
38
|
+
"head_sha": "5555555555555555555555555555555555555555",
|
|
39
|
+
"tree_sha": "6666666666666666666666666666666666666666",
|
|
40
|
+
"event_seq": 21,
|
|
41
|
+
"last_change_seq": 18,
|
|
42
|
+
"last_authority_seq": 20,
|
|
43
|
+
"check_receipt_id": "7777777777777777777777777777777777777777777777777777777777777777"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ledgerVersion": 3,
|
|
3
|
+
"event": "workflow_fact",
|
|
4
|
+
"ts": "2026-08-20T12:00:05.000Z",
|
|
5
|
+
"factId": "fact:00000000-0000-4000-8000-000000000003",
|
|
6
|
+
"source": "principal-pi-skills",
|
|
7
|
+
"provenance": "controller_validated",
|
|
8
|
+
"kind": "transition",
|
|
9
|
+
"subject": "build-to-review",
|
|
10
|
+
"state": "completed",
|
|
11
|
+
"correlation": {
|
|
12
|
+
"schema_version": "1.0",
|
|
13
|
+
"run_id": "run-contract-001",
|
|
14
|
+
"task_id": "task-contract-001",
|
|
15
|
+
"workspace_id": "workspace-contract",
|
|
16
|
+
"context_id": "context-contract",
|
|
17
|
+
"phase": "verify",
|
|
18
|
+
"assurance": "critical",
|
|
19
|
+
"assurance_effective": "critical",
|
|
20
|
+
"policy_label": "policy-contract",
|
|
21
|
+
"assurance_source": "policy",
|
|
22
|
+
"assurance_scope": {
|
|
23
|
+
"kind": "changed-files",
|
|
24
|
+
"paths": [
|
|
25
|
+
"src/**"
|
|
26
|
+
],
|
|
27
|
+
"include_untracked": true
|
|
28
|
+
},
|
|
29
|
+
"activated_at": "2026-08-20T12:00:00.000Z",
|
|
30
|
+
"plan_digest": "1111111111111111111111111111111111111111111111111111111111111111",
|
|
31
|
+
"definition_digest": "2222222222222222222222222222222222222222222222222222222222222222",
|
|
32
|
+
"task_digest": "3333333333333333333333333333333333333333333333333333333333333333",
|
|
33
|
+
"base_sha": "4444444444444444444444444444444444444444",
|
|
34
|
+
"head_sha": "5555555555555555555555555555555555555555",
|
|
35
|
+
"tree_sha": "6666666666666666666666666666666666666666",
|
|
36
|
+
"event_seq": 21,
|
|
37
|
+
"last_change_seq": 18,
|
|
38
|
+
"last_authority_seq": 20,
|
|
39
|
+
"check_receipt_id": "7777777777777777777777777777777777777777777777777777777777777777"
|
|
40
|
+
}
|
|
41
|
+
}
|