portable-agent-layer 0.108.0 → 0.110.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/README.md +3 -2
- package/assets/skills/scientific-research/SKILL.md +58 -12
- package/package.json +6 -2
- package/src/cli/correction.ts +115 -0
- package/src/cli/infer.ts +1 -1
- package/src/cli/rule.ts +121 -14
- package/src/cli/tree.ts +2 -0
- package/src/hooks/handlers/rating.ts +21 -2
- package/src/hooks/handlers/update-check.ts +6 -1
- package/src/hooks/lib/adaptation-candidates.ts +41 -13
- package/src/hooks/lib/adaptation-rules.ts +138 -9
- package/src/hooks/lib/adaptation-steering.ts +7 -2
- package/src/hooks/lib/adaptation-turns.ts +43 -1
- package/src/hooks/lib/context.ts +2 -2
- package/src/hooks/lib/correction-backfill.ts +56 -0
- package/src/hooks/lib/correction-kind.ts +165 -0
- package/src/hooks/lib/correction-rates.ts +151 -0
- package/src/hooks/lib/inference.ts +43 -18
- package/src/hooks/lib/models.ts +76 -28
- package/src/hooks/lib/opinion-gate.ts +73 -0
- package/src/hooks/lib/rule-drafter.ts +57 -24
- package/src/hooks/lib/semi-static.ts +2 -2
- package/src/tools/control-room/relationship.ts +43 -18
- package/src/tools/control-room/server.ts +12 -5
- package/src/tools/control-room/ui/dist/assets/{index-mFpXpiBj.js → index-D0pEd7Ln.js} +1 -1
- package/src/tools/control-room/ui/dist/index.html +1 -1
- package/src/tools/control-room/ui/lib/write.ts +3 -1
- package/src/tools/control-room/ui/screens/relationship.tsx +101 -29
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The Relationship tab: the rule drafts waiting on the user, what the approved
|
|
3
3
|
* rules did, the candidates still being proven, and the last 30 days of labelled
|
|
4
|
-
* turns. A decision goes through `decideRule`, the same
|
|
5
|
-
* rule-review skill use.
|
|
4
|
+
* turns. A decision goes through `decideRule` or `retireRule`, the same rules the
|
|
5
|
+
* CLI and the rule-review skill use.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { type Candidate, readCandidates } from "../../hooks/lib/adaptation-candidates";
|
|
@@ -10,8 +10,16 @@ import {
|
|
|
10
10
|
type AdaptationRule,
|
|
11
11
|
decideRule,
|
|
12
12
|
readRules,
|
|
13
|
+
retireRule,
|
|
14
|
+
type TriggerProof,
|
|
13
15
|
} from "../../hooks/lib/adaptation-rules";
|
|
14
16
|
import { readTurns, type Turn } from "../../hooks/lib/adaptation-turns";
|
|
17
|
+
import {
|
|
18
|
+
EFFECT_WINDOW_DAYS,
|
|
19
|
+
type OpinionEffect,
|
|
20
|
+
opinionEffectOf,
|
|
21
|
+
} from "../../hooks/lib/correction-rates";
|
|
22
|
+
import { gateAdvice } from "../../hooks/lib/opinion-gate";
|
|
15
23
|
import {
|
|
16
24
|
type RuleEffect,
|
|
17
25
|
readRuleEvents,
|
|
@@ -25,12 +33,21 @@ const RECENT_CORRECTIONS = 10;
|
|
|
25
33
|
|
|
26
34
|
export interface ActiveRule extends AdaptationRule {
|
|
27
35
|
effect: RuleEffect;
|
|
36
|
+
opinionEffect: OpinionEffect | null;
|
|
28
37
|
}
|
|
29
38
|
|
|
30
|
-
export interface
|
|
31
|
-
|
|
39
|
+
export interface DraftRule extends AdaptationRule {
|
|
40
|
+
/** Why it cannot be kept as an opinion, and what to do instead. */
|
|
41
|
+
gateAdvice?: string;
|
|
32
42
|
}
|
|
33
43
|
|
|
44
|
+
export type PageDecision = "approved" | "denied" | "opinion" | "retired";
|
|
45
|
+
|
|
46
|
+
export type PipelineCandidate = Candidate & {
|
|
47
|
+
proof: TriggerProof;
|
|
48
|
+
ordinaryNeeded: number;
|
|
49
|
+
};
|
|
50
|
+
|
|
34
51
|
interface TurnStats {
|
|
35
52
|
total: number;
|
|
36
53
|
byReaction: Record<string, number>;
|
|
@@ -40,7 +57,7 @@ interface TurnStats {
|
|
|
40
57
|
|
|
41
58
|
export interface RelationshipView {
|
|
42
59
|
windowDays: number;
|
|
43
|
-
drafts:
|
|
60
|
+
drafts: DraftRule[];
|
|
44
61
|
active: ActiveRule[];
|
|
45
62
|
denied: AdaptationRule[];
|
|
46
63
|
pipeline: PipelineCandidate[];
|
|
@@ -69,33 +86,41 @@ export function relationship(now: Date = new Date()): RelationshipView {
|
|
|
69
86
|
const rules = readRules();
|
|
70
87
|
const turns = readTurns(WINDOW_DAYS, now);
|
|
71
88
|
const effects = ruleEffects(readRuleEvents(WINDOW_DAYS, now), turns);
|
|
89
|
+
const opinionTurns = readTurns(EFFECT_WINDOW_DAYS, now);
|
|
72
90
|
const withStatus = (status: AdaptationRule["status"]) =>
|
|
73
91
|
rules.filter((rule) => rule.status === status);
|
|
74
92
|
return {
|
|
75
93
|
windowDays: WINDOW_DAYS,
|
|
76
|
-
drafts: withStatus("draft")
|
|
94
|
+
drafts: withStatus("draft").map((rule) => {
|
|
95
|
+
const advice = gateAdvice(rule, rules, opinionTurns, now);
|
|
96
|
+
return advice ? { ...rule, gateAdvice: advice } : rule;
|
|
97
|
+
}),
|
|
77
98
|
active: withStatus("approved").map((rule) => ({
|
|
78
99
|
...rule,
|
|
79
100
|
effect: effects[rule.id] ?? NO_EFFECT,
|
|
101
|
+
opinionEffect: opinionEffectOf(rule, rules, opinionTurns, now),
|
|
80
102
|
})),
|
|
81
103
|
denied: withStatus("denied"),
|
|
82
|
-
pipeline: readCandidates()
|
|
83
|
-
.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
104
|
+
pipeline: readCandidates().flatMap((candidate) =>
|
|
105
|
+
candidate.verdict === "passed" || candidate.verdict === "untriggered"
|
|
106
|
+
? []
|
|
107
|
+
: [
|
|
108
|
+
{
|
|
109
|
+
...candidate,
|
|
110
|
+
ordinaryNeeded:
|
|
111
|
+
candidate.verdict === "waiting"
|
|
112
|
+
? ordinaryTurnsNeeded(candidate.proof)
|
|
113
|
+
: 0,
|
|
114
|
+
},
|
|
115
|
+
]
|
|
116
|
+
),
|
|
89
117
|
turns: turnStats(turns),
|
|
90
118
|
};
|
|
91
119
|
}
|
|
92
120
|
|
|
93
|
-
export function decideFromPage(
|
|
94
|
-
id: string,
|
|
95
|
-
decision: "approved" | "denied"
|
|
96
|
-
): WriteOutcome {
|
|
121
|
+
export function decideFromPage(id: string, decision: PageDecision): WriteOutcome {
|
|
97
122
|
const known = readRules().some((rule) => rule.id === id);
|
|
98
|
-
const result = decideRule(id, decision);
|
|
123
|
+
const result = decision === "retired" ? retireRule(id) : decideRule(id, decision);
|
|
99
124
|
if (result.ok) return { ok: true, changed: true };
|
|
100
125
|
return { ok: false, status: known ? 409 : 404, error: result.reason };
|
|
101
126
|
}
|
|
@@ -18,7 +18,7 @@ import { agenda, agentsAtWork, board, handoffs, signal, summary } from "./data";
|
|
|
18
18
|
import { projectDetail } from "./detail";
|
|
19
19
|
import { matrix } from "./matrix";
|
|
20
20
|
import { type PrefUpdate, readPrefs, validatePrefs, writePrefs } from "./prefs";
|
|
21
|
-
import { decideFromPage, relationship } from "./relationship";
|
|
21
|
+
import { decideFromPage, type PageDecision, relationship } from "./relationship";
|
|
22
22
|
import { DEFAULT_PORT, LOOPBACK } from "./server-config";
|
|
23
23
|
import { MAX_SNOOZE_DAYS, setSnooze } from "./snooze";
|
|
24
24
|
import { indexHtml, staticAsset } from "./static";
|
|
@@ -290,16 +290,23 @@ async function prefsWrite(request: Request): Promise<Response> {
|
|
|
290
290
|
return failure ? json({ error: failure }, 400) : json(writePrefs(body as PrefUpdate));
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
|
|
293
|
+
const PAGE_DECISIONS: readonly PageDecision[] = [
|
|
294
|
+
"approved",
|
|
295
|
+
"denied",
|
|
296
|
+
"opinion",
|
|
297
|
+
"retired",
|
|
298
|
+
];
|
|
299
|
+
|
|
300
|
+
/** Decide a rule draft or retire a rule — the same rules `pal cli rule` reaches. */
|
|
294
301
|
async function ruleWrite(request: Request): Promise<Response> {
|
|
295
302
|
const body = await readBody(request);
|
|
296
303
|
if (!body) return json({ error: "expected a JSON body" }, 400);
|
|
297
304
|
const { id, decision } = body;
|
|
298
305
|
if (typeof id !== "string" || !id) return json({ error: "id is required" }, 400);
|
|
299
|
-
if (decision
|
|
300
|
-
return json({ error:
|
|
306
|
+
if (!PAGE_DECISIONS.includes(decision as PageDecision)) {
|
|
307
|
+
return json({ error: `decision must be one of ${PAGE_DECISIONS.join(", ")}` }, 400);
|
|
301
308
|
}
|
|
302
|
-
return answer(decideFromPage(id, decision), { id, decision });
|
|
309
|
+
return answer(decideFromPage(id, decision as PageDecision), { id, decision });
|
|
303
310
|
}
|
|
304
311
|
|
|
305
312
|
const WRITES: Record<string, (request: Request) => Promise<Response>> = {
|