pi-daddy 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/README.md +12 -6
- package/contracts/daily-view/v1/README.md +114 -0
- package/contracts/daily-view/v1/fixtures/view.json +525 -0
- package/contracts/daily-view/v1/fixtures/view.txt +75 -0
- package/contracts/daily-view/v1/fixtures/work.jsonl +17 -0
- package/contracts/daily-view/v1/p03/README.md +26 -0
- package/contracts/daily-view/v1/p03/fixtures/retained-executions.json +241 -0
- package/contracts/daily-view/v1/p03/projection.schema.json +194 -0
- package/contracts/daily-view/v1/p03/provenance.json +21 -0
- package/contracts/dashboard-host/v1/README.md +176 -0
- package/contracts/debrief/v1/README.md +146 -0
- package/contracts/debrief/v1/intervention/README.md +32 -0
- package/contracts/debrief/v1/intervention/fixtures/artifact-3ee11136beb864f518252e5024dae9197421fbf97b6e981d3243c782b5c44bd0.txt +1 -0
- package/contracts/debrief/v1/intervention/fixtures/artifact-58905d872dd3c54a9705f67b05fa82edbad7af6476ae8993faf1a7b9fadfb905.txt +1 -0
- package/contracts/debrief/v1/intervention/fixtures/assessment.json +29 -0
- package/contracts/debrief/v1/intervention/fixtures/blind-view.json +20 -0
- package/contracts/debrief/v1/intervention/fixtures/choice.json +7 -0
- package/contracts/debrief/v1/intervention/fixtures/manifest.json +57 -0
- package/contracts/debrief/v1/intervention/fixtures/reveal.json +39 -0
- package/contracts/debrief/v1/provenance.json +89 -0
- package/contracts/debrief/v1/work-capture/README.md +38 -0
- package/contracts/debrief/v1/work-capture/fixtures/batch.json +17 -0
- package/contracts/debrief/v1/work-capture/fixtures/cases.json +184 -0
- package/contracts/debrief/v1/work-capture/fixtures/review.json +184 -0
- package/contracts/debrief/v1/work-capture/review-request.schema.json +41 -0
- package/contracts/debrief/v1/work-capture/work-case.schema.json +190 -0
- package/contracts/debrief/v2/README.md +71 -0
- package/contracts/debrief/v2/input-pin.json +66 -0
- package/contracts/debrief/v2/intervention-upstream.md +40 -0
- package/contracts/debrief/v2/work-signals-upstream.md +22 -0
- package/contracts/dispatch-control/v1/README.md +109 -0
- package/contracts/dispatch-control/v1/request.schema.json +19 -0
- package/contracts/effect-profile/v1/README.md +124 -0
- package/contracts/execution-retention/v1/README.md +109 -0
- package/contracts/execution-retention/v2/README.md +148 -0
- package/contracts/execution-retention/v2/fixtures/interrupted-native-bytes.json +91 -0
- package/contracts/execution-retention/v2/fixtures/missing-native-session.json +91 -0
- package/contracts/execution-retention/v2/fixtures/native-file-unknown-branch.json +91 -0
- package/contracts/execution-retention/v2/fixtures/native-id-without-bytes.json +91 -0
- package/contracts/execution-retention/v2/fixtures/native-live-branch.json +90 -0
- package/contracts/execution-retention/v2/fixtures/replaced-native-session.json +92 -0
- package/contracts/execution-retention/v2/fixtures/result-82c620cdfeb8ca6b858cf653d7f5e2eedca5315d6244216d60e8b36f03223d6a.bin +1 -0
- package/contracts/execution-retention/v2/fixtures/session-2ec1f134bc739984434f7fca689e1c3d1c39fce2dcadae709e9b6faedfcc4ac7.bin +3 -0
- package/contracts/execution-retention/v2/fixtures/session-9bdb4bd16a901da31580acf056bda525225259e15ec409e0410480109011772f.bin +3 -0
- package/contracts/execution-retention/v2/manifest.schema.json +858 -0
- package/contracts/experiment/v1/README.md +164 -0
- package/contracts/factory-order/v1/README.md +151 -0
- package/contracts/factory-order/v1/adoption-pin.json +8 -0
- package/contracts/intent-control/v1/README.md +135 -0
- package/contracts/intent-control/v1/request.schema.json +1096 -0
- package/contracts/intent-control/v2/README.md +34 -0
- package/contracts/intent-control/v2/request.schema.json +1070 -0
- package/contracts/ledger/v4/README.md +241 -0
- package/contracts/ledger/v4/fixtures/layout-options.json +428 -0
- package/contracts/ledger/v4/fixtures/work-acceptance.json +57 -0
- package/contracts/ledger/v4/fixtures/work-occurrence.json +44 -0
- package/contracts/ledger/v4/fixtures/work-revision.json +26 -0
- package/contracts/ledger/v4/fixtures/work-snapshot.json +73 -0
- package/contracts/ledger/v4/ledger-event.schema.json +162 -0
- package/contracts/ordinary-control/v1/README.md +59 -0
- package/contracts/producer-ipc/v1/README.md +137 -0
- package/dist/check-runner.d.ts +5 -0
- package/dist/check-runner.d.ts.map +1 -1
- package/dist/check-runner.js +16 -2
- package/dist/check-runner.js.map +1 -1
- package/dist/cli.d.ts +3 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +49 -3
- package/dist/cli.js.map +1 -1
- package/dist/control-journal.d.ts +20 -0
- package/dist/control-journal.d.ts.map +1 -0
- package/dist/control-journal.js +73 -0
- package/dist/control-journal.js.map +1 -0
- package/dist/daily-dashboard-host.d.ts +99 -0
- package/dist/daily-dashboard-host.d.ts.map +1 -0
- package/dist/daily-dashboard-host.js +71 -0
- package/dist/daily-dashboard-host.js.map +1 -0
- package/dist/daily-view-input.d.ts +44 -0
- package/dist/daily-view-input.d.ts.map +1 -0
- package/dist/daily-view-input.js +68 -0
- package/dist/daily-view-input.js.map +1 -0
- package/dist/daily-view-render.d.ts +4 -0
- package/dist/daily-view-render.d.ts.map +1 -0
- package/dist/daily-view-render.js +41 -0
- package/dist/daily-view-render.js.map +1 -0
- package/dist/daily-view.d.ts +74 -0
- package/dist/daily-view.d.ts.map +1 -0
- package/dist/daily-view.js +170 -0
- package/dist/daily-view.js.map +1 -0
- package/dist/dashboard-cli.d.ts +26 -1
- package/dist/dashboard-cli.d.ts.map +1 -1
- package/dist/dashboard-cli.js +128 -3
- package/dist/dashboard-cli.js.map +1 -1
- package/dist/dashboard-harness.d.ts +22 -0
- package/dist/dashboard-harness.d.ts.map +1 -0
- package/dist/dashboard-harness.js +89 -0
- package/dist/dashboard-harness.js.map +1 -0
- package/dist/dashboard-herdr.d.ts.map +1 -1
- package/dist/dashboard-herdr.js +7 -2
- package/dist/dashboard-herdr.js.map +1 -1
- package/dist/dashboard-host-contract.d.ts +116 -0
- package/dist/dashboard-host-contract.d.ts.map +1 -0
- package/dist/dashboard-host-contract.js +14 -0
- package/dist/dashboard-host-contract.js.map +1 -0
- package/dist/dashboard-host-transport.d.ts +16 -0
- package/dist/dashboard-host-transport.d.ts.map +1 -0
- package/dist/dashboard-host-transport.js +124 -0
- package/dist/dashboard-host-transport.js.map +1 -0
- package/dist/dashboard-host.d.ts +203 -0
- package/dist/dashboard-host.d.ts.map +1 -0
- package/dist/dashboard-host.js +376 -0
- package/dist/dashboard-host.js.map +1 -0
- package/dist/dashboard-observation.d.ts +28 -0
- package/dist/dashboard-observation.d.ts.map +1 -0
- package/dist/dashboard-observation.js +86 -0
- package/dist/dashboard-observation.js.map +1 -0
- package/dist/debrief-contract.d.ts +65 -0
- package/dist/debrief-contract.d.ts.map +1 -0
- package/dist/debrief-contract.js +151 -0
- package/dist/debrief-contract.js.map +1 -0
- package/dist/debrief-fixture.d.ts +16 -0
- package/dist/debrief-fixture.d.ts.map +1 -0
- package/dist/debrief-fixture.js +41 -0
- package/dist/debrief-fixture.js.map +1 -0
- package/dist/debrief-host.d.ts +59 -0
- package/dist/debrief-host.d.ts.map +1 -0
- package/dist/debrief-host.js +49 -0
- package/dist/debrief-host.js.map +1 -0
- package/dist/debrief-render.d.ts +5 -0
- package/dist/debrief-render.d.ts.map +1 -0
- package/dist/debrief-render.js +65 -0
- package/dist/debrief-render.js.map +1 -0
- package/dist/debrief.d.ts +90 -0
- package/dist/debrief.d.ts.map +1 -0
- package/dist/debrief.js +263 -0
- package/dist/debrief.js.map +1 -0
- package/dist/delegate-types.d.ts +2 -0
- 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 +1 -0
- package/dist/delegate.js.map +1 -1
- package/dist/dispatch-control.d.ts +45 -0
- package/dist/dispatch-control.d.ts.map +1 -0
- package/dist/dispatch-control.js +76 -0
- package/dist/dispatch-control.js.map +1 -0
- package/dist/effect-profile-runtime.d.ts +40 -0
- package/dist/effect-profile-runtime.d.ts.map +1 -0
- package/dist/effect-profile-runtime.js +51 -0
- package/dist/effect-profile-runtime.js.map +1 -0
- package/dist/effect-profile.d.ts +40 -0
- package/dist/effect-profile.d.ts.map +1 -0
- package/dist/effect-profile.js +152 -0
- package/dist/effect-profile.js.map +1 -0
- package/dist/execution-retention.d.ts +90 -0
- package/dist/execution-retention.d.ts.map +1 -0
- package/dist/execution-retention.js +247 -0
- package/dist/execution-retention.js.map +1 -0
- package/dist/experiment-contract.d.ts +56 -0
- package/dist/experiment-contract.d.ts.map +1 -0
- package/dist/experiment-contract.js +80 -0
- package/dist/experiment-contract.js.map +1 -0
- package/dist/experiment-state.d.ts +22 -0
- package/dist/experiment-state.d.ts.map +1 -0
- package/dist/experiment-state.js +79 -0
- package/dist/experiment-state.js.map +1 -0
- package/dist/experiment-store.d.ts +30 -0
- package/dist/experiment-store.d.ts.map +1 -0
- package/dist/experiment-store.js +147 -0
- package/dist/experiment-store.js.map +1 -0
- package/dist/experiment.d.ts +65 -0
- package/dist/experiment.d.ts.map +1 -0
- package/dist/experiment.js +357 -0
- package/dist/experiment.js.map +1 -0
- package/dist/factory-contract.d.ts +79 -0
- package/dist/factory-contract.d.ts.map +1 -0
- package/dist/factory-contract.js +89 -0
- package/dist/factory-contract.js.map +1 -0
- package/dist/factory-migration.d.ts +20 -0
- package/dist/factory-migration.d.ts.map +1 -0
- package/dist/factory-migration.js +55 -0
- package/dist/factory-migration.js.map +1 -0
- package/dist/factory-order.d.ts +848 -0
- package/dist/factory-order.d.ts.map +1 -0
- package/dist/factory-order.js +83 -0
- package/dist/factory-order.js.map +1 -0
- package/dist/factory-registry.d.ts +121 -0
- package/dist/factory-registry.d.ts.map +1 -0
- package/dist/factory-registry.js +133 -0
- package/dist/factory-registry.js.map +1 -0
- package/dist/file-lock.d.ts +8 -2
- package/dist/file-lock.d.ts.map +1 -1
- package/dist/file-lock.js +78 -19
- package/dist/file-lock.js.map +1 -1
- package/dist/herdr-poll.d.ts +8 -0
- package/dist/herdr-poll.d.ts.map +1 -1
- package/dist/herdr-poll.js +23 -0
- package/dist/herdr-poll.js.map +1 -1
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/dist/intent-application.d.ts +17 -0
- package/dist/intent-application.d.ts.map +1 -0
- package/dist/intent-application.js +113 -0
- package/dist/intent-application.js.map +1 -0
- package/dist/intent-control.d.ts +201 -0
- package/dist/intent-control.d.ts.map +1 -0
- package/dist/intent-control.js +110 -0
- package/dist/intent-control.js.map +1 -0
- package/dist/intent-scheduling.d.ts +9 -0
- package/dist/intent-scheduling.d.ts.map +1 -0
- package/dist/intent-scheduling.js +15 -0
- package/dist/intent-scheduling.js.map +1 -0
- package/dist/ledger-append.d.ts +15 -0
- package/dist/ledger-append.d.ts.map +1 -0
- package/dist/ledger-append.js +94 -0
- package/dist/ledger-append.js.map +1 -0
- package/dist/ledger.d.ts +11 -0
- package/dist/ledger.d.ts.map +1 -1
- package/dist/ledger.js +3 -7
- package/dist/ledger.js.map +1 -1
- package/dist/native-session-target.d.ts +9 -0
- package/dist/native-session-target.d.ts.map +1 -0
- package/dist/native-session-target.js +29 -0
- package/dist/native-session-target.js.map +1 -0
- package/dist/native-session.d.ts +59 -0
- package/dist/native-session.d.ts.map +1 -0
- package/dist/native-session.js +154 -0
- package/dist/native-session.js.map +1 -0
- package/dist/order-schedule.d.ts +37 -0
- package/dist/order-schedule.d.ts.map +1 -0
- package/dist/order-schedule.js +81 -0
- package/dist/order-schedule.js.map +1 -0
- package/dist/ordinary-children.d.ts +52 -0
- package/dist/ordinary-children.d.ts.map +1 -0
- package/dist/ordinary-children.js +93 -0
- package/dist/ordinary-children.js.map +1 -0
- package/dist/producer-ipc-contract.d.ts +29 -0
- package/dist/producer-ipc-contract.d.ts.map +1 -0
- package/dist/producer-ipc-contract.js +29 -0
- package/dist/producer-ipc-contract.js.map +1 -0
- package/dist/producer-ipc.d.ts +55 -0
- package/dist/producer-ipc.d.ts.map +1 -0
- package/dist/producer-ipc.js +143 -0
- package/dist/producer-ipc.js.map +1 -0
- package/dist/resource-budget.d.ts +334 -0
- package/dist/resource-budget.d.ts.map +1 -0
- package/dist/resource-budget.js +415 -0
- package/dist/resource-budget.js.map +1 -0
- package/dist/retention-contract.d.ts +73 -0
- package/dist/retention-contract.d.ts.map +1 -0
- package/dist/retention-contract.js +104 -0
- package/dist/retention-contract.js.map +1 -0
- package/dist/retention-json.d.ts +3 -0
- package/dist/retention-json.d.ts.map +1 -0
- package/dist/retention-json.js +32 -0
- package/dist/retention-json.js.map +1 -0
- package/dist/run-child.d.ts +4 -0
- package/dist/run-child.d.ts.map +1 -1
- package/dist/run-child.js +16 -2
- package/dist/run-child.js.map +1 -1
- package/dist/run-herdr.d.ts +6 -0
- package/dist/run-herdr.d.ts.map +1 -1
- package/dist/run-herdr.js +19 -6
- package/dist/run-herdr.js.map +1 -1
- package/dist/vendor/adoption.d.ts +129 -0
- package/dist/vendor/adoption.d.ts.map +1 -0
- package/dist/vendor/adoption.js +102 -0
- package/dist/vendor/adoption.js.map +1 -0
- package/dist/work-command.d.ts +30 -0
- package/dist/work-command.d.ts.map +1 -0
- package/dist/work-command.js +148 -0
- package/dist/work-command.js.map +1 -0
- package/dist/work-ledger-destination.d.ts +20 -0
- package/dist/work-ledger-destination.d.ts.map +1 -0
- package/dist/work-ledger-destination.js +131 -0
- package/dist/work-ledger-destination.js.map +1 -0
- package/dist/work-ledger-json.d.ts +25 -0
- package/dist/work-ledger-json.d.ts.map +1 -0
- package/dist/work-ledger-json.js +267 -0
- package/dist/work-ledger-json.js.map +1 -0
- package/dist/work-ledger-occurrences.d.ts +227 -0
- package/dist/work-ledger-occurrences.d.ts.map +1 -0
- package/dist/work-ledger-occurrences.js +115 -0
- package/dist/work-ledger-occurrences.js.map +1 -0
- package/dist/work-ledger-projection.d.ts +295 -0
- package/dist/work-ledger-projection.d.ts.map +1 -0
- package/dist/work-ledger-projection.js +237 -0
- package/dist/work-ledger-projection.js.map +1 -0
- package/dist/work-ledger-snapshot.d.ts +29 -0
- package/dist/work-ledger-snapshot.d.ts.map +1 -0
- package/dist/work-ledger-snapshot.js +267 -0
- package/dist/work-ledger-snapshot.js.map +1 -0
- package/dist/work-ledger-types.d.ts +261 -0
- package/dist/work-ledger-types.d.ts.map +1 -0
- package/dist/work-ledger-types.js +13 -0
- package/dist/work-ledger-types.js.map +1 -0
- package/dist/work-ledger-validation.d.ts +14 -0
- package/dist/work-ledger-validation.d.ts.map +1 -0
- package/dist/work-ledger-validation.js +226 -0
- package/dist/work-ledger-validation.js.map +1 -0
- package/dist/work-ledger.d.ts +43 -0
- package/dist/work-ledger.d.ts.map +1 -0
- package/dist/work-ledger.js +225 -0
- package/dist/work-ledger.js.map +1 -0
- package/extensions/daily-dashboard-session.ts +30 -0
- package/extensions/daily-work-session.ts +20 -0
- package/extensions/delegate-chain.ts +1 -0
- package/extensions/delegation-native.ts +12 -0
- package/extensions/delegation.ts +25 -11
- package/extensions/execute-child.ts +44 -5
- package/extensions/executor-session.ts +9 -0
- package/extensions/grants-command.ts +14 -15
- package/extensions/grants-connected-command.ts +19 -0
- package/extensions/grants.ts +26 -2
- package/extensions/ordinary-runtime.ts +14 -0
- package/extensions/primary-shadow.ts +11 -0
- package/extensions/run-delegation.ts +9 -7
- package/extensions/session.ts +10 -20
- package/extensions/work-runtime.ts +44 -0
- package/package.json +78 -4
- package/src/check-runner.ts +20 -2
- package/src/cli.ts +41 -4
- package/src/control-journal.ts +26 -0
- package/src/daily-dashboard-host.ts +49 -0
- package/src/daily-view-input.ts +59 -0
- package/src/daily-view-render.ts +44 -0
- package/src/daily-view.ts +152 -0
- package/src/dashboard-cli.ts +108 -4
- package/src/dashboard-harness.ts +37 -0
- package/src/dashboard-herdr.ts +7 -2
- package/src/dashboard-host-contract.ts +45 -0
- package/src/dashboard-host-transport.ts +40 -0
- package/src/dashboard-host.ts +191 -0
- package/src/dashboard-observation.ts +45 -0
- package/src/debrief-contract.ts +127 -0
- package/src/debrief-fixture.ts +29 -0
- package/src/debrief-host.ts +53 -0
- package/src/debrief-render.ts +49 -0
- package/src/debrief.ts +198 -0
- package/src/delegate-types.ts +2 -0
- package/src/delegate.ts +1 -0
- package/src/dispatch-control.ts +81 -0
- package/src/effect-profile-runtime.ts +46 -0
- package/src/effect-profile.ts +129 -0
- package/src/execution-retention.ts +230 -0
- package/src/experiment-contract.ts +66 -0
- package/src/experiment-state.ts +44 -0
- package/src/experiment-store.ts +98 -0
- package/src/experiment.ts +231 -0
- package/src/factory-contract.ts +47 -0
- package/src/factory-migration.ts +29 -0
- package/src/factory-order.ts +56 -0
- package/src/factory-registry.ts +60 -0
- package/src/file-lock.ts +47 -11
- package/src/herdr-poll.ts +18 -0
- package/src/index.ts +32 -0
- package/src/intent-application.ts +90 -0
- package/src/intent-control.ts +107 -0
- package/src/intent-scheduling.ts +14 -0
- package/src/ledger-append.ts +72 -0
- package/src/ledger.ts +3 -9
- package/src/native-session-target.ts +23 -0
- package/src/native-session.ts +139 -0
- package/src/order-schedule.ts +42 -0
- package/src/ordinary-children.ts +59 -0
- package/src/producer-ipc-contract.ts +26 -0
- package/src/producer-ipc.ts +107 -0
- package/src/resource-budget.ts +349 -0
- package/src/retention-contract.ts +84 -0
- package/src/retention-json.ts +20 -0
- package/src/run-child.ts +13 -2
- package/src/run-herdr.ts +11 -7
- package/src/vendor/adoption.ts +109 -0
- package/src/work-command.ts +179 -0
- package/src/work-ledger-destination.ts +113 -0
- package/src/work-ledger-json.ts +228 -0
- package/src/work-ledger-occurrences.ts +99 -0
- package/src/work-ledger-projection.ts +262 -0
- package/src/work-ledger-snapshot.ts +246 -0
- package/src/work-ledger-types.ts +229 -0
- package/src/work-ledger-validation.ts +174 -0
- package/src/work-ledger.ts +186 -0
package/extensions/delegation.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { isCriticalAssuranceBlock, type DelegationOutcome } from "./execute-chil
|
|
|
29
29
|
import { type GrantsSession } from "./session.ts";
|
|
30
30
|
import { newDelegationOccurrence } from "./execution-occurrence.ts";
|
|
31
31
|
import { correlationShape as buildCorrelationShape } from "./correlation-shape.ts";
|
|
32
|
+
import { completePrimary } from "./primary-shadow.ts";
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* Wire a set of children to pi's partial-result channel — ADR-0032.
|
|
@@ -171,11 +172,16 @@ export function registerDelegationTools(pi: ExtensionAPI, session: GrantsSession
|
|
|
171
172
|
access: Type.Union([Type.Literal("read"), Type.Literal("write")]),
|
|
172
173
|
});
|
|
173
174
|
|
|
175
|
+
const thinkingShape = Type.Optional(Type.Union(
|
|
176
|
+
["off", "minimal", "low", "medium", "high", "xhigh", "max"].map(level => Type.Literal(level)),
|
|
177
|
+
{ description: "Requested Pi thinking level; unsupported model/level combinations fail in the child." },
|
|
178
|
+
));
|
|
174
179
|
const childShape = Type.Object({
|
|
175
180
|
task: Type.String({ description: "The task for this sub-agent. It receives only this." }),
|
|
176
181
|
agent: Type.Optional(Type.String({ description: describeAgent(spawnable()) })),
|
|
177
182
|
tools: Type.Optional(Type.Array(Type.String(), { description: "Capabilities, when no 'agent' fits." })),
|
|
178
183
|
model: Type.Optional(Type.String({ description: "Model as provider/id. Defaults to this session's." })),
|
|
184
|
+
thinking: thinkingShape,
|
|
179
185
|
correlation: Type.Optional(correlationShape),
|
|
180
186
|
workspace: Type.Optional(workspaceShape),
|
|
181
187
|
});
|
|
@@ -186,6 +192,8 @@ export function registerDelegationTools(pi: ExtensionAPI, session: GrantsSession
|
|
|
186
192
|
maxItems: MAX_CHILDREN_PER_CALL,
|
|
187
193
|
description: "The sub-agents to run concurrently. Each is independent and unaware of the others.",
|
|
188
194
|
}),
|
|
195
|
+
completion: Type.Optional(Type.Literal("primary", {description:"Return when the selected primary settles; shadows continue under the original owner."})),
|
|
196
|
+
primary: Type.Optional(Type.Integer({minimum:1,maximum:MAX_CHILDREN_PER_CALL,description:"1-based primary child; required with completion=primary."})),
|
|
189
197
|
});
|
|
190
198
|
|
|
191
199
|
const delegateParams = Type.Object({
|
|
@@ -207,6 +215,7 @@ export function registerDelegationTools(pi: ExtensionAPI, session: GrantsSession
|
|
|
207
215
|
"Defaults to this session's model, already provider-qualified.",
|
|
208
216
|
}),
|
|
209
217
|
),
|
|
218
|
+
thinking: thinkingShape,
|
|
210
219
|
correlation: Type.Optional(correlationShape),
|
|
211
220
|
workspace: Type.Optional(workspaceShape),
|
|
212
221
|
});
|
|
@@ -231,6 +240,7 @@ export function registerDelegationTools(pi: ExtensionAPI, session: GrantsSession
|
|
|
231
240
|
agent: params.agent,
|
|
232
241
|
tools: params.tools,
|
|
233
242
|
model: params.model,
|
|
243
|
+
thinking: params.thinking,
|
|
234
244
|
correlation: params.correlation,
|
|
235
245
|
workspace: params.workspace,
|
|
236
246
|
},
|
|
@@ -241,7 +251,7 @@ export function registerDelegationTools(pi: ExtensionAPI, session: GrantsSession
|
|
|
241
251
|
session.fanoutBudget,
|
|
242
252
|
ctx,
|
|
243
253
|
signal,
|
|
244
|
-
{ onProgress: progress.sink(0) },
|
|
254
|
+
{ onProgress: progress.sink(0), toolCallId: _toolCallId },
|
|
245
255
|
);
|
|
246
256
|
progress.settle([outcome]);
|
|
247
257
|
|
|
@@ -259,7 +269,7 @@ export function registerDelegationTools(pi: ExtensionAPI, session: GrantsSession
|
|
|
259
269
|
|
|
260
270
|
return {
|
|
261
271
|
content: [{ type: "text", text: outcome.text || "(no output)" }],
|
|
262
|
-
details: { granted: outcome.granted, depth: outcome.depth, exitCode: outcome.exitCode },
|
|
272
|
+
details: { granted: outcome.granted, depth: outcome.depth, exitCode: outcome.exitCode, retention: outcome.retention },
|
|
263
273
|
};
|
|
264
274
|
},
|
|
265
275
|
});
|
|
@@ -288,10 +298,13 @@ export function registerDelegationTools(pi: ExtensionAPI, session: GrantsSession
|
|
|
288
298
|
`At most ${MAX_CHILDREN_PER_CALL} children per call, and a session-wide budget bounds the total ` +
|
|
289
299
|
"across the whole delegation subtree. Children cannot see each other or share context. Use this " +
|
|
290
300
|
"when independent tasks can proceed in parallel — several reviewers over one diff, say — and read " +
|
|
291
|
-
"every child's outcome, because one can be refused while the others succeed."
|
|
301
|
+
"every child's outcome, because one can be refused while the others succeed. For independent variants, " +
|
|
302
|
+
"completion=primary with a 1-based primary returns that result while shadows remain owned/accounted.",
|
|
292
303
|
parameters: delegateAllParams,
|
|
293
304
|
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
294
|
-
const children = params.children ?? [];
|
|
305
|
+
const children = params.children ?? [],primaryMode=params.completion==="primary";
|
|
306
|
+
if(primaryMode!==Number.isInteger(params.primary)||primaryMode&&(params.primary!<1||params.primary!>children.length))throw new GovernanceRefusal(refusal("FANOUT_EXCEEDED","primary fan-out requires one in-range 1-based primary"));
|
|
307
|
+
if(primaryMode&&session.variantRuns.size>=128)throw new GovernanceRefusal(refusal("FANOUT_EXCEEDED","primary/shadow accounting capacity exhausted"));
|
|
295
308
|
const split = splitBudget(session.fanoutBudget, children.length);
|
|
296
309
|
if (!split.ok) {
|
|
297
310
|
// Thrown, not returned: a returned `isError` is discarded by pi, so a refusal that came back as a
|
|
@@ -310,21 +323,21 @@ export function registerDelegationTools(pi: ExtensionAPI, session: GrantsSession
|
|
|
310
323
|
// live and its writer lease is deliberately retained" — a resource-retention notice, not a per-child
|
|
311
324
|
// failure. Losing it meant nobody was told a lease is held with no owner until the process exits
|
|
312
325
|
// (R-116).
|
|
313
|
-
const infrastructureErrors: unknown[] = [];
|
|
314
|
-
const
|
|
315
|
-
children.map(async (child, index): Promise<DelegationOutcome> => {
|
|
326
|
+
const infrastructureErrors: unknown[] = [],occurrences=children.map((_,index)=>newDelegationOccurrence(session,index));
|
|
327
|
+
const pending = children.map(async (child, index): Promise<DelegationOutcome> => {
|
|
316
328
|
try {
|
|
317
329
|
return await runOneDelegation(
|
|
318
330
|
session, child,
|
|
319
|
-
|
|
320
|
-
split.perChild, ctx, signal, { onProgress: progress.sink(index) },
|
|
331
|
+
occurrences[index],
|
|
332
|
+
split.perChild, ctx, signal, { onProgress: progress.sink(index), toolCallId: _toolCallId },
|
|
321
333
|
);
|
|
322
334
|
} catch (error) {
|
|
323
335
|
infrastructureErrors.push(error);
|
|
324
336
|
return childFailureOutcome(error, session.depth + 1);
|
|
325
337
|
}
|
|
326
|
-
})
|
|
327
|
-
);
|
|
338
|
+
});
|
|
339
|
+
if(primaryMode){const completed=await completePrimary({session,primaryIndex:params.primary!-1,occurrences,pending,settle:progress.settle}),primary=completed.primary;if(!primary.ok){if(isCriticalAssuranceBlock(primary))throw new Error(primary.text);throw totalFanoutFailure([primary],`primary child failed: ${primary.reason}`);}return {content:[{type:"text",text:primary.text||"(no output)"}],details:{primary:params.primary,shadows:children.length-1,primaryExecutionId:completed.runId,shadowSettlement:"retained-by-original-owner",granted:primary.granted,retention:primary.retention}};}
|
|
340
|
+
const outcomes=await Promise.all(pending);
|
|
328
341
|
progress.settle(outcomes);
|
|
329
342
|
// The upstream controller's verdict outranks our own infrastructure noise — it is the answer the
|
|
330
343
|
// caller is waiting for, and ADR-0034 requires it to pass through unchanged. But an infrastructure
|
|
@@ -353,6 +366,7 @@ export function registerDelegationTools(pi: ExtensionAPI, session: GrantsSession
|
|
|
353
366
|
budgetPerChild: split.perChild,
|
|
354
367
|
granted: outcomes.map((o) => o.granted),
|
|
355
368
|
refusals: outcomes.map((o) => o.refusal ?? null),
|
|
369
|
+
retention: outcomes.map((o) => o.retention ?? null),
|
|
356
370
|
},
|
|
357
371
|
};
|
|
358
372
|
},
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { withOrdinaryChild } from "./ordinary-runtime.ts";
|
|
1
2
|
import type { Delegation } from "../src/delegate.ts";
|
|
3
|
+
import { beginExecutionRetention, retentionConfigurationDigest, type RetentionStatus } from "../src/execution-retention.ts";
|
|
2
4
|
import { appendLedgerEvent, buildChildLifecycleEvent } from "../src/ledger.ts";
|
|
3
5
|
import { hasFinalizerError } from "../src/finalization.ts";
|
|
4
6
|
import { mergeChildEnv } from "../src/propagation.ts";
|
|
@@ -9,6 +11,7 @@ import { HerdrWriterCloseError, runHerdrPane } from "../src/run-herdr.ts";
|
|
|
9
11
|
import { GovernanceRefusal, refusal, type StructuredRefusal } from "../src/refusals.ts";
|
|
10
12
|
import { ENV_HERDR_KEEP_PANE, type GrantsSession } from "./session.ts";
|
|
11
13
|
import { releaseDelegationWorkspace, type PreparedWorkspace } from "./workspace-runtime.ts";
|
|
14
|
+
import { beginDeclaredWorkAttempt } from "./work-runtime.ts";
|
|
12
15
|
|
|
13
16
|
export interface DelegationOutcome {
|
|
14
17
|
ok: boolean;
|
|
@@ -23,6 +26,9 @@ export interface DelegationOutcome {
|
|
|
23
26
|
aborted?: boolean;
|
|
24
27
|
truncated?: boolean;
|
|
25
28
|
spawnFailed?: boolean;
|
|
29
|
+
retention?: RetentionStatus;
|
|
30
|
+
/** A loud best-effort post-execution observation failure; execution ownership is still settled. */
|
|
31
|
+
control?: "failed";
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
/**
|
|
@@ -78,13 +84,17 @@ export interface ChildProgressUpdate {
|
|
|
78
84
|
* has already run, so failing closed there prevents nothing and used to discard completed work while
|
|
79
85
|
* blaming "ledger" (R-99). The failure is reported alongside the outcome instead of replacing it.
|
|
80
86
|
*/
|
|
81
|
-
export
|
|
87
|
+
export function executePlannedChild(input: Parameters<typeof executeChildBody>[0]): Promise<DelegationOutcome> {
|
|
88
|
+
return withOrdinaryChild(input, signal => executeChildBody({ ...input, signal }));
|
|
89
|
+
}
|
|
90
|
+
async function executeChildBody(input: {
|
|
82
91
|
session: GrantsSession;
|
|
83
92
|
plan: Delegation;
|
|
84
93
|
agent?: string;
|
|
85
94
|
childId: string;
|
|
86
95
|
executionId: string;
|
|
87
96
|
parentExecutionId: string | null;
|
|
97
|
+
toolCallId?: string;
|
|
88
98
|
cwd: string;
|
|
89
99
|
preparedWorkspace?: PreparedWorkspace;
|
|
90
100
|
signal?: AbortSignal;
|
|
@@ -117,6 +127,10 @@ export async function executePlannedChild(input: {
|
|
|
117
127
|
throw error;
|
|
118
128
|
}
|
|
119
129
|
}
|
|
130
|
+
const workAttempt = await beginDeclaredWorkAttempt({
|
|
131
|
+
session, plan, childId, executionId, parentExecutionId, toolCallId: input.toolCallId,
|
|
132
|
+
preparedWorkspace, configuredTimeoutMs, startedAt,
|
|
133
|
+
});
|
|
120
134
|
|
|
121
135
|
// The recorded deadline and executor timer are one fact. Waiting for the strict starting append consumes
|
|
122
136
|
// the budget; handing the child a fresh full timeout would leave it live after the dashboard truthfully
|
|
@@ -134,9 +148,16 @@ export async function executePlannedChild(input: {
|
|
|
134
148
|
const executionSignal = signal
|
|
135
149
|
? AbortSignal.any([signal, leaseAbort.signal])
|
|
136
150
|
: writerLease ? leaseAbort.signal : undefined;
|
|
151
|
+
const retention = beginExecutionRetention({ executionId, parentExecutionId, childId,
|
|
152
|
+
toolCallId: input.toolCallId ?? null, executor: session.executor.kind, taskDigest: plan.taskDigest,
|
|
153
|
+
definitionDigest: plan.definitionDigest?.sha256 ?? null,
|
|
154
|
+
configurationDigest: retentionConfigurationDigest({ args: plan.args, effective: plan.effective, timeoutMs: configuredTimeoutMs }),
|
|
155
|
+
workspaceId: preparedWorkspace?.workspace.workspaceId ?? null });
|
|
156
|
+
const sessionFlag = plan.args.indexOf("--session");
|
|
157
|
+
if (sessionFlag >= 0) retention.observeSession({ source: "pi-session-file", value: plan.args[sessionFlag + 1] });
|
|
137
158
|
let releaseReason = "failed";
|
|
138
159
|
let retainWriterLease = false;
|
|
139
|
-
let terminalAttempted = false;
|
|
160
|
+
let terminalAttempted = false, workTerminalAttempted = false;
|
|
140
161
|
const teardownFailures: string[] = [];
|
|
141
162
|
let runtimeRecord: Promise<void> | undefined;
|
|
142
163
|
const recordRunning = (executor: "process" | "herdr", pane?: { id: string; agentName: string }): void => {
|
|
@@ -171,7 +192,12 @@ export async function executePlannedChild(input: {
|
|
|
171
192
|
timeoutMs: remainingTimeoutMs,
|
|
172
193
|
keepPane: writerLease ? false : process.env[ENV_HERDR_KEEP_PANE] === "1",
|
|
173
194
|
closeOnSettle: Boolean(writerLease),
|
|
174
|
-
onPane: (paneId, agentName) =>
|
|
195
|
+
onPane: (paneId, agentName) => {
|
|
196
|
+
retention.native({ paneId, agentName });
|
|
197
|
+
onProgress?.({ paneId, agentName, state: "starting" });
|
|
198
|
+
},
|
|
199
|
+
onObservation: (bytes) => retention.capture("paneSnapshot", bytes, true),
|
|
200
|
+
onSessionReference: (reference) => retention.observeSession(reference),
|
|
175
201
|
onRunning: (paneId, agentName) => {
|
|
176
202
|
// Record first: runHerdrPane isolates this display callback, so a renderer exception after the
|
|
177
203
|
// observation cannot suppress the authoritative running event.
|
|
@@ -179,6 +205,7 @@ export async function executePlannedChild(input: {
|
|
|
179
205
|
onProgress?.({ paneId, agentName, state: "running" });
|
|
180
206
|
},
|
|
181
207
|
onTab: preparedWorkspace ? (tabId) => preparedWorkspace.lease.attachHerdrTab(tabId) : undefined,
|
|
208
|
+
onNativeTab: (tabId) => retention.native({ tabId }),
|
|
182
209
|
onSnapshot: onProgress ? (snapshot) => onProgress({ snapshot }) : undefined,
|
|
183
210
|
})
|
|
184
211
|
: await runChild({
|
|
@@ -192,18 +219,26 @@ export async function executePlannedChild(input: {
|
|
|
192
219
|
timeoutMs: Math.max(1, remainingTimeoutMs - terminationGraceMs),
|
|
193
220
|
hardDeadlineAt: Date.parse(deadlineAt),
|
|
194
221
|
onOutput: onProgress ? (chunk) => onProgress({ chunk }) : undefined,
|
|
222
|
+
onObservation: (stream, bytes) => retention.capture(stream, bytes),
|
|
195
223
|
onSpawn: (pid) => {
|
|
196
224
|
// Lease attachment is a security hook and may fail the spawn. The shared reporters isolate
|
|
197
225
|
// display exceptions before they reach this callback; runChild deliberately kills on any error
|
|
198
226
|
// here, so presentation must never be added directly without that reporter boundary.
|
|
199
227
|
preparedWorkspace?.lease.attachProcess(pid);
|
|
228
|
+
retention.native({ pid });
|
|
200
229
|
recordRunning("process");
|
|
201
230
|
onProgress?.({ state: "running" });
|
|
202
231
|
},
|
|
203
232
|
});
|
|
204
233
|
|
|
234
|
+
if (sessionFlag >= 0) retention.observeSession({ source: "pi-session-file", value: plan.args[sessionFlag + 1] });
|
|
235
|
+
retention.capture("result", Buffer.from(output.text), true);
|
|
205
236
|
const childFailed = Boolean(output.spawnError || output.aborted || output.timedOut || output.code !== 0);
|
|
237
|
+
retention.finish({ code: output.code, signal: output.signal ?? null, timedOut: output.timedOut,
|
|
238
|
+
aborted: output.aborted, truncated: output.truncated, failed: childFailed });
|
|
206
239
|
releaseReason = output.timedOut ? "timeout" : output.aborted ? "cancelled" : childFailed ? "failed" : "completed";
|
|
240
|
+
if (workAttempt) try { workTerminalAttempted = true; await workAttempt.finish(childFailed ? "failed" : "completed"); }
|
|
241
|
+
catch (error) { teardownFailures.push(`declared work terminal record failed: ${String(error)}`); }
|
|
207
242
|
if (ledgerPath) {
|
|
208
243
|
terminalAttempted = true;
|
|
209
244
|
await appendAfterRuntimeRecord(runtimeRecord, () => appendLedgerEvent(
|
|
@@ -286,6 +321,9 @@ export async function executePlannedChild(input: {
|
|
|
286
321
|
await teardown();
|
|
287
322
|
return withTeardownNotes(succeeded);
|
|
288
323
|
} catch (error) {
|
|
324
|
+
retention.finish({ code: null, signal: null, timedOut: false, aborted: Boolean(signal?.aborted), truncated: false, failed: true });
|
|
325
|
+
if (workAttempt && !workTerminalAttempted) try { workTerminalAttempted = true; await workAttempt.finish("failed"); }
|
|
326
|
+
catch (cause) { teardownFailures.push(`declared work terminal record failed: ${String(cause)}`); }
|
|
289
327
|
retainWriterLease = Boolean(writerLease && isHerdrWriterCloseFailure(error));
|
|
290
328
|
if (ledgerPath && !terminalAttempted) {
|
|
291
329
|
// Best-effort: this records the failure, so it must not REPLACE the failure. A strict append that
|
|
@@ -338,8 +376,9 @@ function errorWithTeardownNotes(error: unknown, notes: readonly string[]): unkno
|
|
|
338
376
|
}
|
|
339
377
|
|
|
340
378
|
function withTeardownNotes(outcome: DelegationOutcome): DelegationOutcome {
|
|
341
|
-
|
|
342
|
-
|
|
379
|
+
const observed = { ...outcome, retention: retention.status() };
|
|
380
|
+
if (teardownFailures.length === 0) return observed;
|
|
381
|
+
return { ...observed, control: "failed", reason: [outcome.reason, ...teardownFailures].filter(Boolean).join("; ") };
|
|
343
382
|
}
|
|
344
383
|
|
|
345
384
|
async function teardown(): Promise<void> {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { chooseExecutor, needsProbe, ENV_HERDR } from "../src/executor.ts";
|
|
2
|
+
import { probeHerdr } from "../src/herdr-cli.ts";
|
|
3
|
+
import type { GrantsSession } from "./session.ts";
|
|
4
|
+
|
|
5
|
+
/** Settle one executor at session start; a later daemon change never relocates siblings. */
|
|
6
|
+
export async function resolveExecutor(session:GrantsSession):Promise<void>{
|
|
7
|
+
const raw=process.env[ENV_HERDR];
|
|
8
|
+
session.executor=chooseExecutor(raw,needsProbe(raw)?await probeHerdr():null);
|
|
9
|
+
}
|
|
@@ -17,6 +17,8 @@ import type { ExecutorChoice } from "../src/executor.ts";
|
|
|
17
17
|
import type { Catalog } from "../src/catalog.ts";
|
|
18
18
|
import type { SkillDefinition } from "../src/definitions.ts";
|
|
19
19
|
import type { GatedPlan } from "./run-delegation.ts";
|
|
20
|
+
import type { VariantRunAccounting } from "./session.ts";
|
|
21
|
+
import { handleConnectedCommand } from "./grants-connected-command.ts";
|
|
20
22
|
import { loadApprovals, revokeAll, revokeApproval, type SubjectLookup } from "../src/approval-store.ts";
|
|
21
23
|
import { verifyLedger } from "../src/ledger.ts";
|
|
22
24
|
|
|
@@ -62,6 +64,9 @@ export interface GrantsCommandContext {
|
|
|
62
64
|
runInit: () => Promise<void>;
|
|
63
65
|
/** Open or reuse the read-only Herdr dashboard; injected so this diagnostic never becomes enforcement. */
|
|
64
66
|
openDashboard: () => Promise<{ kind: "opened" | "reused"; paneId: string; visibleBesideCaller: boolean }>;
|
|
67
|
+
/** Explicit same-process production host lifecycle; owns no model call and never cancels a child on stop. */
|
|
68
|
+
runHost: (target: string) => Promise<string>;
|
|
69
|
+
variantRuns: Map<string, VariantRunAccounting>;
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
/**
|
|
@@ -71,18 +76,18 @@ export interface GrantsCommandContext {
|
|
|
71
76
|
const PREVIEW_LIMIT = 12;
|
|
72
77
|
|
|
73
78
|
/** The verbs `/grants` answers to. Anything else is refused rather than silently treated as no verb. */
|
|
74
|
-
const KNOWN_SUBCOMMANDS: readonly string[] = ["init", "dashboard", "ledger", "approvals", "revoke"];
|
|
79
|
+
const KNOWN_SUBCOMMANDS: readonly string[] = ["init", "host", "variants", "dashboard", "ledger", "approvals", "revoke"];
|
|
75
80
|
|
|
76
81
|
export const grantsCommand = {
|
|
77
82
|
description:
|
|
78
83
|
"Show this session's capability grant, delegation depth, and known agent-type ceilings; " +
|
|
79
|
-
"/grants dashboard | /grants approvals | /grants ledger | /grants revoke <key>|--all",
|
|
84
|
+
"/grants host <fresh-id>|stop | /grants variants | /grants dashboard | /grants approvals | /grants ledger | /grants revoke <key>|--all",
|
|
80
85
|
handler: async (args: string, ctx: any) => {
|
|
81
86
|
// Everything this command may see, named in one place. Previously these were whatever happened to be in
|
|
82
87
|
// the enclosing closure — which is how a diagnostic came to disagree with the enforcer (R-28).
|
|
83
88
|
const {
|
|
84
89
|
cwd, governed, ownGrant, executor, observed, depth, maxDepth, ledgerPath,
|
|
85
|
-
catalog, definitions, sessionApprovals, inheritedApprovals, snapshotOf, previewDelegation,
|
|
90
|
+
catalog, definitions, sessionApprovals, inheritedApprovals, snapshotOf, previewDelegation, variantRuns,
|
|
86
91
|
} = ctx.grants as GrantsCommandContext;
|
|
87
92
|
|
|
88
93
|
const [sub, target] = args.trim().split(/\s+/).filter(Boolean);
|
|
@@ -92,18 +97,12 @@ handler: async (args: string, ctx: any) => {
|
|
|
92
97
|
return;
|
|
93
98
|
}
|
|
94
99
|
|
|
95
|
-
if (sub
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
"info",
|
|
102
|
-
);
|
|
103
|
-
} catch (error) {
|
|
104
|
-
ctx.ui.notify(`grants: dashboard unavailable — ${error instanceof Error ? error.message : String(error)}`, "error");
|
|
105
|
-
}
|
|
106
|
-
return;
|
|
100
|
+
if(await handleConnectedCommand(sub,target,{runHost:ctx.grants.runHost,openDashboard:ctx.grants.openDashboard,ui:ctx.ui}))return;
|
|
101
|
+
|
|
102
|
+
if (sub === "variants") {
|
|
103
|
+
const lines=[`grants: ${variantRuns.size} retained primary/shadow run(s)`];
|
|
104
|
+
for(const run of variantRuns.values())lines.push(` ${run.runId} ${run.state} — primary ${run.primaryExecutionId}; ${run.shadowExecutionIds.length} shadow(s)`+(!run.outcomes?"":` — ${run.outcomes.map(x=>`${x.role}:${x.ok?"completed":"failed"}`).join(", ")}`));
|
|
105
|
+
ctx.ui.notify(lines.join("\n"),"info");return;
|
|
107
106
|
}
|
|
108
107
|
|
|
109
108
|
if (sub === "ledger") {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface GrantsConnectedCommandContext {
|
|
2
|
+
runHost:(target:string)=>Promise<string>;
|
|
3
|
+
openDashboard:()=>Promise<{kind:"opened"|"reused";paneId:string;visibleBesideCaller:boolean}>;
|
|
4
|
+
ui:{notify(message:string,level:"info"|"error"):void};
|
|
5
|
+
}
|
|
6
|
+
/** Host lifecycle and pane placement live together; neither belongs in the capability-report renderer. */
|
|
7
|
+
export async function handleConnectedCommand(sub:string|undefined,target:string|undefined,ctx:GrantsConnectedCommandContext):Promise<boolean>{
|
|
8
|
+
if(sub==="host"){
|
|
9
|
+
try{ctx.ui.notify(`grants: ${await ctx.runHost(target??"")}`,"info");}
|
|
10
|
+
catch(error){ctx.ui.notify(`grants: host unavailable — ${error instanceof Error?error.message:String(error)}`,"error");}
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
if(sub==="dashboard"){
|
|
14
|
+
try{const opened=await ctx.openDashboard();ctx.ui.notify(`grants: dashboard ${opened.kind} in Herdr pane ${opened.paneId} without changing focus`+(opened.visibleBesideCaller?".":" (the existing pane is in another tab)."),"info");}
|
|
15
|
+
catch(error){ctx.ui.notify(`grants: dashboard unavailable — ${error instanceof Error?error.message:String(error)}`,"error");}
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
package/extensions/grants.ts
CHANGED
|
@@ -37,7 +37,8 @@ import { registerDelegationTools } from "./delegation.ts";
|
|
|
37
37
|
import { grantsCommand } from "./grants-command.ts";
|
|
38
38
|
import { runInit } from "./init-command.ts";
|
|
39
39
|
import { planWithApprovals } from "./run-delegation.ts";
|
|
40
|
-
import { createGrantsSession, loadProjectDefinitions,
|
|
40
|
+
import { createGrantsSession, loadProjectDefinitions, type GrantsSession } from "./session.ts";
|
|
41
|
+
import { resolveExecutor } from "./executor-session.ts";
|
|
41
42
|
import { reportSessionStart } from "./session-report.ts";
|
|
42
43
|
import { SPAWN_TOOLS, tripwireReason } from "./tripwire.ts";
|
|
43
44
|
import { reportGrantStoreRefusal } from "./grant-store-refusal.ts";
|
|
@@ -47,6 +48,10 @@ import {
|
|
|
47
48
|
openDashboardCommand,
|
|
48
49
|
} from "../src/dashboard-handshake.ts";
|
|
49
50
|
|
|
51
|
+
import { associateOrdinaryHost, ordinaryChildrenFor } from "../src/ordinary-children.ts";
|
|
52
|
+
import { loadDeclaredWork } from "../src/work-command.ts";
|
|
53
|
+
import { createDailyDashboardSession } from "./daily-dashboard-session.ts";
|
|
54
|
+
import { replacePublishedDailyWork, type PublishedDailyWork } from "./daily-work-session.ts";
|
|
50
55
|
export default function (pi: ExtensionAPI) {
|
|
51
56
|
// The path pi loads as the extension, so a child granted `tool:delegate` can be started with `-e <this>`.
|
|
52
57
|
// Only this file can say so about itself, which is why the session takes it rather than deriving it.
|
|
@@ -59,6 +64,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
59
64
|
})();
|
|
60
65
|
|
|
61
66
|
const session = createGrantsSession(extensionPath);
|
|
67
|
+
associateOrdinaryHost(pi,session);
|
|
68
|
+
const dailyHost=createDailyDashboardSession({ordinary:()=>ordinaryChildrenFor(pi),declared:()=>session.declaredWork,cwd:()=>session.cwd,env:process.env,author:"local-operator"});
|
|
62
69
|
const dashboardPluginRoot = fileURLToPath(new URL("../herdr-plugin/", import.meta.url));
|
|
63
70
|
const dashboardPaths = defaultDashboardPaths(
|
|
64
71
|
process.env.PI_CODING_AGENT_DIR?.trim() || join(homedir(), ".pi", "agent"),
|
|
@@ -68,6 +75,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
68
75
|
// because the hooks below have to be registered before the tools and both need to call it — the tool
|
|
69
76
|
// schemas describe which definitions are spawnable, and nothing knows that until a hook has run (R-39).
|
|
70
77
|
const delegation = { refreshSpawnable: () => {} };
|
|
78
|
+
const publishedDailyWork: PublishedDailyWork = {};
|
|
71
79
|
|
|
72
80
|
pi.on("session_start", async (_event, ctx) => {
|
|
73
81
|
session.cwd = ctx.cwd;
|
|
@@ -75,6 +83,19 @@ export default function (pi: ExtensionAPI) {
|
|
|
75
83
|
// execution tree across workspaces. Resolve it once at the root's actual pi cwd; descendants inherit
|
|
76
84
|
// this absolute identity verbatim, and resolve(abs) remains abs at every deeper session start.
|
|
77
85
|
if (session.ledgerPath) session.ledgerPath = resolve(ctx.cwd, session.ledgerPath);
|
|
86
|
+
try {
|
|
87
|
+
try {
|
|
88
|
+
replacePublishedDailyWork(process.env, publishedDailyWork, undefined);
|
|
89
|
+
session.declaredWork = (await loadDeclaredWork(join(ctx.cwd, ".pi", "work-current.json"))) ?? undefined;
|
|
90
|
+
replacePublishedDailyWork(process.env, publishedDailyWork, session.declaredWork);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
session.declaredWork = undefined;
|
|
93
|
+
ctx.ui.notify(
|
|
94
|
+
`grants: declared work is invalid (${error instanceof Error ? error.message : String(error)}); ` +
|
|
95
|
+
`delegations remain unbound and no previous selection was substituted.`,
|
|
96
|
+
"error",
|
|
97
|
+
);
|
|
98
|
+
}
|
|
78
99
|
// The one case the stored-grant lookup can get wrong (ADR-0030). The factory reads the store keyed by
|
|
79
100
|
// `process.cwd()` because it runs before any hook and therefore before `ctx` exists — and S-5 forces
|
|
80
101
|
// that ordering, since whether `delegate` is registered is decided there. Almost always the two agree.
|
|
@@ -93,7 +114,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
93
114
|
"warning",
|
|
94
115
|
);
|
|
95
116
|
}
|
|
96
|
-
try {
|
|
97
117
|
try {
|
|
98
118
|
await reportGrantStoreRefusal(session, ctx.ui);
|
|
99
119
|
} catch (error) {
|
|
@@ -230,6 +250,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
230
250
|
* `exit` remains the backstop. SIGKILL still orphans panes, exactly as R-62 records, and no signal handler is
|
|
231
251
|
* installed here for the reason R-62 gives: it would turn pi's "interrupt this turn" into "exit pi".
|
|
232
252
|
*/
|
|
253
|
+
pi.on("session_shutdown", async () => { await dailyHost.close().catch(() => undefined); });
|
|
254
|
+
|
|
233
255
|
pi.on("agent_settled", async () => {
|
|
234
256
|
try {
|
|
235
257
|
if (session.executor.kind !== "herdr" || openPaneCount() === 0) return undefined;
|
|
@@ -348,6 +370,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
348
370
|
definitions: session.definitions,
|
|
349
371
|
sessionApprovals: session.sessionApprovals,
|
|
350
372
|
inheritedApprovals: session.inheritedApprovals,
|
|
373
|
+
variantRuns: session.variantRuns,
|
|
351
374
|
snapshotOf: (subject: string) => snapshotOf(session, subject),
|
|
352
375
|
// The REAL delegation path, minus the one thing a diagnostic must never do. `ctx: null` is what
|
|
353
376
|
// says so: stored approvals count exactly as they would for a spawn, and no human is asked
|
|
@@ -358,6 +381,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
358
381
|
await loadProjectDefinitions(session, ctx.cwd);
|
|
359
382
|
delegation.refreshSpawnable();
|
|
360
383
|
}),
|
|
384
|
+
runHost: (target: string) => dailyHost.run(target),
|
|
361
385
|
openDashboard: () => openDashboardCommand({
|
|
362
386
|
env: process.env,
|
|
363
387
|
pid: process.pid,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { retainSessionChild } from "../src/ordinary-children.ts";
|
|
2
|
+
import { dataDigest } from "../src/debrief-contract.ts";
|
|
3
|
+
import { runWithFinalizers } from "../src/finalization.ts";
|
|
4
|
+
import { releaseDelegationWorkspace,type PreparedWorkspace } from "./workspace-runtime.ts";
|
|
5
|
+
import type { GrantsSession } from "./session.ts";
|
|
6
|
+
import type { DelegationOutcome } from "./execute-child.ts";
|
|
7
|
+
/** One wrapper around the original executor. It neither consumes nor replaces the caller's promise. */
|
|
8
|
+
export async function withOrdinaryChild(input:{session:GrantsSession;executionId:string;parentExecutionId:string|null;childId:string;toolCallId?:string;signal?:AbortSignal;preparedWorkspace?:PreparedWorkspace},operation:(signal?:AbortSignal)=>Promise<DelegationOutcome>){
|
|
9
|
+
let retained:ReturnType<typeof retainSessionChild>;
|
|
10
|
+
try{retained=retainSessionChild(input.session,{executionId:input.executionId,parentExecutionId:input.parentExecutionId,toolCallId:input.toolCallId??null},input.signal);}
|
|
11
|
+
catch(error){return runWithFinalizers(async()=>{throw error;},[{label:"ordinary admission workspace release",run:async()=>{await releaseDelegationWorkspace({prepared:input.preparedWorkspace,childId:input.childId,executionId:input.executionId,parentExecutionId:input.parentExecutionId,ledgerPath:input.session.ledgerPath,reason:"refused"});}}]);}
|
|
12
|
+
try{const outcome=await operation(retained?.signal??input.signal);retained?.settle({ok:outcome.ok,exitCode:outcome.exitCode,aborted:outcome.aborted??false,outputDigest:dataDigest(outcome.text)},outcome.control??"not-assessed",outcome.control==="failed"?"not-assessed":outcome.control??"not-assessed");return outcome;}
|
|
13
|
+
catch(error){retained?.settle({failure:"original executor threw; inspect original caller"},"unknown");throw error;}
|
|
14
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DelegationOutcome } from "./execute-child.ts";
|
|
2
|
+
import type { ExecutionOccurrenceIds } from "./execution-occurrence.ts";
|
|
3
|
+
import type { GrantsSession, VariantRunAccounting } from "./session.ts";
|
|
4
|
+
|
|
5
|
+
/** Return one primary while the original session retains and settles every shadow outcome. */
|
|
6
|
+
export async function completePrimary(input:{session:GrantsSession;primaryIndex:number;occurrences:ExecutionOccurrenceIds[];pending:Promise<DelegationOutcome>[];settle:(outcomes:{ok:boolean}[])=>void}){
|
|
7
|
+
const runId=input.occurrences[input.primaryIndex].executionId,record:VariantRunAccounting={runId,primaryExecutionId:runId,shadowExecutionIds:input.occurrences.filter((_,i)=>i!==input.primaryIndex).map(x=>x.executionId),state:"running",outcomes:null};
|
|
8
|
+
input.session.variantRuns.set(runId,record);
|
|
9
|
+
void Promise.all(input.pending).then(outcomes=>{record.outcomes=outcomes.map((outcome,index)=>({executionId:input.occurrences[index].executionId,role:index===input.primaryIndex?"primary":"shadow",ok:outcome.ok,reason:outcome.ok?null:outcome.reason??"failed"}));record.state="settled";input.settle(outcomes);});
|
|
10
|
+
return {runId,primary:await input.pending[input.primaryIndex]};
|
|
11
|
+
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* tool surface is observed.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
import { nativeDelegationContext } from "./delegation-native.ts";
|
|
14
15
|
import { DELEGATE_SUBJECT, shouldSeekApproval } from "../src/approval.ts";
|
|
15
16
|
import { planDelegation } from "../src/delegate.ts";
|
|
16
17
|
import {
|
|
@@ -43,6 +44,7 @@ interface ChildSpec {
|
|
|
43
44
|
agent?: string;
|
|
44
45
|
tools?: string[];
|
|
45
46
|
model?: string;
|
|
47
|
+
thinking?: string;
|
|
46
48
|
correlation?: CorrelationMetadata;
|
|
47
49
|
workspace?: DelegationWorkspaceSpec;
|
|
48
50
|
}
|
|
@@ -201,6 +203,8 @@ export async function runOneDelegation(
|
|
|
201
203
|
* mistake unspellable.
|
|
202
204
|
*/
|
|
203
205
|
options: {
|
|
206
|
+
/** Actual public execute argument, never read from model-authored correlation or output. */
|
|
207
|
+
toolCallId?: string;
|
|
204
208
|
/** Progress for the parent's status block (ADR-0032). Display only. */
|
|
205
209
|
onProgress?: (update: {
|
|
206
210
|
/** Appended (process executor: a genuine byte stream). */
|
|
@@ -245,6 +249,7 @@ export async function runOneDelegation(
|
|
|
245
249
|
agent: spec.agent,
|
|
246
250
|
tools: spec.tools,
|
|
247
251
|
model: spec.model ?? defaultModel,
|
|
252
|
+
thinking: spec.thinking,
|
|
248
253
|
correlation: spec.workspace
|
|
249
254
|
? { ...(spec.correlation ?? {}), workspace_id: spec.workspace.workspace_id }
|
|
250
255
|
: spec.correlation,
|
|
@@ -254,12 +259,6 @@ export async function runOneDelegation(
|
|
|
254
259
|
boundWorkspaceId: spec.workspace?.workspace_id,
|
|
255
260
|
boundContextId: spec.correlation?.context_id,
|
|
256
261
|
};
|
|
257
|
-
const extra = {
|
|
258
|
-
fanoutBudget: budget,
|
|
259
|
-
spawnId: ids.parentId,
|
|
260
|
-
childSpawnId: ids.childId,
|
|
261
|
-
childExecutionId: ids.executionId,
|
|
262
|
-
};
|
|
263
262
|
|
|
264
263
|
// ADR-0031: herdr was DEMANDED (`PI_GRANTS_HERDR=1`) and is not answering. Refused rather than relocated —
|
|
265
264
|
// the operator chose that over falling back, so the ledger can never name a child that ran somewhere nobody
|
|
@@ -275,13 +274,15 @@ export async function runOneDelegation(
|
|
|
275
274
|
// `ctx: null` rather than skipping the plan entirely: the ledger still gets a full, honest record of what was
|
|
276
275
|
// requested and refused, and stored approvals still count toward it — nothing is *hidden*, only nobody is
|
|
277
276
|
// *asked*. It is the same argument `/grants` uses for its preview.
|
|
278
|
-
|
|
277
|
+
let executorRefusal = session.executor.refusal;
|
|
279
278
|
const modelRefusal = preflightModel(
|
|
280
279
|
request.model,
|
|
281
280
|
ctx.modelRegistry,
|
|
282
281
|
session.modelResolutionCache,
|
|
283
282
|
session.allowUnresolvedModels,
|
|
284
283
|
);
|
|
284
|
+
const {extra,refusal:nativeRefusal}=await nativeDelegationContext(session,ids,budget,Boolean(executorRefusal||modelRefusal));
|
|
285
|
+
executorRefusal ||= nativeRefusal;
|
|
285
286
|
let preparedWorkspace: PreparedWorkspace | undefined;
|
|
286
287
|
let approvalOutcome: ApprovalOutcome | undefined;
|
|
287
288
|
let plan: ReturnType<typeof planDelegation>;
|
|
@@ -388,6 +389,7 @@ export async function runOneDelegation(
|
|
|
388
389
|
childId: ids.childId,
|
|
389
390
|
executionId: ids.executionId,
|
|
390
391
|
parentExecutionId: ids.parentExecutionId,
|
|
392
|
+
toolCallId: options.toolCallId,
|
|
391
393
|
cwd: ctx.cwd,
|
|
392
394
|
preparedWorkspace,
|
|
393
395
|
signal,
|
package/extensions/session.ts
CHANGED
|
@@ -21,8 +21,7 @@ import { makeCatalog, skillPathsFromCatalog, type Catalog } from "../src/catalog
|
|
|
21
21
|
import type { SkillDefinition } from "../src/definitions.ts";
|
|
22
22
|
import { DELEGATE_CAPABILITY, type DelegationContext } from "../src/delegate.ts";
|
|
23
23
|
import { budgetFromEnv } from "../src/fanout.ts";
|
|
24
|
-
import { chooseExecutor,
|
|
25
|
-
import { probeHerdr } from "../src/herdr-cli.ts";
|
|
24
|
+
import { chooseExecutor, ENV_HERDR, type ExecutorChoice } from "../src/executor.ts";
|
|
26
25
|
import { WILDCARD } from "../src/pi-tools.ts";
|
|
27
26
|
import {
|
|
28
27
|
childEnv,
|
|
@@ -47,8 +46,9 @@ import { ENV_WORKSPACE_REGISTRY } from "../src/workspace.ts";
|
|
|
47
46
|
import type { GrantStoreRefusalReason } from "../src/grant-store.ts";
|
|
48
47
|
import { republishable } from "./approvals.ts";
|
|
49
48
|
import { storedGrantSessionState } from "./stored-grant-session.ts";
|
|
49
|
+
import { nativeSessionRootFromEnv, type NativeSessionHost } from "../src/native-session-target.ts";
|
|
50
50
|
import { ENV_ALLOW_UNRESOLVED_MODELS } from "../src/model-preflight.ts";
|
|
51
|
-
|
|
51
|
+
import type { DeclaredWorkState } from "../src/work-command.ts";
|
|
52
52
|
/**
|
|
53
53
|
* Run governed children in herdr panes instead of captured child processes.
|
|
54
54
|
*
|
|
@@ -79,7 +79,8 @@ export { ENV_HERDR_WORKSPACE } from "../src/herdr-cli.ts";
|
|
|
79
79
|
/** Keep each child's pane after it finishes, for inspection. Off by default: fan-out would flood it. */
|
|
80
80
|
export const ENV_HERDR_KEEP_PANE = "PI_GRANTS_HERDR_KEEP_PANE";
|
|
81
81
|
|
|
82
|
-
export interface
|
|
82
|
+
export interface VariantRunAccounting {runId:string;primaryExecutionId:string;shadowExecutionIds:string[];state:"running"|"settled";outcomes:null|{executionId:string;role:"primary"|"shadow";ok:boolean;reason:string|null}[]}
|
|
83
|
+
export interface GrantsSession extends NativeSessionHost {
|
|
83
84
|
/**
|
|
84
85
|
* False when neither `PI_GRANTS_GRANT` nor a stored grant applies: the session holds the wildcard and
|
|
85
86
|
* nothing is governed.
|
|
@@ -126,6 +127,9 @@ export interface GrantsSession {
|
|
|
126
127
|
readonly modelResolutionCache: Map<string, boolean>;
|
|
127
128
|
/** Path to this extension, so a child granted `tool:delegate` can delegate in turn. */
|
|
128
129
|
readonly extensionPath?: string;
|
|
130
|
+
declaredWork?: DeclaredWorkState; // Explicit operator selection; absence leaves execution visibly unbound.
|
|
131
|
+
/** Primary-return fan-outs retained by this original session; bounded and human-readable via /grants variants. */
|
|
132
|
+
readonly variantRuns: Map<string, VariantRunAccounting>;
|
|
129
133
|
|
|
130
134
|
/** Approval keys approved for this session. In memory only — this dies with the process. */
|
|
131
135
|
readonly sessionApprovals: Set<string>;
|
|
@@ -234,22 +238,6 @@ export async function loadProjectDefinitions(session: GrantsSession, cwd: string
|
|
|
234
238
|
session.catalog = await session.catalogReady;
|
|
235
239
|
}
|
|
236
240
|
|
|
237
|
-
/**
|
|
238
|
-
* Probe for herdr and settle this session's executor — ADR-0031.
|
|
239
|
-
*
|
|
240
|
-
* **Once, at session start, and never per spawn.** A fan-out whose children ran under two executors would put
|
|
241
|
-
* two different things under one call in the ledger, and the two plans differ (`--print` is withheld on the
|
|
242
|
-
* herdr path). A herdr server that dies mid-session therefore surfaces as a failed `tab create`, reported as
|
|
243
|
-
* the spawn error it is, rather than as a silent relocation of the remaining children.
|
|
244
|
-
*
|
|
245
|
-
* `probeHerdr` never throws, so this cannot either — which matters because it runs *before* the line that
|
|
246
|
-
* discloses what it decided (R-60: a throw here would cancel that line and every control after it).
|
|
247
|
-
*/
|
|
248
|
-
export async function resolveExecutor(session: GrantsSession): Promise<void> {
|
|
249
|
-
const raw = process.env[ENV_HERDR];
|
|
250
|
-
session.executor = chooseExecutor(raw, needsProbe(raw) ? await probeHerdr() : null);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
241
|
export function createGrantsSession(extensionPath: string | undefined): GrantsSession {
|
|
254
242
|
// Governance is opt-in: with PI_GRANTS_GRANT unset AND no stored grant for this directory, the session
|
|
255
243
|
// holds the wildcard and nothing is blocked. This extension must never silently tighten a normal
|
|
@@ -318,8 +306,10 @@ export function createGrantsSession(extensionPath: string | undefined): GrantsSe
|
|
|
318
306
|
*/
|
|
319
307
|
mayDelegate: !governed || inherited.includes(DELEGATE_CAPABILITY) || inherited.includes(WILDCARD),
|
|
320
308
|
allowUnresolvedModels: process.env[ENV_ALLOW_UNRESOLVED_MODELS] === "1",
|
|
309
|
+
nativeSessionRoot: nativeSessionRootFromEnv(process.env),
|
|
321
310
|
modelResolutionCache: new Map<string, boolean>(),
|
|
322
311
|
extensionPath,
|
|
312
|
+
variantRuns: new Map(),
|
|
323
313
|
|
|
324
314
|
sessionApprovals: new Set<string>(),
|
|
325
315
|
sessionApprovalBindings: new Map<string, ApprovalBinding>(),
|