pi-daddy 0.22.0 → 0.23.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 +30 -0
- 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/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-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 +121 -3
- package/dist/dashboard-cli.js.map +1 -1
- package/dist/dashboard-harness.d.ts +19 -0
- package/dist/dashboard-harness.d.ts.map +1 -0
- package/dist/dashboard-harness.js +75 -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 +111 -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 +15 -0
- package/dist/dashboard-host-transport.d.ts.map +1 -0
- package/dist/dashboard-host-transport.js +122 -0
- package/dist/dashboard-host-transport.js.map +1 -0
- package/dist/dashboard-host.d.ts +149 -0
- package/dist/dashboard-host.d.ts.map +1 -0
- package/dist/dashboard-host.js +329 -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 +28 -0
- package/dist/experiment-store.d.ts.map +1 -0
- package/dist/experiment-store.js +130 -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-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/delegate-chain.ts +1 -0
- package/extensions/delegation-native.ts +12 -0
- package/extensions/delegation.ts +4 -3
- package/extensions/execute-child.ts +34 -4
- package/extensions/grants.ts +2 -0
- package/extensions/ordinary-runtime.ts +14 -0
- package/extensions/run-delegation.ts +7 -7
- package/extensions/session.ts +3 -1
- package/package.json +78 -4
- package/src/check-runner.ts +20 -2
- package/src/control-journal.ts +26 -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 +103 -4
- package/src/dashboard-harness.ts +28 -0
- package/src/dashboard-herdr.ts +7 -2
- package/src/dashboard-host-contract.ts +42 -0
- package/src/dashboard-host-transport.ts +38 -0
- package/src/dashboard-host.ts +168 -0
- package/src/dashboard-observation.ts +44 -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 +90 -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-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
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Explicit work-signal and durable blind host integration
|
|
2
|
+
|
|
3
|
+
Additive P08 integration; v1/manual case-v2 remains unchanged by default. No provider, automatic
|
|
4
|
+
worker prompt, attention hook, Herdr control, model evaluation, routing or acceptance is introduced.
|
|
5
|
+
|
|
6
|
+
## Actual host boundary
|
|
7
|
+
|
|
8
|
+
`pi-daddy/debrief-host` (also root exports) accepts a trusted host's loaded harness modules:
|
|
9
|
+
`createWorkCaseReviewer`, `createWorkSignalReviewer`, `retainBlindIntervention`, `openBlindIntervention`.
|
|
10
|
+
The actual tested source is skill-harness638494af0a0058edf9a9b1b02e57af894ab46ed6. Exact source bodies,
|
|
11
|
+
SHA256 pins and ordinary isolated compilation are in test/fixtures/debrief-durable-host; upstream
|
|
12
|
+
contracts are retained beside this README. No dependency install, dynamic worker module loader,
|
|
13
|
+
replacement archive/decision ledger, cached permission or fake authenticated operator is supplied.
|
|
14
|
+
The structural DebriefHarness interface is NOT runtime module authentication: loading/provenance and
|
|
15
|
+
independent host authorization remain host obligations. No caller pin string can authorize a writer.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// Explicit host action, with independently configured author and private archive.
|
|
19
|
+
const blind = retainDebriefBlind(harnessPorts, archiveRoot,
|
|
20
|
+
{ manifest, evidence, qualification }, author);
|
|
21
|
+
// Retain blind.comparisonId AND author independently before reconnect/exposure.
|
|
22
|
+
const preview = openDebriefBlindPreview(harnessPorts, archiveRoot, blind);
|
|
23
|
+
// preview has ONLY view/readArtifact/quality, never archive metadata/choose/reveal.
|
|
24
|
+
const presenter = createRetainedDebrief(harnessPorts, {
|
|
25
|
+
archiveRoot, author, blind, scope: retainedAttentionScope, persistence: hostAttentionCAS,
|
|
26
|
+
cases: { version: 'work-signals-v1', batchId, observationId }, offset: 0,
|
|
27
|
+
});
|
|
28
|
+
await presenter.open({mode:'manual', userPresent:true});
|
|
29
|
+
// Existing dashboard presenter/actions, after explicit manual requests:
|
|
30
|
+
await presenter.choose({kind:'one', labels:[opaqueLabel]});
|
|
31
|
+
await presenter.reveal();
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Retention freezes private inputs through the actual adapter, including independent private random seed.
|
|
35
|
+
It is never implicit during open/reconnect. Reconnect binds the original comparison ID/author and reads
|
|
36
|
+
`quality()`, NOT `reveal()`, to discover an existing vote. The adapter re-reads original inputs/artifacts
|
|
37
|
+
on every access; missing/corrupt input or immutable choice refuses. Different choices remain refused
|
|
38
|
+
across presenter/process restarts. Same-choice replay does not create another vote. A required write/sync
|
|
39
|
+
failure remains failure even when complete choice bytes subsequently exist; explicit reopen may observe
|
|
40
|
+
those original bytes without another writer call or automatic reveal. No crash durability is inferred.
|
|
41
|
+
|
|
42
|
+
Only opaque labels, verified artifact previews and explicit quality state reach the pre-reveal blind card.
|
|
43
|
+
Private seed, raw roles, costs/configuration and archive metadata do not. Arbitrary artifact content can
|
|
44
|
+
still disclose identity; this is not universal redaction or a real blind study. The existing bounded
|
|
45
|
+
consumer supports2..4 arms, up to4 artifacts/card and64KiB/artifact, with320-character previews. Larger
|
|
46
|
+
producer comparisons are refused, not silently truncated into a qualified study.
|
|
47
|
+
|
|
48
|
+
## Signal cases and attention
|
|
49
|
+
|
|
50
|
+
`cases.version:'work-signals-v1'` explicitly invokes createWorkSignalReviewer. Its page includes the exact
|
|
51
|
+
independent observation ID and issues, even with ZERO cards. Counts are SELECTED BATCH counts (<=1024),
|
|
52
|
+
not all live work or calibration denominators. Pages are<=5. Case-v3 reasons/metrics/IDs are validated
|
|
53
|
+
against the pinned formula; case-v2 coverage issues remain coverage, not defect labels. Existing v2
|
|
54
|
+
reviewer/batches are not silently reinterpreted. `work-case-v2` explicitly selects the old route.
|
|
55
|
+
|
|
56
|
+
The signal reader rederives exact case membership from the original retained observation; foreign cases,
|
|
57
|
+
old/wrong batch, malformed/missing input and stale author/CAS cannot become labels or promotion. Labels
|
|
58
|
+
use the existing durable decision writer/history and exact evidence/author/prior decision digest.
|
|
59
|
+
Skip, uncertainty, deferred/busy/absent context and unselected cards remain unresolved.
|
|
60
|
+
|
|
61
|
+
One blind question consumes ONE of FIVE TOTAL slots, normally four cases plus one blind. Answers, skip,
|
|
62
|
+
close/reopen and reconnect do not refill slots. No next page is inferred automatically. New explicit
|
|
63
|
+
host scope/offset and independent selection are required for another page.
|
|
64
|
+
|
|
65
|
+
Signals or durable blind binding opt into `debrief-checkpoint-v2`: original v1 fields plus bindingDigest
|
|
66
|
+
of the independently configured signal batch/observation and blind comparison/author. A changed/old
|
|
67
|
+
checkpoint refuses, including zero-card batch switches. Checkpoints retain attention/request transport
|
|
68
|
+
only; canonical case/quality decisions remain in harness storage. Loss/rollback-safe attention storage,
|
|
69
|
+
authenticated human identity and live pause policy remain host qualification, not properties inferred
|
|
70
|
+
from a file, a supplied identity string or a caller-present flag. Frame freshness stays snapshot-unknown,
|
|
71
|
+
automatic presentation unqualified and acceptance not-assessed.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"repository": "https://github.com/mojomanyana/skill-harness",
|
|
3
|
+
"commit": "638494af0a0058edf9a9b1b02e57af894ab46ed6",
|
|
4
|
+
"sources": [
|
|
5
|
+
{
|
|
6
|
+
"source": "packages/core/src/work-capture.ts",
|
|
7
|
+
"target": "work-capture.ts.txt",
|
|
8
|
+
"commit": "638494af0a0058edf9a9b1b02e57af894ab46ed6",
|
|
9
|
+
"sha256": "a258861619e92d5b41336ee83d41c42fec33212643c22b7d6ace8e55561b98ea"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"source": "packages/core/src/work-signals.ts",
|
|
13
|
+
"target": "work-signals.ts.txt",
|
|
14
|
+
"commit": "638494af0a0058edf9a9b1b02e57af894ab46ed6",
|
|
15
|
+
"sha256": "5e14a6069bcecfd358b5e3d034a78ee896c6f7f646c8208d8233cb9dd751dca4"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"source": "packages/core/src/intervention.ts",
|
|
19
|
+
"target": "intervention.ts.txt",
|
|
20
|
+
"commit": "638494af0a0058edf9a9b1b02e57af894ab46ed6",
|
|
21
|
+
"sha256": "05377d1045942334016e7154bb092cf2fdeb4d95c86c2c4170b321f11d9d0312"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"source": "packages/adapters/src/evidence-archive.ts",
|
|
25
|
+
"target": "evidence-archive.ts.txt",
|
|
26
|
+
"commit": "638494af0a0058edf9a9b1b02e57af894ab46ed6",
|
|
27
|
+
"sha256": "f41fd69daa4326cefad673fbf4eee2e0c44aa12de595d8a9c4deec209fe38807"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"source": "packages/adapters/src/work-case-archive.ts",
|
|
31
|
+
"target": "work-case-archive.ts.txt",
|
|
32
|
+
"commit": "638494af0a0058edf9a9b1b02e57af894ab46ed6",
|
|
33
|
+
"sha256": "6998556f29c068ae8d5f383b76e913f429235aa90bb6f50e34a20785d870d4a6"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"source": "packages/adapters/src/work-case-review.ts",
|
|
37
|
+
"target": "work-case-review.ts.txt",
|
|
38
|
+
"commit": "638494af0a0058edf9a9b1b02e57af894ab46ed6",
|
|
39
|
+
"sha256": "d7b374c80f182b20367a3968d9815fffae8ca70a452a5c6f246e7678158c7a7a"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"source": "packages/adapters/src/work-signal-cases.ts",
|
|
43
|
+
"target": "work-signal-cases.ts.txt",
|
|
44
|
+
"commit": "638494af0a0058edf9a9b1b02e57af894ab46ed6",
|
|
45
|
+
"sha256": "947dc22f35e8f40510e8a37c5630fd38afe2400c112993f322e2bce8af4f467f"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"source": "packages/adapters/src/work-signal-observation.ts",
|
|
49
|
+
"target": "work-signal-observation.ts.txt",
|
|
50
|
+
"commit": "638494af0a0058edf9a9b1b02e57af894ab46ed6",
|
|
51
|
+
"sha256": "b97b727f2c90634f977abbba837411d01b96eb24c85430ea129c97956b48efac"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"source": "packages/adapters/src/blind-intervention.ts",
|
|
55
|
+
"target": "blind-intervention.ts.txt",
|
|
56
|
+
"commit": "638494af0a0058edf9a9b1b02e57af894ab46ed6",
|
|
57
|
+
"sha256": "9b73d85927cc3386b9ab2fae7e647793929e360e5fda892e4db2ab692ab756e4"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"source": "packages/adapters/src/work-candidates.ts",
|
|
61
|
+
"target": "work-candidates.ts.txt",
|
|
62
|
+
"commit": "638494af0a0058edf9a9b1b02e57af894ab46ed6",
|
|
63
|
+
"sha256": "2b0bd7188b9da6951f050e9889ed3fdf5adafbd4b5cc5a81ec417a14fac20117"
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Frozen intervention comparison primitives — P12 partial, P08 fixture input
|
|
2
|
+
|
|
3
|
+
This is a SEPARATE family from existing fixed-model `buildComparison`/`compare`. Their same-model/judge/input guards are unchanged. No model is launched here.
|
|
4
|
+
|
|
5
|
+
`freezeIntervention` binds an investigation digest, common scenario/rubric/fixture/held-out/harness/judge-policy inputs, mode, repetition/criterion/critical thresholds, resource metric and explicit candidate axes. Undeclared model/effort/skill/prompt/configuration changes reject. Multiple changed axes are a package intervention, not evidence of one variable's causal effect. LLM sampling is not claimed deterministic.
|
|
6
|
+
|
|
7
|
+
`assertInterventionRoles` is a pre-spend check over independently resolved HOST context. Missing roles and proposer/judge/subject canonical identity conflicts refuse. Same subjects may repeat across arms. It does not resolve providers, authenticate arbitrary context or qualify a delivery route. Do not derive qualification or expected evidence digests from incoming arm claims.
|
|
8
|
+
|
|
9
|
+
`assessIntervention` checks exact host-confirmed evidence digests and frozen input/cell policy. Delivery NOT-MEASURED/ERROR and missing/unknown/suspect cells keep the comparison incomplete; objective failure prevents judging/eligibility. Votes are retained per criterion. Actual output bytes must match per-cell/arm hashes; digests alone are missing evidence. Retained bytes are copied for later blind reads. Cheap failed arms cannot become eligible. Cheapest eligible is only a conditional measurement; routingDefault is always null and adoptionAuthorized false.
|
|
10
|
+
|
|
11
|
+
`interventionEvidenceFromResults` uses existing schema3 validation and retains complete source results/votes beside the summary. It requires recorded `source_hashes['intervention:manifest']` and `['intervention:inputs']`, matching model/mode/judge/plan, and supplied output bytes. It never stamps missing bindings onto historical runs. Multi-judge conversion is not yet supported rather than choosing a convenient panel vote. The orchestrator that records these bindings and qualifies actual execution remains integration work.
|
|
12
|
+
|
|
13
|
+
## Blind view API
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
const blind = createBlindComparison(manifest, recomputedAssessment);
|
|
17
|
+
const view = blind.view(); // opaque labels + artifact hashes + explicit clue limitation; no configuration/cost
|
|
18
|
+
const bytes = blind.readArtifact(label, artifactHash); // only retained bytes admitted to that label
|
|
19
|
+
blind.choose({kind:'one'|'tie'|'none'|'insufficient', labels:[/* opaque labels, or [] */]});
|
|
20
|
+
const revealed = blind.reveal(); // refuses before choice; different choice refuses after reveal
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
An optional private seed supports fixtures/host-controlled restoration; real independent views need fresh private randomness, not a public fixed seed. Public view omits identity metadata, but arbitrary artifact text may reveal clues. The host must enforce user/judge identity, persist quality/seed/reveal state before exposure, and expose only the public view/read methods before choice. This in-memory API is not durable human authentication or proof a host did not leak the assessment/configuration. P08 must keep its total five-card budget and real pause/exposure boundaries.
|
|
24
|
+
|
|
25
|
+
`fixtures/` is generated by actual code from fixed synthetic evidence, retained Layout A/B bytes, fixture role identities and a public zero seed. It is NOT live qualification, real human blinding, efficacy or casting evidence. It supplies a concrete UI contract: blind-view.json before choice; choice.json; reveal.json only afterward.
|
|
26
|
+
|
|
27
|
+
## Durable local blind review
|
|
28
|
+
|
|
29
|
+
`retainBlindIntervention(root, manifest, evidence, qualification, author)` explicitly retains a private comparison and returns its immutable archive ID. It checks the actual supplied output bytes and complete assessment before retention; roles remain independently supplied host declarations, not authentication. An independent random seed is retained privately with each new comparison. `openBlindIntervention(root, id, author)` reopens exactly that comparison. Each `view`, `quality`, `readArtifact`, `choose` and `reveal` re-reads verified archive inputs and recomputes the assessment and label mapping; no stored eligibility verdict is trusted. Artifact loss blocks access, including reveal.
|
|
30
|
+
|
|
31
|
+
The durable adapter intentionally commits ONE immutable initial quality choice, stricter than the in-memory primitive's editable pre-reveal choice. `quality()` reads it without revealing identity/cost; `reveal()` refuses until it exists. Same-choice resubmission is read-only and idempotent; a different choice refuses even after process restart. An atomic directory claim admits one initial writer; a competing writer may observe a conflict or incomplete claim, never overwrite it. Partial/missing/malformed claimed records require explicit recovery, not automatic deletion or another vote. A write/fsync error can follow a committed choice: retain unknown acknowledgement and inspect that same comparison. No automatic retry or filesystem cleanup occurs.
|
|
32
|
+
|
|
33
|
+
Private archive ownership is required. This is not protection against a malicious same-UID owner deleting/rewriting an archive or creating a separate comparison, remote user authentication, automatic exposure, a claim that artifact content cannot disclose identity, or crash-durability proof beyond successful file/directory synchronization. Choice files live under `blind-decisions/<comparison-id>/choice.json`; archive metadata (including seed/roles/cost) is operator-private, never a dashboard payload. Only the restricted view/artifact/quality methods go to a pre-reveal client. Records are bounded (2MiB input JSON, 8MiB per artifact/64MiB aggregate, 4096 artifacts, 16KiB choice read). No provider call, routing default or adoption is introduced.
|
|
34
|
+
|
|
35
|
+
Remaining P12: qualified model-backed orchestration, complete panel/authenticated blind workflow, verified role/receipt integration, applicable casting rows/uncertainty/revalidation and live P08 demonstration. Full acceptance and any routing/adoption default remain pending.
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
node scripts/generate-intervention-fixture.mjs --check
|
|
39
|
+
node node_modules/vitest/vitest.mjs run packages/core/test/intervention.test.ts packages/core/test/intervention-results.test.ts packages/core/test/comparison.test.ts
|
|
40
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Frozen work signals and explicit review bridge — v1
|
|
2
|
+
|
|
3
|
+
Additive adapter APIs, not a reinterpretation of `contracts/work-capture/v2`.
|
|
4
|
+
|
|
5
|
+
1. `retainWorkSignalObservation(root, snapshot, facts)` validates closed bounded host declarations and retains canonical `work-signal-observation-v1` bytes. Returns `{manifestId,inputSha256}`.
|
|
6
|
+
2. `readWorkSignalObservation(root, manifestId)` reopens verified bytes and rederives `work-signals-v1` cases. It rejects missing/corrupt/mismatched/unsupported input; unknown scope stays an explicit issue, not an empty success claim.
|
|
7
|
+
3. `captureWorkSignalCases(root, observationId)` creates immutable case references and a selected batch. Case parser `work-signal-case`/`1` stores `{version:'work-signal-case-v1',observationId,caseId}`; no cached verdict. Batch parser `work-signal-batch`/`1` stores `{version:'work-signal-batch-v1',observationId,candidateIds,visibility:'silent',promotion:'not-authorized'}`. Both source identities bind the referenced observation/case.
|
|
8
|
+
4. `createWorkSignalReviewer(root,batchId,operatorAuthor)` exposes `list(offset=0,limit=5)`, `history(caseManifestId)` and `decide({caseManifestId,priorDecisionId,disposition,note})`. Decisions use the existing durable lock/CAS/history writer and `decision_schema:1`. No new history engine or worker control path.
|
|
9
|
+
|
|
10
|
+
Each selected case is rederived from its original input on access, including immediately before decision storage. Case membership in the exact observation is checked; a valid case from a different observation cannot be substituted. Missing original input blocks decisions. `list` additionally returns `observationId` and observation `issues`, so unresolved scope with zero cards is not hidden. Counts describe the selected batch, not exhaustive live work or calibration denominators.
|
|
11
|
+
|
|
12
|
+
Defect cards have `capture_schema:3` and explicit `overdue_checkpoint`, `reopened_acceptance`, or `intent_conflict` reason/metrics. Coverage issues retain `capture_schema:2`. Both remain silent/unresolved/causal-not-established nominations. The old `createWorkCaseReviewer` accepts only its original v2 batch contract and REFUSES these new batches. A UI must opt into this bridge and these card versions; existing pi-daddy pinned v2 clients are not upgraded by this library addition.
|
|
13
|
+
|
|
14
|
+
`operatorAuthor` and supplied facts are conditional host declarations, not authentication. Retained inputs do not prove the truth/availability of external referenced evidence, active branch, an authenticated human pause or authority to expose/promote/adopt. Live source capture, actual dashboard version selection, privacy/role authority and automatic pause/exposure policy remain integration work.
|
|
15
|
+
|
|
16
|
+
Limits: closed input arrays at most256 entries, input bytes at most1MiB, selected batch at most1024 unique case manifest IDs, batch/case payload reads at most128KiB, pages at most5. Existing non-expiring decision locks and1MiB history bound remain. Trusted local archive integrity is not hostile same-UID containment, rollback resistance or a storage quota.
|
|
17
|
+
|
|
18
|
+
`captureArchivedWorkSignals(root,workManifestId,independentWorkContext,facts)` additionally consumes the pinned real Work-v4 reader. It derives scope, binding identities, coverage and acceptance from the actual projection rather than accepting replacement fields from the signal caller. Its `archived-work-signals-v1` link retains the raw source identity, producer pin, full projection, frozen observation and review batch references. Missing/malformed/unselected work refuses. Missing authority remains coverage, even when a supplied objective fact says FAIL.
|
|
19
|
+
|
|
20
|
+
This adapter's `work-v4-revision-digests-v1` binding profile uses obligation/intent/policy/artifact REVISION digests, not artifact content digests; prior-acceptance facts must use the same profile. A valid P01 selection with multiple bindings for the same obligation digest is currently refused by the narrower signal profile, never collapsed. The retained full projection preserves detailed coverage/problems; the signal projection remains conservative. Supplied checkpoint/outcome facts and Work context still need independent host provenance/authorization. No live collection or authentication is created by this mapping. Original work bytes are verified at capture; the case reader subsequently verifies its retained input, not every external artifact mentioned in that input.
|
|
21
|
+
|
|
22
|
+
Changing rule semantics requires a new explicit observation format/reader. Preserve old inputs, outcomes and decision corrections; never silently relabel a saved nomination or erase an unknown result.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# P05 bounded dispatch control v1 — contract for P15
|
|
2
|
+
|
|
3
|
+
Later local continuation: [actual P01 intent application](../../intent-control/v1/README.md) supplies
|
|
4
|
+
scope/priority/alternative adapters under a separate v3 resource binding and intent protocol. The matrix
|
|
5
|
+
below remains the contract for **this v1 dispatch-only protocol**, not a permanent claim of external blockers.
|
|
6
|
+
|
|
7
|
+
Implemented local candidate; overall review and formal acceptance pending. This is **not general live
|
|
8
|
+
worker steering**. No new dashboard authority database, model judgment, worker prompt, terminal typing,
|
|
9
|
+
Herdr control call or background reconciler is introduced. P04 status remains read-only and unchanged.
|
|
10
|
+
|
|
11
|
+
## Exact action matrix
|
|
12
|
+
|
|
13
|
+
| Request | Supported target/boundary | Result |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `pause-dispatch` | One independently bound **v2 resource budget**; application only under the reservation lock with zero active reservations | Pause future reservations; never interrupt admitted work |
|
|
16
|
+
| `resume-dispatch` | Same exact budget and zero-reservation boundary | Re-enable only its original fixed limits; no scope/effect expansion |
|
|
17
|
+
| Busy pause/resume | Same budget, original live permits still outstanding | Pending; admission barrier blocks new reservations; explicit authorized reconciliation after settlement |
|
|
18
|
+
| `cancel-execution` | No atomic durable request-to-live-executor cancellation primitive implemented | Explicit unsupported/not-applied, never ordinary steering or terminal fallback |
|
|
19
|
+
| `revise-scope`, `reprioritize`, `select-alternative` | No supported atomic P01 revision application adapter supplied | Explicit unsupported/not-applied; work-v4 remains sole intent source |
|
|
20
|
+
| Targeted live pi/Herdr steering | No verified atomic session/target/safe-boundary mechanism established | BLOCKED; pane/title/PID/idle/last-entry facts are not authority |
|
|
21
|
+
| Arbitrary bash/model/shared-write or alternative budget/lease stores | Outside the partial P06 profile | BLOCKED; no global dispatch/containment claim |
|
|
22
|
+
|
|
23
|
+
The useful demonstrated route is `prepareDigestProfile(v2Binding)` / `runDigestProfile`: its actual existing
|
|
24
|
+
reservation seam obeys the gate. Preparation probes are not workload dispatch and are not disabled by the
|
|
25
|
+
workload gate. Other budgets and executors that do not use this binding are not governed. The boundary is
|
|
26
|
+
**verified reservation quiescence**, not global process silence or an authenticated live-pi safe point.
|
|
27
|
+
P06's original live owner settles its own permit after executor finalization; orphan reservations remain
|
|
28
|
+
active across restart. There is no PID/TTL/receipt-based recovery or general worker-state inference.
|
|
29
|
+
|
|
30
|
+
## Authority and revision
|
|
31
|
+
|
|
32
|
+
The host retains the independently created budget binding and supplies independent `DispatchAuthority`
|
|
33
|
+
declarations: its exact authority digest plus at most 128 approved request digests. These are trusted host
|
|
34
|
+
inputs, not request metadata, authentication credentials or a wire-authority loader. A host must not derive
|
|
35
|
+
approval from an incoming request/claimed result or merely copy its identifiers. Defaults are denied.
|
|
36
|
+
No mutable approval list is persisted. Existing trusted-store/same-UID/rollback limitations still apply;
|
|
37
|
+
this library is not a remote authentication boundary or a revocable distributed authority service.
|
|
38
|
+
|
|
39
|
+
`DispatchRequest` has a closed version `1.0`, immutable request ID, exact `bindingDigest`, expected **dispatch
|
|
40
|
+
revision**, action and nullable execution target. That revision is operational budget state, **not a P01
|
|
41
|
+
scope revision**. Requests cannot rewrite P01 intent or claim acceptance. `targetExecutionId` is non-null
|
|
42
|
+
only for the distinct unsupported cancellation route. Wire input uses `parseDispatchRequest` (4096-byte
|
|
43
|
+
limit, duplicate-aware/exact numeric parsing); `request.schema.json` describes the decoded closed shape.
|
|
44
|
+
Do not first round lossy numeric tokens through JSON.parse and call them validated original wire bytes.
|
|
45
|
+
|
|
46
|
+
Use `dispatchRequestDigest` over the complete canonical request to join independent approval. Missing/wrong
|
|
47
|
+
authority refuses; then unsupported route, stale revision and another pending decision refuse. One approved
|
|
48
|
+
request advances dispatch revision immediately, including when busy; stale UI cannot supersede it. A busy
|
|
49
|
+
admission barrier prevents new reservations while existing work drains. The application itself waits for
|
|
50
|
+
zero active reservations under the same non-stale-recoverable lock used by reserve/settle. A barrier is not
|
|
51
|
+
a claim that pause has already applied, or that the active worker stopped.
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { createDispatchBudget, openResourceBudget } from 'pi-daddy/resource-budget';
|
|
55
|
+
import { parseDispatchRequest } from 'pi-daddy/dispatch-control';
|
|
56
|
+
// One-time host creation under an explicitly owned private parent; persist binding independently.
|
|
57
|
+
const binding = await createDispatchBudget({ directory, authorityDigest, limits });
|
|
58
|
+
const budget = openResourceBudget(binding);
|
|
59
|
+
const controls = budget.controls(independentHostDeclarations); // or null: no authority
|
|
60
|
+
const request = parseDispatchRequest(operatorRequestBytes);
|
|
61
|
+
const result = await controls.request(request);
|
|
62
|
+
const observed = await controls.inspect(); // read-only; never calls request/reconcile
|
|
63
|
+
// Only an explicit authorized controller operation may apply pending work:
|
|
64
|
+
const reconciled = await controls.reconcile(request.requestId);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Durable request / decision / application / outcome
|
|
68
|
+
|
|
69
|
+
No parallel intent store: controls extend the existing pinned `budget.jsonl` transaction and reservation
|
|
70
|
+
replay. **Explicit binding/header version 2.0** opts into these semantics; unchanged `createResourceBudget`
|
|
71
|
+
still creates v1.0 and retains its v1 static return type. Old v1 readers reject a v2 binding rather than
|
|
72
|
+
silently skipping controls. No conversion/reset/in-place upgrade API exists.
|
|
73
|
+
|
|
74
|
+
- `control-request` atomically records the exact request and its approved/refused decision. Approved state
|
|
75
|
+
starts pending with boundary-pending outcome; refusals are not-applied/refused. Each ID occupies one slot.
|
|
76
|
+
- `control-apply` records application of the one approved pending request and projects its paused/enabled
|
|
77
|
+
outcome. It is invalid when reservations are active. No transport callback or caller-supplied receipt
|
|
78
|
+
may mark application. `reserve` replays and enforces both committed pause and the pending barrier.
|
|
79
|
+
- `DispatchSnapshot` version `dispatch-control-snapshot-v1` includes exact binding digest, revision, paused
|
|
80
|
+
flag, **admission: blocked-pending|paused|enabled**, immutable records and `acceptance:not-assessed`.
|
|
81
|
+
Freshness is `snapshot-unknown`. Readback is not work acceptance or new host authorization.
|
|
82
|
+
- An exact duplicate ID/digest only reads the existing result, including pending. It never applies, emits
|
|
83
|
+
another record or repeats an effect. Reusing an ID for another digest rejects. Reconciliation explicitly
|
|
84
|
+
names one exact request ID and rechecks its independently supplied approval and boundary; another ID
|
|
85
|
+
cannot reconcile the pending request. Repeated reconciliation is idempotent.
|
|
86
|
+
- No acknowledgement or a thrown I/O/cleanup error means the caller must retain **unknown application**;
|
|
87
|
+
it must not assume success or silently retry a new ID. A complete append may precede an error, including
|
|
88
|
+
fsync/close/lock-cleanup failure: this is not a no-write/no-effect-on-error guarantee. Inspect/reconcile
|
|
89
|
+
the exact ID in the bound store. A pending record is not application; a complete current application
|
|
90
|
+
record is readback, not proof of crash durability, authenticated remote delivery or live worker state.
|
|
91
|
+
|
|
92
|
+
Mandatory failures reject, including after bytes were written. Partial/invalid/replaced journals refuse
|
|
93
|
+
further admission; no truncation, alternate store or recovery credit is attempted. Capacity is bounded by
|
|
94
|
+
128 request records and at most 128 applications in addition to the existing attempt/settlement limits,
|
|
95
|
+
2305 total v2 lines and 2 MiB. Cumulative attempts/bytes are never refunded. Read-only inspections use
|
|
96
|
+
O_RDONLY, no lock creation, bounded descriptor/path consistency checks and no write/control callbacks.
|
|
97
|
+
Concurrent changes can make an inspection fail; no old state is substituted.
|
|
98
|
+
|
|
99
|
+
## Evidence and exclusions
|
|
100
|
+
|
|
101
|
+
Ordinary owned fixtures exercise real file locking, cross-process duplicate delivery, exact independent
|
|
102
|
+
fixture declarations, busy original permits, stale revisions, missing authority, mandatory-sync failure,
|
|
103
|
+
source replacement/partial data, read-only byte/directory preservation and actual probed fixed-digest
|
|
104
|
+
execution behind the gate. They do not qualify hostile same-UID writers, rollback resistance, complete
|
|
105
|
+
controller-crash cleanup or installed/live pi/Herdr operation. No native/model test messages were sent.
|
|
106
|
+
|
|
107
|
+
P02 native branch/availability gaps, P04 unqualified live freshness/transport, and P06 arbitrary-effect and
|
|
108
|
+
aggregate CPU/memory/PID/disk/provider-money limitations remain. P15 must preserve this exact bounded matrix,
|
|
109
|
+
unknown acknowledgements, independent approval, request identity and acceptance separation.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "P05 bounded dispatch request v1 (not authority)",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"additionalProperties": false,
|
|
6
|
+
"required": ["version", "requestId", "bindingDigest", "expectedRevision", "action", "targetExecutionId"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"version": { "const": "1.0" },
|
|
9
|
+
"requestId": { "type": "string", "pattern": "^[a-zA-Z0-9:_-]{1,128}$" },
|
|
10
|
+
"bindingDigest": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
|
|
11
|
+
"expectedRevision": { "type": "integer", "minimum": 0, "maximum": 128 },
|
|
12
|
+
"action": { "enum": ["pause-dispatch", "resume-dispatch", "cancel-execution", "revise-scope", "reprioritize", "select-alternative"] },
|
|
13
|
+
"targetExecutionId": { "anyOf": [{ "type": "null" }, { "type": "string", "pattern": "^[a-zA-Z0-9:_-]{1,128}$" }] }
|
|
14
|
+
},
|
|
15
|
+
"anyOf": [
|
|
16
|
+
{ "properties": { "action": { "const": "cancel-execution" }, "targetExecutionId": { "type": "string" } } },
|
|
17
|
+
{ "properties": { "action": { "enum": ["pause-dispatch", "resume-dispatch", "revise-scope", "reprioritize", "select-alternative"] }, "targetExecutionId": { "type": "null" } } }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# P06 local candidate: a fixed digest boundary and durable resource accounting
|
|
2
|
+
|
|
3
|
+
**Version 1.0, local only; overall review and formal acceptance pending.** This is not a sandbox for pi,
|
|
4
|
+
bash, arbitrary JavaScript, model invocations, or writable workspaces. Existing delegation/check behavior
|
|
5
|
+
is unchanged. The one supported new operation is `linux-bwrap-digest-v1`: hash at most 16 KiB of byte input
|
|
6
|
+
with a fixed trusted worker and return its digest/length on stdout. It is useful for independently checking
|
|
7
|
+
small evidence payloads, not executing an arbitrary factory order. Full P06 remains only partially covered.
|
|
8
|
+
|
|
9
|
+
The unchanged executable guard checks Linux, resolved Node then exact bwrap/prlimit paths, regular-file
|
|
10
|
+
type, no group/other write bits, and size<=256MiB. Refusals keep the original error message and add exact
|
|
11
|
+
path/details plus RUNTIME_NOT_REGULAR / RUNTIME_WRITABLE / RUNTIME_TOO_LARGE. Independent read-only CI
|
|
12
|
+
telemetry observes all prerequisites; conforms:false is not namespace success and does not skip tests.
|
|
13
|
+
No installation, shared chmod, runner provisioning or host policy weakening is performed. Actual remote
|
|
14
|
+
24.20 predicate remains unknown in the old logs; Node22's missing bwrap remains a provisioning blocker.
|
|
15
|
+
|
|
16
|
+
## Public API
|
|
17
|
+
|
|
18
|
+
`pi-daddy/resource-budget`: `createResourceBudget`, `openResourceBudget`, `resourceBindingDigest` and types.
|
|
19
|
+
`pi-daddy/effect-profile`: `prepareDigestProfile`, `runDigestProfile`, `DIGEST_PROFILE` and types.
|
|
20
|
+
Both are also exported from the root. Historical dist is not a build of these exports.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
const binding = await createResourceBudget({
|
|
24
|
+
directory: '/operator-private/new-budget', // fresh child of a canonical owner-private directory
|
|
25
|
+
authorityDigest: independentlySelectedPolicyDigest,
|
|
26
|
+
limits: { maxAttempts: 8, maxInputBytes: 65536, maxConcurrent: 2 },
|
|
27
|
+
});
|
|
28
|
+
// Persist this detached/frozen binding in the trusted controller, separately from its journal.
|
|
29
|
+
const profile = await prepareDigestProfile(binding); // actual bounded native probes; may reject
|
|
30
|
+
const result = await runDigestProfile(profile, {
|
|
31
|
+
attempt: { attemptId: 'exec:unique', orderId: 'order:a', experimentId: 'experiment:b',
|
|
32
|
+
kind: 'primary', parentAttemptId: null },
|
|
33
|
+
bytes: Buffer.from('evidence'),
|
|
34
|
+
}, signal);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The byte input and identity are detached before asynchronous work. No input is interpreted as code, an
|
|
38
|
+
option, path, command, environment, lease store or destination. Byte input is base64-encoded in process
|
|
39
|
+
argv; this is **not a secret-transport API**. Worker output is just digest/length, not raw input. The
|
|
40
|
+
profile token is process-local and opaque: a JSON roundtrip or receipt-shaped object cannot admit work.
|
|
41
|
+
The public producer validator/retention manifest is not an admission capability or work approval.
|
|
42
|
+
|
|
43
|
+
## Actual boundary and supported/unsupported matrix
|
|
44
|
+
|
|
45
|
+
| Route/property | Disposition |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| Linux bwrap user/mount/PID/network namespace setup | Observed supported on the measured WSL2 host; re-probed per prepared handle |
|
|
48
|
+
| Owned outside-file read/write; mutation of owned read-only mount | Actual fixture attempts denied (`ENOENT`, `EROFS`), allowed fixture read succeeds |
|
|
49
|
+
| Reach host loopback listener | Actual owned listener remains unreachable from the network namespace |
|
|
50
|
+
| Untrusted code / shell / child launch API | Not exposed by this profile; Node permission child-process tripwire also actually denies spawn |
|
|
51
|
+
| Worker cancellation | Existing `runChild` signal/deadline path; actual owned namespace worker/helpers observed stopped |
|
|
52
|
+
| Cgroup aggregate CPU/memory/PID enforcement | Unsupported: no writable delegated cgroup measured |
|
|
53
|
+
| `prlimit` | Per-process CPU/FD tripwire only, not aggregate limits; V8 heap flag is not an OS memory cap |
|
|
54
|
+
| Persistent destinations / writable or shared workspace roots / alternative lease stores | Unsupported; absent from the closed API, no host workspace/store mounted |
|
|
55
|
+
| Arbitrary pi/bash/model profiles; provider-money hard cap | Unsupported before workload launch; no fallback or inferred/posthoc dollar allowance |
|
|
56
|
+
|
|
57
|
+
The launcher uses existing `/usr/bin/bwrap`, `/usr/bin/prlimit` and the current trusted Node executable.
|
|
58
|
+
It drops capabilities **inside the child**, clears its environment, creates new namespaces and exposes
|
|
59
|
+
only read-only system runtime directories plus the fixed Node binary. No host capability configuration,
|
|
60
|
+
installation, privilege escalation or service/cgroup configuration changes are performed. The preparation
|
|
61
|
+
probe alone mounts a fresh owned read-only fixture. That exact fixture is removed only after every awaited
|
|
62
|
+
probe child has settled, on success and failure; removal failure is loud and does not replace an earlier
|
|
63
|
+
probe failure. Old or caller-selected directories are never cleanup targets. The production worker mounts no user workspace.
|
|
64
|
+
The production Node worker has permission mode enabled; Node permission mode by itself is not claimed
|
|
65
|
+
as a hostile-JavaScript sandbox. Only fixed package code executes, so ungoverned descendants are not an
|
|
66
|
+
admitted operation. Internal Node/helper threads/processes are not separate billable attempts.
|
|
67
|
+
|
|
68
|
+
The selected binary fingerprints are pinned and rechecked before each workload. The operator/kernel,
|
|
69
|
+
trusted package code, runtime installation and control-owned filesystem are the trust boundary. Runtime
|
|
70
|
+
updates during an invocation, malicious same-UID host writers, rollback of trusted storage, kernel/runtime
|
|
71
|
+
exploits and hostile-process containment are not qualified. Read-only bind mounts do not freeze a host
|
|
72
|
+
administrator's runtime files. This route therefore cannot be relabelled a general shared-root sandbox.
|
|
73
|
+
No user payload launches merely because executables exist or a caller claims a profile name.
|
|
74
|
+
|
|
75
|
+
## What is actually reserved
|
|
76
|
+
|
|
77
|
+
One independently retained `BudgetBinding` pins the canonical private directory and journal device/inode,
|
|
78
|
+
external authority digest and closed limits. The budget is **one scope across all orders and experiments**
|
|
79
|
+
using that binding, not a new allowance per logical name. A different binding is a different explicit
|
|
80
|
+
scope, never proof of sharing an aggregate limit. There is exactly one fixed journal/lock location; the
|
|
81
|
+
API offers no alternative lease-store override. Binding/header mismatch or physical replacement fails.
|
|
82
|
+
|
|
83
|
+
Admission reserves **one cumulative attempt, its full input-byte count, and one active invocation slot**
|
|
84
|
+
before the existing execution seam is called. Those are the only aggregate hard counters claimed. A
|
|
85
|
+
maximum of 1024 attempts, 16 MiB cumulative inputs and 32 active invocations is configurable downward.
|
|
86
|
+
No aggregate CPU, memory, disk, PID or money cap is asserted. Bounded trusted preparation probes are
|
|
87
|
+
control/setup work, not admitted user attempts. There are no provider calls or money estimates.
|
|
88
|
+
|
|
89
|
+
Primary, retry, shadow and explicitly governed descendant attempts all consume allowance; non-primary
|
|
90
|
+
attempts require an existing parent reference in the same scope. A duplicate attempt ID is rejected,
|
|
91
|
+
including redelivery after completion. Cancellation/failure never refunds attempts or bytes. The live
|
|
92
|
+
controller releases only the active slot, after executor settlement; a mandatory settlement failure still
|
|
93
|
+
rejects even if the worker exited zero. Existing finalization helpers preserve primary errors.
|
|
94
|
+
|
|
95
|
+
Reopening preserves all outstanding charges/slots. An exited PID, timeout, new controller, late result or
|
|
96
|
+
receipt-shaped data does **not** reclaim an orphan. Only the original live permit can settle its exact
|
|
97
|
+
reservation; exact repeated settlement is idempotent and contradictory late settlement rejects. There is
|
|
98
|
+
no recovery/reclaim API. Exhausted orphan capacity requires a separately designed, authorized quiescent
|
|
99
|
+
reconciliation—not deleting a journal, new lease store, renamed directory or pretending a retry is free.
|
|
100
|
+
|
|
101
|
+
The private journal is strict bounded JSONL, opened without symlink following, validated against independent
|
|
102
|
+
binding/counters, serialized with the existing no-stale-recovery lock, and fsynced before launch. Incomplete
|
|
103
|
+
writes fail closed without truncation/repair. A completed append can precede a cleanup error: no exactly-once
|
|
104
|
+
blind retry guarantee. Creation is explicit/exclusive; reopening never creates/reset state. This relies on
|
|
105
|
+
a trusted durable filesystem and sole cooperative host protocol, not tamper-proof consensus storage.
|
|
106
|
+
|
|
107
|
+
Opt-in P02 retention records exact attempt/parent IDs, actual raw/result bytes and runtime outcomes. It is
|
|
108
|
+
still `not-assessed`, and missing native session/branch fields do not become complete evidence.
|
|
109
|
+
|
|
110
|
+
## Checks and limitations
|
|
111
|
+
|
|
112
|
+
Direct Node tests (retained dependencies only):
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
node --test packages/pi-daddy/test/resource-budget.test.ts packages/pi-daddy/test/effect-profile.test.ts
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
These native effect tests require the demonstrated Linux/bwrap/Node primitive and deliberately fail rather
|
|
119
|
+
than silently count unavailable containment as a passing qualification. Arithmetic tests include real
|
|
120
|
+
cross-process contention, duplicate delivery, byte/count exhaustion, cancellation/restart, replaced stores,
|
|
121
|
+
partial journals and immutable authority. Native tests use disposable owned fixtures and a local listener,
|
|
122
|
+
not provider traffic or an untrusted hostile executable. A forwarding spawn observer verifies zero real
|
|
123
|
+
spawn calls for unsupported inputs and a real post-spawn mandatory-accounting failure. No production test
|
|
124
|
+
control, guard bypass, model review/test, installation or mutation machinery is introduced.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Execution retention 1.0 — producer contract for P03
|
|
2
|
+
|
|
3
|
+
Opt-in candidate API: `pi-daddy/execution-retention` (also the root export). This is a new archive
|
|
4
|
+
manifest, **not** ledger v3/v4, a check-receipt schema revision, or acceptance authority. The TypeScript
|
|
5
|
+
wire definition is `src/execution-retention.ts::ExecutionRetentionManifest`.
|
|
6
|
+
|
|
7
|
+
## Activation and actual wiring
|
|
8
|
+
|
|
9
|
+
The operator sets `PI_GRANTS_EXECUTION_ARCHIVE` to an absolute, private, operator-owned archive directory.
|
|
10
|
+
No model-facing parameter is added. `delegate`, `delegate_all` and `delegate_chain` carry the actual
|
|
11
|
+
public execute call ID into their shared governed executor. Each launch has its existing unique
|
|
12
|
+
execution ID and parent execution ID; logical child names are NOT join keys. `runNamedCheck` uses the
|
|
13
|
+
same retention writer and also accepts host `retentionDirectory` and `toolCallId` options. Unknown check
|
|
14
|
+
parentage stays null. No correlation claim supplies any of these identities.
|
|
15
|
+
|
|
16
|
+
The archive is asynchronous observation. Required provisioning/lease/check ledger writes retain their
|
|
17
|
+
previous failure semantics; archive publication is never awaited on the worker path. No extra worker
|
|
18
|
+
turn, prompt, message, extension or Herdr RPC is introduced. Herdr observation reuses existing reads.
|
|
19
|
+
Absent configuration disables archival without changing spawn argv or granting any authority.
|
|
20
|
+
|
|
21
|
+
## Directory and wire contract
|
|
22
|
+
|
|
23
|
+
Each admitted observation gets a random archive ID, independent of the logical name and execution ID:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
<operator-directory>/<archiveId>/manifest.json
|
|
27
|
+
<operator-directory>/<archiveId>/<kind>-<sha256>.bin
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The manifest is a small JSON object plus LF, atomically renamed from `manifest.pending`. Blob paths
|
|
31
|
+
are relative basenames. Existing blobs are not overwritten; unexpected pre-existing blobs fail the
|
|
32
|
+
observation. Completed generations remain readable while a new checkpoint publishes. Superseded blob
|
|
33
|
+
files are retained, not deleted. External archival owns retention duration and garbage collection.
|
|
34
|
+
|
|
35
|
+
- `version`: exactly `1.0`; reject unknown versions.
|
|
36
|
+
- `identity`: execution/parent/child/public-call identity; executor; task, definition and configuration
|
|
37
|
+
digests; resolved workspace ID. Configuration hashes the exact plan argv/effective grant/timeout, or
|
|
38
|
+
the check's explicit executable/argv/access/bounds. It does **not** dump environment or credentials.
|
|
39
|
+
Task/definition/configuration digests are pins, **not retained instruction bytes**.
|
|
40
|
+
- `native`: actual process PID or actual Herdr pane/tab/launch name. Session ID and branch leaf are null
|
|
41
|
+
in this slice. An explicitly supplied `--session` path can be recorded, but does not prove existence.
|
|
42
|
+
- `state`: `running` checkpoint or `terminal`; no terminal manifest means observation is incomplete.
|
|
43
|
+
- `outcome`: nullable numeric exit code and signal, timeout/abort/truncation/failure flags. A check whose
|
|
44
|
+
control record fails can have child exit code 0 and `failed:true`; its required receipt failure still throws.
|
|
45
|
+
- `content`: `stdout`, `stderr`, `paneSnapshot`, `result`, `checkReceipt`, `session`. Every member is either
|
|
46
|
+
`{status:"missing",path:null,sha256:null,bytes:null}` or
|
|
47
|
+
`{status:"retained",path:<basename>,sha256:<hex>,bytes:<length>}`. `retained` means the producer wrote those
|
|
48
|
+
exact bytes before publishing that checkpoint, **not** that an external archive still possesses them.
|
|
49
|
+
- `coverage`: `complete:false` and explicit loss reasons. This slice never claims evidence completeness.
|
|
50
|
+
- `acceptance`: always `not-assessed`. No receipt, tool result, terminal outcome or digest implies acceptance.
|
|
51
|
+
|
|
52
|
+
`stdout`/`stderr` are separate raw bytes, including available structured JSON output, not parsed into
|
|
53
|
+
trusted facts. Their cross-stream interleaving is not reconstructed. `result` is the exact executor's
|
|
54
|
+
assembled UTF-8 result before delegation display trimming; for checks its digest matches the returned
|
|
55
|
+
receipt's `output_sha256`. `paneSnapshot` replaces prior snapshots and is not a session transcript.
|
|
56
|
+
`checkReceipt` contains **the complete JSON serialization of the actual CheckReceipt plus LF**, including
|
|
57
|
+
all fields, not just `receipt_id`. Available receipt bytes survive later required ledger failure; that
|
|
58
|
+
failure still rejects the check. Absent receipt content stays missing.
|
|
59
|
+
|
|
60
|
+
## Bounds, loss, and privacy
|
|
61
|
+
|
|
62
|
+
At most 32 admitted observations are active. Each buffers at most 1 MiB of stream/snapshot data,
|
|
63
|
+
plus separate 1 MiB allowances for an indivisible result and an indivisible receipt. Oversize receipts
|
|
64
|
+
or results are missing, never represented by partial retained bytes. Streams may drop with explicit
|
|
65
|
+
loss reasons. Checkpoints coalesce; this is not an unbounded event queue. Archive errors become `lost`;
|
|
66
|
+
returned tool details may still say `pending` when publication has not completed. Treat pending,
|
|
67
|
+
missing files, invalid hashes, running-only checkpoints and all coverage gaps as incomplete, not success.
|
|
68
|
+
A whole producer-process crash can prevent final publication; this is not an fsync/crash-durability promise.
|
|
69
|
+
External hosts may call `flush()` at quiescence with their own timeout; worker control never does so.
|
|
70
|
+
|
|
71
|
+
No auth files, ambient environment dump, task text, monitoring state, or native transcript directory is
|
|
72
|
+
harvested. Retained output is untrusted and **can itself contain secrets printed by a worker**; no general
|
|
73
|
+
secret-redaction claim is made. Opt in only at an access-controlled harness archive boundary with an
|
|
74
|
+
appropriate content-handling policy. This is not malicious-filesystem race containment.
|
|
75
|
+
|
|
76
|
+
## Explicit prerequisite gap
|
|
77
|
+
|
|
78
|
+
Existing governed plans normally use `--no-session`. Existing Herdr replies used here expose pane/tab
|
|
79
|
+
identity, not a verified pi session ID, session file, or active branch. This slice does not change that
|
|
80
|
+
privacy/control default, read auth/session directories, invent a session join, or infer branch identity
|
|
81
|
+
from output. Therefore native session/transcript retention and verified session/branch TUI joins remain
|
|
82
|
+
**missing** pending a separately agreed native identity/session-export seam. P03 must not treat pane ID,
|
|
83
|
+
logical name, process PID, a requested session path, or output-shaped labels as that seam.
|
|
84
|
+
|
|
85
|
+
## Public consumer example
|
|
86
|
+
|
|
87
|
+
After a fresh build (the owner's historical dist is NOT current compiled proof):
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
import { readFile } from 'node:fs/promises';
|
|
91
|
+
import { dirname, join } from 'node:path';
|
|
92
|
+
import { verifyRetainedBytes } from 'pi-daddy/execution-retention';
|
|
93
|
+
|
|
94
|
+
const m = JSON.parse(await readFile(manifestPath, 'utf8'));
|
|
95
|
+
if (m.version !== '1.0') throw Error('unsupported retention version');
|
|
96
|
+
const ref = m.content.checkReceipt;
|
|
97
|
+
let bytes;
|
|
98
|
+
if (ref.status === 'retained' && /^checkReceipt-[a-f0-9]{64}\.bin$/.test(ref.path)) {
|
|
99
|
+
try { bytes = await readFile(join(dirname(manifestPath), ref.path)); } catch { /* missing */ }
|
|
100
|
+
}
|
|
101
|
+
const observed = verifyRetainedBytes(ref, bytes); // retained | missing | mismatch
|
|
102
|
+
// Even retained + terminal is NOT accepted work. Reconstruct independent P01 authority separately.
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Apply archive size/path policies before reading untrusted manifests/blobs; never follow arbitrary paths.
|
|
106
|
+
`test/execution-retention.test.ts` supplies ordinary producer/consumer fixtures: real credential-free
|
|
107
|
+
fixture processes through public concurrent tools, interrupted structured bytes, complete real check
|
|
108
|
+
receipt generation with a **synthetic Git identity transport**, and deterministic Herdr replies. These
|
|
109
|
+
are not real pi/model/Herdr integration, real Git candidate assurance, installed smoke or formal acceptance.
|