@mastra/factory 0.12.0-alpha.0 → 0.12.0-alpha.10
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/factory.d.ts.map +1 -1
- package/dist/factory.js +37 -15
- package/dist/factory.js.map +1 -1
- package/dist/feed-events.d.ts +13 -0
- package/dist/feed-events.d.ts.map +1 -0
- package/dist/feed-events.js +25 -0
- package/dist/feed-events.js.map +1 -0
- package/dist/integrations/base.d.ts +9 -0
- package/dist/integrations/base.d.ts.map +1 -1
- package/dist/integrations/github/commits.d.ts +29 -0
- package/dist/integrations/github/commits.d.ts.map +1 -0
- package/dist/integrations/github/commits.js +29 -0
- package/dist/integrations/github/commits.js.map +1 -0
- package/dist/integrations/github/integration.d.ts.map +1 -1
- package/dist/integrations/github/integration.js +47 -10
- package/dist/integrations/github/integration.js.map +1 -1
- package/dist/integrations/github/issue-reconciler.d.ts.map +1 -1
- package/dist/integrations/github/issue-reconciler.js +22 -14
- package/dist/integrations/github/issue-reconciler.js.map +1 -1
- package/dist/integrations/github/reconcile-worker.d.ts.map +1 -1
- package/dist/integrations/github/reconcile-worker.js +3 -3
- package/dist/integrations/github/reconcile-worker.js.map +1 -1
- package/dist/integrations/github/routes.d.ts.map +1 -1
- package/dist/integrations/github/routes.js +35 -0
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/github/rules.d.ts +6 -0
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +58 -12
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/github/settle-or-abort.d.ts +7 -0
- package/dist/integrations/github/settle-or-abort.d.ts.map +1 -0
- package/dist/integrations/github/settle-or-abort.js +25 -0
- package/dist/integrations/github/settle-or-abort.js.map +1 -0
- package/dist/integrations/issue-reconcile-worker.js +1 -1
- package/dist/integrations/platform/github/event-worker.d.ts.map +1 -1
- package/dist/integrations/platform/github/event-worker.js +4 -4
- package/dist/integrations/platform/github/event-worker.js.map +1 -1
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.js +37 -5
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/integrations/platform/linear/event-worker.js +1 -1
- package/dist/integrations/slack/feed-publisher.d.ts +26 -0
- package/dist/integrations/slack/feed-publisher.d.ts.map +1 -0
- package/dist/integrations/slack/feed-publisher.js +44 -0
- package/dist/integrations/slack/feed-publisher.js.map +1 -0
- package/dist/integrations/slack/integration.d.ts +2 -0
- package/dist/integrations/slack/integration.d.ts.map +1 -1
- package/dist/integrations/slack/integration.js +5 -0
- package/dist/integrations/slack/integration.js.map +1 -1
- package/dist/integrations/slack/slack.d.ts +13 -1
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +78 -6
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/routes/attention-activity.d.ts +24 -0
- package/dist/routes/attention-activity.d.ts.map +1 -0
- package/dist/routes/attention-activity.js +143 -0
- package/dist/routes/attention-activity.js.map +1 -0
- package/dist/routes/attention-providers.d.ts +31 -1
- package/dist/routes/attention-providers.d.ts.map +1 -1
- package/dist/routes/attention-providers.js +4 -4
- package/dist/routes/attention-providers.js.map +1 -1
- package/dist/routes/attention.d.ts.map +1 -1
- package/dist/routes/attention.js +39 -11
- package/dist/routes/attention.js.map +1 -1
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/projects.js +4 -0
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/skills.d.ts.map +1 -1
- package/dist/routes/skills.js +9 -3
- package/dist/routes/skills.js.map +1 -1
- package/dist/routes/surface.d.ts +5 -0
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +34 -6
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/tenant-credentials.d.ts +4 -4
- package/dist/routes/tenant-credentials.d.ts.map +1 -1
- package/dist/routes/tenant-credentials.js +22 -7
- package/dist/routes/tenant-credentials.js.map +1 -1
- package/dist/routes/work-items.d.ts.map +1 -1
- package/dist/routes/work-items.js +12 -1
- package/dist/routes/work-items.js.map +1 -1
- package/dist/rules/defaults.d.ts.map +1 -1
- package/dist/rules/defaults.js +20 -8
- package/dist/rules/defaults.js.map +1 -1
- package/dist/rules/dispatch-errors.d.ts.map +1 -1
- package/dist/rules/dispatch-errors.js +8 -0
- package/dist/rules/dispatch-errors.js.map +1 -1
- package/dist/rules/dispatcher.d.ts +5 -0
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +125 -62
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/processor.d.ts.map +1 -1
- package/dist/rules/processor.js +2 -3
- package/dist/rules/processor.js.map +1 -1
- package/dist/rules/start-coordinator.d.ts +2 -0
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/start-coordinator.js +6 -1
- package/dist/rules/start-coordinator.js.map +1 -1
- package/dist/rules/transition-service.d.ts +2 -2
- package/dist/rules/transition-service.d.ts.map +1 -1
- package/dist/rules/transition-service.js +33 -12
- package/dist/rules/transition-service.js.map +1 -1
- package/dist/rules/types.d.ts +27 -1
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js +37 -1
- package/dist/rules/types.js.map +1 -1
- package/dist/rules/validation.d.ts.map +1 -1
- package/dist/rules/validation.js +3 -1
- package/dist/rules/validation.js.map +1 -1
- package/dist/sandbox/session-sandbox.d.ts.map +1 -1
- package/dist/sandbox/session-sandbox.js +2 -2
- package/dist/sandbox/session-sandbox.js.map +1 -1
- package/dist/sandbox/workdir.d.ts +7 -2
- package/dist/sandbox/workdir.d.ts.map +1 -1
- package/dist/sandbox/workdir.js +11 -4
- package/dist/sandbox/workdir.js.map +1 -1
- package/dist/skills/catalog.d.ts +4 -1
- package/dist/skills/catalog.d.ts.map +1 -1
- package/dist/skills/catalog.js +11 -4
- package/dist/skills/catalog.js.map +1 -1
- package/dist/skills/service.d.ts +2 -1
- package/dist/skills/service.d.ts.map +1 -1
- package/dist/skills/service.js +5 -2
- package/dist/skills/service.js.map +1 -1
- package/dist/storage/domains/comments/activity.d.ts +40 -0
- package/dist/storage/domains/comments/activity.d.ts.map +1 -0
- package/dist/storage/domains/comments/activity.js +94 -0
- package/dist/storage/domains/comments/activity.js.map +1 -0
- package/dist/storage/domains/comments/base.d.ts +13 -1
- package/dist/storage/domains/comments/base.d.ts.map +1 -1
- package/dist/storage/domains/comments/base.js +43 -7
- package/dist/storage/domains/comments/base.js.map +1 -1
- package/dist/storage/domains/comments/domain.d.ts +13 -3
- package/dist/storage/domains/comments/domain.d.ts.map +1 -1
- package/dist/storage/domains/comments/domain.js +31 -16
- package/dist/storage/domains/comments/domain.js.map +1 -1
- package/dist/storage/domains/comments/feed-context.d.ts +2 -0
- package/dist/storage/domains/comments/feed-context.d.ts.map +1 -1
- package/dist/storage/domains/comments/feed-context.js +6 -4
- package/dist/storage/domains/comments/feed-context.js.map +1 -1
- package/dist/storage/domains/comments/feed-sync.d.ts +9 -26
- package/dist/storage/domains/comments/feed-sync.d.ts.map +1 -1
- package/dist/storage/domains/comments/parse.d.ts +1 -0
- package/dist/storage/domains/comments/parse.d.ts.map +1 -1
- package/dist/storage/domains/comments/parse.js +2 -2
- package/dist/storage/domains/comments/parse.js.map +1 -1
- package/dist/storage/domains/comments/routes.d.ts +2 -0
- package/dist/storage/domains/comments/routes.d.ts.map +1 -1
- package/dist/storage/domains/comments/routes.js +49 -3
- package/dist/storage/domains/comments/routes.js.map +1 -1
- package/dist/storage/domains/comments/schema.d.ts +1 -0
- package/dist/storage/domains/comments/schema.d.ts.map +1 -1
- package/dist/storage/domains/comments/schema.js +45 -1
- package/dist/storage/domains/comments/schema.js.map +1 -1
- package/dist/storage/domains/projects/base.d.ts +3 -0
- package/dist/storage/domains/projects/base.d.ts.map +1 -1
- package/dist/storage/domains/projects/base.js +7 -0
- package/dist/storage/domains/projects/base.js.map +1 -1
- package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -1
- package/dist/storage/domains/source-control/inmemory.js +5 -1
- package/dist/storage/domains/source-control/inmemory.js.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts +46 -4
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +159 -61
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/dist/workspace.d.ts +20 -2
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +49 -15
- package/dist/workspace.js.map +1 -1
- package/factory-skills/factory-rereview/SKILL.md +13 -12
- package/factory-skills/factory-review/SKILL.md +13 -11
- package/factory-skills/factory-triage/SKILL.md +27 -6
- package/package.json +11 -12
- package/CHANGELOG.md +0 -3330
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isTerminalFactoryRuleStage } from "../../../rules/types.js";
|
|
2
|
-
import { WORK_ITEM_COMMENTS_SCHEMA, WORK_ITEM_COMMENT_MENTIONS_SCHEMA } from "../comments/schema.js";
|
|
2
|
+
import { WORK_ITEM_ACTIVITY_SCHEMA, WORK_ITEM_COMMENTS_SCHEMA, WORK_ITEM_COMMENT_MENTIONS_SCHEMA } from "../comments/schema.js";
|
|
3
3
|
import { createHash } from "crypto";
|
|
4
4
|
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
5
5
|
//#region src/storage/domains/work-items/base.ts
|
|
@@ -43,6 +43,8 @@ const FACTORY_DISPATCH_FAILURE_CODES = [
|
|
|
43
43
|
"source_repository_missing",
|
|
44
44
|
"unsupported_provider_item",
|
|
45
45
|
"notification_delivery_failed",
|
|
46
|
+
"plan_awaiting_approval",
|
|
47
|
+
"run_awaiting_input",
|
|
46
48
|
"repository_git_missing",
|
|
47
49
|
"repository_egress_blocked",
|
|
48
50
|
"repository_clone_failed",
|
|
@@ -70,6 +72,14 @@ function factoryMentionAttentionIdentity(commentId) {
|
|
|
70
72
|
occurrence: 0
|
|
71
73
|
};
|
|
72
74
|
}
|
|
75
|
+
/** Collapsed per work item, so the occurrence is what a new comment bumps. */
|
|
76
|
+
function factoryActivityAttentionIdentity(workItemId, occurrence) {
|
|
77
|
+
return {
|
|
78
|
+
kind: "activity",
|
|
79
|
+
sourceId: workItemId,
|
|
80
|
+
occurrence
|
|
81
|
+
};
|
|
82
|
+
}
|
|
73
83
|
function factoryAttentionKey(factoryProjectId, identity) {
|
|
74
84
|
return `factory:${factoryProjectId}:attention:${identity.kind}:${identity.sourceId}:${identity.occurrence}`;
|
|
75
85
|
}
|
|
@@ -119,6 +129,10 @@ const WORK_ITEMS_SCHEMA = {
|
|
|
119
129
|
type: "timestamp",
|
|
120
130
|
nullable: true
|
|
121
131
|
},
|
|
132
|
+
plans_preapproved_at: {
|
|
133
|
+
type: "timestamp",
|
|
134
|
+
nullable: true
|
|
135
|
+
},
|
|
122
136
|
comment_count: {
|
|
123
137
|
type: "integer",
|
|
124
138
|
default: 0
|
|
@@ -139,25 +153,39 @@ const WORK_ITEMS_SCHEMA = {
|
|
|
139
153
|
name: "work_items_project_source_key_unique",
|
|
140
154
|
columns: ["factory_project_id", "source_key"]
|
|
141
155
|
}],
|
|
142
|
-
indexes: [
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
"
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
indexes: [
|
|
157
|
+
{
|
|
158
|
+
name: "work_items_org_project_created_at_id_idx",
|
|
159
|
+
columns: [
|
|
160
|
+
"org_id",
|
|
161
|
+
"factory_project_id",
|
|
162
|
+
"created_at",
|
|
163
|
+
"id"
|
|
164
|
+
]
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: "work_items_project_parent_idx",
|
|
168
|
+
columns: [
|
|
169
|
+
"org_id",
|
|
170
|
+
"factory_project_id",
|
|
171
|
+
"parent_work_item_id"
|
|
172
|
+
]
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: "work_items_source_key_idx",
|
|
176
|
+
columns: ["source_key"]
|
|
177
|
+
}
|
|
178
|
+
]
|
|
158
179
|
};
|
|
159
|
-
|
|
160
|
-
|
|
180
|
+
/**
|
|
181
|
+
* The one shape a platform id takes in a lookup key, for cards and for the
|
|
182
|
+
* comments mirrored off them alike: whoever writes a second builder reopens the
|
|
183
|
+
* cross-workspace collision the `workspaceId` is here to close.
|
|
184
|
+
*/
|
|
185
|
+
function externalSourceKey(source) {
|
|
186
|
+
if (!source) return null;
|
|
187
|
+
const workspace = source.workspaceId ? `${source.workspaceId}:` : "";
|
|
188
|
+
return `${source.integrationId}:${source.type}:${workspace}${source.externalId}`;
|
|
161
189
|
}
|
|
162
190
|
function toWorkItem(row) {
|
|
163
191
|
return {
|
|
@@ -173,6 +201,7 @@ function toWorkItem(row) {
|
|
|
173
201
|
metadata: row.metadata,
|
|
174
202
|
triageType: row.triage_type ?? null,
|
|
175
203
|
autonomyArmedAt: row.autonomy_armed_at ?? null,
|
|
204
|
+
plansPreapprovedAt: row.plans_preapproved_at ?? null,
|
|
176
205
|
commentCount: row.comment_count ?? 0,
|
|
177
206
|
feedActivityAt: row.feed_activity_at ?? null,
|
|
178
207
|
revision: row.revision,
|
|
@@ -191,7 +220,7 @@ function patchColumns(changes) {
|
|
|
191
220
|
...changes.sessions !== void 0 ? { sessions: changes.sessions } : {},
|
|
192
221
|
...changes.metadata !== void 0 ? { metadata: changes.metadata } : {},
|
|
193
222
|
...changes.triageType !== void 0 ? { triage_type: changes.triageType } : {},
|
|
194
|
-
...changes.autonomyArmedAt !== void 0
|
|
223
|
+
...changes.autonomyArmedAt !== void 0 ? { autonomy_armed_at: changes.autonomyArmedAt } : {},
|
|
195
224
|
...changes.revision !== void 0 ? { revision: changes.revision } : {},
|
|
196
225
|
...changes.updatedAt !== void 0 ? { updated_at: changes.updatedAt } : {}
|
|
197
226
|
};
|
|
@@ -577,6 +606,10 @@ const FACTORY_GOVERNANCE_SCHEMAS = [
|
|
|
577
606
|
type: "text",
|
|
578
607
|
nullable: true
|
|
579
608
|
},
|
|
609
|
+
failure_code: {
|
|
610
|
+
type: "text",
|
|
611
|
+
nullable: true
|
|
612
|
+
},
|
|
580
613
|
completed_at: {
|
|
581
614
|
type: "timestamp",
|
|
582
615
|
nullable: true
|
|
@@ -644,7 +677,7 @@ function toDeferredDecision(row) {
|
|
|
644
677
|
};
|
|
645
678
|
}
|
|
646
679
|
function attentionReceiptKind(value) {
|
|
647
|
-
if (value === "automation-failed" || value === "mention") return value;
|
|
680
|
+
if (value === "automation-failed" || value === "mention" || value === "activity") return value;
|
|
648
681
|
throw new Error(`Unsupported attention receipt kind '${String(value)}'.`);
|
|
649
682
|
}
|
|
650
683
|
function attentionReceiptState(value) {
|
|
@@ -689,21 +722,32 @@ function toPendingStart(row) {
|
|
|
689
722
|
leaseOwner: row.lease_owner ?? null,
|
|
690
723
|
leaseExpiresAt: row.lease_expires_at ?? null,
|
|
691
724
|
lastError: row.last_error ?? null,
|
|
725
|
+
failureCode: row.failure_code ?? null,
|
|
692
726
|
completedAt: row.completed_at ?? null,
|
|
693
727
|
createdAt: row.created_at,
|
|
694
728
|
updatedAt: row.updated_at
|
|
695
729
|
};
|
|
696
730
|
}
|
|
697
731
|
var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
732
|
+
#attentionChanged = () => {};
|
|
698
733
|
constructor() {
|
|
699
734
|
super("work-items");
|
|
700
735
|
}
|
|
736
|
+
/**
|
|
737
|
+
* Wired once at boot. Every write below that changes what this project's
|
|
738
|
+
* attention list projects announces it here — the one place a new such write
|
|
739
|
+
* has to remember, since clients stop polling while their stream is up.
|
|
740
|
+
*/
|
|
741
|
+
onAttentionChanged(listener) {
|
|
742
|
+
this.#attentionChanged = listener;
|
|
743
|
+
}
|
|
701
744
|
async init() {
|
|
702
745
|
await this.ensureCollections([
|
|
703
746
|
WORK_ITEMS_SCHEMA,
|
|
704
747
|
...FACTORY_GOVERNANCE_SCHEMAS,
|
|
705
748
|
WORK_ITEM_COMMENTS_SCHEMA,
|
|
706
|
-
WORK_ITEM_COMMENT_MENTIONS_SCHEMA
|
|
749
|
+
WORK_ITEM_COMMENT_MENTIONS_SCHEMA,
|
|
750
|
+
WORK_ITEM_ACTIVITY_SCHEMA
|
|
707
751
|
]);
|
|
708
752
|
await this.repairLegacyAttentionState();
|
|
709
753
|
}
|
|
@@ -812,7 +856,7 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
812
856
|
lease_owner: null,
|
|
813
857
|
lease_expires_at: null,
|
|
814
858
|
last_error: input.lastError,
|
|
815
|
-
|
|
859
|
+
failure_code: input.failureCode,
|
|
816
860
|
completed_at: input.terminal ? input.now : null,
|
|
817
861
|
...table === "factory_deferred_decisions" && input.terminal ? { failure_occurrence: Number(current.failure_occurrence ?? 0) + 1 } : {},
|
|
818
862
|
updated_at: input.now
|
|
@@ -873,6 +917,16 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
873
917
|
});
|
|
874
918
|
return row ? toWorkItem(row) : null;
|
|
875
919
|
}
|
|
920
|
+
/**
|
|
921
|
+
* Resolve the card a platform thread created, given only its external source.
|
|
922
|
+
* Bare of org/project because an inbound platform message carries neither: an
|
|
923
|
+
* unlinked sender has no tenant. Tenant safety rides on the key's
|
|
924
|
+
* `workspaceId` instead. Ambiguous matches resolve to nothing, not a guess.
|
|
925
|
+
*/
|
|
926
|
+
async getBySource(source) {
|
|
927
|
+
const rows = await this.#db.findMany("work_items", { source_key: externalSourceKey(source) });
|
|
928
|
+
return rows.length === 1 ? toWorkItem(rows[0]) : null;
|
|
929
|
+
}
|
|
876
930
|
async getForProject(orgId, factoryProjectId, id) {
|
|
877
931
|
const row = await this.#db.findOne("work_items", {
|
|
878
932
|
id,
|
|
@@ -922,19 +976,22 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
922
976
|
reason = input.evaluation.reason;
|
|
923
977
|
return null;
|
|
924
978
|
}
|
|
925
|
-
const arm = input.
|
|
979
|
+
const arm = input.autonomy === "arm" && !existing.autonomyArmedAt;
|
|
980
|
+
const disarm = input.autonomy === "disarm" && existing.autonomyArmedAt !== null;
|
|
926
981
|
const triageType = existing.triageType ?? input.triageType ?? null;
|
|
927
982
|
const classified = triageType !== existing.triageType;
|
|
928
|
-
if (existing.stages.length === 1 && existing.stages[0] === input.destinationStage) return arm || classified ? patchColumns({
|
|
983
|
+
if (existing.stages.length === 1 && existing.stages[0] === input.destinationStage) return arm || disarm || classified ? patchColumns({
|
|
929
984
|
...arm ? { autonomyArmedAt: now } : {},
|
|
930
|
-
...
|
|
985
|
+
...disarm ? { autonomyArmedAt: null } : {},
|
|
931
986
|
...classified ? {
|
|
987
|
+
triageType,
|
|
932
988
|
revision: existing.revision + 1,
|
|
933
989
|
updatedAt: now
|
|
934
990
|
} : {}
|
|
935
991
|
}) : null;
|
|
936
992
|
return patchColumns({
|
|
937
993
|
...arm ? { autonomyArmedAt: now } : {},
|
|
994
|
+
...disarm ? { autonomyArmedAt: null } : {},
|
|
938
995
|
...classified ? { triageType } : {},
|
|
939
996
|
stages: [input.destinationStage],
|
|
940
997
|
stageHistory: applyStageTransition(existing.stageHistory, existing.stages, [input.destinationStage], input.actorId, now),
|
|
@@ -983,29 +1040,34 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
983
1040
|
causal_chain: input.causalChain,
|
|
984
1041
|
created_at: now
|
|
985
1042
|
});
|
|
986
|
-
if (outcome === "accepted" && input.evaluation.outcome === "accepted") for (const [index, decision] of input.evaluation.decisions.entries())
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1043
|
+
if (outcome === "accepted" && input.evaluation.outcome === "accepted") for (const [index, decision] of input.evaluation.decisions.entries()) {
|
|
1044
|
+
const approvedBy = decision.type === "invokeSkill" ? input.consentedBy ?? null : null;
|
|
1045
|
+
await ops.insertOne("factory_deferred_decisions", {
|
|
1046
|
+
org_id: input.orgId,
|
|
1047
|
+
factory_project_id: input.factoryProjectId,
|
|
1048
|
+
evaluation_id: evaluation.id,
|
|
1049
|
+
work_item_id: item.id,
|
|
1050
|
+
source_key: decisionSourceKey(decision),
|
|
1051
|
+
idempotency_key: String(decision.idempotencyKey),
|
|
1052
|
+
effect_ordinal: index,
|
|
1053
|
+
effect_hash: factoryDecisionHash(decision),
|
|
1054
|
+
causal_chain: input.causalChain,
|
|
1055
|
+
actor: null,
|
|
1056
|
+
decision,
|
|
1057
|
+
status: "pending",
|
|
1058
|
+
attempts: 0,
|
|
1059
|
+
delivery_generation: 0,
|
|
1060
|
+
available_at: now,
|
|
1061
|
+
lease_owner: null,
|
|
1062
|
+
lease_expires_at: null,
|
|
1063
|
+
last_error: null,
|
|
1064
|
+
approved_at: approvedBy ? now : null,
|
|
1065
|
+
approved_by: approvedBy,
|
|
1066
|
+
completed_at: null,
|
|
1067
|
+
created_at: new Date(now.getTime() + index),
|
|
1068
|
+
updated_at: now
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1009
1071
|
}
|
|
1010
1072
|
return {
|
|
1011
1073
|
status: "committed",
|
|
@@ -1282,6 +1344,13 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1282
1344
|
});
|
|
1283
1345
|
return Boolean(decision) && currentOccurrence;
|
|
1284
1346
|
}
|
|
1347
|
+
if (identity.kind === "activity") return await ops.findOne("work_item_activity", {
|
|
1348
|
+
work_item_id: identity.sourceId,
|
|
1349
|
+
participant_id: userId,
|
|
1350
|
+
org_id: orgId,
|
|
1351
|
+
factory_project_id: factoryProjectId,
|
|
1352
|
+
occurrence: identity.occurrence
|
|
1353
|
+
}) !== null;
|
|
1285
1354
|
if (identity.occurrence !== 0) return false;
|
|
1286
1355
|
if (!await ops.findOne("work_item_comment_mentions", {
|
|
1287
1356
|
comment_id: identity.sourceId,
|
|
@@ -1364,7 +1433,10 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1364
1433
|
}
|
|
1365
1434
|
async failDeferredDecision(input) {
|
|
1366
1435
|
const row = await this.#failLease("factory_deferred_decisions", input);
|
|
1367
|
-
|
|
1436
|
+
if (!row) return null;
|
|
1437
|
+
const record = toDeferredDecision(row);
|
|
1438
|
+
if (input.terminal) this.#attentionChanged(record);
|
|
1439
|
+
return record;
|
|
1368
1440
|
}
|
|
1369
1441
|
/** Park a claimed effect for human approval; the dispatcher never claims `proposed` rows. */
|
|
1370
1442
|
async proposeDeferredDecision(identity, now) {
|
|
@@ -1384,7 +1456,10 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1384
1456
|
updated_at: now
|
|
1385
1457
|
};
|
|
1386
1458
|
});
|
|
1387
|
-
|
|
1459
|
+
if (!proposed || !row) return null;
|
|
1460
|
+
const record = toDeferredDecision(row);
|
|
1461
|
+
this.#attentionChanged(record);
|
|
1462
|
+
return record;
|
|
1388
1463
|
}
|
|
1389
1464
|
/**
|
|
1390
1465
|
* Release an approved effect back to the dispatcher; only `proposed` rows are
|
|
@@ -1393,7 +1468,7 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1393
1468
|
* leaving its follow-up work parked for re-approval.
|
|
1394
1469
|
*/
|
|
1395
1470
|
async approveDeferredDecision(orgId, factoryProjectId, decisionId, now, approvedBy) {
|
|
1396
|
-
|
|
1471
|
+
const approved = await this.storage.withTransaction(async (ops) => {
|
|
1397
1472
|
let settled = false;
|
|
1398
1473
|
const row = await ops.updateAtomic("factory_deferred_decisions", {
|
|
1399
1474
|
id: decisionId,
|
|
@@ -1419,6 +1494,8 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1419
1494
|
}, (current) => current.autonomy_armed_at ? null : { autonomy_armed_at: now });
|
|
1420
1495
|
return record;
|
|
1421
1496
|
});
|
|
1497
|
+
if (approved) this.#attentionChanged(approved);
|
|
1498
|
+
return approved;
|
|
1422
1499
|
}
|
|
1423
1500
|
/** Retire a proposal nobody wants: `dismissed` is terminal, so the run never happens. */
|
|
1424
1501
|
async dismissDeferredDecision(orgId, factoryProjectId, decisionId, now) {
|
|
@@ -1477,10 +1554,13 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1477
1554
|
settled = true;
|
|
1478
1555
|
return patch;
|
|
1479
1556
|
});
|
|
1480
|
-
|
|
1557
|
+
if (!settled || !row) return null;
|
|
1558
|
+
const record = toDeferredDecision(row);
|
|
1559
|
+
this.#attentionChanged(record);
|
|
1560
|
+
return record;
|
|
1481
1561
|
}
|
|
1482
1562
|
async #resolveFailedDecision({ orgId, factoryProjectId, decisionId, status, now }) {
|
|
1483
|
-
|
|
1563
|
+
const resolved = await this.storage.withTransaction(async (ops) => {
|
|
1484
1564
|
let resolved = false;
|
|
1485
1565
|
const row = await ops.updateAtomic("factory_deferred_decisions", {
|
|
1486
1566
|
id: decisionId,
|
|
@@ -1504,6 +1584,8 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1504
1584
|
});
|
|
1505
1585
|
return toDeferredDecision(row);
|
|
1506
1586
|
});
|
|
1587
|
+
if (resolved) this.#attentionChanged(resolved);
|
|
1588
|
+
return resolved;
|
|
1507
1589
|
}
|
|
1508
1590
|
async supersedeTerminalDecisionsForWorkItem(input) {
|
|
1509
1591
|
await this.supersedeDecisionsForWorkItem(input);
|
|
@@ -1560,7 +1642,7 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1560
1642
|
}
|
|
1561
1643
|
/** Requeue the same idempotent terminal effect; non-failed decisions are never rerun. */
|
|
1562
1644
|
async retryDeferredDecision(orgId, factoryProjectId, decisionId, now) {
|
|
1563
|
-
|
|
1645
|
+
const retriedRecord = await this.storage.withTransaction(async (ops) => {
|
|
1564
1646
|
let retried = false;
|
|
1565
1647
|
const row = await ops.updateAtomic("factory_deferred_decisions", {
|
|
1566
1648
|
id: decisionId,
|
|
@@ -1592,6 +1674,8 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1592
1674
|
});
|
|
1593
1675
|
return toDeferredDecision(row);
|
|
1594
1676
|
});
|
|
1677
|
+
if (retriedRecord) this.#attentionChanged(retriedRecord);
|
|
1678
|
+
return retriedRecord;
|
|
1595
1679
|
}
|
|
1596
1680
|
/** Resolve exact active agent authority; partial session matches never authorize. */
|
|
1597
1681
|
async findActiveRunBinding(address) {
|
|
@@ -1769,10 +1853,10 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1769
1853
|
id: input.workItem.id,
|
|
1770
1854
|
org_id: input.orgId,
|
|
1771
1855
|
factory_project_id: input.factoryProjectId
|
|
1772
|
-
}) :
|
|
1856
|
+
}) : externalSourceKey(create.externalSource) ? await ops.findOne("work_items", {
|
|
1773
1857
|
org_id: input.orgId,
|
|
1774
1858
|
factory_project_id: input.factoryProjectId,
|
|
1775
|
-
source_key:
|
|
1859
|
+
source_key: externalSourceKey(create.externalSource)
|
|
1776
1860
|
}) : null;
|
|
1777
1861
|
let item;
|
|
1778
1862
|
if (row) {
|
|
@@ -1794,7 +1878,7 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1794
1878
|
created_by: input.userId,
|
|
1795
1879
|
factory_project_id: input.factoryProjectId,
|
|
1796
1880
|
external_source: create.externalSource ?? null,
|
|
1797
|
-
source_key:
|
|
1881
|
+
source_key: externalSourceKey(create.externalSource),
|
|
1798
1882
|
parent_work_item_id: create.parentWorkItemId ?? null,
|
|
1799
1883
|
title: create.title,
|
|
1800
1884
|
stages: create.stages ?? [],
|
|
@@ -1811,6 +1895,10 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1811
1895
|
const armedRow = await ops.updateAtomic("work_items", { id: item.id }, (current) => current.autonomy_armed_at ? null : { autonomy_armed_at: now });
|
|
1812
1896
|
if (armedRow) item = toRow(armedRow);
|
|
1813
1897
|
}
|
|
1898
|
+
if (input.preapprovePlans && !item.plansPreapprovedAt) {
|
|
1899
|
+
const grantedRow = await ops.updateAtomic("work_items", { id: item.id }, (current) => current.plans_preapproved_at ? null : { plans_preapproved_at: now });
|
|
1900
|
+
if (grantedRow) item = toRow(grantedRow);
|
|
1901
|
+
}
|
|
1814
1902
|
await ops.updateMany("factory_run_bindings", {
|
|
1815
1903
|
org_id: input.orgId,
|
|
1816
1904
|
factory_project_id: input.factoryProjectId,
|
|
@@ -1857,6 +1945,7 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1857
1945
|
lease_owner: null,
|
|
1858
1946
|
lease_expires_at: null,
|
|
1859
1947
|
last_error: null,
|
|
1948
|
+
failure_code: null,
|
|
1860
1949
|
completed_at: null,
|
|
1861
1950
|
created_at: now,
|
|
1862
1951
|
updated_at: now
|
|
@@ -1904,7 +1993,7 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
1904
1993
|
}
|
|
1905
1994
|
}
|
|
1906
1995
|
async #upsert({ orgId, userId, factoryProjectId, input, reuseMode = "update" }, ops) {
|
|
1907
|
-
const key =
|
|
1996
|
+
const key = externalSourceKey(input.externalSource);
|
|
1908
1997
|
const reuse = async () => {
|
|
1909
1998
|
if (!key) return null;
|
|
1910
1999
|
const existing = await ops.findOne("work_items", {
|
|
@@ -2101,6 +2190,13 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
2101
2190
|
if (comments.length < ATTENTION_RECEIPT_QUERY_BATCH_SIZE) break;
|
|
2102
2191
|
}
|
|
2103
2192
|
await ops.deleteMany("work_item_comment_mentions", where);
|
|
2193
|
+
await ops.deleteMany("factory_attention_receipts", {
|
|
2194
|
+
org_id: orgId,
|
|
2195
|
+
factory_project_id: factoryProjectId,
|
|
2196
|
+
kind: "activity",
|
|
2197
|
+
source_id: workItemId
|
|
2198
|
+
});
|
|
2199
|
+
await ops.deleteMany("work_item_activity", where);
|
|
2104
2200
|
}
|
|
2105
2201
|
async delete({ orgId, id }) {
|
|
2106
2202
|
const candidate = await this.#db.findOne("work_items", {
|
|
@@ -2108,7 +2204,7 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
2108
2204
|
id
|
|
2109
2205
|
});
|
|
2110
2206
|
if (!candidate) return null;
|
|
2111
|
-
|
|
2207
|
+
const removed = await this.#withProjectRelationTransaction(orgId, candidate.factory_project_id, async (ops) => {
|
|
2112
2208
|
const existing = await ops.findOne("work_items", {
|
|
2113
2209
|
org_id: orgId,
|
|
2114
2210
|
id
|
|
@@ -2137,9 +2233,11 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
2137
2233
|
});
|
|
2138
2234
|
return toWorkItem(existing);
|
|
2139
2235
|
});
|
|
2236
|
+
if (removed) this.#attentionChanged(removed);
|
|
2237
|
+
return removed;
|
|
2140
2238
|
}
|
|
2141
2239
|
};
|
|
2142
2240
|
//#endregion
|
|
2143
|
-
export { FACTORY_PULL_REQUEST_RECONCILIATION_KEY, FACTORY_RULE_MATERIALIZATION_KEY, WORK_ITEMS_SCHEMA, WorkItemRelationError, WorkItemsStorage, applyStageTransition, factoryAttentionKey, factoryDecisionAttentionIdentity, factoryDecisionHash, factoryMentionAttentionIdentity, isAgentActor, stampSessions, validateParentRelation };
|
|
2241
|
+
export { FACTORY_PULL_REQUEST_RECONCILIATION_KEY, FACTORY_RULE_MATERIALIZATION_KEY, WORK_ITEMS_SCHEMA, WorkItemRelationError, WorkItemsStorage, applyStageTransition, externalSourceKey, factoryActivityAttentionIdentity, factoryAttentionKey, factoryDecisionAttentionIdentity, factoryDecisionHash, factoryMentionAttentionIdentity, isAgentActor, stampSessions, validateParentRelation };
|
|
2144
2242
|
|
|
2145
2243
|
//# sourceMappingURL=base.js.map
|