@agentproto/apps 0.20.3 → 0.21.1
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/agents-overview/panel.mjs +21 -8
- package/dist/agents-overview/panel.mjs.map +1 -1
- package/dist/agents-overview.mjs +21 -8
- package/dist/agents-overview.mjs.map +1 -1
- package/dist/bin/sync.mjs +19 -2
- package/dist/bin/sync.mjs.map +1 -1
- package/dist/bureau-sessions/panel.mjs +21 -8
- package/dist/bureau-sessions/panel.mjs.map +1 -1
- package/dist/bureau-sessions.mjs +21 -8
- package/dist/bureau-sessions.mjs.map +1 -1
- package/dist/index.mjs +63 -20
- package/dist/index.mjs.map +1 -1
- package/dist/live-session/panel.mjs +21 -8
- package/dist/live-session/panel.mjs.map +1 -1
- package/dist/live-session.mjs +21 -8
- package/dist/live-session.mjs.map +1 -1
- package/dist/ops-panel/ui.d.ts +1 -1
- package/dist/ops-panel/ui.d.ts.map +1 -1
- package/dist/ops-panel.mjs +19 -2
- package/dist/ops-panel.mjs.map +1 -1
- package/dist/panel-bridge.d.ts.map +1 -1
- package/dist/review-panel/panel.d.ts +1 -1
- package/dist/review-panel/panel.d.ts.map +1 -1
- package/dist/review-panel/panel.generated.d.ts +1 -1
- package/dist/review-panel/panel.generated.d.ts.map +1 -1
- package/dist/review-panel/panel.mjs +1 -1
- package/dist/review-panel/panel.mjs.map +1 -1
- package/dist/review-panel.mjs +1 -1
- package/dist/review-panel.mjs.map +1 -1
- package/dist/session-chat/panel.mjs +21 -8
- package/dist/session-chat/panel.mjs.map +1 -1
- package/dist/session-chat.mjs +21 -8
- package/dist/session-chat.mjs.map +1 -1
- package/dist/session-story/panel.mjs +21 -8
- package/dist/session-story/panel.mjs.map +1 -1
- package/dist/session-story.mjs +21 -8
- package/dist/session-story.mjs.map +1 -1
- package/dist/sessions-panel/panel.mjs +21 -8
- package/dist/sessions-panel/panel.mjs.map +1 -1
- package/dist/sessions-panel.mjs +21 -8
- package/dist/sessions-panel.mjs.map +1 -1
- package/dist/store/panel.d.ts +1 -1
- package/dist/store/panel.d.ts.map +1 -1
- package/dist/store/panel.generated.d.ts +1 -1
- package/dist/store/panel.generated.d.ts.map +1 -1
- package/dist/store/panel.mjs +1 -1
- package/dist/store/panel.mjs.map +1 -1
- package/dist/store.mjs +1 -1
- package/dist/store.mjs.map +1 -1
- package/dist/work-board/panel.d.ts +1 -1
- package/dist/work-board/panel.d.ts.map +1 -1
- package/dist/work-board/panel.generated.d.ts +1 -1
- package/dist/work-board/panel.generated.d.ts.map +1 -1
- package/dist/work-board/panel.mjs +21 -8
- package/dist/work-board/panel.mjs.map +1 -1
- package/dist/work-board.mjs +21 -8
- package/dist/work-board.mjs.map +1 -1
- package/package.json +3 -3
- package/repo-maintenance/.agentproto/workflows/maintain/WORKFLOW.md +17 -1
- package/repo-maintenance/.agentproto/workflows/maintain/entry.mjs +88 -5
- package/session-steward/.agentproto/workflows/session-steward/WORKFLOW.md +38 -6
- package/session-steward/.agentproto/workflows/session-steward/entry.mjs +44 -6
- package/session-steward/.agentproto/workflows/session-steward/origin-policy.mjs +2 -2
- package/session-steward/README.md +12 -4
- package/session-steward/routines/session-steward-hourly/ROUTINE.md +6 -3
|
@@ -57,6 +57,11 @@ import {
|
|
|
57
57
|
|
|
58
58
|
const DEFAULT_IDLE_MINUTES = 30
|
|
59
59
|
const DEFAULT_MIN_CONFIDENCE = 0.8
|
|
60
|
+
/** Recurring (scheduled) runs only: a keepAlive session must have been idle
|
|
61
|
+
* this long before it may be asked, so a session its owner meant to pick up
|
|
62
|
+
* tomorrow is not closed overnight. 0 turns the recurring keepAlive ask off.
|
|
63
|
+
* An on-demand run (`recurring: false`) has no such delay. */
|
|
64
|
+
const DEFAULT_KEEPALIVE_ASK_AFTER_MINUTES = 1440
|
|
60
65
|
/** Terminal sessions older than this (hours since they ended) are not listed
|
|
61
66
|
* as relabel candidates. */
|
|
62
67
|
const DEFAULT_RELABEL_WINDOW_HOURS = 24
|
|
@@ -118,6 +123,8 @@ export function resolveSettings(input, modelRoles) {
|
|
|
118
123
|
jevModel: typeof i.jevModel === "string" && i.jevModel.trim() ? i.jevModel.trim() : DEFAULT_JEV_MODEL,
|
|
119
124
|
maxJudged: Math.floor(num(i.maxJudged, DEFAULT_MAX_JUDGED)),
|
|
120
125
|
askSessions: i.askSessions === true,
|
|
126
|
+
recurring: i.recurring === true,
|
|
127
|
+
keepAliveAskAfterMinutes: num(i.keepAliveAskAfterMinutes, DEFAULT_KEEPALIVE_ASK_AFTER_MINUTES, { min: 0 }),
|
|
121
128
|
callerSessionId: typeof i.callerSessionId === "string" && i.callerSessionId ? i.callerSessionId : null,
|
|
122
129
|
callerOrigin: typeof i.callerOrigin === "string" && i.callerOrigin ? i.callerOrigin : null,
|
|
123
130
|
appId: typeof i.appId === "string" ? i.appId.trim() : DEFAULT_APP_ID,
|
|
@@ -427,8 +434,33 @@ export function collectVerdicts(evidenceResult, judgeQueue, jevResult, jevQueue,
|
|
|
427
434
|
|
|
428
435
|
// ── ask (opt-in) ─────────────────────────────────────────────────────────
|
|
429
436
|
|
|
430
|
-
/**
|
|
431
|
-
*
|
|
437
|
+
/** Nothing to lose in the session's worktree: it is merged (the plan's signal
|
|
438
|
+
* or the PR state), or it is a linked worktree with no uncommitted changes
|
|
439
|
+
* and no commits beyond the base. No worktree info at all is unknown, not
|
|
440
|
+
* clean — a session in a plain checkout stays out. */
|
|
441
|
+
export function worktreeHasNothingToLose(evidence) {
|
|
442
|
+
if (evidence?.signals?.worktreeMerged === true) return true
|
|
443
|
+
const wt = evidence?.worktree
|
|
444
|
+
if (!wt) return false
|
|
445
|
+
if (wt.pr?.state === "merged") return true
|
|
446
|
+
return wt.dirty === false && wt.ahead === 0
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/** keepAlive is the restart-relight flag; closing is a separate, active
|
|
450
|
+
* decision. A keepAlive session whose worktree holds nothing to lose may be
|
|
451
|
+
* asked. An on-demand run (a human asked for it) applies no idle delay beyond
|
|
452
|
+
* the plan's own `idleMinutes`. A `recurring` run closes things nobody asked
|
|
453
|
+
* about, so it also waits `keepAliveAskAfterMinutes` of idleness (0 = never). */
|
|
454
|
+
export function keepAliveAskEligible(evidence, settings) {
|
|
455
|
+
if (evidence?.keepAlive !== true || !worktreeHasNothingToLose(evidence)) return false
|
|
456
|
+
if (settings.recurring !== true) return true
|
|
457
|
+
const after = settings.keepAliveAskAfterMinutes
|
|
458
|
+
return after > 0 && typeof evidence.idleMinutes === "number" && evidence.idleMinutes >= after
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/** Sessions to ask directly: judged below `minConfidence`, not awaitingInput
|
|
462
|
+
* or busy, and either not keepAlive or a keepAlive passing
|
|
463
|
+
* {@link keepAliveAskEligible} — only when `askSessions`. */
|
|
432
464
|
export function buildAskQueue(verdicts, settings) {
|
|
433
465
|
if (!settings?.askSessions) return []
|
|
434
466
|
return (verdicts ?? [])
|
|
@@ -436,7 +468,7 @@ export function buildAskQueue(verdicts, settings) {
|
|
|
436
468
|
r =>
|
|
437
469
|
r.evidence &&
|
|
438
470
|
r.confidence < settings.minConfidence &&
|
|
439
|
-
r.evidence.keepAlive !== true &&
|
|
471
|
+
(r.evidence.keepAlive !== true || keepAliveAskEligible(r.evidence, settings)) &&
|
|
440
472
|
r.evidence.awaitingInput !== true &&
|
|
441
473
|
r.evidence.busy !== true,
|
|
442
474
|
)
|
|
@@ -995,12 +1027,14 @@ export default {
|
|
|
995
1027
|
judgeModel: { type: "string", description: `Model for the agent judge. Default: the \`${ROLE_JUDGE_SESSION}\` model role (repo agentproto.json \`models\` > daemon config \`models\` > built-in).` },
|
|
996
1028
|
maxJudged: { type: "number", description: `Most \`judge\` sessions judged per run, most RAM first. Default ${DEFAULT_MAX_JUDGED}.`, default: DEFAULT_MAX_JUDGED },
|
|
997
1029
|
askSessions: { type: "boolean", description: "Ask low-confidence idle sessions directly whether they're done. Default false — it spends a turn in someone else's conversation.", default: false },
|
|
1030
|
+
recurring: { type: "boolean", description: "Set by scheduled runs (the hourly routine). A recurring run closes sessions nobody asked about, so a keepAlive session must also have been idle `keepAliveAskAfterMinutes`. Default false = an on-demand run, which applies no such delay.", default: false },
|
|
1031
|
+
keepAliveAskAfterMinutes: { type: "number", description: `With \`askSessions\`, for \`recurring\` runs only: a keepAlive session whose worktree is merged or clean (nothing uncommitted, nothing ahead of base) is asked only once idle this many minutes; 0 disables the recurring keepAlive ask. On-demand runs ignore it. keepAlive only re-lights a session after a daemon restart; it does not stop a declared DONE from closing it. Default ${DEFAULT_KEEPALIVE_ASK_AFTER_MINUTES}.`, default: DEFAULT_KEEPALIVE_ASK_AFTER_MINUTES },
|
|
998
1032
|
callerSessionId: { type: "string", description: "The calling session's id — never a candidate. The CLI passes AGENTPROTO_SESSION_ID." },
|
|
999
1033
|
callerOrigin: { type: "string", description: "The calling session's origin (`cron:<jobId>`) — an older run of the SAME cron job is never judged as user work." },
|
|
1000
1034
|
appId: { type: "string", description: `Installed app whose \`app_state\` ledger holds the verdict memory. Default ${DEFAULT_APP_ID}.` },
|
|
1001
1035
|
stableVerdictPasses: { type: "number", description: `Consecutive passes on an unchanged evidence fingerprint before the judge cache stops re-judging. Default ${DEFAULT_STABLE_VERDICT_PASSES}.`, default: DEFAULT_STABLE_VERDICT_PASSES },
|
|
1002
1036
|
userOrigins: { type: "array", description: `Origins that are ALWAYS flag-only, never closed (a human is in the loop). Trailing \`*\` is a prefix wildcard. Default ${JSON.stringify(DEFAULT_USER_ORIGINS)}.`, items: { type: "string" }, default: DEFAULT_USER_ORIGINS },
|
|
1003
|
-
closableOrigins: { type: "array", description: `Origins that may be closed under the current rules (cron jobs, gates). Trailing \`*\` is a prefix wildcard. Executors (a session with a parentSessionId) are closable regardless. Default ${JSON.stringify(DEFAULT_CLOSABLE_ORIGINS)}.`, items: { type: "string" }, default: DEFAULT_CLOSABLE_ORIGINS },
|
|
1037
|
+
closableOrigins: { type: "array", description: `Origins that may be closed under the current rules (cron jobs, gates, workflow steps, reviewer lanes). Trailing \`*\` is a prefix wildcard. Executors (a session with a parentSessionId) are closable regardless. Default ${JSON.stringify(DEFAULT_CLOSABLE_ORIGINS)}.`, items: { type: "string" }, default: DEFAULT_CLOSABLE_ORIGINS },
|
|
1004
1038
|
},
|
|
1005
1039
|
outputs: {},
|
|
1006
1040
|
steps: [
|
|
@@ -1038,7 +1072,10 @@ export default {
|
|
|
1038
1072
|
id: "autoApplyOne",
|
|
1039
1073
|
kind: "tool",
|
|
1040
1074
|
tool: "session_wrapup_apply",
|
|
1041
|
-
|
|
1075
|
+
// `wait: true` — past its 25 s default `waitMs` the tool returns a
|
|
1076
|
+
// bare `{ jobId, status: "running" }` and the report would show no
|
|
1077
|
+
// outcome for a session that did get closed.
|
|
1078
|
+
inputs: { sessionIds: ["$item.sessionId"], verdict: "$item.verdict", note: "$item.note", wait: true },
|
|
1042
1079
|
},
|
|
1043
1080
|
],
|
|
1044
1081
|
},
|
|
@@ -1229,7 +1266,8 @@ export default {
|
|
|
1229
1266
|
id: "judgedApplyOne",
|
|
1230
1267
|
kind: "tool",
|
|
1231
1268
|
tool: "session_wrapup_apply",
|
|
1232
|
-
|
|
1269
|
+
// `wait: true`: same as autoApplyOne.
|
|
1270
|
+
inputs: { sessionIds: ["$item.sessionId"], verdict: "$item.verdict", judgedBy: "$item.judgedBy", note: "$item.note", wait: true },
|
|
1233
1271
|
},
|
|
1234
1272
|
],
|
|
1235
1273
|
},
|
|
@@ -12,7 +12,7 @@ export const DEFAULT_USER_ORIGINS = ["chat-starter", "vscode"]
|
|
|
12
12
|
/** Origins the steward MAY close under the current rules. `cron:*` matches
|
|
13
13
|
* every cron-spawned job (`origin: "cron:<jobId>"`); `gate` matches
|
|
14
14
|
* supervision-gate sessions. */
|
|
15
|
-
export const DEFAULT_CLOSABLE_ORIGINS = ["cron:*", "gate"]
|
|
15
|
+
export const DEFAULT_CLOSABLE_ORIGINS = ["cron:*", "gate", "workflow", "review"]
|
|
16
16
|
|
|
17
17
|
/** The reason shown (and recorded) when a would-be close is bounded by origin. */
|
|
18
18
|
export const USER_ORIGIN_REASON = "flag (origine utilisateur)"
|
|
@@ -46,7 +46,7 @@ export function resolveOriginPolicy(policy) {
|
|
|
46
46
|
/** The origin class of a candidate:
|
|
47
47
|
* - `"user"` — human-launched: a `userOrigins` match, OR a root with no
|
|
48
48
|
* origin and no parent. FLAG ONLY, never close.
|
|
49
|
-
* - `"closable"` — a `closableOrigins` match (cron:*, gate) or an executor
|
|
49
|
+
* - `"closable"` — a `closableOrigins` match (cron:*, gate, workflow, review) or an executor
|
|
50
50
|
* (has a `parentSessionId`). Close allowed under the current rules.
|
|
51
51
|
* `userOrigins` wins over both `closableOrigins` and the executor rule, so a
|
|
52
52
|
* `vscode` executor is still user-origin. An unrecognized root origin is
|
|
@@ -33,10 +33,18 @@ loader path can carry.
|
|
|
33
33
|
judge session is released (killed + archived) when its item settles.
|
|
34
34
|
Verdicts: `done|abandoned|blocked|needs-input|active`. A judge error never
|
|
35
35
|
closes anything.
|
|
36
|
-
5. `ask` (only with `askSessions`) — low-confidence, idle,
|
|
37
|
-
|
|
36
|
+
5. `ask` (only with `askSessions`) — low-confidence, idle, not-awaiting-input
|
|
37
|
+
sessions get ONE prompt asking them to reply
|
|
38
38
|
`STEWARD: DONE …` / `STEWARD: NOT-DONE …`; a ~3 min bounded wait; the
|
|
39
|
-
answer becomes a `declared` verdict.
|
|
39
|
+
answer becomes a `declared` verdict. `keepAlive` only re-lights a session
|
|
40
|
+
after a daemon restart, so it does not exempt one from the ask: a keepAlive
|
|
41
|
+
session whose worktree is merged or clean (nothing uncommitted, nothing
|
|
42
|
+
ahead of base; no worktree info counts as not clean) is asked too. Closing
|
|
43
|
+
is an active act: an on-demand run (`agentproto steward --ask-sessions`)
|
|
44
|
+
adds no idle delay beyond `--idle`. Only a scheduled run (`recurring: true`,
|
|
45
|
+
as the hourly routine sets) waits `keepAliveAskAfterMinutes` (default 1440,
|
|
46
|
+
24 h; 0 turns it off), so a session you meant to resume is not closed
|
|
47
|
+
overnight.
|
|
40
48
|
6. `judgedApply` (only with `apply`) — confident `done`/`abandoned` close
|
|
41
49
|
(resumable, with a recorded outcome); confident `blocked`/`needs-input`
|
|
42
50
|
only flag. Everything else is left alone and reported.
|
|
@@ -53,7 +61,7 @@ the `userOrigins` / `closableOrigins` inputs:
|
|
|
53
61
|
`origin` and no `parentSessionId` (a human launched it). A would-be close —
|
|
54
62
|
even a rule-certain `close`/`stuck`, even a confident `done` — is recorded
|
|
55
63
|
as a `needs-input` flag with reason `flag (origine utilisateur)`.
|
|
56
|
-
- **Close allowed:** `cron:*`, `gate`, and executors (a session with a
|
|
64
|
+
- **Close allowed:** `cron:*`, `gate`, `workflow` (step sessions), `review` (reviewer lanes), and executors (a session with a
|
|
57
65
|
`parentSessionId`).
|
|
58
66
|
|
|
59
67
|
A trailing `*` in either list is a prefix wildcard. The report carries the
|
|
@@ -21,12 +21,15 @@ target:
|
|
|
21
21
|
inputs:
|
|
22
22
|
apply: true
|
|
23
23
|
askSessions: false
|
|
24
|
+
# Scheduled run: if askSessions is ever turned on here, a keepAlive session
|
|
25
|
+
# is asked only after keepAliveAskAfterMinutes idle (default 1440, 0 = never).
|
|
26
|
+
recurring: true
|
|
24
27
|
# Origin policy (the committed default): never close a human's session.
|
|
25
28
|
# `chat-starter`/`vscode` (and any root with no origin and no parent) are
|
|
26
|
-
# FLAG-ONLY; `cron:*` jobs, `gate` sessions, and executors (a session with
|
|
29
|
+
# FLAG-ONLY; `cron:*` jobs, `gate`, `workflow` and `review` sessions, and executors (a session with
|
|
27
30
|
# a parentSessionId) stay closeable. A trailing `*` is a prefix wildcard.
|
|
28
31
|
userOrigins: ["chat-starter", "vscode"]
|
|
29
|
-
closableOrigins: ["cron:*", "gate"]
|
|
32
|
+
closableOrigins: ["cron:*", "gate", "workflow", "review"]
|
|
30
33
|
retry:
|
|
31
34
|
max_attempts: 1
|
|
32
35
|
backoff: fixed
|
|
@@ -68,7 +71,7 @@ The steward bounds every action by the candidate's `origin` (pure
|
|
|
68
71
|
`origin` and no `parentSessionId` (a human launched it). A would-be close —
|
|
69
72
|
even a rule-certain `close`/`stuck`, even a confident `done` — becomes a
|
|
70
73
|
`needs-input` flag with reason `flag (origine utilisateur)`.
|
|
71
|
-
- **Close allowed:** `cron:*` (any cron job), `gate`, and executors (a
|
|
74
|
+
- **Close allowed:** `cron:*` (any cron job), `gate`, `workflow` (workflow-step sessions), `review` (reviewer lanes), and executors (a
|
|
72
75
|
session with a `parentSessionId`).
|
|
73
76
|
|
|
74
77
|
Both lists are workflow inputs (`userOrigins`, `closableOrigins`); the values
|