patchwork-os 0.2.0-beta.13.canary.282 → 0.2.0-beta.13.canary.284
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/dist/workers/contextRisk.d.ts +35 -0
- package/dist/workers/contextRisk.js +20 -0
- package/dist/workers/contextRisk.js.map +1 -0
- package/dist/workers/runWorkerShadow.d.ts +3 -0
- package/dist/workers/runWorkerShadow.js +12 -2
- package/dist/workers/runWorkerShadow.js.map +1 -1
- package/dist/workers/shadowObserver.d.ts +28 -0
- package/dist/workers/shadowObserver.js +42 -0
- package/dist/workers/shadowObserver.js.map +1 -1
- package/dist/workers/shadowReport.d.ts +4 -1
- package/dist/workers/shadowReport.js +8 -2
- package/dist/workers/shadowReport.js.map +1 -1
- package/dist/workers/workerGate.d.ts +15 -2
- package/dist/workers/workerGate.js +26 -2
- package/dist/workers/workerGate.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { TrustLevel } from "./trustLevel.js";
|
|
2
|
+
/**
|
|
3
|
+
* Context-risk — the FAST, situational half of the autonomy decision.
|
|
4
|
+
*
|
|
5
|
+
* Earned trust answers "is this worker generally reliable on this action-class?"
|
|
6
|
+
* (slow, accrued over many runs). Context-risk answers a DIFFERENT, orthogonal
|
|
7
|
+
* question: "is THIS situation safe to act in RIGHT NOW?" — computed per-action
|
|
8
|
+
* from signals the bridge already exposes (open diagnostics in the touched
|
|
9
|
+
* files, test coverage, git hotspot-ness, diff size, CI status). It has no
|
|
10
|
+
* cold-start: it is fully computable on day one, so it can de-rate autonomy from
|
|
11
|
+
* the very first action while the trust posterior is still accruing.
|
|
12
|
+
*
|
|
13
|
+
* It is a DE-RATER only: it can lower the effective autonomy level, never raise
|
|
14
|
+
* it (never-widen). Combined with earned trust + the autonomy ceiling, the gate
|
|
15
|
+
* becomes `min(earned, ceiling, contextCeiling)` — a worker stays at its earned
|
|
16
|
+
* level when the situation is clean and is throttled toward propose-only as live
|
|
17
|
+
* risk climbs. This is the dimension "approve-once / approve-similar" structurally
|
|
18
|
+
* cannot model. See docs/worker-autonomy-policy-gate.md §3a.
|
|
19
|
+
*/
|
|
20
|
+
export interface ContextRisk {
|
|
21
|
+
/** 0 (clean) … 1 (dangerous). Out-of-range / NaN is treated as "unknown". */
|
|
22
|
+
score: number;
|
|
23
|
+
/** Human-readable contributors (e.g. "CI red", "diff 1.2k lines", "hotspot
|
|
24
|
+
* file"), surfaced in the gate reason + audit trail. */
|
|
25
|
+
reasons?: string[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Map a context-risk score to the MAX autonomy rung permitted in this situation.
|
|
29
|
+
* DESCENDING only — higher risk ⇒ lower ceiling. Returns L4 (no de-rate) for a
|
|
30
|
+
* clean OR unknown/unmeasurable score: context-risk adds caution when danger is
|
|
31
|
+
* MEASURED; when it can't be measured the base gate (earned trust + ceiling)
|
|
32
|
+
* still applies its own floor, so an unknown situation must not silently throttle
|
|
33
|
+
* everything to zero.
|
|
34
|
+
*/
|
|
35
|
+
export declare function contextRiskCeiling(score: number): TrustLevel;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map a context-risk score to the MAX autonomy rung permitted in this situation.
|
|
3
|
+
* DESCENDING only — higher risk ⇒ lower ceiling. Returns L4 (no de-rate) for a
|
|
4
|
+
* clean OR unknown/unmeasurable score: context-risk adds caution when danger is
|
|
5
|
+
* MEASURED; when it can't be measured the base gate (earned trust + ceiling)
|
|
6
|
+
* still applies its own floor, so an unknown situation must not silently throttle
|
|
7
|
+
* everything to zero.
|
|
8
|
+
*/
|
|
9
|
+
export function contextRiskCeiling(score) {
|
|
10
|
+
if (!Number.isFinite(score) || score <= 0)
|
|
11
|
+
return 4; // clean / unknown → no de-rate
|
|
12
|
+
if (score >= 0.8)
|
|
13
|
+
return 0; // dangerous → propose-only: every risky action gated
|
|
14
|
+
if (score >= 0.5)
|
|
15
|
+
return 1; // elevated → reversible only flows freely
|
|
16
|
+
if (score >= 0.3)
|
|
17
|
+
return 2; // moderate → compensable ok, irreversible still gated
|
|
18
|
+
return 4; // mild → no de-rate
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=contextRisk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextRisk.js","sourceRoot":"","sources":["../../src/workers/contextRisk.ts"],"names":[],"mappings":"AA4BA;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,+BAA+B;IACpF,IAAI,KAAK,IAAI,GAAG;QAAE,OAAO,CAAC,CAAC,CAAC,qDAAqD;IACjF,IAAI,KAAK,IAAI,GAAG;QAAE,OAAO,CAAC,CAAC,CAAC,0CAA0C;IACtE,IAAI,KAAK,IAAI,GAAG;QAAE,OAAO,CAAC,CAAC,CAAC,sDAAsD;IAClF,OAAO,CAAC,CAAC,CAAC,oBAAoB;AAChC,CAAC"}
|
|
@@ -15,6 +15,9 @@ export interface RunWorkerShadowOpts {
|
|
|
15
15
|
patchworkDir?: string;
|
|
16
16
|
/** ~/.claude/ide (activity-*.jsonl) override (tests). */
|
|
17
17
|
ideDir?: string;
|
|
18
|
+
/** Wall-clock override (tests) for durable-outcome labelling. Defaults to
|
|
19
|
+
* Date.now() — supplied here (the I/O entry) so the observer stays pure. */
|
|
20
|
+
now?: number;
|
|
18
21
|
}
|
|
19
22
|
export interface WorkerShadowData {
|
|
20
23
|
workers: WorkerShadowReport[];
|
|
@@ -121,7 +121,12 @@ export function getWorkerShadowData(opts = {}) {
|
|
|
121
121
|
: [];
|
|
122
122
|
const decisions = workers.length ? readDecisions(ideDir) : [];
|
|
123
123
|
return {
|
|
124
|
-
|
|
124
|
+
// `now` drives durable-outcome labelling (recent non-reversible successes
|
|
125
|
+
// are withheld until they survive the durability window). Real Date.now() in
|
|
126
|
+
// production; tests inject opts.now.
|
|
127
|
+
workers: buildShadowReport(workers, runs, decisions, undefined, {
|
|
128
|
+
now: opts.now ?? Date.now(),
|
|
129
|
+
}),
|
|
125
130
|
runsScanned: runs.length,
|
|
126
131
|
decisionsScanned: decisions.length,
|
|
127
132
|
workersDir,
|
|
@@ -143,7 +148,12 @@ export function loadWorkerTrustForRecipe(recipeName, opts = {}) {
|
|
|
143
148
|
const workers = loadWorkersFromDir(workersDir);
|
|
144
149
|
if (!workers.length)
|
|
145
150
|
return null;
|
|
146
|
-
|
|
151
|
+
// Same durable-outcome labelling as the dial (one source of truth): the live
|
|
152
|
+
// gate must not count a recent non-reversible success that could still be
|
|
153
|
+
// reverted. Real Date.now() in production; tests inject opts.now.
|
|
154
|
+
const observer = new WorkerShadowObserver(workers, {
|
|
155
|
+
now: opts.now ?? Date.now(),
|
|
156
|
+
});
|
|
147
157
|
const worker = observer.workerForRecipe(recipeName);
|
|
148
158
|
if (!worker)
|
|
149
159
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runWorkerShadow.js","sourceRoot":"","sources":["../../src/workers/runWorkerShadow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAGL,oBAAoB,GAErB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"runWorkerShadow.js","sourceRoot":"","sources":["../../src/workers/runWorkerShadow.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Reversibility } from "./actionClass.js";
|
|
1
2
|
import { type GraduationConfig } from "./graduation.js";
|
|
2
3
|
import { type WorkerManifest } from "./worker.js";
|
|
3
4
|
import { type AuditEvent, type BoardRow, WorkerLevelStore } from "./workerLevelStore.js";
|
|
@@ -57,14 +58,41 @@ export interface WorkerShadowReport {
|
|
|
57
58
|
agreed: number;
|
|
58
59
|
divergences: Divergence[];
|
|
59
60
|
}
|
|
61
|
+
/** Default durability window — a non-reversible success must survive this long
|
|
62
|
+
* before it counts as earned trust. 24h is long enough to catch a revert /
|
|
63
|
+
* close-as-junk / rollback, short enough that a genuinely-good action graduates
|
|
64
|
+
* within a day. */
|
|
65
|
+
export declare const DEFAULT_DURABILITY_WINDOW_MS: number;
|
|
66
|
+
/**
|
|
67
|
+
* Durable-outcome label. `good = step.status:ok` is an OPTIMISTIC proxy: a PR
|
|
68
|
+
* that merged, an issue that filed — but a junk issue closed seconds later, or a
|
|
69
|
+
* commit reverted within the hour, "succeeded" at the moment yet is not earned
|
|
70
|
+
* trust. So a SUCCESS on a non-reversible (compensable/irreversible) action is
|
|
71
|
+
* "durable" — i.e. counts as evidence — only once it has survived the durability
|
|
72
|
+
* window. Reversible successes (undoable / re-runnable: reads, ledgered writes,
|
|
73
|
+
* local commits, CI) are always durable. Failures are unaffected (a failure is
|
|
74
|
+
* durable evidence of failure regardless of age).
|
|
75
|
+
*
|
|
76
|
+
* This only ever WITHHOLDS recent risky successes (reduces evidence → lower
|
|
77
|
+
* trust → more gating), so it never widens autonomy. See
|
|
78
|
+
* docs/worker-autonomy-policy-gate.md §3d.
|
|
79
|
+
*/
|
|
80
|
+
export declare function isDurableSuccess(reversibility: Reversibility, runAt: number, now: number, windowMs: number): boolean;
|
|
60
81
|
export declare class WorkerShadowObserver {
|
|
61
82
|
private readonly store;
|
|
62
83
|
private readonly cfg;
|
|
63
84
|
private readonly workers;
|
|
64
85
|
private readonly compare;
|
|
86
|
+
/** Wall-clock supplied by the I/O entry (the observer stays pure — no
|
|
87
|
+
* Date.now). When set, durable-outcome labelling is active; when undefined,
|
|
88
|
+
* the prior status-only behaviour is preserved (back-compat for pure tests). */
|
|
89
|
+
private readonly now?;
|
|
90
|
+
private readonly durabilityWindowMs;
|
|
65
91
|
constructor(workers: WorkerManifest[], opts?: {
|
|
66
92
|
store?: WorkerLevelStore;
|
|
67
93
|
cfg?: GraduationConfig;
|
|
94
|
+
now?: number;
|
|
95
|
+
durabilityWindowMs?: number;
|
|
68
96
|
});
|
|
69
97
|
/**
|
|
70
98
|
* The populated level store. Exposed so the LIVE worker-autonomy gate
|
|
@@ -4,15 +4,47 @@ import { DEFAULT_GRADUATION_CONFIG, } from "./graduation.js";
|
|
|
4
4
|
import { recommend } from "./shadowGate.js";
|
|
5
5
|
import { ownsAction, ownsClassKey, priorFor, } from "./worker.js";
|
|
6
6
|
import { WorkerLevelStore, } from "./workerLevelStore.js";
|
|
7
|
+
/** Default durability window — a non-reversible success must survive this long
|
|
8
|
+
* before it counts as earned trust. 24h is long enough to catch a revert /
|
|
9
|
+
* close-as-junk / rollback, short enough that a genuinely-good action graduates
|
|
10
|
+
* within a day. */
|
|
11
|
+
export const DEFAULT_DURABILITY_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
12
|
+
/**
|
|
13
|
+
* Durable-outcome label. `good = step.status:ok` is an OPTIMISTIC proxy: a PR
|
|
14
|
+
* that merged, an issue that filed — but a junk issue closed seconds later, or a
|
|
15
|
+
* commit reverted within the hour, "succeeded" at the moment yet is not earned
|
|
16
|
+
* trust. So a SUCCESS on a non-reversible (compensable/irreversible) action is
|
|
17
|
+
* "durable" — i.e. counts as evidence — only once it has survived the durability
|
|
18
|
+
* window. Reversible successes (undoable / re-runnable: reads, ledgered writes,
|
|
19
|
+
* local commits, CI) are always durable. Failures are unaffected (a failure is
|
|
20
|
+
* durable evidence of failure regardless of age).
|
|
21
|
+
*
|
|
22
|
+
* This only ever WITHHOLDS recent risky successes (reduces evidence → lower
|
|
23
|
+
* trust → more gating), so it never widens autonomy. See
|
|
24
|
+
* docs/worker-autonomy-policy-gate.md §3d.
|
|
25
|
+
*/
|
|
26
|
+
export function isDurableSuccess(reversibility, runAt, now, windowMs) {
|
|
27
|
+
if (reversibility === "reversible")
|
|
28
|
+
return true;
|
|
29
|
+
return runAt <= now - windowMs;
|
|
30
|
+
}
|
|
7
31
|
export class WorkerShadowObserver {
|
|
8
32
|
store;
|
|
9
33
|
cfg;
|
|
10
34
|
workers;
|
|
11
35
|
compare = new Map();
|
|
36
|
+
/** Wall-clock supplied by the I/O entry (the observer stays pure — no
|
|
37
|
+
* Date.now). When set, durable-outcome labelling is active; when undefined,
|
|
38
|
+
* the prior status-only behaviour is preserved (back-compat for pure tests). */
|
|
39
|
+
now;
|
|
40
|
+
durabilityWindowMs;
|
|
12
41
|
constructor(workers, opts = {}) {
|
|
13
42
|
this.workers = workers;
|
|
14
43
|
this.store = opts.store ?? new WorkerLevelStore();
|
|
15
44
|
this.cfg = opts.cfg ?? DEFAULT_GRADUATION_CONFIG;
|
|
45
|
+
this.now = opts.now;
|
|
46
|
+
this.durabilityWindowMs =
|
|
47
|
+
opts.durabilityWindowMs ?? DEFAULT_DURABILITY_WINDOW_MS;
|
|
16
48
|
}
|
|
17
49
|
/**
|
|
18
50
|
* The populated level store. Exposed so the LIVE worker-autonomy gate
|
|
@@ -50,6 +82,16 @@ export class WorkerShadowObserver {
|
|
|
50
82
|
if (step.status === "error" &&
|
|
51
83
|
categoriseHaltReason(step.haltReason) === "approval_rejected")
|
|
52
84
|
continue;
|
|
85
|
+
// Durable-outcome label: a recent SUCCESS on a non-reversible action is
|
|
86
|
+
// provisional (a filed issue / pushed commit / merged PR can be reverted
|
|
87
|
+
// or closed-as-junk minutes later), so it is NOT yet counted as evidence.
|
|
88
|
+
// Only active when `now` was supplied by the I/O entry; otherwise the prior
|
|
89
|
+
// status-only fold is used. Withholds evidence only → never widens.
|
|
90
|
+
if (this.now !== undefined && step.status === "ok") {
|
|
91
|
+
const ac = classifyActionClass(step.tool);
|
|
92
|
+
if (!isDurableSuccess(ac.reversibility, run.at, this.now, this.durabilityWindowMs))
|
|
93
|
+
continue; // pending — survives the window before it earns trust
|
|
94
|
+
}
|
|
53
95
|
this.store.apply(worker.id, { toolName: step.tool, good: step.status === "ok", at: run.at }, { prior, cfg: this.cfg });
|
|
54
96
|
}
|
|
55
97
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shadowObserver.js","sourceRoot":"","sources":["../../src/workers/shadowObserver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"shadowObserver.js","sourceRoot":"","sources":["../../src/workers/shadowObserver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAsB,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EACL,yBAAyB,GAE1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EACL,UAAU,EACV,YAAY,EACZ,QAAQ,GAET,MAAM,aAAa,CAAC;AACrB,OAAO,EAGL,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAmE/B;;;oBAGoB;AACpB,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhE;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAC9B,aAA4B,EAC5B,KAAa,EACb,GAAW,EACX,QAAgB;IAEhB,IAAI,aAAa,KAAK,YAAY;QAAE,OAAO,IAAI,CAAC;IAChD,OAAO,KAAK,IAAI,GAAG,GAAG,QAAQ,CAAC;AACjC,CAAC;AAED,MAAM,OAAO,oBAAoB;IACd,KAAK,CAAmB;IACxB,GAAG,CAAmB;IACtB,OAAO,CAAmB;IAC1B,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC1D;;qFAEiF;IAChE,GAAG,CAAU;IACb,kBAAkB,CAAS;IAE5C,YACE,OAAyB,EACzB,OAKI,EAAE;QAEN,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,gBAAgB,EAAE,CAAC;QAClD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,yBAAyB,CAAC;QACjD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,kBAAkB;YACrB,IAAI,CAAC,kBAAkB,IAAI,4BAA4B,CAAC;IAC5D,CAAC;IAED;;;;;OAKG;IACH,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,4DAA4D;IAC5D,eAAe,CAAC,UAAkB;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;IAC3D,CAAC;IAED,0EAA0E;IAClE,eAAe,CACrB,QAAgB,EAChB,MAAgC;QAEhC,MAAM,EAAE,GAAG,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7D,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACrD,CAAC;IAED,uEAAuE;IACvE,SAAS,CAAC,GAAc;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBAAE,SAAS,CAAC,qBAAqB;YAC5E,0EAA0E;YAC1E,wEAAwE;YACxE,wEAAwE;YACxE,wEAAwE;YACxE,sBAAsB;YACtB,IACE,IAAI,CAAC,MAAM,KAAK,OAAO;gBACvB,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,mBAAmB;gBAE7D,SAAS;YACX,wEAAwE;YACxE,yEAAyE;YACzE,0EAA0E;YAC1E,4EAA4E;YAC5E,oEAAoE;YACpE,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;gBACnD,MAAM,EAAE,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1C,IACE,CAAC,gBAAgB,CACf,EAAE,CAAC,aAAa,EAChB,GAAG,CAAC,EAAE,EACN,IAAI,CAAC,GAAG,EACR,IAAI,CAAC,kBAAkB,CACxB;oBAED,SAAS,CAAC,sDAAsD;YACpE,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,KAAK,CACd,MAAM,CAAC,EAAE,EACT,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAC/D,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CACzB,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;0CAMsC;IACtC,cAAc,CAAC,CAAiB;QAC9B,IAAI,CAAC,CAAC,CAAC,UAAU;YAAE,OAAO;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAChE,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;QAC7C,MAAM,WAAW,GAAG,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC;QAC3C,0EAA0E;QAC1E,MAAM,KAAK,GAAG,UAAU,KAAK,WAAW,CAAC;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI;YAC1C,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,CAAC;YACT,WAAW,EAAE,EAAE;SAChB,CAAC;QACF,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;gBACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,IAAI,EAAE,GAAG,CAAC,QAAQ;gBAClB,IAAI,EAAE,CAAC,CAAC,QAAQ;gBAChB,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,IAAI,EAAE,UAAU;oBACd,CAAC,CAAC,wBAAwB,GAAG,CAAC,MAAM,qBAAqB;oBACzD,CAAC,CAAC,+BAA+B;aACpC,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI;gBAClC,QAAQ,EAAE,CAAC;gBACX,MAAM,EAAE,CAAC;gBACT,WAAW,EAAE,EAAE;aAChB,CAAC;YACF,OAAO;gBACL,QAAQ,EAAE,CAAC,CAAC,EAAE;gBACd,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,eAAe,EAAE,CAAC,CAAC,eAAe;gBAClC,uEAAuE;gBACvE,wEAAwE;gBACxE,wEAAwE;gBACxE,sEAAsE;gBACtE,KAAK,EAAE,IAAI,CAAC,KAAK;qBACd,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;qBACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC7D,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/B,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,WAAW,EAAE,CAAC,CAAC,WAAW;aAC3B,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -7,5 +7,8 @@ import type { WorkerManifest } from "./worker.js";
|
|
|
7
7
|
* that moment (not the final state). Pure — the I/O entry (runWorkerShadow)
|
|
8
8
|
* supplies the records read from the real logs.
|
|
9
9
|
*/
|
|
10
|
-
export declare function buildShadowReport(workers: WorkerManifest[], runs: RunRecord[], decisions: DecisionRecord[], cfg?: GraduationConfig
|
|
10
|
+
export declare function buildShadowReport(workers: WorkerManifest[], runs: RunRecord[], decisions: DecisionRecord[], cfg?: GraduationConfig, opts?: {
|
|
11
|
+
now?: number;
|
|
12
|
+
durabilityWindowMs?: number;
|
|
13
|
+
}): WorkerShadowReport[];
|
|
11
14
|
export declare function formatShadowReport(reports: WorkerShadowReport[]): string;
|
|
@@ -5,8 +5,14 @@ import { WorkerShadowObserver, } from "./shadowObserver.js";
|
|
|
5
5
|
* that moment (not the final state). Pure — the I/O entry (runWorkerShadow)
|
|
6
6
|
* supplies the records read from the real logs.
|
|
7
7
|
*/
|
|
8
|
-
export function buildShadowReport(workers, runs, decisions, cfg) {
|
|
9
|
-
const obs = new WorkerShadowObserver(workers, {
|
|
8
|
+
export function buildShadowReport(workers, runs, decisions, cfg, opts = {}) {
|
|
9
|
+
const obs = new WorkerShadowObserver(workers, {
|
|
10
|
+
cfg,
|
|
11
|
+
...(opts.now !== undefined && { now: opts.now }),
|
|
12
|
+
...(opts.durabilityWindowMs !== undefined && {
|
|
13
|
+
durabilityWindowMs: opts.durabilityWindowMs,
|
|
14
|
+
}),
|
|
15
|
+
});
|
|
10
16
|
const merged = [
|
|
11
17
|
...runs.map((r) => ({ at: r.at, run: r })),
|
|
12
18
|
...decisions.map((d) => ({ at: d.at, dec: d })),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shadowReport.js","sourceRoot":"","sources":["../../src/workers/shadowReport.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,oBAAoB,GAErB,MAAM,qBAAqB,CAAC;AAG7B;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAyB,EACzB,IAAiB,EACjB,SAA2B,EAC3B,GAAsB;
|
|
1
|
+
{"version":3,"file":"shadowReport.js","sourceRoot":"","sources":["../../src/workers/shadowReport.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ActionClass } from "./actionClass.js";
|
|
2
|
+
import { type ContextRisk } from "./contextRisk.js";
|
|
2
3
|
import type { TrustLevel } from "./trustLevel.js";
|
|
3
4
|
import { type WorkerManifest } from "./worker.js";
|
|
4
5
|
import type { WorkerLevelStore } from "./workerLevelStore.js";
|
|
@@ -41,17 +42,29 @@ export interface WorkerGateDecision {
|
|
|
41
42
|
/** Trust actually earned on this class (for logging / the dial). */
|
|
42
43
|
earnedLevel: TrustLevel;
|
|
43
44
|
autonomyCeiling: TrustLevel;
|
|
44
|
-
/** What the gate operates at: min(earned, ceiling), 0 if not
|
|
45
|
+
/** What the gate operates at: min(earned, ceiling, contextCeiling), 0 if not
|
|
46
|
+
* owned. */
|
|
45
47
|
effectiveLevel: TrustLevel;
|
|
48
|
+
/** The descending ceiling imposed by live context-risk (4 = no de-rate).
|
|
49
|
+
* Present only when a contextRisk was supplied. Diagnostic / audit. */
|
|
50
|
+
contextCeiling?: TrustLevel;
|
|
46
51
|
reason: string;
|
|
47
52
|
}
|
|
53
|
+
/** Optional, descending-only signals that fold into the autonomy decision
|
|
54
|
+
* alongside earned trust (the keystone seam — see
|
|
55
|
+
* docs/worker-autonomy-policy-gate.md). All absent ⇒ byte-identical to the
|
|
56
|
+
* earned-trust-only gate. New signals may only LOWER autonomy, never raise it. */
|
|
57
|
+
export interface AutonomyDecisionOpts {
|
|
58
|
+
/** Live situational risk for THIS action (fast, day-1, no cold-start). */
|
|
59
|
+
contextRisk?: ContextRisk;
|
|
60
|
+
}
|
|
48
61
|
/**
|
|
49
62
|
* Undoable → flows un-gated even when unearned. Only reversible actions are
|
|
50
63
|
* exempt from the trust requirement; compensable ones graduate to autonomous
|
|
51
64
|
* at L2+; irreversible ones wait for earned L4.
|
|
52
65
|
*/
|
|
53
66
|
export declare function flowsUngated(ac: ActionClass): boolean;
|
|
54
|
-
export declare function decideWorkerAction(worker: WorkerManifest, toolName: string, params: Record<string, unknown> | undefined, store: WorkerLevelStore): WorkerGateDecision;
|
|
67
|
+
export declare function decideWorkerAction(worker: WorkerManifest, toolName: string, params: Record<string, unknown> | undefined, store: WorkerLevelStore, opts?: AutonomyDecisionOpts): WorkerGateDecision;
|
|
55
68
|
/**
|
|
56
69
|
* Tools a worker's AGENT step must be barred from calling.
|
|
57
70
|
*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { classifyTool, getRiskTierMap } from "../riskTier.js";
|
|
2
2
|
import { classifyActionClass, knownActionTools, } from "./actionClass.js";
|
|
3
|
+
import { contextRiskCeiling } from "./contextRisk.js";
|
|
3
4
|
import { ownsAction } from "./worker.js";
|
|
4
5
|
/**
|
|
5
6
|
* Compensable actions (git-remote, issue) unlock autonomous execution at L2.
|
|
@@ -25,7 +26,7 @@ const BRIDGE_MCP_TOOL_PREFIX = "mcp__patchwork__";
|
|
|
25
26
|
export function flowsUngated(ac) {
|
|
26
27
|
return ac.reversibility === "reversible";
|
|
27
28
|
}
|
|
28
|
-
export function decideWorkerAction(worker, toolName, params, store) {
|
|
29
|
+
export function decideWorkerAction(worker, toolName, params, store, opts) {
|
|
29
30
|
const ac = classifyActionClass(toolName, params);
|
|
30
31
|
const owned = ownsAction(worker, ac);
|
|
31
32
|
const earnedLevel = (store.getState(worker.id, ac.key)?.level ??
|
|
@@ -33,6 +34,16 @@ export function decideWorkerAction(worker, toolName, params, store) {
|
|
|
33
34
|
let effectiveLevel = owned ? earnedLevel : 0;
|
|
34
35
|
if (effectiveLevel > worker.autonomyCeiling)
|
|
35
36
|
effectiveLevel = worker.autonomyCeiling;
|
|
37
|
+
// Descending context-risk clamp (keystone seam). A live, situational de-rater:
|
|
38
|
+
// it can only LOWER the effective level (never-widen). Absent ⇒ no-op, so the
|
|
39
|
+
// earned-trust-only path is byte-identical. A worker with a clean situation
|
|
40
|
+
// keeps its earned autonomy; a dangerous live context (red CI, huge diff,
|
|
41
|
+
// hotspot file) throttles it toward propose-only regardless of earned level.
|
|
42
|
+
const contextCeiling = opts?.contextRisk
|
|
43
|
+
? contextRiskCeiling(opts.contextRisk.score)
|
|
44
|
+
: undefined;
|
|
45
|
+
if (contextCeiling !== undefined && effectiveLevel > contextCeiling)
|
|
46
|
+
effectiveLevel = contextCeiling;
|
|
36
47
|
const base = {
|
|
37
48
|
classKey: ac.key,
|
|
38
49
|
domain: ac.domain,
|
|
@@ -42,6 +53,7 @@ export function decideWorkerAction(worker, toolName, params, store) {
|
|
|
42
53
|
earnedLevel,
|
|
43
54
|
autonomyCeiling: worker.autonomyCeiling,
|
|
44
55
|
effectiveLevel,
|
|
56
|
+
...(contextCeiling !== undefined && { contextCeiling }),
|
|
45
57
|
};
|
|
46
58
|
// Agent (reasoning) steps are not a durable side-effecting action-class: the
|
|
47
59
|
// claude subprocess produces an output var, and any tool calls it makes are
|
|
@@ -88,7 +100,19 @@ export function decideWorkerAction(worker, toolName, params, store) {
|
|
|
88
100
|
? COMPENSABLE_AUTONOMY_LEVEL
|
|
89
101
|
: AUTONOMOUS_LEVEL;
|
|
90
102
|
let reason;
|
|
91
|
-
|
|
103
|
+
// Context-risk is the BINDING constraint when it dropped the effective level
|
|
104
|
+
// below what earned trust + ceiling alone would have allowed. Attribute it so
|
|
105
|
+
// the audit trail shows the situation throttled the action, not stale trust.
|
|
106
|
+
const earnedCapped = Math.min(owned ? earnedLevel : 0, worker.autonomyCeiling);
|
|
107
|
+
if (contextCeiling !== undefined &&
|
|
108
|
+
contextCeiling < threshold &&
|
|
109
|
+
contextCeiling < earnedCapped) {
|
|
110
|
+
const why = opts?.contextRisk?.reasons?.length
|
|
111
|
+
? ` (${opts.contextRisk.reasons.join(", ")})`
|
|
112
|
+
: "";
|
|
113
|
+
reason = `${ac.reversibility} throttled by live context-risk (ceiling L${contextCeiling} < L${threshold})${why} — gated`;
|
|
114
|
+
}
|
|
115
|
+
else if (!owned) {
|
|
92
116
|
reason = `${ac.reversibility} action outside the worker's owned domain — gated`;
|
|
93
117
|
}
|
|
94
118
|
else if (worker.autonomyCeiling < threshold) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workerGate.js","sourceRoot":"","sources":["../../src/workers/workerGate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAEL,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"workerGate.js","sourceRoot":"","sources":["../../src/workers/workerGate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAEL,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAoB,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAExE,OAAO,EAAE,UAAU,EAAuB,MAAM,aAAa,CAAC;AA8D9D;;;;;;;GAOG;AACH,MAAM,0BAA0B,GAAG,CAAU,CAAC;AAE9C,4EAA4E;AAC5E,MAAM,gBAAgB,GAAG,CAAU,CAAC;AAEpC;;;kFAGkF;AAClF,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AAElD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,EAAe;IAC1C,OAAO,EAAE,CAAC,aAAa,KAAK,YAAY,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,MAAsB,EACtB,QAAgB,EAChB,MAA2C,EAC3C,KAAuB,EACvB,IAA2B;IAE3B,MAAM,EAAE,GAAG,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACrC,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK;QAC3D,CAAC,CAAe,CAAC;IAEnB,IAAI,cAAc,GAAe,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,IAAI,cAAc,GAAG,MAAM,CAAC,eAAe;QACzC,cAAc,GAAG,MAAM,CAAC,eAAe,CAAC;IAE1C,+EAA+E;IAC/E,8EAA8E;IAC9E,4EAA4E;IAC5E,0EAA0E;IAC1E,6EAA6E;IAC7E,MAAM,cAAc,GAA2B,IAAI,EAAE,WAAW;QAC9D,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QAC5C,CAAC,CAAC,SAAS,CAAC;IACd,IAAI,cAAc,KAAK,SAAS,IAAI,cAAc,GAAG,cAAc;QACjE,cAAc,GAAG,cAAc,CAAC;IAElC,MAAM,IAAI,GAAG;QACX,QAAQ,EAAE,EAAE,CAAC,GAAG;QAChB,MAAM,EAAE,EAAE,CAAC,MAAM;QACjB,KAAK;QACL,SAAS,EAAE,EAAE,CAAC,SAAS;QACvB,aAAa,EAAE,EAAE,CAAC,aAAa;QAC/B,WAAW;QACX,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,cAAc;QACd,GAAG,CAAC,cAAc,KAAK,SAAS,IAAI,EAAE,cAAc,EAAE,CAAC;KAC/C,CAAC;IAEX,6EAA6E;IAC7E,4EAA4E;IAC5E,2EAA2E;IAC3E,8EAA8E;IAC9E,6EAA6E;IAC7E,8EAA8E;IAC9E,8DAA8D;IAC9D,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,iDAAiD;SAC1D,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,IAAI,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC;QACrB,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,eAAe,EAAE,CAAC,SAAS,oCAAoC;SACxE,CAAC;IACJ,CAAC;IAED,4EAA4E;IAC5E,2EAA2E;IAC3E,oDAAoD;IACpD,IACE,EAAE,CAAC,aAAa,KAAK,aAAa;QAClC,cAAc,IAAI,0BAA0B,EAC5C,CAAC;QACD,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,qBAAqB,cAAc,6CAA6C,0BAA0B,GAAG;SACtH,CAAC;IACJ,CAAC;IAED,wEAAwE;IACxE,IAAI,cAAc,IAAI,gBAAgB,EAAE,CAAC;QACvC,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,2BAA2B,EAAE,CAAC,aAAa,QAAQ;SAC5D,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GACb,EAAE,CAAC,aAAa,KAAK,aAAa;QAChC,CAAC,CAAC,0BAA0B;QAC5B,CAAC,CAAC,gBAAgB,CAAC;IACvB,IAAI,MAAc,CAAC;IACnB,6EAA6E;IAC7E,8EAA8E;IAC9E,6EAA6E;IAC7E,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAC3B,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EACvB,MAAM,CAAC,eAAe,CACvB,CAAC;IACF,IACE,cAAc,KAAK,SAAS;QAC5B,cAAc,GAAG,SAAS;QAC1B,cAAc,GAAG,YAAY,EAC7B,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM;YAC5C,CAAC,CAAC,KAAK,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAC7C,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,6CAA6C,cAAc,OAAO,SAAS,IAAI,GAAG,UAAU,CAAC;IAC3H,CAAC;SAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,mDAAmD,CAAC;IAClF,CAAC;SAAM,IAAI,MAAM,CAAC,eAAe,GAAG,SAAS,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,uCAAuC,MAAM,CAAC,eAAe,OAAO,SAAS,kBAAkB,CAAC;IAC9H,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,2BAA2B,cAAc,OAAO,SAAS,wBAAwB,CAAC;IAChH,CAAC;IACD,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,2BAA2B,CACzC,MAAsB,EACtB,KAAuB;IAEvB,2EAA2E;IAC3E,wEAAwE;IACxE,+EAA+E;IAC/E,0BAA0B;IAC1B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC;QACvB,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QAChC,GAAG,gBAAgB,EAAE;KACtB,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAChC,0EAA0E;QAC1E,mEAAmE;QACnE,IAAI,QAAQ,KAAK,OAAO;YAAE,SAAS;QACnC,2EAA2E;QAC3E,0EAA0E;QAC1E,4EAA4E;QAC5E,qEAAqE;QACrE,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,SAAS;QACrC,IACE,kBAAkB,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,MAAM,KAAK,MAAM;YAExE,SAAS;QACX,iEAAiE;QACjE,2EAA2E;QAC3E,6EAA6E;QAC7E,sEAAsE;QACtE,4EAA4E;QAC5E,2EAA2E;QAC3E,2EAA2E;QAC3E,4EAA4E;QAC5E,sEAAsE;QACtE,MAAM,EAAE,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,EAAE,CAAC,MAAM,KAAK,OAAO,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,MAAM;YAAE,SAAS;QACzE,4EAA4E;QAC5E,2EAA2E;QAC3E,kEAAkE;QAClE,4EAA4E;QAC5E,wEAAwE;QACxE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,GAAG,sBAAsB,GAAG,QAAQ,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AACpC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,yBAAyB,CACvC,QAAmB,EACnB,UAAqB;IAErB,IAAI,CAAC,UAAU,EAAE,MAAM;QAAE,OAAO,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,IAAI,CAAC,QAAQ,EAAE,MAAM;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACrE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAClE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "patchwork-os",
|
|
3
|
-
"version": "0.2.0-beta.13.canary.
|
|
3
|
+
"version": "0.2.0-beta.13.canary.284",
|
|
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",
|