patchwork-os 1.1.0-beta.4.canary.480 → 1.1.0-beta.4.canary.482

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.
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The control boundary for a live worker — composition, not policy.
3
+ *
4
+ * `previewActions` answers "what would the gate say about these candidates?"
5
+ * given a worker and its trust store. This resolves those two from a recipe
6
+ * name, so a caller with nothing but "release-notes" can render the boundary.
7
+ *
8
+ * It reuses `loadWorkerTrustForRecipe` — the same resolution the live gate
9
+ * performs in `buildWorkerAutonomyGate`. That matters for the same reason
10
+ * `previewActions` reuses `decideWorkerAction`: if the preview resolved trust
11
+ * its own way, it could show a boundary computed from a different worker
12
+ * manifest or a staler store than the one enforcement will use, and be
13
+ * confidently wrong. Every layer of this screen has to be a view of the gate.
14
+ *
15
+ * Returns null when no worker owns the recipe — the honest answer, and
16
+ * distinguishable from "a worker that may do nothing", which is an empty
17
+ * boundary rather than a missing one.
18
+ */
19
+ import type { ForbidRule } from "./forbidPolicy.js";
20
+ import { type ActionBoundary, type CandidateAction } from "./previewActions.js";
21
+ import type { RunWorkerShadowOpts } from "./runWorkerShadow.js";
22
+ export interface WorkerBoundary {
23
+ workerId: string;
24
+ workerName: string;
25
+ recipeName: string;
26
+ boundary: ActionBoundary;
27
+ /**
28
+ * False when the worker-autonomy flag is off. The boundary is still computed
29
+ * and still correct as a statement of policy — but nothing is enforcing it,
30
+ * and a screen that does not say so would imply protection that is not
31
+ * running. The caller must surface this.
32
+ */
33
+ enforced: boolean;
34
+ }
35
+ export interface BoundaryPreviewOpts {
36
+ /** Caller-supplied candidates. Omitted ⇒ derived from the worker's `owns`. */
37
+ candidates?: readonly CandidateAction[];
38
+ forbidRules?: readonly ForbidRule[];
39
+ trustOpts?: RunWorkerShadowOpts;
40
+ }
41
+ /**
42
+ * Compute the control boundary for whichever worker owns `recipeName`.
43
+ *
44
+ * Read-only: resolves trust, evaluates hypotheticals, writes nothing. No
45
+ * approval is enqueued and no decision is recorded — see `previewActions`.
46
+ */
47
+ export declare function boundaryForRecipe(recipeName: string, opts?: BoundaryPreviewOpts): WorkerBoundary | null;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The control boundary for a live worker — composition, not policy.
3
+ *
4
+ * `previewActions` answers "what would the gate say about these candidates?"
5
+ * given a worker and its trust store. This resolves those two from a recipe
6
+ * name, so a caller with nothing but "release-notes" can render the boundary.
7
+ *
8
+ * It reuses `loadWorkerTrustForRecipe` — the same resolution the live gate
9
+ * performs in `buildWorkerAutonomyGate`. That matters for the same reason
10
+ * `previewActions` reuses `decideWorkerAction`: if the preview resolved trust
11
+ * its own way, it could show a boundary computed from a different worker
12
+ * manifest or a staler store than the one enforcement will use, and be
13
+ * confidently wrong. Every layer of this screen has to be a view of the gate.
14
+ *
15
+ * Returns null when no worker owns the recipe — the honest answer, and
16
+ * distinguishable from "a worker that may do nothing", which is an empty
17
+ * boundary rather than a missing one.
18
+ */
19
+ import { FLAG_WORKER_AUTONOMY, isEnabled } from "../featureFlags.js";
20
+ import { defaultCandidatesFor, previewActions, } from "./previewActions.js";
21
+ import { loadWorkerTrustForRecipe } from "./runWorkerShadow.js";
22
+ /**
23
+ * Compute the control boundary for whichever worker owns `recipeName`.
24
+ *
25
+ * Read-only: resolves trust, evaluates hypotheticals, writes nothing. No
26
+ * approval is enqueued and no decision is recorded — see `previewActions`.
27
+ */
28
+ export function boundaryForRecipe(recipeName, opts = {}) {
29
+ const trust = loadWorkerTrustForRecipe(recipeName, opts.trustOpts);
30
+ if (!trust)
31
+ return null;
32
+ const { worker, store } = trust;
33
+ const candidates = opts.candidates ?? defaultCandidatesFor(worker);
34
+ return {
35
+ workerId: worker.id,
36
+ workerName: worker.name,
37
+ recipeName,
38
+ boundary: previewActions(worker, candidates, store, {
39
+ ...(opts.forbidRules ? { forbidRules: opts.forbidRules } : {}),
40
+ }),
41
+ // Deliberately reported rather than used to suppress the result. An
42
+ // operator asking "what may this worker do?" while the flag is off should
43
+ // get the answer AND be told it is not being enforced — hiding the boundary
44
+ // would leave them with no information at all, which is worse.
45
+ enforced: isEnabled(FLAG_WORKER_AUTONOMY),
46
+ };
47
+ }
48
+ //# sourceMappingURL=boundaryPreview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundaryPreview.js","sourceRoot":"","sources":["../../src/workers/boundaryPreview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,EAGL,oBAAoB,EACpB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAuBhE;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAAkB,EAClB,OAA4B,EAAE;IAE9B,MAAM,KAAK,GAAG,wBAAwB,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACnE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAChC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAEnE,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,EAAE;QACnB,UAAU,EAAE,MAAM,CAAC,IAAI;QACvB,UAAU;QACV,QAAQ,EAAE,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE;YAClD,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/D,CAAC;QACF,oEAAoE;QACpE,0EAA0E;QAC1E,4EAA4E;QAC5E,+DAA+D;QAC/D,QAAQ,EAAE,SAAS,CAAC,oBAAoB,CAAC;KAC1C,CAAC;AACJ,CAAC"}
@@ -37,7 +37,7 @@
37
37
  * that never happened.
38
38
  */
39
39
  import type { ForbidRule } from "./forbidPolicy.js";
40
- import type { WorkerManifest } from "./worker.js";
40
+ import { type WorkerManifest } from "./worker.js";
41
41
  import type { WorkerLevelStore } from "./workerLevelStore.js";
42
42
  /** An action to ask about. `label` is what a person should see. */
43
43
  export interface CandidateAction {
@@ -78,3 +78,27 @@ export interface PreviewOpts {
78
78
  export declare function previewActions(worker: WorkerManifest, candidates: readonly CandidateAction[], store: WorkerLevelStore, opts?: PreviewOpts): ActionBoundary;
79
79
  /** Total candidates evaluated — for a "N actions considered" caption. */
80
80
  export declare function boundarySize(b: ActionBoundary): number;
81
+ /**
82
+ * The default candidate set for a worker: every action-class tool it owns.
83
+ *
84
+ * A boundary screen needs something to evaluate. Making the caller always
85
+ * supply that list would mean the generic product has no default view, and the
86
+ * only way to see a worker's boundary would be to hand-write its actions —
87
+ * which is fine for a scripted walkthrough and useless for an operator asking
88
+ * "what can this thing actually do?".
89
+ *
90
+ * So the default is derived from the worker's own manifest: the tools the
91
+ * classifier knows (`knownActionTools`), filtered to the classes this worker
92
+ * `owns`. That is the honest answer to the question, because a worker's `owns`
93
+ * IS the declaration of what it is for.
94
+ *
95
+ * Deliberately NOT the whole tool registry. Showing every tool in the product
96
+ * would bury the handful that matter under a hundred rows the worker will never
97
+ * touch, and every one of them would land in "needs approval" — a screen that
98
+ * is technically true and tells an operator nothing.
99
+ *
100
+ * Callers with a specific set in mind (a case, a scripted scenario) pass their
101
+ * own candidates to `previewActions` instead. This is the default, not the
102
+ * only, list.
103
+ */
104
+ export declare function defaultCandidatesFor(worker: WorkerManifest): CandidateAction[];
@@ -36,6 +36,8 @@
36
36
  * not a decision, and writing one would pollute the audit trail with things
37
37
  * that never happened.
38
38
  */
39
+ import { classifyActionClass, knownActionTools } from "./actionClass.js";
40
+ import { ownsAction } from "./worker.js";
39
41
  import { decideWorkerAction, gateOutcomeFor } from "./workerGate.js";
40
42
  /**
41
43
  * Bucket candidate actions into the three columns.
@@ -83,4 +85,33 @@ export function previewActions(worker, candidates, store, opts = {}) {
83
85
  export function boundarySize(b) {
84
86
  return b.mayDoNow.length + b.needsApproval.length + b.notPermitted.length;
85
87
  }
88
+ /**
89
+ * The default candidate set for a worker: every action-class tool it owns.
90
+ *
91
+ * A boundary screen needs something to evaluate. Making the caller always
92
+ * supply that list would mean the generic product has no default view, and the
93
+ * only way to see a worker's boundary would be to hand-write its actions —
94
+ * which is fine for a scripted walkthrough and useless for an operator asking
95
+ * "what can this thing actually do?".
96
+ *
97
+ * So the default is derived from the worker's own manifest: the tools the
98
+ * classifier knows (`knownActionTools`), filtered to the classes this worker
99
+ * `owns`. That is the honest answer to the question, because a worker's `owns`
100
+ * IS the declaration of what it is for.
101
+ *
102
+ * Deliberately NOT the whole tool registry. Showing every tool in the product
103
+ * would bury the handful that matter under a hundred rows the worker will never
104
+ * touch, and every one of them would land in "needs approval" — a screen that
105
+ * is technically true and tells an operator nothing.
106
+ *
107
+ * Callers with a specific set in mind (a case, a scripted scenario) pass their
108
+ * own candidates to `previewActions` instead. This is the default, not the
109
+ * only, list.
110
+ */
111
+ export function defaultCandidatesFor(worker) {
112
+ return knownActionTools()
113
+ .filter((toolName) => ownsAction(worker, classifyActionClass(toolName)))
114
+ .sort()
115
+ .map((toolName) => ({ toolName }));
116
+ }
86
117
  //# sourceMappingURL=previewActions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"previewActions.js","sourceRoot":"","sources":["../../src/workers/previewActions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAIH,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAoCrE;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAsB,EACtB,UAAsC,EACtC,KAAuB,EACvB,OAAoB,EAAE;IAEtB,MAAM,QAAQ,GAAmB;QAC/B,QAAQ,EAAE,EAAE;QACZ,aAAa,EAAE,EAAE;QACjB,YAAY,EAAE,EAAE;KACjB,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE;YACvE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/D,CAAC,CAAC;QAEH,MAAM,KAAK,GAAoB;YAC7B,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,QAAQ;YAC5B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM;SACxB,CAAC;QAEF,wEAAwE;QACxE,sDAAsD;QACtD,QAAQ,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACxC,KAAK,MAAM;gBACT,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC9B,MAAM;YACR,KAAK,OAAO;gBACV,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACnC,MAAM;YACR;gBACE,qEAAqE;gBACrE,kEAAkE;gBAClE,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAClC,MAAM;QACV,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,YAAY,CAAC,CAAiB;IAC5C,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC;AAC5E,CAAC"}
1
+ {"version":3,"file":"previewActions.js","sourceRoot":"","sources":["../../src/workers/previewActions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzE,OAAO,EAAE,UAAU,EAAuB,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAoCrE;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAsB,EACtB,UAAsC,EACtC,KAAuB,EACvB,OAAoB,EAAE;IAEtB,MAAM,QAAQ,GAAmB;QAC/B,QAAQ,EAAE,EAAE;QACZ,aAAa,EAAE,EAAE;QACjB,YAAY,EAAE,EAAE;KACjB,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE;YACvE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/D,CAAC,CAAC;QAEH,MAAM,KAAK,GAAoB;YAC7B,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,QAAQ;YAC5B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM;SACxB,CAAC;QAEF,wEAAwE;QACxE,sDAAsD;QACtD,QAAQ,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACxC,KAAK,MAAM;gBACT,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC9B,MAAM;YACR,KAAK,OAAO;gBACV,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACnC,MAAM;YACR;gBACE,qEAAqE;gBACrE,kEAAkE;gBAClE,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAClC,MAAM;QACV,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,YAAY,CAAC,CAAiB;IAC5C,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC;AAC5E,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAsB;IAEtB,OAAO,gBAAgB,EAAE;SACtB,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC;SACvE,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchwork-os",
3
- "version": "1.1.0-beta.4.canary.480",
3
+ "version": "1.1.0-beta.4.canary.482",
4
4
  "description": "Your personal AI runtime, local-first. Patchwork OS gives any AI model a consistent set of tools, YAML recipes, a delegation policy with approval queue, and a durable trace memory — all on your machine, all under your policy.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",