pi-daddy 0.24.0 → 0.25.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 +10 -0
- package/README.md +11 -3
- package/contracts/ledger/v4/README.md +1 -1
- package/dist/daily-dashboard-host.d.ts +26 -2
- package/dist/daily-dashboard-host.d.ts.map +1 -1
- package/dist/daily-dashboard-host.js +78 -8
- package/dist/daily-dashboard-host.js.map +1 -1
- package/dist/dashboard-handshake.d.ts.map +1 -1
- package/dist/dashboard-handshake.js +13 -4
- package/dist/dashboard-handshake.js.map +1 -1
- package/dist/dashboard-harness.d.ts +1 -1
- package/dist/dashboard-harness.js +3 -3
- package/dist/dashboard-harness.js.map +1 -1
- package/dist/dashboard-herdr.d.ts +1 -0
- package/dist/dashboard-herdr.d.ts.map +1 -1
- package/dist/dashboard-herdr.js +10 -8
- package/dist/dashboard-herdr.js.map +1 -1
- package/dist/dashboard-host-contract.d.ts +10 -1
- package/dist/dashboard-host-contract.d.ts.map +1 -1
- package/dist/dashboard-host-contract.js +1 -1
- package/dist/dashboard-host-contract.js.map +1 -1
- package/dist/dashboard-host.d.ts +8 -0
- package/dist/dashboard-host.d.ts.map +1 -1
- package/dist/dashboard-host.js +24 -6
- package/dist/dashboard-host.js.map +1 -1
- package/dist/dashboard-observation.d.ts.map +1 -1
- package/dist/dashboard-observation.js +1 -0
- package/dist/dashboard-observation.js.map +1 -1
- package/dist/experiment.d.ts.map +1 -1
- package/dist/experiment.js +9 -4
- package/dist/experiment.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/intent-application.d.ts.map +1 -1
- package/dist/intent-application.js +3 -2
- package/dist/intent-application.js.map +1 -1
- package/dist/measured-order.d.ts +249 -0
- package/dist/measured-order.d.ts.map +1 -0
- package/dist/measured-order.js +251 -0
- package/dist/measured-order.js.map +1 -0
- package/dist/measured-session.d.ts +97 -0
- package/dist/measured-session.d.ts.map +1 -0
- package/dist/measured-session.js +134 -0
- package/dist/measured-session.js.map +1 -0
- package/dist/work-command.d.ts +2 -0
- package/dist/work-command.d.ts.map +1 -1
- package/dist/work-command.js +15 -2
- package/dist/work-command.js.map +1 -1
- package/extensions/daily-dashboard-session.ts +9 -8
- package/extensions/grants-command.ts +2 -0
- package/extensions/grants.ts +1 -1
- package/package.json +13 -1
- package/src/daily-dashboard-host.ts +49 -10
- package/src/dashboard-handshake.ts +14 -5
- package/src/dashboard-harness.ts +3 -3
- package/src/dashboard-herdr.ts +12 -9
- package/src/dashboard-host-contract.ts +5 -2
- package/src/dashboard-host.ts +14 -9
- package/src/dashboard-observation.ts +1 -0
- package/src/experiment.ts +8 -3
- package/src/index.ts +17 -0
- package/src/intent-application.ts +3 -2
- package/src/measured-order.ts +67 -0
- package/src/measured-session.ts +70 -0
- package/src/work-command.ts +8 -2
package/dist/work-command.js
CHANGED
|
@@ -3,6 +3,7 @@ import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
4
|
import { appendWorkLedgerEventOnce, buildWorkOccurrenceEvent, buildWorkRevisionEvent, buildWorkSnapshotEvent, parseWorkLedgerText, projectWorkLedger, } from "./work-ledger.js";
|
|
5
5
|
import { withFileLock } from "./file-lock.js";
|
|
6
|
+
import { resolveWorkSnapshotText } from "./work-ledger-snapshot.js";
|
|
6
7
|
const ID = /^[A-Za-z0-9][A-Za-z0-9._:/@+\-]{0,127}$/;
|
|
7
8
|
const DIGEST = /^[a-f0-9]{64}$/;
|
|
8
9
|
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
|
|
@@ -71,8 +72,8 @@ export async function declareWork(input) {
|
|
|
71
72
|
if (!ID.test(input.id) || typeof input.outcome !== "string" || !input.outcome.trim())
|
|
72
73
|
throw new TypeError("work declaration requires an identifier and non-empty outcome");
|
|
73
74
|
const resolved = paths(input), outcomeDigest = sha256(input.outcome.trim());
|
|
74
|
-
await mkdir(dirname(resolved.ledgerPath), { recursive: true });
|
|
75
|
-
await mkdir(dirname(resolved.statePath), { recursive: true });
|
|
75
|
+
await mkdir(dirname(resolved.ledgerPath), { recursive: true, mode: 0o700 });
|
|
76
|
+
await mkdir(dirname(resolved.statePath), { recursive: true, mode: 0o700 });
|
|
76
77
|
return withFileLock(resolved.statePath, "declared work", async () => {
|
|
77
78
|
const existing = await loadDeclaredWork(resolved.statePath);
|
|
78
79
|
if (existing) {
|
|
@@ -125,6 +126,18 @@ export async function declareWork(input) {
|
|
|
125
126
|
return Object.freeze({ ...stored, statePath: resolved.statePath });
|
|
126
127
|
});
|
|
127
128
|
}
|
|
129
|
+
/** Persist an already-applied exact selection so the next governed dispatch cannot keep using the old cached declaration. */
|
|
130
|
+
export async function rebindDeclaredWork(state, selectedSnapshot) {
|
|
131
|
+
return withFileLock(state.statePath, "declared work rebind", async () => { const current = await loadDeclaredWork(state.statePath); if (!current || JSON.stringify(current.selectedSnapshot) !== JSON.stringify(state.selectedSnapshot))
|
|
132
|
+
throw Error("declared work rebind is stale; new dispatch remains unsupported"); const text = await readFile(state.ledgerPath, "utf8"), resolved = resolveWorkSnapshotText(text, selectedSnapshot), binding = resolved.snapshot?.bindings[0]; if (resolved.scopeState !== "valid" || !resolved.scope || !resolved.snapshot || !binding)
|
|
133
|
+
throw Error("applied declared selection cannot bind future dispatch"); const stored = { version: "pi-daddy-declared-work-v1", id: state.id, outcomeDigest: state.outcomeDigest, ledgerPath: state.ledgerPath, grantLedgerPath: state.grantLedgerPath, selectedSnapshot, scope: { kind: resolved.scope.kind, id: resolved.scope.id, revision: resolved.scope.revision, digest: resolved.scope.digest }, intent: binding.intent, obligation: binding.obligation, policy: binding.policy }; const temporary = `${state.statePath}.${process.pid}.${randomUUID()}.tmp`; try {
|
|
134
|
+
await writeFile(temporary, `${JSON.stringify(stored, null, 2)}\n`, { encoding: "utf8", mode: 0o600, flag: "wx" });
|
|
135
|
+
await rename(temporary, state.statePath);
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
await rm(temporary, { force: true });
|
|
139
|
+
} return Object.freeze({ ...stored, statePath: state.statePath }); });
|
|
140
|
+
}
|
|
128
141
|
export async function appendDeclaredWorkOccurrence(state, identity, occurrenceState) {
|
|
129
142
|
const { executionId, parentExecutionId, childId, variantId, now, ...rawLabels } = identity;
|
|
130
143
|
const label = (name, value) => value === null ? null : ID.test(value) ? value : `${name}:${sha256(value)}`;
|
package/dist/work-command.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-command.js","sourceRoot":"","sources":["../src/work-command.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"work-command.js","sourceRoot":"","sources":["../src/work-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { mkdir } from "node:fs/promises";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -10,21 +10,22 @@ import type { OrdinaryChildren } from "../src/ordinary-children.ts";
|
|
|
10
10
|
|
|
11
11
|
const BRIDGE=Symbol.for("skill-harness.dashboard-host.v1"),idPattern=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
12
12
|
export function dailyDashboardPaths(cwd:string,id:string,home=homedir(),uid=process.getuid?.()??0){const key=createHash("sha256").update(`${cwd}\0${id}`).digest("hex");return {directory:join(home,".local","state","pi-daddy","hosts",key.slice(0,16)),socketDirectory:join("/tmp",`pi-daddy-${uid}`),socketPath:join("/tmp",`pi-daddy-${uid}`,`host-${key.slice(0,20)}.sock`)};}
|
|
13
|
-
export function createDailyDashboardSession(input:{ordinary:()=>OrdinaryChildren;declared:()=>DeclaredWorkState|undefined;cwd:()=>string;env:Record<string,string|undefined>;author:string}){
|
|
14
|
-
let current:null|Awaited<ReturnType<typeof startDailyDashboardHost>>=null,publishedSocket:string|undefined;
|
|
13
|
+
export function createDailyDashboardSession(input:{ordinary:()=>OrdinaryChildren;declared:()=>DeclaredWorkState|undefined;rebind:(state:DeclaredWorkState)=>void;cwd:()=>string;env:Record<string,string|undefined>;author:string}){
|
|
14
|
+
let current:null|Awaited<ReturnType<typeof startDailyDashboardHost>>=null,publishedSocket:string|undefined,closing:null|{present:true;closing:true;evidenceDigest:string;expiresAt:number}=null;
|
|
15
15
|
return Object.freeze({
|
|
16
16
|
async run(target:string){
|
|
17
17
|
if(target==="stop"){
|
|
18
|
-
if(!current)return "daily host is not running";await current.close();current=null;if(publishedSocket&&input.env[ENV_DASHBOARD_HOST_SOCKET]===publishedSocket)delete input.env[ENV_DASHBOARD_HOST_SOCKET];publishedSocket=undefined;return "daily host stopped; no child was cancelled";
|
|
18
|
+
if(!current)return "daily host is not running";await current.close();current=null;closing=null;if(publishedSocket&&input.env[ENV_DASHBOARD_HOST_SOCKET]===publishedSocket)delete input.env[ENV_DASHBOARD_HOST_SOCKET];publishedSocket=undefined;return "daily host stopped; no child was cancelled";
|
|
19
19
|
}
|
|
20
|
-
if(
|
|
20
|
+
if(target==="closing"){if(!current)throw Error("daily host is not running");const expiresAt=Date.now()+120_000;closing={present:true,closing:true,evidenceDigest:createHash("sha256").update(`${input.cwd()}\0${expiresAt}\0${randomUUID()}`).digest("hex"),expiresAt};return "explicit closing presence recorded for two minutes; pause new dispatch and finish/cancel active attempts, then choose prepare-case-cards in the dashboard. No card is counted as delivered until visibly acknowledged.";}
|
|
21
|
+
if(!idPattern.test(target))throw Error("usage — /grants host <fresh-id> | closing | stop");if(current)throw Error("daily host already running in this session; use closing or stop");
|
|
21
22
|
const declared=input.declared();if(!declared)throw Error("declare current work first with pi-daddy work add, then reload");
|
|
22
23
|
const bridge=(globalThis as Record<PropertyKey,unknown>)[BRIDGE];if(!bridge)throw Error("loaded skill-harness extension bridge unavailable; load the candidate skill-harness extension in this Pi session");
|
|
23
24
|
const paths=dailyDashboardPaths(input.cwd(),target);await mkdir(join(homedir(),".local","state","pi-daddy","hosts"),{recursive:true,mode:0o700});await mkdir(paths.socketDirectory,{recursive:true,mode:0o700});
|
|
24
|
-
current=await startDailyDashboardHost({id:target,cwd:input.cwd(),directory:paths.directory,socketPath:paths.socketPath,declared,ordinary:input.ordinary(),harness:adoptDashboardHarnessBridge(bridge) as never,author:input.author});
|
|
25
|
+
current=await startDailyDashboardHost({id:target,cwd:input.cwd(),directory:paths.directory,socketPath:paths.socketPath,declared,ordinary:input.ordinary(),harness:adoptDashboardHarnessBridge(bridge) as never,author:input.author,presence:()=>closing,onDeclaredWorkChanged:input.rebind});
|
|
25
26
|
publishedSocket=current.socketPath;input.env[ENV_DASHBOARD_HOST_SOCKET]=publishedSocket;
|
|
26
|
-
return `daily host started at ${publishedSocket}; current declared work/facts were captured. Run /grants dashboard, then use only its listed pause/resume/refresh action keys. Runtime remains unaccepted.`;
|
|
27
|
+
return `daily host started at ${publishedSocket}; current declared work/facts were captured. Run /grants dashboard, then use only its listed pause/resume/refresh/cancel/scope/priority/alternative action keys. Runtime remains unaccepted.`;
|
|
27
28
|
},
|
|
28
|
-
async close(){if(current)await current.close();if(publishedSocket&&input.env[ENV_DASHBOARD_HOST_SOCKET]===publishedSocket)delete input.env[ENV_DASHBOARD_HOST_SOCKET];current=null;publishedSocket=undefined;}
|
|
29
|
+
async close(){if(current)await current.close();if(publishedSocket&&input.env[ENV_DASHBOARD_HOST_SOCKET]===publishedSocket)delete input.env[ENV_DASHBOARD_HOST_SOCKET];current=null;closing=null;publishedSocket=undefined;}
|
|
29
30
|
});
|
|
30
31
|
}
|
|
@@ -102,6 +102,8 @@ handler: async (args: string, ctx: any) => {
|
|
|
102
102
|
if (sub === "variants") {
|
|
103
103
|
const lines=[`grants: ${variantRuns.size} retained primary/shadow run(s)`];
|
|
104
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
|
+
lines.push(" provider usage unavailable on the default child print transport; fan-out, output bytes and wall time remain controller-bounded");
|
|
106
|
+
lines.push(" opt-in measured no-tool sessions can retain Pi Usage for exact Sol/Terra attempts; this is not ordinary-child or subscription-billing coverage");
|
|
105
107
|
ctx.ui.notify(lines.join("\n"),"info");return;
|
|
106
108
|
}
|
|
107
109
|
|
package/extensions/grants.ts
CHANGED
|
@@ -65,7 +65,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
65
65
|
|
|
66
66
|
const session = createGrantsSession(extensionPath);
|
|
67
67
|
associateOrdinaryHost(pi,session);
|
|
68
|
-
const dailyHost=createDailyDashboardSession({ordinary:()=>ordinaryChildrenFor(pi),declared:()=>session.declaredWork,cwd:()=>session.cwd,env:process.env,author:"local-operator"});
|
|
68
|
+
const dailyHost=createDailyDashboardSession({ordinary:()=>ordinaryChildrenFor(pi),declared:()=>session.declaredWork,rebind:state=>{session.declaredWork=state;},cwd:()=>session.cwd,env:process.env,author:"local-operator"});
|
|
69
69
|
const dashboardPluginRoot = fileURLToPath(new URL("../herdr-plugin/", import.meta.url));
|
|
70
70
|
const dashboardPaths = defaultDashboardPaths(
|
|
71
71
|
process.env.PI_CODING_AGENT_DIR?.trim() || join(homedir(), ".pi", "agent"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-daddy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Capability governance for pi sub-agents: spawn Agent Skills (SKILL.md) definitions whose allowed-tools becomes a grant that can only narrow going down a delegation tree, enforced by pi's own --tools allowlist, with an append-only ledger.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -53,6 +53,10 @@
|
|
|
53
53
|
"types": "./dist/dashboard-harness.d.ts",
|
|
54
54
|
"default": "./dist/dashboard-harness.js"
|
|
55
55
|
},
|
|
56
|
+
"./daily-dashboard-host": {
|
|
57
|
+
"types": "./dist/daily-dashboard-host.d.ts",
|
|
58
|
+
"default": "./dist/daily-dashboard-host.js"
|
|
59
|
+
},
|
|
56
60
|
"./dashboard-host": {
|
|
57
61
|
"types": "./dist/dashboard-host.d.ts",
|
|
58
62
|
"default": "./dist/dashboard-host.js"
|
|
@@ -94,6 +98,14 @@
|
|
|
94
98
|
"types": "./dist/effect-profile.d.ts",
|
|
95
99
|
"default": "./dist/effect-profile.js"
|
|
96
100
|
},
|
|
101
|
+
"./measured-session": {
|
|
102
|
+
"types": "./dist/measured-session.d.ts",
|
|
103
|
+
"default": "./dist/measured-session.js"
|
|
104
|
+
},
|
|
105
|
+
"./measured-order": {
|
|
106
|
+
"types": "./dist/measured-order.d.ts",
|
|
107
|
+
"default": "./dist/measured-order.js"
|
|
108
|
+
},
|
|
97
109
|
"./execution-retention": {
|
|
98
110
|
"types": "./dist/execution-retention.d.ts",
|
|
99
111
|
"default": "./dist/execution-retention.js"
|
|
@@ -4,16 +4,37 @@ import { isAbsolute, resolve, join } from "node:path";
|
|
|
4
4
|
import { createDashboardHost, dashboardHostDigest, dashboardHostRequestDigest, type DashboardHostAuthority, type DashboardHostConfig, type DashboardHostRequest } from "./dashboard-host.ts";
|
|
5
5
|
import type { DashboardHarness } from "./dashboard-host-contract.ts";
|
|
6
6
|
import { loadedDashboardHarnessDigest } from "./dashboard-harness.ts";
|
|
7
|
-
import {
|
|
7
|
+
import { createIntentBudget, openResourceBudget, resourceBindingDigest } from "./resource-budget.ts";
|
|
8
8
|
import { dispatchRequestDigest, type DispatchRequest } from "./dispatch-control.ts";
|
|
9
9
|
import { serveDashboardHost } from "./dashboard-host-transport.ts";
|
|
10
|
-
import type
|
|
11
|
-
import type
|
|
10
|
+
import { rebindDeclaredWork, type DeclaredWorkState } from "./work-command.ts";
|
|
11
|
+
import { ordinaryCancellation, ordinaryCancellationDigest, type OrdinaryChildren, type OrdinaryTarget } from "./ordinary-children.ts";
|
|
12
12
|
import { dataDigest } from "./debrief-contract.ts";
|
|
13
|
+
import { bindWorkIntent } from "./intent-application.ts";
|
|
14
|
+
import { intentKey, intentRequest, intentRequestDigest, type IntentPriority, type IntentRequest, type IntentSelection } from "./intent-control.ts";
|
|
15
|
+
import { parseWorkLedgerText, type WorkRevisionEvent, type WorkSnapshotEvent } from "./work-ledger.ts";
|
|
16
|
+
import { resolveWorkSnapshotText } from "./work-ledger-snapshot.ts";
|
|
13
17
|
|
|
14
|
-
export interface
|
|
18
|
+
export interface DailyIntentAction {key:string;label:string;action:"revise-scope"|"reprioritize"|"select-alternative";fromSelection:IntentSelection;events:(WorkRevisionEvent|WorkSnapshotEvent)[];selection:IntentSelection;priorities:IntentPriority[]}
|
|
19
|
+
export interface DailyDashboardHostInput {id:string;cwd:string;directory:string;socketPath?:string;declared:DeclaredWorkState;ordinary:OrdinaryChildren;harness:DashboardHarness;author:string;priorities?:IntentPriority[];intentActions?:DailyIntentAction[];presence?:()=>{present:boolean;closing:boolean;evidenceDigest:string;expiresAt:number}|null;onDeclaredWorkChanged?:(state:DeclaredWorkState)=>void|Promise<void>}
|
|
15
20
|
const idPattern=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
16
21
|
const hash=(value:string)=>createHash("sha256").update(value).digest("hex");
|
|
22
|
+
const same=(a:unknown,b:unknown)=>intentKey(a)===intentKey(b);
|
|
23
|
+
/** Recorded P01 snapshots become labelled proposals; choosing a label still traverses intent validation and exact host/CAS authority. */
|
|
24
|
+
export function discoverDailyIntentActions(text:string,selection:IntentSelection,priorities:readonly IntentPriority[]):DailyIntentAction[]{
|
|
25
|
+
const parsed=parseWorkLedgerText(text);if(!parsed.complete||parsed.events.length>512)throw Error("bounded complete recorded proposal ledger required");const label=(value:string)=>value.length<=80?value:`${value.slice(0,67)}…${hash(value).slice(0,12)}`;
|
|
26
|
+
const current=resolveWorkSnapshotText(text,selection);if(current.scopeState!=="valid"||!current.scope||!current.snapshot)throw Error("current declared work unavailable");
|
|
27
|
+
const actions:DailyIntentAction[]=[];for(const priority of priorities.slice(1)){
|
|
28
|
+
const ordered=[priority,...priorities.filter(x=>!same(x.obligation,priority.obligation))].map((x,rank)=>({...x,rank}));
|
|
29
|
+
actions.push({key:`priority-${hash(intentKey(priority.obligation)).slice(0,12)}`,label:`Put ${label(priority.obligation.id)} first`,action:"reprioritize",fromSelection:selection,events:[],selection,priorities:ordered});
|
|
30
|
+
}
|
|
31
|
+
for(const event of parsed.events){if(event.event!=="work_snapshot")continue;const candidate={snapshot:{id:event.payload.snapshot.snapshotId,digest:event.payload.snapshot.digest},event:{eventId:event.eventId,digest:event.digest}};if(same(candidate,selection))continue;
|
|
32
|
+
const next=resolveWorkSnapshotText(text,candidate);if(next.scopeState!=="valid"||!next.scope||!next.snapshot||next.snapshot.bindings.length>32)continue;
|
|
33
|
+
const action=next.scope.digest===current.scope.digest?"select-alternative":next.scope.predecessor&&same(next.scope.predecessor,{kind:current.scope.kind,id:current.scope.id,revision:current.scope.revision,digest:current.scope.digest})?"revise-scope":null;if(!action)continue;
|
|
34
|
+
actions.push({key:`${action==="revise-scope"?"scope":"alternative"}-${hash(intentKey(candidate)).slice(0,12)}`,label:`Select recorded ${action==="revise-scope"?"scope":"alternative"} ${label(event.payload.snapshot.snapshotId)}`,action,fromSelection:selection,events:[],selection:candidate,priorities:next.snapshot.bindings.map((b,rank)=>({obligation:b.obligation,rank}))});
|
|
35
|
+
}
|
|
36
|
+
return actions.sort((a,b)=>a.key.localeCompare(b.key)).slice(0,8);
|
|
37
|
+
}
|
|
17
38
|
|
|
18
39
|
/** One explicitly started, process-owned daily host. No authority, controller or prior host is recovered from disk. */
|
|
19
40
|
export async function startDailyDashboardHost(input:DailyDashboardHostInput){
|
|
@@ -22,7 +43,7 @@ export async function startDailyDashboardHost(input:DailyDashboardHostInput){
|
|
|
22
43
|
if(input.declared.ledgerPath!==join(input.cwd,".pi","work.jsonl"))throw Error("current declared work must belong to this host project");
|
|
23
44
|
await mkdir(input.directory,{mode:0o700});const archiveRoot=join(input.directory,"archive");await mkdir(archiveRoot,{mode:0o700});
|
|
24
45
|
const reference=input.harness.retainArchiveSource(archiveRoot,{sourceId:`host-${input.id}-bootstrap`,parser:{id:"daily-host-bootstrap",version:"1"},retention:"exact",bytes:Buffer.from("explicit daily host bootstrap")});
|
|
25
|
-
const component={kind:"detector",id:"
|
|
46
|
+
const component={kind:"detector",id:"coverage_gap",version:"work-signals-v1:declared-work-v1",population:`daily:${input.id}`};
|
|
26
47
|
const trustInput={archiveRoot,component,seed:hash(`daily-host\0${input.id}`),maxUnflagged:0,cohort:[{incidentId:"bootstrap",manifestId:reference.manifestId,flagged:true,split:"calibration"}],exposure:null};
|
|
27
48
|
const trustPolicyId=input.harness.trustPolicyDigest(trustInput),trustDirectory=join(input.directory,"trust");input.harness.createTrustLifecycle(trustDirectory,trustInput,[trustPolicyId]);
|
|
28
49
|
const workRelative="work.jsonl",factsRelative="facts.jsonl",workMirror=join(input.directory,workRelative);await writeFile(workMirror,await readFile(input.declared.ledgerPath),{mode:0o600,flag:"wx"});
|
|
@@ -30,18 +51,36 @@ export async function startDailyDashboardHost(input:DailyDashboardHostInput){
|
|
|
30
51
|
const facts={scopeDigest:input.declared.selectedSnapshot.snapshot.digest,version:"declared-work-v1",population:`daily:${input.id}`,expectedWaits:[],checkpoints:[],violations:[],priorAccepted:[]};await writeFile(join(input.directory,factsRelative),JSON.stringify(facts)+"\n",{mode:0o600,flag:"wx"});
|
|
31
52
|
const policy={version:"archive-policy-v2",id:`daily-${input.id}`,revision:"1",sourceRoot:input.directory,archiveRoot,maxBytes:8*1024*1024,retention:"exact",expiresAt:new Date(Date.now()+24*60*60*1000).toISOString(),sources:[{id:"work",path:workRelative,parser:{id:"pi-daddy-work-ledger",version:"4"},contentPolicy:"manifest-only"},{id:"facts",path:factsRelative,parser:{id:"pi-daddy-work-signal-facts",version:"1"},contentPolicy:"manifest-only"}]};
|
|
32
53
|
const policyPath=join(input.directory,"archive-policy.json"),policyBytes=JSON.stringify(policy);await writeFile(policyPath,policyBytes,{mode:0o600,flag:"wx"});
|
|
33
|
-
const authorityDigest=dataDigest({kind:"daily-dashboard-host",id:input.id,cwd:input.cwd}),
|
|
54
|
+
const authorityDigest=dataDigest({kind:"daily-dashboard-host",id:input.id,cwd:input.cwd}),initialPriorities=input.priorities??[{obligation:input.declared.obligation,rank:0}];
|
|
55
|
+
const workIntent=await bindWorkIntent({path:input.declared.ledgerPath,grantLedgerPath:input.declared.grantLedgerPath,selection:input.declared.selectedSnapshot,priorities:initialPriorities});
|
|
56
|
+
const budget=await createIntentBudget({directory:join(input.directory,"budget"),authorityDigest,limits:{maxAttempts:6,maxInputBytes:65536,maxConcurrent:3}},workIntent);
|
|
34
57
|
const config:DashboardHostConfig={version:"producer-dashboard-host-v1",trustDirectory,trustPolicyId,archiveRoot,scope:`daily:${input.id}`,author:input.author,policyPath,policySha256:hash(policyBytes),sources:[{id:"work",kind:"work"},{id:"facts",kind:"facts"}],selection:input.declared.selectedSnapshot,cases:null,blind:null,budgetDigest:resourceBindingDigest(budget),experimentDigest:null,harnessArtifactDigest:harnessDigest,ordinaryDigest:input.ordinary.bindingDigest};
|
|
35
|
-
const
|
|
36
|
-
const
|
|
58
|
+
const proposals=input.intentActions??[];if(proposals.length>8||new Set(proposals.map(x=>x.key)).size!==proposals.length||proposals.some(x=>!idPattern.test(x.key)||typeof x.label!=="string"||!x.label.trim()||Buffer.byteLength(x.label)>120))throw Error("bounded friendly intent actions required");
|
|
59
|
+
const requestDigests=new Set<string>(),dispatchDigests=new Set<string>(),ordinaryDigests=new Set<string>();let host:ReturnType<typeof createDashboardHost>,factsResultManifest:string|null=null,workSelection:IntentSelection=input.declared.selectedSnapshot,declaredState=input.declared,reboundSnapshotId:string|null=null;
|
|
60
|
+
const authority=():DashboardHostAuthority=>({hostDigests:[dashboardHostDigest(config)],requestDigests:[...requestDigests],workContext:{selectedSnapshot:workSelection,authority:null},dispatch:{authorityDigest,requestDigests:[...dispatchDigests]},experiment:null,ordinary:{bindingDigest:input.ordinary.bindingDigest,requestDigests:[...ordinaryDigests]}});
|
|
37
61
|
const request=(context:{hostDigest:string;selectionDigest:string;tip:string},operation:DashboardHostRequest["operation"],payload:unknown,requestId:string):DashboardHostRequest=>({version:"1.0",requestId,hostDigest:context.hostDigest,selectionDigest:context.selectionDigest,expectedTip:context.tip,operation,payload});
|
|
38
62
|
host=createDashboardHost({harness:input.harness,config,budget,ordinary:input.ordinary,authority,beforeObservation:sourceId=>sourceId==="work"?refreshWork():Promise.resolve(),humanActions:async context=>{
|
|
39
63
|
const state=await openResourceBudget(budget).controls(null).inspect(),action=state.paused?"resume-dispatch":"pause-dispatch",key=state.paused?"resume-dispatch":"pause-new-dispatch";
|
|
40
64
|
const native:DispatchRequest={version:"1.0",requestId:`${action}:${state.revision}`,bindingDigest:config.budgetDigest,expectedRevision:state.revision,action,targetExecutionId:null};dispatchDigests.add(dispatchRequestDigest(native));
|
|
41
65
|
const hostRequest=request(context,"dispatch",native,`host-${action}:${state.revision}`);requestDigests.add(dashboardHostRequestDigest(hostRequest));
|
|
42
66
|
const previous=context.observations.find(x=>x.sourceId==="work")?.checkpointId??null,refresh=request(context,"observe",{sourceId:"work",previousCheckpointId:previous,facts:context.observations.find(x=>x.sourceId==="facts")?.checkpointId?factsResultManifest:null},`refresh-work:${state.revision}:${context.tip.slice(0,12)}`);requestDigests.add(dashboardHostRequestDigest(refresh));
|
|
43
|
-
|
|
44
|
-
|
|
67
|
+
const intentState=await openResourceBudget(budget).intentControls(null).inspect(),automatic=discoverDailyIntentActions(await readFile(input.declared.ledgerPath,"utf8"),intentState.selection,intentState.priorities);
|
|
68
|
+
const candidates=[...proposals,...automatic].filter((p,index,all)=>all.findIndex(x=>x.key===p.key)===index).filter(p=>p.action==="reprioritize"||Boolean(input.onDeclaredWorkChanged)).slice(0,8);
|
|
69
|
+
const intents=(input.ordinary.quiescent()?candidates:[]).filter(p=>intentKey(p.fromSelection)===intentKey(intentState.selection)).map(p=>{
|
|
70
|
+
const native=intentRequest({version:"intent-request-v1",requestId:`${p.key}:${intentState.revision}`,bindingDigest:config.budgetDigest,expectedRevision:intentState.revision,expectedSelection:intentState.selection,action:p.action,events:p.events,selection:p.selection,priorities:p.priorities});dispatchDigests.add(intentRequestDigest(native));
|
|
71
|
+
const proposed=request(context,"intent",native,`host-intent:${p.key}:${intentState.revision}`);requestDigests.add(dashboardHostRequestDigest(proposed));return {key:p.key,label:p.label,request:proposed};
|
|
72
|
+
});
|
|
73
|
+
const ordinary=input.ordinary.inspect() as {revision:number;children:{target:OrdinaryTarget;state:string}[]},accounting=await openResourceBudget(budget).inspect(),presence=input.presence?.();
|
|
74
|
+
const presentation:{key:string;label:string;request:DashboardHostRequest}[]=[];
|
|
75
|
+
if(context.preparedPresentationDigest){const shown=request(context,"presented",{frameDigest:context.preparedPresentationDigest},`host-presented:${state.revision}:${context.tip.slice(0,12)}`);requestDigests.add(dashboardHostRequestDigest(shown));presentation.push({key:"acknowledge-case-cards",label:"Acknowledge these case cards are visible",request:shown});}
|
|
76
|
+
else if(presence?.present===true&&presence.closing===true&&presence.expiresAt>Date.now()&&state.paused&&accounting.active===0&&!ordinary.children.some(row=>row.state==="active")){const present=request(context,"present",{userPresent:true,closing:true,evidenceDigest:presence.evidenceDigest,dispatchRevision:state.revision},`host-present:${state.revision}:${context.tip.slice(0,12)}`);requestDigests.add(dashboardHostRequestDigest(present));presentation.push({key:"prepare-case-cards",label:"Prepare up to five retained case cards",request:present});}
|
|
77
|
+
const cancellations=ordinary.children.filter(row=>row.state==="active").sort((a,b)=>a.target.executionId.localeCompare(b.target.executionId)).slice(0,8).map(row=>{
|
|
78
|
+
const native=ordinaryCancellation({version:"ordinary-cancel-v1",requestId:`cancel:${row.target.executionId.slice(5)}`,bindingDigest:input.ordinary.bindingDigest,expectedRevision:ordinary.revision,target:row.target});ordinaryDigests.add(ordinaryCancellationDigest(native));
|
|
79
|
+
const cancel=request(context,"ordinary-cancel",native,`host-cancel:${row.target.executionId.slice(5)}:${ordinary.revision}`);requestDigests.add(dashboardHostRequestDigest(cancel));
|
|
80
|
+
return {key:`cancel-${row.target.executionId.replace(":","-")}`,label:`Cancel running attempt ${row.target.executionId}`,request:cancel};
|
|
81
|
+
});
|
|
82
|
+
return [{key,label:state.paused?"Resume new governed dispatch":"Pause new governed dispatch; running children continue",request:hostRequest},{key:"refresh-current-work",label:reboundSnapshotId?`Capture rebound declared work; next dispatch uses ${reboundSnapshotId}`:"Capture current declared work and attempts",request:refresh},...intents,...presentation,...cancellations];
|
|
83
|
+
},afterIntentApplied:async selection=>{const rebound=await rebindDeclaredWork(declaredState,selection);declaredState=rebound;workSelection=selection;reboundSnapshotId=selection.snapshot.id;await input.onDeclaredWorkChanged?.(rebound);},presence:input.presence});
|
|
45
84
|
const before=await host.frame(),observeFacts=request({hostDigest:host.hostDigest,selectionDigest:before.selectionDigest,tip:before.tip},"observe",{sourceId:"facts",previousCheckpointId:null,facts:null},"observe-current-facts");requestDigests.add(dashboardHostRequestDigest(observeFacts));const factsResult=await host.action(observeFacts) as {result:{sourceManifestId:string}};factsResultManifest=factsResult.result.sourceManifestId;
|
|
46
85
|
const afterFacts=await host.frame(),observeWork=request({hostDigest:host.hostDigest,selectionDigest:afterFacts.selectionDigest,tip:afterFacts.tip},"observe",{sourceId:"work",previousCheckpointId:null,facts:factsResult.result.sourceManifestId},"observe-current-work");requestDigests.add(dashboardHostRequestDigest(observeWork));await host.action(observeWork);
|
|
47
86
|
const socketPath=input.socketPath??join(input.directory,"dashboard.sock"),server=await serveDashboardHost(socketPath,host);
|
|
@@ -88,22 +88,31 @@ export async function offerDashboardHandshake(input: DashboardHandshakeInput): P
|
|
|
88
88
|
if (preference) return "suppressed";
|
|
89
89
|
const plugin = await inspectDashboardPlugin(exec, input.pluginRoot);
|
|
90
90
|
if (plugin.state === "compatible") return "already-installed";
|
|
91
|
-
|
|
91
|
+
const replacingDifferentPackage = plugin.state === "incompatible" && plugin.incompatibility === "package-root";
|
|
92
|
+
if (plugin.state !== "absent" && !replacingDifferentPackage) {
|
|
92
93
|
input.ui.notify(`pi-daddy dashboard: ${plugin.diagnostic}`, "error");
|
|
93
94
|
return "failed";
|
|
94
95
|
}
|
|
95
96
|
|
|
97
|
+
const affirmative = replacingDifferentPackage ? "Relink and open" : "Install and open";
|
|
98
|
+
const choices = replacingDifferentPackage ? [affirmative, "Not now"] : [affirmative, "Not now", "Never ask"];
|
|
96
99
|
const choice = await input.ui.select(
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
replacingDifferentPackage
|
|
101
|
+
? "The pi-daddy dashboard is linked from a different package. Relink this bundled copy and open it?"
|
|
102
|
+
: "Herdr detected. Install and open the pi-daddy dashboard?",
|
|
103
|
+
choices,
|
|
99
104
|
);
|
|
100
|
-
if (choice
|
|
105
|
+
if (!choices.includes(choice ?? "")) {
|
|
101
106
|
// Escape, timeout and UI teardown return undefined. None is an operator choice, so none may become a
|
|
102
107
|
// durable preference merely because the dialog disappeared.
|
|
103
108
|
input.ui.notify("pi-daddy dashboard: installation prompt dismissed; no preference was stored.", "info");
|
|
104
109
|
return "deferred";
|
|
105
110
|
}
|
|
106
|
-
if (choice !==
|
|
111
|
+
if (choice !== affirmative) {
|
|
112
|
+
if (replacingDifferentPackage) {
|
|
113
|
+
input.ui.notify("pi-daddy dashboard: existing link unchanged; no preference was stored.", "info");
|
|
114
|
+
return "deferred";
|
|
115
|
+
}
|
|
107
116
|
const recorded = choice === "Never ask" ? "never" : "not-now";
|
|
108
117
|
await savePreference(input.preferencePath, recorded);
|
|
109
118
|
input.ui.notify(
|
package/src/dashboard-harness.ts
CHANGED
|
@@ -6,8 +6,8 @@ import { dataDigest,byteDigest,detached,sha } from "./debrief-contract.ts";
|
|
|
6
6
|
import { DASHBOARD_HARNESS_PIN,type DashboardHarness } from "./dashboard-host-contract.ts";
|
|
7
7
|
export interface DashboardHarnessArtifact {version:"dashboard-harness-artifact-v1";sourceCommit:typeof DASHBOARD_HARNESS_PIN;files:Record<string,string>;typeboxRoot:string;typeboxPackageSha256:string}
|
|
8
8
|
const loaded=new WeakMap<object,string>();
|
|
9
|
-
export const DASHBOARD_HARNESS_BRIDGE_SOURCE="
|
|
10
|
-
const bridgeFunctions=["learningJournal","createTrustLifecycle","openTrustLifecycle","trustPolicyDigest","archivePolicyBinding","ingestPolicySource","readArchiveCheckpoint","readArchiveSource","retainArchiveSource","captureArchivedWorkSignals","readRetainedExecution","projectRetainedExecutions","createWorkCaseReviewer","createWorkSignalReviewer","retainBlindIntervention","openBlindIntervention"] as const;
|
|
9
|
+
export const DASHBOARD_HARNESS_BRIDGE_SOURCE="d123257e53d48a2cad6919708976b5371dc7590e";
|
|
10
|
+
const bridgeFunctions=["learningJournal","createTrustLifecycle","openTrustLifecycle","trustPolicyDigest","archivePolicyBinding","ingestPolicySource","readArchiveCheckpoint","readArchiveSource","retainArchiveSource","captureArchivedWorkSignals","readRetainedExecution","projectRetainedExecutions","createWorkCaseReviewer","createWorkSignalReviewer","retainBlindIntervention","openBlindIntervention","retainLearningLifecycle","readLearningLifecycle"] as const;
|
|
11
11
|
/** Adopt the API published by the already-loaded skill-harness extension. Same-process source identity is not human authentication. */
|
|
12
12
|
export function adoptDashboardHarnessBridge(input:unknown):DashboardHarness{
|
|
13
13
|
const value=input as {version?:unknown;sourceCommit?:unknown;api?:unknown};
|
|
@@ -30,7 +30,7 @@ export async function loadDashboardHarness(artifactRoot:string,input:DashboardHa
|
|
|
30
30
|
if(content.get("package.json")?.toString()!=='{"type":"module"}')throw Error("explicit ESM artifact root required");
|
|
31
31
|
const directory=await mkdtemp(join(parent,"loaded-harness-"));for(const[p,b]of content){await mkdir(dirname(join(directory,p)),{recursive:true,mode:0o700});await writeFile(join(directory,p),b,{flag:"wx",mode:0o400});}
|
|
32
32
|
await mkdir(join(directory,"node_modules"));await symlink(manifest.typeboxRoot,join(directory,"node_modules/typebox"));
|
|
33
|
-
const names=["learning-journal","trust-lifecycle","archive-policy","archive-observer","archive-checkpoint","archived-work","execution-retention-archive","work-case-review","blind-intervention","evidence-archive","work-signal-observation","work-signal-cases","work-case-archive"];
|
|
33
|
+
const names=["learning-journal","trust-lifecycle","archive-policy","archive-observer","archive-checkpoint","archived-work","execution-retention-archive","work-case-review","blind-intervention","learning-lifecycle","evidence-archive","work-signal-observation","work-signal-cases","work-case-archive"];
|
|
34
34
|
const api=Object.assign({},...await Promise.all([...names.map(n=>"packages/adapters/src/"+n+".js"),"core.js"].map(p=>{if(!content.has(p))throw Error("missing genuine harness entry");return import(pathToFileURL(join(directory,p)).href);}))) as DashboardHarness;
|
|
35
35
|
for(const[p,digest]of files)if(byteDigest(await bytes(join(directory,p)))!==digest)throw Error("loaded harness bytes changed");
|
|
36
36
|
Object.freeze(api);const digest=dataDigest(manifest);loaded.set(api,digest);return Object.freeze({api,artifactDigest:digest,directory,manifest});
|
package/src/dashboard-herdr.ts
CHANGED
|
@@ -97,6 +97,7 @@ export type DashboardPluginState = "absent" | "disabled" | "compatible" | "incom
|
|
|
97
97
|
export interface DashboardPluginStatus {
|
|
98
98
|
state: DashboardPluginState;
|
|
99
99
|
diagnostic: string;
|
|
100
|
+
incompatibility?: "package-root" | "protocol";
|
|
100
101
|
plugin?: Record<string, unknown>;
|
|
101
102
|
}
|
|
102
103
|
|
|
@@ -116,15 +117,8 @@ export async function inspectDashboardPlugin(
|
|
|
116
117
|
const plugins = Array.isArray(parsed.result?.plugins) ? parsed.result.plugins as Record<string, unknown>[] : [];
|
|
117
118
|
const plugin = plugins.find((candidate) => candidate.plugin_id === DASHBOARD_PLUGIN_ID);
|
|
118
119
|
if (!plugin) return { state: "absent", diagnostic: `Herdr plugin ${DASHBOARD_PLUGIN_ID} is not installed.` };
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
if (expectedPluginRoot && (typeof plugin.plugin_root !== "string" || resolve(plugin.plugin_root) !== resolve(expectedPluginRoot))) {
|
|
122
|
-
return {
|
|
123
|
-
state: "incompatible",
|
|
124
|
-
diagnostic: `Herdr plugin ${DASHBOARD_PLUGIN_ID} is linked from a different package; relink the bundled copy.`,
|
|
125
|
-
plugin,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
120
|
+
// Protocol and provenance both precede enabled state. A root-only repair is offered only when the
|
|
121
|
+
// registered manifest already speaks this core's protocol; unknown software is never replaced by guesswork.
|
|
128
122
|
const major = protocolMajor(plugin.version);
|
|
129
123
|
if (major !== DASHBOARD_PROTOCOL_VERSION) {
|
|
130
124
|
return {
|
|
@@ -132,6 +126,15 @@ export async function inspectDashboardPlugin(
|
|
|
132
126
|
diagnostic:
|
|
133
127
|
`Herdr plugin ${DASHBOARD_PLUGIN_ID} uses protocol ${major ?? "unknown"}; ` +
|
|
134
128
|
`this pi-daddy core requires ${DASHBOARD_PROTOCOL_VERSION}. Relink both from the same package.`,
|
|
129
|
+
incompatibility: "protocol",
|
|
130
|
+
plugin,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (expectedPluginRoot && (typeof plugin.plugin_root !== "string" || resolve(plugin.plugin_root) !== resolve(expectedPluginRoot))) {
|
|
134
|
+
return {
|
|
135
|
+
state: "incompatible",
|
|
136
|
+
diagnostic: `Herdr plugin ${DASHBOARD_PLUGIN_ID} is linked from a different package; relink the bundled copy.`,
|
|
137
|
+
incompatibility: "package-root",
|
|
135
138
|
plugin,
|
|
136
139
|
};
|
|
137
140
|
}
|
|
@@ -5,7 +5,7 @@ import type { WorkProjectionContext, WorkFrozen } from "./work-ledger.ts";
|
|
|
5
5
|
import type { DispatchAuthority } from "./dispatch-control.ts";
|
|
6
6
|
import type { OrdinaryAuthority } from "./ordinary-children.ts";
|
|
7
7
|
import type { ExperimentAuthority } from "./experiment-contract.ts";
|
|
8
|
-
export const DASHBOARD_HARNESS_PIN = "
|
|
8
|
+
export const DASHBOARD_HARNESS_PIN = "d123257e53d48a2cad6919708976b5371dc7590e";
|
|
9
9
|
export interface HostEvent { id: string; prior: string | null; value: Record<string, unknown> }
|
|
10
10
|
export interface HostJournal { read(): HostEvent[]; append(prior: string, value: Record<string, unknown>): HostEvent }
|
|
11
11
|
/** Loaded trusted ports; an interface or caller-supplied pin is NOT module/human authentication. */
|
|
@@ -19,9 +19,11 @@ export interface DashboardHarness extends DebriefHarness {
|
|
|
19
19
|
ingestPolicySource(path: string, source: string, previous?: string, expectedPolicy?: string): { checkpointId: string; sourceStatus: string; issues?: string[]; [key: string]: unknown };
|
|
20
20
|
readArchiveCheckpoint(root: string, checkpoint: string): { checkpoint: { sourceManifestId: string; issues: string[]; [key: string]: unknown } };
|
|
21
21
|
readArchiveSource(root: string, id: string): { status: string; bytes?: Uint8Array; reference?: { retention: string; sha256: string; [key: string]: unknown } };
|
|
22
|
-
captureArchivedWorkSignals(root: string, id: string, context: WorkFrozen<WorkProjectionContext>, facts: unknown): { caseBatchId: string; observationId: string; linkageManifestId: string };
|
|
22
|
+
captureArchivedWorkSignals(root: string, id: string, context: WorkFrozen<WorkProjectionContext>, facts: unknown): { caseBatchId: string; observationId: string; linkageManifestId: string; runtimeFactsManifestId: string };
|
|
23
23
|
readRetainedExecution(root: string, id: string): { projection: unknown };
|
|
24
24
|
projectRetainedExecutions(values: readonly unknown[]): unknown;
|
|
25
|
+
retainLearningLifecycle(root:string,input:unknown):string;
|
|
26
|
+
readLearningLifecycle(root:string,id:string):{version:string;state:string;predecessorManifestId:string|null;links:Record<string,unknown>};
|
|
25
27
|
}
|
|
26
28
|
export interface DashboardHostConfig {
|
|
27
29
|
version: "producer-dashboard-host-v1"; trustDirectory: string; trustPolicyId: string; archiveRoot: string; scope: string; author: string;
|
|
@@ -29,6 +31,7 @@ export interface DashboardHostConfig {
|
|
|
29
31
|
selection: WorkProjectionContext["selectedSnapshot"]; cases: CaseSelection | null; blind: DurableBlindBinding | null;
|
|
30
32
|
budgetDigest: string; experimentDigest: string | null; harnessArtifactDigest: string;
|
|
31
33
|
ordinaryDigest?: string;
|
|
34
|
+
learningLifecycleId?: string;
|
|
32
35
|
}
|
|
33
36
|
export interface DashboardHostRequest { version: "1.0"; requestId: string; hostDigest: string; expectedTip: string; selectionDigest: string; operation: "observe" | "present" | "presented" | "defer" | "debrief" | "dispatch" | "intent" | "cancel" | "dispatch-reconcile" | "intent-reconcile" | "ordinary-cancel"; payload: unknown }
|
|
34
37
|
export interface DashboardHostAuthority {
|
package/src/dashboard-host.ts
CHANGED
|
@@ -18,15 +18,18 @@ export const isDashboardHost=(value:unknown):value is DashboardHost=>typeof valu
|
|
|
18
18
|
export type DashboardHost=ReturnType<typeof openDashboardHost>;
|
|
19
19
|
export interface DashboardHostOptions { ordinary?:OrdinaryChildren; harness:DashboardHarness; config:DashboardHostConfig; budget:GovernedBudgetBinding; experiment?:ReturnType<typeof openExperiment>; authority:()=>DashboardHostAuthority|null;
|
|
20
20
|
/** Exact actions constructed and authorized by the owner; the dashboard exposes only human labels/keys. */
|
|
21
|
-
humanActions?:(context:{hostDigest:string;selectionDigest:string;tip:string;observations:readonly {sourceId:string;checkpointId:string}[]})=>readonly {key:string;label:string;request:DashboardHostRequest}[]|Promise<readonly {key:string;label:string;request:DashboardHostRequest}[]>;
|
|
21
|
+
humanActions?:(context:{hostDigest:string;selectionDigest:string;tip:string;observations:readonly {sourceId:string;checkpointId:string}[];preparedPresentationDigest:string|null})=>readonly {key:string;label:string;request:DashboardHostRequest}[]|Promise<readonly {key:string;label:string;request:DashboardHostRequest}[]>;
|
|
22
22
|
/** Explicit approved observation effect only; refresh/frame never invokes it. */
|
|
23
23
|
beforeObservation?:(sourceId:string)=>Promise<void>;
|
|
24
|
+
/** Owner callback after the exact intent journal reports applied; failure keeps host acknowledgement unknown. */
|
|
25
|
+
afterIntentApplied?:(selection:IntentRequest["selection"])=>void|Promise<void>;
|
|
24
26
|
/** Independently sourced current declaration. Never inferred from idle, a PID, title or request fields. */
|
|
25
27
|
presence?:()=>{present:boolean;closing:boolean;evidenceDigest:string;expiresAt:number}|null;
|
|
26
28
|
}
|
|
27
29
|
function configuration(input:DashboardHostConfig){
|
|
28
|
-
const c=detached(input);controlShape(c,["version","trustDirectory","trustPolicyId","archiveRoot","scope","author","policyPath","policySha256","sources","selection","cases","blind","budgetDigest","experimentDigest","harnessArtifactDigest",...(Object.hasOwn(c,"ordinaryDigest")?["ordinaryDigest"]:[])]);
|
|
30
|
+
const c=detached(input);controlShape(c,["version","trustDirectory","trustPolicyId","archiveRoot","scope","author","policyPath","policySha256","sources","selection","cases","blind","budgetDigest","experimentDigest","harnessArtifactDigest",...(Object.hasOwn(c,"ordinaryDigest")?["ordinaryDigest"]:[]),...(Object.hasOwn(c,"learningLifecycleId")?["learningLifecycleId"]:[])]);
|
|
29
31
|
if(Object.hasOwn(c,"ordinaryDigest")&&!sha(c.ordinaryDigest))throw Error("invalid ordinary binding digest");
|
|
32
|
+
if(Object.hasOwn(c,"learningLifecycleId")&&!sha(c.learningLifecycleId))throw Error("invalid learning lifecycle manifest");
|
|
30
33
|
if(c.version!=="producer-dashboard-host-v1"||![c.trustDirectory,c.archiveRoot,c.policyPath].every(p=>typeof p==="string"&&isAbsolute(p))||![c.trustPolicyId,c.policySha256,c.budgetDigest,c.harnessArtifactDigest].every(sha)||!(c.experimentDigest===null||sha(c.experimentDigest))||typeof c.scope!=="string"||!c.scope||c.scope.length>128||typeof c.author!=="string"||!c.author||c.author.length>256||!Array.isArray(c.sources)||c.sources.length<1||c.sources.length>32||new Set(c.sources.map(s=>s.id)).size!==c.sources.length||c.sources.filter(s=>s.kind==="work").length>1||c.sources.some(s=>!/^[a-zA-Z0-9:_-]{1,128}$/.test(s.id)||!["work","retention","facts"].includes(s.kind)))throw Error("invalid explicit dashboard host binding");
|
|
31
34
|
return freeze(c);
|
|
32
35
|
}
|
|
@@ -56,7 +59,7 @@ export function openDashboardHost(options:DashboardHostOptions){
|
|
|
56
59
|
const observation=dashboardObservations(h,c,journal.read),history=()=>journal.read();
|
|
57
60
|
const append=(value:Record<string,unknown>)=>journal.append(history().at(-1)!.id,value);
|
|
58
61
|
const saved=():DebriefCheckpoint|null=>{const rows=history().filter(e=>e.value.type==="checkpoint");return rows.length?detached(rows.at(-1)!.value.checkpoint) as DebriefCheckpoint:null;};
|
|
59
|
-
let presenter:DebriefPresenter|undefined,busy=false,poisoned=false,presentationRevision:number|null=null,presenceDigest:string|null=null,attentionDeferred:string|null=null;
|
|
62
|
+
let presenter:DebriefPresenter|undefined,busy=false,poisoned=false,presentationRevision:number|null=null,presenceDigest:string|null=null,attentionDeferred:string|null=null,presentationAcknowledged=false;
|
|
60
63
|
const ordinaryDispatchHoldKey=dataDigest({hostDigest,control:"pause-new-ordinary-dispatch"});
|
|
61
64
|
let displayedActions:null|{tip:string;actions:{key:string;label:string;operation:DashboardHostRequest["operation"];request:DashboardHostRequest}[];digest:string}=null;
|
|
62
65
|
const presence=()=>{const p=options.presence?.();return p&&p.present===true&&p.closing===true&&sha(p.evidenceDigest)&&Number.isFinite(p.expiresAt)&&p.expiresAt>Date.now()?p:null;};
|
|
@@ -73,7 +76,7 @@ export function openDashboardHost(options:DashboardHostOptions){
|
|
|
73
76
|
const nativeRead=async()=>({dispatch:await budget.controls(null).inspect(),intent:budget.binding.intent?await budget.intentControls(null).inspect():null,experiment:experiment?await experiment.inspect():null,ordinary:ordinary?ordinary.inspect():null});
|
|
74
77
|
const availableHumanActions=async()=>{
|
|
75
78
|
const rows=history(),tip=rows.at(-1)!.id,selection=await currentSelection(),seen=new Set<string>();
|
|
76
|
-
const declared=await options.humanActions?.({hostDigest,selectionDigest:dashboardSelectionDigest(selection),tip,observations:observation.latest().map(x=>({sourceId:x.sourceId,checkpointId:x.checkpointId}))})??[],a=authority();
|
|
79
|
+
const declared=await options.humanActions?.({hostDigest,selectionDigest:dashboardSelectionDigest(selection),tip,observations:observation.latest().map(x=>({sourceId:x.sourceId,checkpointId:x.checkpointId})),preparedPresentationDigest:presenter&&presentationRevision!==null&&!presentationAcknowledged?dataDigest(presenter.view()):null})??[],a=authority();
|
|
77
80
|
return declared.map(value=>{const x=detached(value);controlShape(x,["key","label","request"]);const request=dashboardHostRequest(x.request);
|
|
78
81
|
if(!/^[a-zA-Z0-9:_-]{1,64}$/.test(x.key)||typeof x.label!=="string"||!x.label.trim()||Buffer.byteLength(x.label)>120||seen.has(x.key))throw Error("invalid human dashboard action");seen.add(x.key);
|
|
79
82
|
if(request.hostDigest!==hostDigest||request.expectedTip!==tip||request.selectionDigest!==dashboardSelectionDigest(selection)||!a?.requestDigests.includes(dashboardHostRequestDigest(request)))throw Error("human dashboard action is stale or not exactly authorized");
|
|
@@ -88,11 +91,12 @@ export function openDashboardHost(options:DashboardHostOptions){
|
|
|
88
91
|
let debrief:unknown=null;
|
|
89
92
|
if(a&&presenter&&presentationRevision!==null&&presence()?.evidenceDigest===presenceDigest){try{await paused(presentationRevision);debrief=presenter.view();}catch{debrief=null;}}
|
|
90
93
|
let controls:unknown=null;try{controls=await nativeRead();}catch(e){error=String(e);}
|
|
94
|
+
let learning:unknown=null;if(c.learningLifecycleId)try{learning=h.readLearningLifecycle(c.archiveRoot,c.learningLifecycleId);}catch(e){error=String(e);}
|
|
91
95
|
const attention=trust.inspect(Date.now());let actions:{key:string;label:string;operation:string}[]=[];
|
|
92
96
|
try{const available=await availableHumanActions(),digest=dataDigest(available.map(({key,label,operation,request})=>({key,label,operation,requestDigest:dashboardHostRequestDigest(request)})));
|
|
93
97
|
if(displayedActions?.tip===tip&&displayedActions.digest!==digest)throw Error("displayed dashboard actions changed before journal advance");
|
|
94
98
|
displayedActions={tip,actions:available,digest};actions=available.map(({key,label,operation})=>({key,label,operation}));}catch(e){error=String(e);}
|
|
95
|
-
return freeze(detached({version:"producer-dashboard-frame-v1",hostDigest,selectionDigest:dashboardSelectionDigest(selection),selectionState,tip,source,controls,debrief,attention,error,actions,
|
|
99
|
+
return freeze(detached({version:"producer-dashboard-frame-v1",hostDigest,selectionDigest:dashboardSelectionDigest(selection),selectionState,tip,source,controls,learning,debrief,attention,error,actions,
|
|
96
100
|
requests:rows.filter(e=>["claim","result","presentation","defer","ordinary-intent-pending"].includes(String(e.value.type))).map(e=>e.value),
|
|
97
101
|
control:rows.some(e=>e.value.type==="host-failure")?"failed":rows.some(e=>e.value.type==="claim"&&!rows.some(r=>r.value.type==="result"&&r.value.requestId===e.value.requestId))?"unknown":"not-assessed",
|
|
98
102
|
acknowledgement:poisoned?"unknown":"readback-only",identity:"independently-declared-host; not human/module authentication",activeBranch:null,acceptance:"not-assessed",freshness:"snapshot-unknown",workerInteractions:0}));
|
|
@@ -132,11 +136,11 @@ export function openDashboardHost(options:DashboardHostOptions){
|
|
|
132
136
|
attentionDeferred=null;const view=await presenter.open({mode:"manual",userPresent:true});await paused(p.dispatchRevision);
|
|
133
137
|
if(attentionDeferred){presenter.close();presentationRevision=null;append({type:"defer",requestId:request.requestId,reason:attentionDeferred,weekly:true});result={state:"deferred",reason:attentionDeferred};}
|
|
134
138
|
else {if(view.state!=="open")throw Error("presentation data/attention acknowledgement unavailable");
|
|
135
|
-
presentationRevision=p.dispatchRevision;presenceDigest=p.evidenceDigest;const frameDigest=dataDigest(view);append({type:"presentation",requestId:request.requestId,evidence:p,frameDigest,state:"prepared-not-delivery",automatic:"unqualified"});result={state:"prepared",frameDigest};}
|
|
139
|
+
presentationRevision=p.dispatchRevision;presenceDigest=p.evidenceDigest;presentationAcknowledged=false;const frameDigest=dataDigest(view);append({type:"presentation",requestId:request.requestId,evidence:p,frameDigest,state:"prepared-not-delivery",automatic:"unqualified"});result={state:"prepared",frameDigest};}
|
|
136
140
|
}
|
|
137
141
|
}else if(request.operation==="presented"){
|
|
138
142
|
const p=detached(request.payload) as {frameDigest:string};if(Object.keys(p).join()!=="frameDigest"||!presenter||presentationRevision===null)throw Error("original prepared presentation required");
|
|
139
|
-
await paused(presentationRevision);if(presence()?.evidenceDigest!==presenceDigest)throw Error("user absent/presence changed");if(p.frameDigest!==dataDigest(presenter.view()))throw Error("stale presentation acknowledgement");result={state:"host-acknowledged-presentation",frameDigest:p.frameDigest,humanAuthentication:"unqualified"};
|
|
143
|
+
await paused(presentationRevision);if(presence()?.evidenceDigest!==presenceDigest)throw Error("user absent/presence changed");if(p.frameDigest!==dataDigest(presenter.view()))throw Error("stale presentation acknowledgement");presentationAcknowledged=true;result={state:"host-acknowledged-presentation",frameDigest:p.frameDigest,humanAuthentication:"unqualified"};
|
|
140
144
|
}else if(request.operation==="defer"){
|
|
141
145
|
presenter?.close();presentationRevision=null;append({type:"defer",requestId:request.requestId,weekly:true,evidence:request.payload});result={state:"deferred"};
|
|
142
146
|
}else if(request.operation==="debrief"){
|
|
@@ -153,7 +157,7 @@ export function openDashboardHost(options:DashboardHostOptions){
|
|
|
153
157
|
}else if(request.operation==="intent"||request.operation==="intent-reconcile"){
|
|
154
158
|
const native=detached(intentRequest(request.payload as IntentRequest)) as IntentRequest,port=budget.intentControls(a!.dispatch),digest=intentRequestDigest(native);
|
|
155
159
|
if(c.ordinaryDigest&&!ordinary)throw Error("original ordinary boundary unavailable; no recovery");
|
|
156
|
-
if(!ordinary)result=request.operation==="intent"?await port.request(native):await port.reconcile(native);
|
|
160
|
+
if(!ordinary){result=request.operation==="intent"?await port.request(native):await port.reconcile(native);const snapshot=result as {selection:IntentRequest["selection"];records:{requestId:string;application:string}[]},outcome=snapshot.records.find(r=>r.requestId===native.requestId);if(outcome?.application==="applied")await options.afterIntentApplied?.(snapshot.selection);}
|
|
157
161
|
else {
|
|
158
162
|
const pending=history().filter(e=>e.value.type==="ordinary-intent-pending"&&e.value.nativeRequestId===native.requestId);
|
|
159
163
|
if(pending.some(e=>e.value.digest!==digest))throw Error("immutable pending ordinary intent ID");
|
|
@@ -167,8 +171,9 @@ export function openDashboardHost(options:DashboardHostOptions){
|
|
|
167
171
|
result={state:"pending-ordinary-boundary",nativeRequestId:native.requestId,application:"not-acknowledged"};
|
|
168
172
|
}else{
|
|
169
173
|
result=(request.operation==="intent"||pending.length>0&&!exists)?await port.request(native):await port.reconcile(native);
|
|
170
|
-
const
|
|
174
|
+
const snapshot=result as {selection:IntentRequest["selection"];records:{requestId:string;application:string}[]},outcome=snapshot.records.find(r=>r.requestId===native.requestId);
|
|
171
175
|
if(held&&!outcome)throw Error("native intent application acknowledgement unavailable");
|
|
176
|
+
if(outcome?.application==="applied")await options.afterIntentApplied?.(snapshot.selection);
|
|
172
177
|
if(held&&["applied","not-applied"].includes(outcome!.application))releaseOrdinary=held.release;
|
|
173
178
|
}
|
|
174
179
|
}
|
|
@@ -25,6 +25,7 @@ export function dashboardObservations(h: DashboardHarness, c: DashboardHostConfi
|
|
|
25
25
|
captured.factSourceManifestId=factSource?.sourceManifestId??null;captured.factBasis=factSource?"explicit-host-declarations-not-authenticated-truth":"derived-retained-work-only";
|
|
26
26
|
if(dataDigest(authority.workContext.selectedSnapshot)!==dataDigest(selection))throw Error("independent source selection changed");
|
|
27
27
|
try { const signals=h.captureArchivedWorkSignals(root,sourceManifestId,authority.workContext,facts);
|
|
28
|
+
captured.runtimeFactsManifestId=signals.runtimeFactsManifestId;
|
|
28
29
|
cases={version:"work-signals-v1",batchId:signals.caseBatchId,observationId:signals.observationId};linkageManifestId=signals.linkageManifestId;
|
|
29
30
|
} catch(error) { captured.semanticFailure=String(error); } // Retain checkpoint/gap even when nomination is unavailable.
|
|
30
31
|
} else {if(input.facts!==null||captured.kind!=="execution-retention-v2")throw Error("retention source requires exact referenced-blobs policy");h.readRetainedExecution(root,captured.checkpointId);}
|
package/src/experiment.ts
CHANGED
|
@@ -146,6 +146,12 @@ export function openExperiment(input: ExperimentBinding, hostAuthority: Experime
|
|
|
146
146
|
let resolve!: (success: boolean) => void;
|
|
147
147
|
return { promise: new Promise<boolean>(done => { resolve = done; }), done: (success: boolean) => resolve(success) };
|
|
148
148
|
});
|
|
149
|
+
// Public readiness includes the durable spawn observation, not merely process creation.
|
|
150
|
+
// This closes the process-start -> spawn-ledger race for inspect and cancellation callers.
|
|
151
|
+
const observedStarted = reserved.map((run, i) => run.started.then(async value => {
|
|
152
|
+
if (value === "spawned") await append({ type: "spawn", executionId: c.variants[i].executionId });
|
|
153
|
+
return value;
|
|
154
|
+
}));
|
|
149
155
|
const one = async (i: number) => {
|
|
150
156
|
const v = c.variants[i]; let success = false, launched = false, primaryResult: VariantRecord | null = null;
|
|
151
157
|
try {
|
|
@@ -155,8 +161,7 @@ export function openExperiment(input: ExperimentBinding, hostAuthority: Experime
|
|
|
155
161
|
launched = true;
|
|
156
162
|
const running = reserved[i].run(handles.get(v.executionId)!.signal);
|
|
157
163
|
// Consume both promises even on bookkeeping failure. No untracked rejection or worker.
|
|
158
|
-
const
|
|
159
|
-
const [result, observation] = await Promise.allSettled([running, observed]);
|
|
164
|
+
const [result, observation] = await Promise.allSettled([running, observedStarted[i]]);
|
|
160
165
|
if (result.status === "rejected" || observation.status === "rejected") throw new Error("runtime/accounting/observation unknown");
|
|
161
166
|
const data = Buffer.from(JSON.stringify(result.value) + "\n"), out = result.value.output;
|
|
162
167
|
const cancelled = out.aborted && (Boolean(out.signal) || await reserved[i].started === "settled-without-spawn");
|
|
@@ -218,7 +223,7 @@ export function openExperiment(input: ExperimentBinding, hostAuthority: Experime
|
|
|
218
223
|
}
|
|
219
224
|
const view = await inspect().catch(unknown); primary.resolve(view.variants[0]); resolveBoundary(view); return view;
|
|
220
225
|
})();
|
|
221
|
-
live = Object.freeze({ primary: primary.promise, completion, boundary: c.order ? boundary : completion, started: Object.freeze(
|
|
226
|
+
live = Object.freeze({ primary: primary.promise, completion, boundary: c.order ? boundary : completion, started: Object.freeze(observedStarted) }); return live;
|
|
222
227
|
} catch (error) {
|
|
223
228
|
fault = true;
|
|
224
229
|
for (const run of reserved) await run.run(AbortSignal.abort()).catch(() => {});
|