crewly 1.20.376 → 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.
Files changed (96) hide show
  1. package/config/hooks/destructive-git-guard/guard.mjs +168 -9
  2. package/config/hooks/destructive-git-guard/local-gates.json +13 -0
  3. package/config/skills/agent/core/record-local-gate/SKILL.md +46 -0
  4. package/config/skills/agent/core/record-local-gate/execute.sh +87 -0
  5. package/config/skills/agent/core/record-local-gate/execute.test.sh +64 -0
  6. package/config/skills/agent/core/record-tl-verification/SKILL.md +39 -0
  7. package/config/skills/agent/core/record-tl-verification/execute.sh +71 -0
  8. package/config/skills/agent/core/record-tl-verification/execute.test.sh +56 -0
  9. package/dist/backend/backend/src/constants.d.ts +64 -0
  10. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  11. package/dist/backend/backend/src/constants.js +64 -0
  12. package/dist/backend/backend/src/constants.js.map +1 -1
  13. package/dist/backend/backend/src/controllers/experiments/experiments.routes.d.ts +1 -1
  14. package/dist/backend/backend/src/controllers/experiments/experiments.routes.js +1 -1
  15. package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.controller.d.ts +17 -0
  16. package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.controller.d.ts.map +1 -1
  17. package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.controller.js +49 -0
  18. package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.controller.js.map +1 -1
  19. package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.routes.d.ts +2 -0
  20. package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.routes.d.ts.map +1 -1
  21. package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.routes.js +5 -1
  22. package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.routes.js.map +1 -1
  23. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts.map +1 -1
  24. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js +7 -1
  25. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js.map +1 -1
  26. package/dist/backend/backend/src/controllers/trace/trace.controller.d.ts.map +1 -1
  27. package/dist/backend/backend/src/controllers/trace/trace.controller.js +60 -7
  28. package/dist/backend/backend/src/controllers/trace/trace.controller.js.map +1 -1
  29. package/dist/backend/backend/src/index.d.ts.map +1 -1
  30. package/dist/backend/backend/src/index.js +23 -0
  31. package/dist/backend/backend/src/index.js.map +1 -1
  32. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
  33. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +5 -0
  34. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
  35. package/dist/backend/backend/src/services/experiments/experiment.service.d.ts +24 -1
  36. package/dist/backend/backend/src/services/experiments/experiment.service.d.ts.map +1 -1
  37. package/dist/backend/backend/src/services/experiments/experiment.service.js +49 -0
  38. package/dist/backend/backend/src/services/experiments/experiment.service.js.map +1 -1
  39. package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.d.ts +22 -0
  40. package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.d.ts.map +1 -1
  41. package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js +64 -3
  42. package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js.map +1 -1
  43. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts +30 -2
  44. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts.map +1 -1
  45. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js +63 -7
  46. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js.map +1 -1
  47. package/dist/backend/backend/src/services/project-tickets/ticket-routine-nudge.d.ts +59 -0
  48. package/dist/backend/backend/src/services/project-tickets/ticket-routine-nudge.d.ts.map +1 -0
  49. package/dist/backend/backend/src/services/project-tickets/ticket-routine-nudge.js +123 -0
  50. package/dist/backend/backend/src/services/project-tickets/ticket-routine-nudge.js.map +1 -0
  51. package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.d.ts +173 -0
  52. package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.d.ts.map +1 -0
  53. package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.js +263 -0
  54. package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.js.map +1 -0
  55. package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.loader.d.ts +35 -0
  56. package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.loader.d.ts.map +1 -0
  57. package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.loader.js +47 -0
  58. package/dist/backend/backend/src/services/v3/owner-receipt/owner-pulls-weekly.loader.js.map +1 -0
  59. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt-data.d.ts +20 -1
  60. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt-data.d.ts.map +1 -1
  61. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt-data.js +30 -3
  62. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt-data.js.map +1 -1
  63. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.renderer.d.ts +7 -0
  64. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.renderer.d.ts.map +1 -1
  65. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.renderer.js +8 -1
  66. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.renderer.js.map +1 -1
  67. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.d.ts +39 -0
  68. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.d.ts.map +1 -1
  69. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.js +93 -2
  70. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.js.map +1 -1
  71. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.types.d.ts +13 -1
  72. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.types.d.ts.map +1 -1
  73. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.types.js +1 -0
  74. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.types.js.map +1 -1
  75. package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.d.ts +110 -0
  76. package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.d.ts.map +1 -0
  77. package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.js +243 -0
  78. package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.js.map +1 -0
  79. package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.loader.d.ts +27 -0
  80. package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.loader.d.ts.map +1 -0
  81. package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.loader.js +45 -0
  82. package/dist/backend/backend/src/services/v3/owner-receipt/verified-spot-check.loader.js.map +1 -0
  83. package/dist/backend/backend/src/types/experiment.types.d.ts +14 -0
  84. package/dist/backend/backend/src/types/experiment.types.d.ts.map +1 -1
  85. package/dist/backend/backend/src/types/experiment.types.js.map +1 -1
  86. package/dist/backend/build-info.json +2 -2
  87. package/dist/cli/backend/src/constants.d.ts +64 -0
  88. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  89. package/dist/cli/backend/src/constants.js +64 -0
  90. package/dist/cli/backend/src/constants.js.map +1 -1
  91. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
  92. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +5 -0
  93. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
  94. package/frontend/dist/assets/{index-b4db6abe.js → index-19c47468.js} +76 -76
  95. package/frontend/dist/index.html +1 -1
  96. 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"}