crewly 1.20.377 → 1.20.379
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/config/hooks/destructive-git-guard/guard.mjs +33 -4
- package/config/hooks/destructive-git-guard/local-gates.json +3 -2
- package/config/skills/agent/core/record-tl-verification/SKILL.md +39 -0
- package/config/skills/agent/core/record-tl-verification/execute.sh +71 -0
- package/config/skills/agent/core/record-tl-verification/execute.test.sh +56 -0
- package/dist/backend/backend/src/constants.d.ts +60 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +60 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.controller.d.ts +17 -0
- package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.controller.js +49 -0
- package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.routes.d.ts +2 -0
- package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.routes.js +5 -1
- package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js +3 -0
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +23 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +5 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.d.ts +22 -0
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js +64 -3
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-routine-nudge.d.ts +59 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-routine-nudge.d.ts.map +1 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-routine-nudge.js +123 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-routine-nudge.js.map +1 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.d.ts +173 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.js +263 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.js.map +1 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.loader.d.ts +35 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.loader.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.loader.js +47 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.loader.js.map +1 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.d.ts +39 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.js +93 -2
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.types.d.ts +2 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.types.js.map +1 -1
- package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.d.ts +110 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.js +243 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.js.map +1 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.loader.d.ts +27 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.loader.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.loader.js +45 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.loader.js.map +1 -0
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +60 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +60 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +5 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/frontend/dist/assets/{index-b4db6abe.js → index-19c47468.js} +76 -76
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Routine nudge for done tickets (crewly#1034).
|
|
3
|
+
*
|
|
4
|
+
* A ticket whose verified result says "at least one card per day" or "check
|
|
5
|
+
* this every Monday" is a recurring plan, but nothing turns it into a
|
|
6
|
+
* schedule. These pure helpers detect the cadence, decide whether the lead
|
|
7
|
+
* still needs telling, and build the one nudge. They never schedule anything.
|
|
8
|
+
*
|
|
9
|
+
* @module services/project-tickets/ticket-routine-nudge
|
|
10
|
+
*/
|
|
11
|
+
import { TICKET_ROUTINE_NUDGE_CONSTANTS as C } from '../../constants.js';
|
|
12
|
+
/**
|
|
13
|
+
* A recurring cadence in English or Chinese. Deliberately narrow: "updated"
|
|
14
|
+
* or "dailymotion" do not match (word boundaries).
|
|
15
|
+
*/
|
|
16
|
+
const CADENCE_PATTERNS = [
|
|
17
|
+
/\b(?:daily|weekly|monthly|hourly|nightly|biweekly|fortnightly)\b/i,
|
|
18
|
+
/\bevery\s+(?:other\s+)?(?:day|weekday|week|month|morning|evening|night|hour|monday|tuesday|wednesday|thursday|friday|saturday|sunday)s?\b/i,
|
|
19
|
+
/\b(?:once|twice|\d+\s*(?:x|times?))\s+(?:a|per|each)\s+(?:day|week|month)\b/i,
|
|
20
|
+
/\b(?:per|each)\s+(?:day|week|month)\b/i,
|
|
21
|
+
/\bon\s+(?:mondays|tuesdays|wednesdays|thursdays|fridays|saturdays|sundays|weekdays)\b/i,
|
|
22
|
+
/每(?:个)?\s*(?:天|日|周|星期|礼拜|月|工作日)/,
|
|
23
|
+
/每\s*\d+\s*(?:天|周|个月|小时)/,
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Collect the text of a WorkItem result / output: string leaves only, in
|
|
27
|
+
* order, capped. Numbers and booleans are not prose and are skipped.
|
|
28
|
+
*
|
|
29
|
+
* @param values - Result and output objects
|
|
30
|
+
* @returns One string to scan
|
|
31
|
+
*/
|
|
32
|
+
export function collectResultText(...values) {
|
|
33
|
+
const parts = [];
|
|
34
|
+
let size = 0;
|
|
35
|
+
const walk = (v, depth) => {
|
|
36
|
+
if (size >= C.MAX_SCAN_CHARS || depth > 4)
|
|
37
|
+
return;
|
|
38
|
+
if (typeof v === 'string') {
|
|
39
|
+
parts.push(v);
|
|
40
|
+
size += v.length;
|
|
41
|
+
}
|
|
42
|
+
else if (Array.isArray(v)) {
|
|
43
|
+
for (const x of v)
|
|
44
|
+
walk(x, depth + 1);
|
|
45
|
+
}
|
|
46
|
+
else if (v && typeof v === 'object') {
|
|
47
|
+
for (const x of Object.values(v))
|
|
48
|
+
walk(x, depth + 1);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
for (const v of values)
|
|
52
|
+
walk(v, 0);
|
|
53
|
+
return parts.join('\n').slice(0, C.MAX_SCAN_CHARS);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Find a recurring cadence in a result text.
|
|
57
|
+
*
|
|
58
|
+
* @param text - Result / summary text
|
|
59
|
+
* @returns The sentence that names the cadence (trimmed, capped), or null
|
|
60
|
+
*/
|
|
61
|
+
export function detectRecurringCadence(text) {
|
|
62
|
+
if (!text)
|
|
63
|
+
return null;
|
|
64
|
+
const sentences = text.split(/(?<=[.!?。!?])\s*|\n+/);
|
|
65
|
+
for (const raw of sentences) {
|
|
66
|
+
const sentence = raw.trim();
|
|
67
|
+
if (sentence && CADENCE_PATTERNS.some((re) => re.test(sentence))) {
|
|
68
|
+
return sentence.length > C.MAX_QUOTE_CHARS ? `${sentence.slice(0, C.MAX_QUOTE_CHARS)}…` : sentence;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Whether the nudge was already sent for a ticket (its Log carries the marker).
|
|
75
|
+
*
|
|
76
|
+
* @param log - Ticket Log lines
|
|
77
|
+
* @returns True when it was sent
|
|
78
|
+
*/
|
|
79
|
+
export function routineNudgeAlreadySent(log) {
|
|
80
|
+
return log.some((line) => line.includes(C.LOG_MARKER));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Whether a live trigger already references the ticket (its id appears in the
|
|
84
|
+
* trigger's name or action), so a routine is already set.
|
|
85
|
+
*
|
|
86
|
+
* @param triggers - All triggers
|
|
87
|
+
* @param ticketId - Ticket id (e.g. `CE-101`)
|
|
88
|
+
* @returns True when an active or paused trigger names the ticket
|
|
89
|
+
*/
|
|
90
|
+
export function triggerReferencesTicket(triggers, ticketId) {
|
|
91
|
+
const escaped = ticketId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
92
|
+
const re = new RegExp(`(?<![A-Za-z0-9-])${escaped}(?![A-Za-z0-9])`, 'i');
|
|
93
|
+
return triggers.some((t) => {
|
|
94
|
+
if (t.status !== 'active' && t.status !== 'paused')
|
|
95
|
+
return false;
|
|
96
|
+
return re.test(`${t.name ?? ''}\n${JSON.stringify(t.action ?? {})}`);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The nudge text for the lead (internal; the owner never sees it).
|
|
101
|
+
*
|
|
102
|
+
* @param input - Ticket and cadence
|
|
103
|
+
* @returns Markdown brief
|
|
104
|
+
*/
|
|
105
|
+
export function buildRoutineNudgeBrief(input) {
|
|
106
|
+
const title = input.title.length > C.TITLE_MAX_CHARS ? `${input.title.slice(0, C.TITLE_MAX_CHARS)}…` : input.title;
|
|
107
|
+
return [
|
|
108
|
+
`Ticket ${input.ticketId} ("${title}") is done, and its result describes recurring work:`,
|
|
109
|
+
'',
|
|
110
|
+
`> ${input.quote}`,
|
|
111
|
+
'',
|
|
112
|
+
'Nothing runs this on a schedule yet. Either set a routine, or say why not (one line in the ticket log is enough).',
|
|
113
|
+
'',
|
|
114
|
+
'Command shape (keep the ticket id in --name or --title so this check sees it):',
|
|
115
|
+
'',
|
|
116
|
+
'```',
|
|
117
|
+
`schedule-followup --cron "<cron>" --max-fires <N> --target ${input.lead} --name "${input.ticketId}-routine" --title "${input.ticketId}: <what to do each time>"`,
|
|
118
|
+
'```',
|
|
119
|
+
'',
|
|
120
|
+
'This is the only reminder for this ticket.',
|
|
121
|
+
].join('\n');
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=ticket-routine-nudge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket-routine-nudge.js","sourceRoot":"","sources":["../../../../../../backend/src/services/project-tickets/ticket-routine-nudge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owner pulls, weekly (#1387, first slice) — how often agents put something in
|
|
3
|
+
* front of the owner, by kind and by team, and what became of it.
|
|
4
|
+
*
|
|
5
|
+
* Measures only; it never changes when agents ping the owner. Pure functions:
|
|
6
|
+
* the caller reads decisions / Request open items / traces and passes them in.
|
|
7
|
+
* Spec: specs/owner-pulls-weekly.md.
|
|
8
|
+
*
|
|
9
|
+
* ## The rule for "FYI that did not need an answer"
|
|
10
|
+
*
|
|
11
|
+
* An agent post to the owner (a plain chat message, not a card) is an FYI when
|
|
12
|
+
* ALL of these hold ({@link classifyAgentPost}):
|
|
13
|
+
* 1. it did not end with a question,
|
|
14
|
+
* 2. it did not open a decision card, and
|
|
15
|
+
* 3. no WorkItem stayed blocked on the owner afterwards.
|
|
16
|
+
* Any one of them failing makes it a "needed an answer" pull (a decision),
|
|
17
|
+
* unless it reports a failure / stuck work (then it is `stuck`). This is the
|
|
18
|
+
* issue's first guess; it is a rule on facts the harness already has, so the
|
|
19
|
+
* owner is never asked per post. Decision cards always ask, so they are never
|
|
20
|
+
* FYIs.
|
|
21
|
+
*
|
|
22
|
+
* @module services/v3/owner-receipt/owner-pulls-weekly
|
|
23
|
+
*/
|
|
24
|
+
import type { OwnerDecision } from '../../../types/decision.types.js';
|
|
25
|
+
import type { RequestOpenItem } from '../../../types/v2/open-item.types.js';
|
|
26
|
+
/** What the agent wanted from the owner. */
|
|
27
|
+
export type PullKind = 'decision' | 'review' | 'fyi' | 'stuck';
|
|
28
|
+
/** Every kind, in the order the line names them. */
|
|
29
|
+
export declare const PULL_KINDS: readonly PullKind[];
|
|
30
|
+
/**
|
|
31
|
+
* What became of a pull.
|
|
32
|
+
* - `answered`: the owner chose / replied
|
|
33
|
+
* - `aged_out`: the deadline passed and the default was applied, or it expired / parked unanswered
|
|
34
|
+
* - `ignored`: the owner skipped it ("no need")
|
|
35
|
+
* - `open`: still waiting
|
|
36
|
+
*/
|
|
37
|
+
export type PullOutcome = 'answered' | 'aged_out' | 'ignored' | 'open';
|
|
38
|
+
/** Every outcome, in the order the line names them. */
|
|
39
|
+
export declare const PULL_OUTCOMES: readonly PullOutcome[];
|
|
40
|
+
/** One agent pull on the owner. */
|
|
41
|
+
export interface PullRecord {
|
|
42
|
+
/** When the agent pulled (ISO) */
|
|
43
|
+
at: string;
|
|
44
|
+
kind: PullKind;
|
|
45
|
+
/** Team name, or the unknown-team label */
|
|
46
|
+
team: string;
|
|
47
|
+
outcome: PullOutcome;
|
|
48
|
+
}
|
|
49
|
+
/** Facts about one agent post to the owner that is not a card. */
|
|
50
|
+
export interface AgentPostFacts {
|
|
51
|
+
/** The post's last sentence is a question */
|
|
52
|
+
endsWithQuestion: boolean;
|
|
53
|
+
/** The agent opened a decision card for it */
|
|
54
|
+
openedDecisionCard: boolean;
|
|
55
|
+
/** A WorkItem stayed blocked on the owner after the post */
|
|
56
|
+
workItemBlockedOnOwner: boolean;
|
|
57
|
+
/** It reports an error, a failure or work that is stuck */
|
|
58
|
+
reportsFailure: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Classify a plain agent post by the FYI rule (see the module doc).
|
|
62
|
+
*
|
|
63
|
+
* @param facts - What the harness knows about the post
|
|
64
|
+
* @returns `stuck` for a failure report, `decision` when it needed an answer, else `fyi`
|
|
65
|
+
*/
|
|
66
|
+
export declare function classifyAgentPost(facts: AgentPostFacts): PullKind;
|
|
67
|
+
/**
|
|
68
|
+
* Kind of a decision card: a held action / merge / sensitive ask is a review
|
|
69
|
+
* or approval, a spend cap is the agent being stopped, the rest are decisions.
|
|
70
|
+
*
|
|
71
|
+
* @param d - The card
|
|
72
|
+
* @returns Its pull kind
|
|
73
|
+
*/
|
|
74
|
+
export declare function decisionPullKind(d: OwnerDecision): PullKind;
|
|
75
|
+
/**
|
|
76
|
+
* Outcome of a decision card, or null when the card does not count as a pull
|
|
77
|
+
* (withdrawn by the agent before the owner dealt with it).
|
|
78
|
+
*
|
|
79
|
+
* @param d - The card
|
|
80
|
+
* @returns Outcome or null
|
|
81
|
+
*/
|
|
82
|
+
export declare function decisionPullOutcome(d: OwnerDecision): PullOutcome | null;
|
|
83
|
+
/**
|
|
84
|
+
* Turn decision cards into pull records. Cards the harness asks itself (runtime
|
|
85
|
+
* terms, receipt format) are not agent pulls and are left out; a spend cap is
|
|
86
|
+
* kept (an agent was stopped).
|
|
87
|
+
*
|
|
88
|
+
* @param decisions - Every card
|
|
89
|
+
* @param teamOf - Team name for a card, or null
|
|
90
|
+
* @returns Records
|
|
91
|
+
*/
|
|
92
|
+
export declare function pullsFromDecisions(decisions: readonly OwnerDecision[], teamOf: (d: OwnerDecision) => string | null): PullRecord[];
|
|
93
|
+
/**
|
|
94
|
+
* Turn the questions agents left in their replies (Request open items) into
|
|
95
|
+
* pull records. A question already carded (a `reply_question` decision tracks
|
|
96
|
+
* it) is counted once, by its card; superseded / cancelled items are not pulls.
|
|
97
|
+
*
|
|
98
|
+
* @param items - Open items with their Request id
|
|
99
|
+
* @param cardedKeys - `requestId:itemId` of items that have a decision card
|
|
100
|
+
* @param teamOfAgent - Team name for an agent session, or null
|
|
101
|
+
* @returns Records
|
|
102
|
+
*/
|
|
103
|
+
export declare function pullsFromOpenItems(items: ReadonlyArray<{
|
|
104
|
+
requestId: string;
|
|
105
|
+
item: RequestOpenItem;
|
|
106
|
+
}>, cardedKeys: ReadonlySet<string>, teamOfAgent: (session: string) => string | null): PullRecord[];
|
|
107
|
+
/** Counts for one week. */
|
|
108
|
+
export interface PullsWeek {
|
|
109
|
+
total: number;
|
|
110
|
+
byKind: Record<PullKind, number>;
|
|
111
|
+
byOutcome: Record<PullOutcome, number>;
|
|
112
|
+
/** Most pulls first, then by name */
|
|
113
|
+
byTeam: Array<{
|
|
114
|
+
team: string;
|
|
115
|
+
count: number;
|
|
116
|
+
}>;
|
|
117
|
+
}
|
|
118
|
+
/** The weekly rollup. */
|
|
119
|
+
export interface PullsWeekly {
|
|
120
|
+
/** Window of the counted week (ISO) */
|
|
121
|
+
window: {
|
|
122
|
+
from: string;
|
|
123
|
+
to: string;
|
|
124
|
+
};
|
|
125
|
+
thisWeek: PullsWeek;
|
|
126
|
+
lastWeek: PullsWeek;
|
|
127
|
+
/** `thisWeek.total - lastWeek.total` */
|
|
128
|
+
change: number;
|
|
129
|
+
/**
|
|
130
|
+
* The owner's own touches in runs (trace owner-touch metrics: replies,
|
|
131
|
+
* approvals, send-backs, corrections), when the caller supplied them.
|
|
132
|
+
*/
|
|
133
|
+
ownerTouches?: {
|
|
134
|
+
thisWeek: number;
|
|
135
|
+
lastWeek: number;
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Roll pulls up into this week and last week.
|
|
140
|
+
*
|
|
141
|
+
* @param records - All pull records (any age)
|
|
142
|
+
* @param now - End of the counted week
|
|
143
|
+
* @param ownerTouches - Optional owner-touch counts from traces
|
|
144
|
+
* @returns The rollup
|
|
145
|
+
*/
|
|
146
|
+
export declare function rollupPulls(records: readonly PullRecord[], now: Date, ownerTouches?: {
|
|
147
|
+
thisWeek: number;
|
|
148
|
+
lastWeek: number;
|
|
149
|
+
}): PullsWeekly;
|
|
150
|
+
/**
|
|
151
|
+
* Sum the owner touches of traces whose root falls in each week.
|
|
152
|
+
*
|
|
153
|
+
* @param traces - Trace rows: root time and the owner-touch total from metrics
|
|
154
|
+
* @param now - End of the counted week
|
|
155
|
+
* @returns Counts for this and last week
|
|
156
|
+
*/
|
|
157
|
+
export declare function countOwnerTouches(traces: ReadonlyArray<{
|
|
158
|
+
createdAt: string;
|
|
159
|
+
ownerTouches: number;
|
|
160
|
+
}>, now: Date): {
|
|
161
|
+
thisWeek: number;
|
|
162
|
+
lastWeek: number;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Render the weekly line for the owner (Slack mrkdwn, at most four lines, no
|
|
166
|
+
* ticket or card numbers). Empty string when there were no pulls this week
|
|
167
|
+
* and last week: nothing to say.
|
|
168
|
+
*
|
|
169
|
+
* @param w - The rollup
|
|
170
|
+
* @returns Text or ''
|
|
171
|
+
*/
|
|
172
|
+
export declare function renderPullsWeekly(w: PullsWeekly): string;
|
|
173
|
+
//# sourceMappingURL=owner-pulls-weekly.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-pulls-weekly.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/v3/owner-receipt/owner-pulls-weekly.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owner pulls, weekly (#1387, first slice) — how often agents put something in
|
|
3
|
+
* front of the owner, by kind and by team, and what became of it.
|
|
4
|
+
*
|
|
5
|
+
* Measures only; it never changes when agents ping the owner. Pure functions:
|
|
6
|
+
* the caller reads decisions / Request open items / traces and passes them in.
|
|
7
|
+
* Spec: specs/owner-pulls-weekly.md.
|
|
8
|
+
*
|
|
9
|
+
* ## The rule for "FYI that did not need an answer"
|
|
10
|
+
*
|
|
11
|
+
* An agent post to the owner (a plain chat message, not a card) is an FYI when
|
|
12
|
+
* ALL of these hold ({@link classifyAgentPost}):
|
|
13
|
+
* 1. it did not end with a question,
|
|
14
|
+
* 2. it did not open a decision card, and
|
|
15
|
+
* 3. no WorkItem stayed blocked on the owner afterwards.
|
|
16
|
+
* Any one of them failing makes it a "needed an answer" pull (a decision),
|
|
17
|
+
* unless it reports a failure / stuck work (then it is `stuck`). This is the
|
|
18
|
+
* issue's first guess; it is a rule on facts the harness already has, so the
|
|
19
|
+
* owner is never asked per post. Decision cards always ask, so they are never
|
|
20
|
+
* FYIs.
|
|
21
|
+
*
|
|
22
|
+
* @module services/v3/owner-receipt/owner-pulls-weekly
|
|
23
|
+
*/
|
|
24
|
+
import { OWNER_RECEIPT_CONSTANTS, PULLS_WEEKLY_KIND_LABELS } from '../../../constants.js';
|
|
25
|
+
/** Every kind, in the order the line names them. */
|
|
26
|
+
export const PULL_KINDS = ['decision', 'review', 'fyi', 'stuck'];
|
|
27
|
+
/** Every outcome, in the order the line names them. */
|
|
28
|
+
export const PULL_OUTCOMES = ['answered', 'aged_out', 'ignored', 'open'];
|
|
29
|
+
/**
|
|
30
|
+
* Classify a plain agent post by the FYI rule (see the module doc).
|
|
31
|
+
*
|
|
32
|
+
* @param facts - What the harness knows about the post
|
|
33
|
+
* @returns `stuck` for a failure report, `decision` when it needed an answer, else `fyi`
|
|
34
|
+
*/
|
|
35
|
+
export function classifyAgentPost(facts) {
|
|
36
|
+
if (facts.reportsFailure)
|
|
37
|
+
return 'stuck';
|
|
38
|
+
if (facts.endsWithQuestion || facts.openedDecisionCard || facts.workItemBlockedOnOwner)
|
|
39
|
+
return 'decision';
|
|
40
|
+
return 'fyi';
|
|
41
|
+
}
|
|
42
|
+
/** Decision kinds that ask the owner to approve something an agent holds. */
|
|
43
|
+
const REVIEW_DECISION_KINDS = new Set([
|
|
44
|
+
'browser_action',
|
|
45
|
+
'gmail_send',
|
|
46
|
+
'app_collaborator',
|
|
47
|
+
'app_template',
|
|
48
|
+
'model_tier_change',
|
|
49
|
+
]);
|
|
50
|
+
/**
|
|
51
|
+
* Kind of a decision card: a held action / merge / sensitive ask is a review
|
|
52
|
+
* or approval, a spend cap is the agent being stopped, the rest are decisions.
|
|
53
|
+
*
|
|
54
|
+
* @param d - The card
|
|
55
|
+
* @returns Its pull kind
|
|
56
|
+
*/
|
|
57
|
+
export function decisionPullKind(d) {
|
|
58
|
+
if (d.kind === 'spend_cap')
|
|
59
|
+
return 'stuck';
|
|
60
|
+
if ((d.kind && REVIEW_DECISION_KINDS.has(d.kind)) || d.merge === true || d.sensitive !== undefined)
|
|
61
|
+
return 'review';
|
|
62
|
+
return 'decision';
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Outcome of a decision card, or null when the card does not count as a pull
|
|
66
|
+
* (withdrawn by the agent before the owner dealt with it).
|
|
67
|
+
*
|
|
68
|
+
* @param d - The card
|
|
69
|
+
* @returns Outcome or null
|
|
70
|
+
*/
|
|
71
|
+
export function decisionPullOutcome(d) {
|
|
72
|
+
switch (d.status) {
|
|
73
|
+
case 'resolved':
|
|
74
|
+
// A default applied at the deadline is resolved with `answeredVia: 'deadline'`.
|
|
75
|
+
return d.answeredVia === 'deadline' ? 'aged_out' : 'answered';
|
|
76
|
+
case 'defaulted':
|
|
77
|
+
case 'expired':
|
|
78
|
+
case 'parked':
|
|
79
|
+
return 'aged_out';
|
|
80
|
+
case 'skipped':
|
|
81
|
+
return 'ignored';
|
|
82
|
+
case 'open':
|
|
83
|
+
return 'open';
|
|
84
|
+
case 'cancelled':
|
|
85
|
+
return null;
|
|
86
|
+
default:
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Turn decision cards into pull records. Cards the harness asks itself (runtime
|
|
92
|
+
* terms, receipt format) are not agent pulls and are left out; a spend cap is
|
|
93
|
+
* kept (an agent was stopped).
|
|
94
|
+
*
|
|
95
|
+
* @param decisions - Every card
|
|
96
|
+
* @param teamOf - Team name for a card, or null
|
|
97
|
+
* @returns Records
|
|
98
|
+
*/
|
|
99
|
+
export function pullsFromDecisions(decisions, teamOf) {
|
|
100
|
+
const out = [];
|
|
101
|
+
for (const d of decisions) {
|
|
102
|
+
if (d.system && d.kind !== 'spend_cap')
|
|
103
|
+
continue;
|
|
104
|
+
const outcome = decisionPullOutcome(d);
|
|
105
|
+
if (!outcome)
|
|
106
|
+
continue;
|
|
107
|
+
out.push({
|
|
108
|
+
at: d.askedAt ?? d.createdAt,
|
|
109
|
+
kind: decisionPullKind(d),
|
|
110
|
+
team: teamOf(d) ?? OWNER_RECEIPT_CONSTANTS.UNASSIGNED_TEAM,
|
|
111
|
+
outcome,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Turn the questions agents left in their replies (Request open items) into
|
|
118
|
+
* pull records. A question already carded (a `reply_question` decision tracks
|
|
119
|
+
* it) is counted once, by its card; superseded / cancelled items are not pulls.
|
|
120
|
+
*
|
|
121
|
+
* @param items - Open items with their Request id
|
|
122
|
+
* @param cardedKeys - `requestId:itemId` of items that have a decision card
|
|
123
|
+
* @param teamOfAgent - Team name for an agent session, or null
|
|
124
|
+
* @returns Records
|
|
125
|
+
*/
|
|
126
|
+
export function pullsFromOpenItems(items, cardedKeys, teamOfAgent) {
|
|
127
|
+
const out = [];
|
|
128
|
+
for (const { requestId, item } of items) {
|
|
129
|
+
if (item.type !== 'question' || cardedKeys.has(`${requestId}:${item.id}`))
|
|
130
|
+
continue;
|
|
131
|
+
let outcome;
|
|
132
|
+
switch (item.status) {
|
|
133
|
+
case 'resolved':
|
|
134
|
+
outcome = 'answered';
|
|
135
|
+
break;
|
|
136
|
+
case 'skipped':
|
|
137
|
+
outcome = 'ignored';
|
|
138
|
+
break;
|
|
139
|
+
case 'expired':
|
|
140
|
+
outcome = 'aged_out';
|
|
141
|
+
break;
|
|
142
|
+
case 'open':
|
|
143
|
+
case 'waiting_owner':
|
|
144
|
+
case 'overdue':
|
|
145
|
+
case 'ready':
|
|
146
|
+
outcome = 'open';
|
|
147
|
+
break;
|
|
148
|
+
default:
|
|
149
|
+
continue; // superseded / cancelled / delivered
|
|
150
|
+
}
|
|
151
|
+
out.push({
|
|
152
|
+
at: item.createdAt,
|
|
153
|
+
// A question left in a reply ends with a question by construction.
|
|
154
|
+
kind: classifyAgentPost({ endsWithQuestion: true, openedDecisionCard: false, workItemBlockedOnOwner: false, reportsFailure: false }),
|
|
155
|
+
team: teamOfAgent(item.agent) ?? OWNER_RECEIPT_CONSTANTS.UNASSIGNED_TEAM,
|
|
156
|
+
outcome,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return out;
|
|
160
|
+
}
|
|
161
|
+
function emptyWeek() {
|
|
162
|
+
return {
|
|
163
|
+
total: 0,
|
|
164
|
+
byKind: { decision: 0, review: 0, fyi: 0, stuck: 0 },
|
|
165
|
+
byOutcome: { answered: 0, aged_out: 0, ignored: 0, open: 0 },
|
|
166
|
+
byTeam: [],
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function countWeek(records, fromMs, toMs) {
|
|
170
|
+
const week = emptyWeek();
|
|
171
|
+
const teams = new Map();
|
|
172
|
+
for (const r of records) {
|
|
173
|
+
const t = Date.parse(r.at);
|
|
174
|
+
if (!Number.isFinite(t) || t < fromMs || t >= toMs)
|
|
175
|
+
continue;
|
|
176
|
+
week.total += 1;
|
|
177
|
+
week.byKind[r.kind] += 1;
|
|
178
|
+
week.byOutcome[r.outcome] += 1;
|
|
179
|
+
teams.set(r.team, (teams.get(r.team) ?? 0) + 1);
|
|
180
|
+
}
|
|
181
|
+
week.byTeam = [...teams.entries()].map(([team, count]) => ({ team, count })).sort((a, b) => b.count - a.count || a.team.localeCompare(b.team));
|
|
182
|
+
return week;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Roll pulls up into this week and last week.
|
|
186
|
+
*
|
|
187
|
+
* @param records - All pull records (any age)
|
|
188
|
+
* @param now - End of the counted week
|
|
189
|
+
* @param ownerTouches - Optional owner-touch counts from traces
|
|
190
|
+
* @returns The rollup
|
|
191
|
+
*/
|
|
192
|
+
export function rollupPulls(records, now, ownerTouches) {
|
|
193
|
+
const span = OWNER_RECEIPT_CONSTANTS.PULLS_WEEKLY.WINDOW_MS;
|
|
194
|
+
const to = now.getTime();
|
|
195
|
+
const from = to - span;
|
|
196
|
+
const thisWeek = countWeek(records, from, to);
|
|
197
|
+
const lastWeek = countWeek(records, from - span, from);
|
|
198
|
+
return {
|
|
199
|
+
window: { from: new Date(from).toISOString(), to: new Date(to).toISOString() },
|
|
200
|
+
thisWeek,
|
|
201
|
+
lastWeek,
|
|
202
|
+
change: thisWeek.total - lastWeek.total,
|
|
203
|
+
...(ownerTouches ? { ownerTouches } : {}),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Sum the owner touches of traces whose root falls in each week.
|
|
208
|
+
*
|
|
209
|
+
* @param traces - Trace rows: root time and the owner-touch total from metrics
|
|
210
|
+
* @param now - End of the counted week
|
|
211
|
+
* @returns Counts for this and last week
|
|
212
|
+
*/
|
|
213
|
+
export function countOwnerTouches(traces, now) {
|
|
214
|
+
const span = OWNER_RECEIPT_CONSTANTS.PULLS_WEEKLY.WINDOW_MS;
|
|
215
|
+
const to = now.getTime();
|
|
216
|
+
const out = { thisWeek: 0, lastWeek: 0 };
|
|
217
|
+
for (const t of traces) {
|
|
218
|
+
const at = Date.parse(t.createdAt);
|
|
219
|
+
if (!Number.isFinite(at) || at >= to)
|
|
220
|
+
continue;
|
|
221
|
+
if (at >= to - span)
|
|
222
|
+
out.thisWeek += t.ownerTouches;
|
|
223
|
+
else if (at >= to - 2 * span)
|
|
224
|
+
out.lastWeek += t.ownerTouches;
|
|
225
|
+
}
|
|
226
|
+
return out;
|
|
227
|
+
}
|
|
228
|
+
/** `+3`, `-2`, `no change`. */
|
|
229
|
+
function changeWords(change) {
|
|
230
|
+
if (change === 0)
|
|
231
|
+
return 'same as last week';
|
|
232
|
+
return `${change > 0 ? 'up' : 'down'} ${Math.abs(change)} from last week`;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Render the weekly line for the owner (Slack mrkdwn, at most four lines, no
|
|
236
|
+
* ticket or card numbers). Empty string when there were no pulls this week
|
|
237
|
+
* and last week: nothing to say.
|
|
238
|
+
*
|
|
239
|
+
* @param w - The rollup
|
|
240
|
+
* @returns Text or ''
|
|
241
|
+
*/
|
|
242
|
+
export function renderPullsWeekly(w) {
|
|
243
|
+
if (w.thisWeek.total === 0 && w.lastWeek.total === 0)
|
|
244
|
+
return '';
|
|
245
|
+
const { thisWeek } = w;
|
|
246
|
+
const noun = thisWeek.total === 1 ? 'time' : 'times';
|
|
247
|
+
const lines = [`*Pulled you in ${thisWeek.total} ${noun} this week* (${changeWords(w.change)})`];
|
|
248
|
+
if (thisWeek.total > 0) {
|
|
249
|
+
const kinds = PULL_KINDS.filter((k) => thisWeek.byKind[k] > 0).map((k) => `${thisWeek.byKind[k]} ${PULLS_WEEKLY_KIND_LABELS[k]}`);
|
|
250
|
+
lines.push(`• By kind: ${kinds.join(', ')}`);
|
|
251
|
+
const outcomes = PULL_OUTCOMES.filter((o) => thisWeek.byOutcome[o] > 0).map((o) => `${o.replace('_', ' ')} ${thisWeek.byOutcome[o]}`);
|
|
252
|
+
lines.push(`• ${outcomes.join(', ').replace(/^./, (c) => c.toUpperCase())}`);
|
|
253
|
+
const max = OWNER_RECEIPT_CONSTANTS.PULLS_WEEKLY.MAX_TEAMS;
|
|
254
|
+
const shown = thisWeek.byTeam.slice(0, max).map((t) => `${t.team} ${t.count}`);
|
|
255
|
+
const rest = thisWeek.byTeam.length - shown.length;
|
|
256
|
+
lines.push(`• By team: ${shown.join(', ')}${rest > 0 ? `, +${rest} more` : ''}`);
|
|
257
|
+
}
|
|
258
|
+
if (w.ownerTouches && w.ownerTouches.thisWeek + w.ownerTouches.lastWeek > 0) {
|
|
259
|
+
lines.push(`• You replied or approved ${w.ownerTouches.thisWeek} times in runs (last week ${w.ownerTouches.lastWeek})`);
|
|
260
|
+
}
|
|
261
|
+
return lines.join('\n');
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=owner-pulls-weekly.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-pulls-weekly.js","sourceRoot":"","sources":["../../../../../../../backend/src/services/v3/owner-receipt/owner-pulls-weekly.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loader for the weekly owner-pulls rollup (#1387): reads decision cards,
|
|
3
|
+
* Request open items and trace owner touches, and hands them to the pure
|
|
4
|
+
* rollup in {@link ./owner-pulls-weekly}.
|
|
5
|
+
*
|
|
6
|
+
* @module services/v3/owner-receipt/owner-pulls-weekly.loader
|
|
7
|
+
*/
|
|
8
|
+
import type { OwnerDecision } from '../../../types/decision.types.js';
|
|
9
|
+
import type { Request } from '../../../types/v2/request.types.js';
|
|
10
|
+
import { type PullsWeekly } from './owner-pulls-weekly.js';
|
|
11
|
+
/** Where the loader reads from. */
|
|
12
|
+
export interface PullsWeeklyLoaderDeps {
|
|
13
|
+
listDecisions: () => Promise<OwnerDecision[]>;
|
|
14
|
+
listRequests: () => Promise<Request[]>;
|
|
15
|
+
/** session → team name */
|
|
16
|
+
loadTeamIndex: () => Promise<Map<string, string>>;
|
|
17
|
+
/** Team id → team name (a card carries the id of the team whose channel has it) */
|
|
18
|
+
loadTeamNameById?: () => Promise<Map<string, string>>;
|
|
19
|
+
/**
|
|
20
|
+
* Trace rows with their owner-touch total, newest first; absent = the
|
|
21
|
+
* owner-touch count is left out.
|
|
22
|
+
*/
|
|
23
|
+
listTraceTouches?: (since: Date, limit: number) => Promise<Array<{
|
|
24
|
+
createdAt: string;
|
|
25
|
+
ownerTouches: number;
|
|
26
|
+
}>>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build the `loadPullsWeekly` dependency of the owner receipt service.
|
|
30
|
+
*
|
|
31
|
+
* @param deps - Data sources
|
|
32
|
+
* @returns Function that computes the rollup for the week ending at `now`
|
|
33
|
+
*/
|
|
34
|
+
export declare function createPullsWeeklyLoader(deps: PullsWeeklyLoaderDeps): (now: Date) => Promise<PullsWeekly>;
|
|
35
|
+
//# sourceMappingURL=owner-pulls-weekly.loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-pulls-weekly.loader.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/v3/owner-receipt/owner-pulls-weekly.loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAEjC,mCAAmC;AACnC,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAC9C,YAAY,EAAE,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACvC,0BAA0B;IAC1B,aAAa,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CAChH;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,GAAG,CAAC,GAAG,EAAE,IAAI,KAAK,OAAO,CAAC,WAAW,CAAC,CA2BxG"}
|