@happyvertical/smrt-projects 0.34.0 → 0.34.2

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.
@@ -91,13 +91,20 @@ export declare class IssueCollection extends SmrtCollection<Issue> {
91
91
  */
92
92
  findByTenant(tenantId: string): Promise<Issue[]>;
93
93
  /**
94
- * Find global issues (no tenant)
94
+ * Find all global issues (no tenant association).
95
+ *
96
+ * Routes through the shared tenant-global helper so it does not throw under
97
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
98
+ * flagged as an isolation violation). (#1600)
95
99
  *
96
100
  * @returns Array of global issues
97
101
  */
98
102
  findGlobal(): Promise<Issue[]>;
99
103
  /**
100
- * Find issues for a tenant including global issues
104
+ * Find issues for a tenant plus all global issues.
105
+ *
106
+ * Fails closed if an active tenant context requests a different tenant's
107
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
101
108
  *
102
109
  * @param tenantId - Tenant ID to filter by
103
110
  * @returns Array of tenant and global issues
@@ -1 +1 @@
1
- {"version":3,"file":"Issues.d.ts","sourceRoot":"","sources":["../../src/collections/Issues.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,qBAAa,eAAgB,SAAQ,cAAc,CAAC,KAAK,CAAC;IACxD,MAAM,CAAC,QAAQ,CAAC,UAAU,eAAS;IAEnC;;;;;;;;;;OAUG;IACG,QAAQ,CAAC,OAAO,EAAE;QACtB,UAAU,EAAE,UAAU,CAAC;QACvB,OAAO,CAAC,EAAE,aAAa,CAAC;KACzB,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA2DpB;;;;;OAKG;IACG,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAM9D;;;;;OAKG;IACG,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAQvD;;;;;;OAMG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IASzE;;;;;;OAMG;IACG,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,KAAK,EAAE,CAAC;IASnB;;;;;OAKG;IACG,iBAAiB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAahE;;;;;;OAMG;IACG,YAAY,CAChB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAQxB;;;;;;;OAOG;IACG,8BAA8B,CAClC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,KAAK,EAAE,CAAC;IAQnB;;;;;;OAMG;IACG,SAAS,CACb,UAAU,EAAE,UAAU,EACtB,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAChC,OAAO,CAAC,KAAK,EAAE,CAAC;IAYnB;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAItD;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAIpC;;;;;OAKG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;CAM1D"}
1
+ {"version":3,"file":"Issues.d.ts","sourceRoot":"","sources":["../../src/collections/Issues.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,qBAAa,eAAgB,SAAQ,cAAc,CAAC,KAAK,CAAC;IACxD,MAAM,CAAC,QAAQ,CAAC,UAAU,eAAS;IAEnC;;;;;;;;;;OAUG;IACG,QAAQ,CAAC,OAAO,EAAE;QACtB,UAAU,EAAE,UAAU,CAAC;QACvB,OAAO,CAAC,EAAE,aAAa,CAAC;KACzB,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA2DpB;;;;;OAKG;IACG,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAM9D;;;;;OAKG;IACG,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAQvD;;;;;;OAMG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IASzE;;;;;;OAMG;IACG,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,KAAK,EAAE,CAAC;IASnB;;;;;OAKG;IACG,iBAAiB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAahE;;;;;;OAMG;IACG,YAAY,CAChB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAQxB;;;;;;;OAOG;IACG,8BAA8B,CAClC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,KAAK,EAAE,CAAC;IAQnB;;;;;;OAMG;IACG,SAAS,CACb,UAAU,EAAE,UAAU,EACtB,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAChC,OAAO,CAAC,KAAK,EAAE,CAAC;IAYnB;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAItD;;;;;;;;OAQG;IACG,UAAU,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAIpC;;;;;;;;OAQG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;CAG1D"}
@@ -74,13 +74,20 @@ export declare class ProjectCollection extends SmrtCollection<Project> {
74
74
  */
75
75
  findByTenant(tenantId: string): Promise<Project[]>;
76
76
  /**
77
- * Find global projects (no tenant)
77
+ * Find all global projects (no tenant association).
78
+ *
79
+ * Routes through the shared tenant-global helper so it does not throw under
80
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
81
+ * flagged as an isolation violation). (#1600)
78
82
  *
79
83
  * @returns Array of global projects
80
84
  */
81
85
  findGlobal(): Promise<Project[]>;
82
86
  /**
83
- * Find projects for a tenant including global projects
87
+ * Find projects for a tenant plus all global projects.
88
+ *
89
+ * Fails closed if an active tenant context requests a different tenant's
90
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
84
91
  *
85
92
  * @param tenantId - Tenant ID to filter by
86
93
  * @returns Array of tenant and global projects
@@ -1 +1 @@
1
- {"version":3,"file":"Projects.d.ts","sourceRoot":"","sources":["../../src/collections/Projects.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAIpD,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,OAAO,CAAC;IAC5D,MAAM,CAAC,QAAQ,CAAC,UAAU,iBAAW;IAErC;;;;;OAKG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAQzD;;;;;OAKG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAMpD;;;;;OAKG;IACG,cAAc,CAAC,YAAY,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAM3E;;;;;;OAMG;IACG,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,mBAAmB,CAAC;QACnC,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACnC,GACL,OAAO,CAAC,OAAO,CAAC;IAwBnB;;;;;OAKG;IACG,OAAO,CAAC,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAYpE;;;;;OAKG;IACG,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAqB/D;;;;;OAKG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAC9C,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACtC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACrC,CAAC;IAoCF;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAIxD;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAItC;;;;;OAKG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAM5D"}
1
+ {"version":3,"file":"Projects.d.ts","sourceRoot":"","sources":["../../src/collections/Projects.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAIpD,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,OAAO,CAAC;IAC5D,MAAM,CAAC,QAAQ,CAAC,UAAU,iBAAW;IAErC;;;;;OAKG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAQzD;;;;;OAKG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAMpD;;;;;OAKG;IACG,cAAc,CAAC,YAAY,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAM3E;;;;;;OAMG;IACG,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,mBAAmB,CAAC;QACnC,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACnC,GACL,OAAO,CAAC,OAAO,CAAC;IAwBnB;;;;;OAKG;IACG,OAAO,CAAC,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAYpE;;;;;OAKG;IACG,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAqB/D;;;;;OAKG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAC9C,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACtC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACrC,CAAC;IAoCF;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAIxD;;;;;;;;OAQG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAItC;;;;;;;;OAQG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAG5D"}
@@ -91,13 +91,20 @@ export declare class PullRequestCollection extends SmrtCollection<PullRequest> {
91
91
  */
92
92
  findByTenant(tenantId: string): Promise<PullRequest[]>;
93
93
  /**
94
- * Find global pull requests (no tenant)
94
+ * Find all global pull requests (no tenant association).
95
+ *
96
+ * Routes through the shared tenant-global helper so it does not throw under
97
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
98
+ * flagged as an isolation violation). (#1600)
95
99
  *
96
100
  * @returns Array of global pull requests
97
101
  */
98
102
  findGlobal(): Promise<PullRequest[]>;
99
103
  /**
100
- * Find pull requests for a tenant including global pull requests
104
+ * Find pull requests for a tenant plus all global pull requests.
105
+ *
106
+ * Fails closed if an active tenant context requests a different tenant's
107
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
101
108
  *
102
109
  * @param tenantId - Tenant ID to filter by
103
110
  * @returns Array of tenant and global pull requests
@@ -1 +1 @@
1
- {"version":3,"file":"PullRequests.d.ts","sourceRoot":"","sources":["../../src/collections/PullRequests.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,UAAU,CAAC;AAI9D,qBAAa,qBAAsB,SAAQ,cAAc,CAAC,WAAW,CAAC;IACpE,MAAM,CAAC,QAAQ,CAAC,UAAU,qBAAe;IAEzC;;;;;OAKG;IACG,QAAQ,CAAC,OAAO,EAAE;QACtB,UAAU,EAAE,UAAU,CAAC;QACvB,OAAO,CAAC,EAAE,aAAa,CAAC;KACzB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAuF1B;;;;;OAKG;IACG,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAMpE;;;;;OAKG;IACG,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAQ7D;;;;;OAKG;IACG,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAK/D;;;;;OAKG;IACG,gBAAgB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAKrE;;;;;;OAMG;IACG,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,EAAE,CAAC;IAQzB;;;;;;OAMG;IACG,YAAY,CAChB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAQ9B;;;;;OAKG;IACG,kBAAkB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAavE;;;;;;OAMG;IACG,UAAU,CACd,IAAI,EAAE,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,EACnC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,EAAE,CAAC;IAKzB;;;;;;OAMG;IACG,SAAS,CACb,UAAU,EAAE,UAAU,EACtB,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAChC,OAAO,CAAC,WAAW,EAAE,CAAC;IAYzB;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI5D;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAI1C;;;;;OAKG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;CAMhE"}
1
+ {"version":3,"file":"PullRequests.d.ts","sourceRoot":"","sources":["../../src/collections/PullRequests.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,UAAU,CAAC;AAI9D,qBAAa,qBAAsB,SAAQ,cAAc,CAAC,WAAW,CAAC;IACpE,MAAM,CAAC,QAAQ,CAAC,UAAU,qBAAe;IAEzC;;;;;OAKG;IACG,QAAQ,CAAC,OAAO,EAAE;QACtB,UAAU,EAAE,UAAU,CAAC;QACvB,OAAO,CAAC,EAAE,aAAa,CAAC;KACzB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAuF1B;;;;;OAKG;IACG,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAMpE;;;;;OAKG;IACG,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAQ7D;;;;;OAKG;IACG,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAK/D;;;;;OAKG;IACG,gBAAgB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAKrE;;;;;;OAMG;IACG,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,EAAE,CAAC;IAQzB;;;;;;OAMG;IACG,YAAY,CAChB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAQ9B;;;;;OAKG;IACG,kBAAkB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAavE;;;;;;OAMG;IACG,UAAU,CACd,IAAI,EAAE,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,EACnC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,EAAE,CAAC;IAKzB;;;;;;OAMG;IACG,SAAS,CACb,UAAU,EAAE,UAAU,EACtB,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAChC,OAAO,CAAC,WAAW,EAAE,CAAC;IAYzB;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI5D;;;;;;;;OAQG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAI1C;;;;;;;;OAQG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;CAOhE"}
@@ -61,13 +61,20 @@ export declare class RepositoryCollection extends SmrtCollection<Repository> {
61
61
  */
62
62
  findByTenant(tenantId: string): Promise<Repository[]>;
63
63
  /**
64
- * Find global repositories (no tenant)
64
+ * Find all global repositories (no tenant association).
65
+ *
66
+ * Routes through the shared tenant-global helper so it does not throw under
67
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
68
+ * flagged as an isolation violation). (#1600)
65
69
  *
66
70
  * @returns Array of global repositories
67
71
  */
68
72
  findGlobal(): Promise<Repository[]>;
69
73
  /**
70
- * Find repositories for a tenant including global repositories
74
+ * Find repositories for a tenant plus all global repositories.
75
+ *
76
+ * Fails closed if an active tenant context requests a different tenant's
77
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
71
78
  *
72
79
  * @param tenantId - Tenant ID to filter by
73
80
  * @returns Array of tenant and global repositories
@@ -1 +1 @@
1
- {"version":3,"file":"Repositories.d.ts","sourceRoot":"","sources":["../../src/collections/Repositories.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAIvD,qBAAa,oBAAqB,SAAQ,cAAc,CAAC,UAAU,CAAC;IAClE,MAAM,CAAC,QAAQ,CAAC,UAAU,oBAAc;IAExC;;;;;;OAMG;IACG,cAAc,CAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAQ7B;;;;;OAKG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAMvD;;;;;OAKG;IACG,cAAc,CAClB,YAAY,EAAE,sBAAsB,GACnC,OAAO,CAAC,UAAU,EAAE,CAAC;IAMxB;;;;;;;OAOG;IACG,WAAW,CACf,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;QACP,YAAY,CAAC,EAAE,sBAAsB,CAAC;QACtC,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,CAAC;KACb,GACL,OAAO,CAAC,UAAU,CAAC;IAkBtB;;;;;OAKG;IACG,OAAO,CAAC,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAYvE;;;;OAIG;IACG,kBAAkB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAsBjD;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAI3D;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAIzC;;;;;OAKG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;CAM/D"}
1
+ {"version":3,"file":"Repositories.d.ts","sourceRoot":"","sources":["../../src/collections/Repositories.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAIvD,qBAAa,oBAAqB,SAAQ,cAAc,CAAC,UAAU,CAAC;IAClE,MAAM,CAAC,QAAQ,CAAC,UAAU,oBAAc;IAExC;;;;;;OAMG;IACG,cAAc,CAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAQ7B;;;;;OAKG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAMvD;;;;;OAKG;IACG,cAAc,CAClB,YAAY,EAAE,sBAAsB,GACnC,OAAO,CAAC,UAAU,EAAE,CAAC;IAMxB;;;;;;;OAOG;IACG,WAAW,CACf,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;QACP,YAAY,CAAC,EAAE,sBAAsB,CAAC;QACtC,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,CAAC;KACb,GACL,OAAO,CAAC,UAAU,CAAC;IAkBtB;;;;;OAKG;IACG,OAAO,CAAC,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAYvE;;;;OAIG;IACG,kBAAkB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAsBjD;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAI3D;;;;;;;;OAQG;IACG,UAAU,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAIzC;;;;;;;;OAQG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;CAO/D"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ObjectRegistry, foreignKey, smrt, SmrtObject, config, SmrtCollection } from "@happyvertical/smrt-core";
2
+ import { tenantId, TenantScoped, queryGlobal, queryWithGlobals } from "@happyvertical/smrt-tenancy";
2
3
  import { getAI } from "@happyvertical/ai";
3
4
  import { definePrompt, resolvePrompt } from "@happyvertical/smrt-prompts";
4
- import { tenantId, TenantScoped } from "@happyvertical/smrt-tenancy";
5
5
  import { loadEnvConfig } from "@happyvertical/utils";
6
6
  import { createLogger } from "@happyvertical/logger";
7
7
  import { getProject } from "@happyvertical/projects";
@@ -713,24 +713,28 @@ class IssueCollection extends SmrtCollection {
713
713
  return this.list({ where: { tenantId: tenantId2 } });
714
714
  }
715
715
  /**
716
- * Find global issues (no tenant)
716
+ * Find all global issues (no tenant association).
717
+ *
718
+ * Routes through the shared tenant-global helper so it does not throw under
719
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
720
+ * flagged as an isolation violation). (#1600)
717
721
  *
718
722
  * @returns Array of global issues
719
723
  */
720
724
  async findGlobal() {
721
- return this.list({ where: { tenantId: null } });
725
+ return queryGlobal(this);
722
726
  }
723
727
  /**
724
- * Find issues for a tenant including global issues
728
+ * Find issues for a tenant plus all global issues.
729
+ *
730
+ * Fails closed if an active tenant context requests a different tenant's
731
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
725
732
  *
726
733
  * @param tenantId - Tenant ID to filter by
727
734
  * @returns Array of tenant and global issues
728
735
  */
729
736
  async findWithGlobals(tenantId2) {
730
- return this.query(
731
- `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,
732
- [tenantId2]
733
- );
737
+ return queryWithGlobals(this, tenantId2, "Issue.findWithGlobals");
734
738
  }
735
739
  }
736
740
  const Issues = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -1213,24 +1217,28 @@ class ProjectCollection extends SmrtCollection {
1213
1217
  return this.list({ where: { tenantId: tenantId2 } });
1214
1218
  }
1215
1219
  /**
1216
- * Find global projects (no tenant)
1220
+ * Find all global projects (no tenant association).
1221
+ *
1222
+ * Routes through the shared tenant-global helper so it does not throw under
1223
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
1224
+ * flagged as an isolation violation). (#1600)
1217
1225
  *
1218
1226
  * @returns Array of global projects
1219
1227
  */
1220
1228
  async findGlobal() {
1221
- return this.list({ where: { tenantId: null } });
1229
+ return queryGlobal(this);
1222
1230
  }
1223
1231
  /**
1224
- * Find projects for a tenant including global projects
1232
+ * Find projects for a tenant plus all global projects.
1233
+ *
1234
+ * Fails closed if an active tenant context requests a different tenant's
1235
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
1225
1236
  *
1226
1237
  * @param tenantId - Tenant ID to filter by
1227
1238
  * @returns Array of tenant and global projects
1228
1239
  */
1229
1240
  async findWithGlobals(tenantId2) {
1230
- return this.query(
1231
- `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,
1232
- [tenantId2]
1233
- );
1241
+ return queryWithGlobals(this, tenantId2, "Project.findWithGlobals");
1234
1242
  }
1235
1243
  }
1236
1244
  const Projects = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -1712,23 +1720,31 @@ class PullRequestCollection extends SmrtCollection {
1712
1720
  return this.list({ where: { tenantId: tenantId2 } });
1713
1721
  }
1714
1722
  /**
1715
- * Find global pull requests (no tenant)
1723
+ * Find all global pull requests (no tenant association).
1724
+ *
1725
+ * Routes through the shared tenant-global helper so it does not throw under
1726
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
1727
+ * flagged as an isolation violation). (#1600)
1716
1728
  *
1717
1729
  * @returns Array of global pull requests
1718
1730
  */
1719
1731
  async findGlobal() {
1720
- return this.list({ where: { tenantId: null } });
1732
+ return queryGlobal(this);
1721
1733
  }
1722
1734
  /**
1723
- * Find pull requests for a tenant including global pull requests
1735
+ * Find pull requests for a tenant plus all global pull requests.
1736
+ *
1737
+ * Fails closed if an active tenant context requests a different tenant's
1738
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
1724
1739
  *
1725
1740
  * @param tenantId - Tenant ID to filter by
1726
1741
  * @returns Array of tenant and global pull requests
1727
1742
  */
1728
1743
  async findWithGlobals(tenantId2) {
1729
- return this.query(
1730
- `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,
1731
- [tenantId2]
1744
+ return queryWithGlobals(
1745
+ this,
1746
+ tenantId2,
1747
+ "PullRequest.findWithGlobals"
1732
1748
  );
1733
1749
  }
1734
1750
  }
@@ -1920,6 +1936,7 @@ let Repository = class extends SmrtObject {
1920
1936
  commentsCount: created.commentsCount,
1921
1937
  lastSyncedAt: /* @__PURE__ */ new Date()
1922
1938
  });
1939
+ await issue.initialize();
1923
1940
  await issue.save();
1924
1941
  return issue;
1925
1942
  }
@@ -1955,6 +1972,7 @@ let Repository = class extends SmrtObject {
1955
1972
  draft: created.draft,
1956
1973
  lastSyncedAt: /* @__PURE__ */ new Date()
1957
1974
  });
1975
+ await pr.initialize();
1958
1976
  await pr.save();
1959
1977
  return pr;
1960
1978
  }
@@ -2120,23 +2138,31 @@ class RepositoryCollection extends SmrtCollection {
2120
2138
  return this.list({ where: { tenantId: tenantId2 } });
2121
2139
  }
2122
2140
  /**
2123
- * Find global repositories (no tenant)
2141
+ * Find all global repositories (no tenant association).
2142
+ *
2143
+ * Routes through the shared tenant-global helper so it does not throw under
2144
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
2145
+ * flagged as an isolation violation). (#1600)
2124
2146
  *
2125
2147
  * @returns Array of global repositories
2126
2148
  */
2127
2149
  async findGlobal() {
2128
- return this.list({ where: { tenantId: null } });
2150
+ return queryGlobal(this);
2129
2151
  }
2130
2152
  /**
2131
- * Find repositories for a tenant including global repositories
2153
+ * Find repositories for a tenant plus all global repositories.
2154
+ *
2155
+ * Fails closed if an active tenant context requests a different tenant's
2156
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
2132
2157
  *
2133
2158
  * @param tenantId - Tenant ID to filter by
2134
2159
  * @returns Array of tenant and global repositories
2135
2160
  */
2136
2161
  async findWithGlobals(tenantId2) {
2137
- return this.query(
2138
- `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,
2139
- [tenantId2]
2162
+ return queryWithGlobals(
2163
+ this,
2164
+ tenantId2,
2165
+ "Repository.findWithGlobals"
2140
2166
  );
2141
2167
  }
2142
2168
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/__smrt-register__.ts","../src/constants.ts","../src/prompts.ts","../src/models/Issue.ts","../src/collections/Issues.ts","../src/models/Project.ts","../src/collections/Projects.ts","../src/models/PullRequest.ts","../src/collections/PullRequests.ts","../src/models/Repository.ts","../src/collections/Repositories.ts","../src/models/Comment.ts","../src/models/Label.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * Constants for smrt-projects package\n */\n\n/**\n * Default sync throttle duration in milliseconds (5 minutes)\n * Prevents excessive API calls by skipping sync if synced recently\n */\nexport const SYNC_THROTTLE_MS = 5 * 60 * 1000;\n","import { definePrompt } from '@happyvertical/smrt-prompts';\n\nexport const issueIncorporateFeedbackPrompt = definePrompt({\n key: 'projects.issue.incorporateFeedback',\n template: `You are updating a specification document based on team feedback.\n\nCurrent specification:\n{body}\n\nTeam comments and feedback:\n{comments}\n\nInstructions:\n1. Analyze the comments for consensus, changes, and new requirements\n2. Update the specification to reflect the agreed-upon changes\n3. Maintain the original structure and formatting where possible\n4. Mark any conflicting feedback that needs resolution\n5. Return ONLY the updated specification text, no additional commentary`,\n ai: {\n temperature: 0.2,\n },\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n","/**\n * Issue model - SMRT wrapper for issue tracking\n *\n * Provides persistent issue tracking with AI-powered feedback incorporation.\n * Uses @happyvertical/repos SDK for actual API calls.\n */\n\nimport { getAI } from '@happyvertical/ai';\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n config as smrtConfig,\n} from '@happyvertical/smrt-core';\nimport { resolvePrompt } from '@happyvertical/smrt-prompts';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { loadEnvConfig } from '@happyvertical/utils';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport { issueIncorporateFeedbackPrompt } from '../prompts';\nimport type {\n IncorporateFeedbackOptions,\n IncorporateFeedbackResult,\n IRepository,\n SDKComment,\n SyncOptions,\n} from '../types';\nimport type { Comment } from './Comment';\nimport type { Repository } from './Repository';\n\nexport interface IssueOptions extends SmrtObjectOptions {\n repositoryId?: string;\n number?: number;\n nodeId?: string;\n title?: string;\n body?: string;\n state?: 'open' | 'closed';\n author?: string;\n labels?: string[];\n assignees?: string[];\n commentsCount?: number;\n lastSyncedAt?: Date | null;\n originalBody?: string;\n synthesisCount?: number;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync', 'incorporateFeedback'] },\n // sync/incorporateFeedback/rollback are operator commands invoked in-process\n // via the CLI; they intentionally aren't exposed over HTTP today.\n cli: {\n include: ['list', 'get', 'sync', 'incorporateFeedback', 'rollback'],\n skipApiCheck: true,\n },\n})\nexport class Issue extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Repository this issue belongs to\n */\n @foreignKey('Repository', { required: true })\n repositoryId?: string;\n\n /**\n * Issue number (provider-specific)\n */\n number: number = 0;\n\n /**\n * Node ID for GraphQL operations (GitHub Projects API)\n */\n nodeId: string = '';\n\n /**\n * Issue title\n */\n title: string = '';\n\n /**\n * Issue body/description\n */\n body: string = '';\n\n /**\n * Issue state\n */\n state: 'open' | 'closed' = 'open';\n\n /**\n * Author's login/username\n */\n author: string = '';\n\n /**\n * Labels attached to the issue\n */\n labels: string[] = [];\n\n /**\n * Assignee logins\n */\n assignees: string[] = [];\n\n /**\n * Number of comments on the issue\n */\n commentsCount: number = 0;\n\n /**\n * Last sync timestamp\n */\n lastSyncedAt: Date | null = null;\n\n /**\n * Original body before any AI synthesis (for rollback)\n */\n originalBody: string = '';\n\n /**\n * Number of times feedback has been incorporated\n */\n synthesisCount: number = 0;\n\n /**\n * Transient: Cached repository (not persisted)\n * Protected so PullRequest can access it\n */\n protected _repository?: Repository;\n\n /**\n * Transient: Cached client (not persisted)\n */\n protected _client?: IRepository;\n\n constructor(options: IssueOptions = {}) {\n super(options);\n if (options.repositoryId !== undefined)\n this.repositoryId = options.repositoryId;\n if (options.number !== undefined) this.number = options.number;\n if (options.nodeId !== undefined) this.nodeId = options.nodeId;\n if (options.title !== undefined) this.title = options.title;\n if (options.body !== undefined) this.body = options.body;\n if (options.state !== undefined) this.state = options.state;\n if (options.author !== undefined) this.author = options.author;\n if (options.labels !== undefined) this.labels = options.labels;\n if (options.assignees !== undefined) this.assignees = options.assignees;\n if (options.commentsCount !== undefined)\n this.commentsCount = options.commentsCount;\n if (options.lastSyncedAt !== undefined)\n this.lastSyncedAt = options.lastSyncedAt;\n if (options.originalBody !== undefined)\n this.originalBody = options.originalBody;\n if (options.synthesisCount !== undefined)\n this.synthesisCount = options.synthesisCount;\n if (options.tenantId !== undefined)\n (this as any).tenantId = options.tenantId;\n }\n\n /**\n * Get the repository this issue belongs to\n */\n async getRepository(): Promise<Repository> {\n if (this._repository) {\n return this._repository;\n }\n\n if (!this.repositoryId) {\n throw new Error('Issue has no repositoryId set');\n }\n\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await (RepositoryCollection as any).create(this.options);\n const repo = await collection.get({ id: this.repositoryId });\n\n if (!repo) {\n throw new Error(`Repository ${this.repositoryId} not found`);\n }\n\n this._repository = repo;\n return repo;\n }\n\n /**\n * Get the repository client for API operations\n */\n async getClient(): Promise<IRepository> {\n if (this._client) {\n return this._client;\n }\n\n const repo = await this.getRepository();\n this._client = await repo.getClient();\n return this._client;\n }\n\n /**\n * Clear cached repository and client\n */\n clearCache(): void {\n this._repository = undefined;\n this._client = undefined;\n }\n\n /**\n * Sync issue data from the provider\n *\n * @param options - Sync options\n * @returns This issue with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const issueData = await client.getIssue(this.number);\n\n // Update fields from remote\n this.nodeId = issueData.id;\n this.title = issueData.title;\n this.body = issueData.body;\n this.state = issueData.state;\n this.author = issueData.author.login;\n this.labels = issueData.labels.map((l) => l.name);\n this.assignees = issueData.assignees.map((a) => a.login);\n this.commentsCount = issueData.commentsCount;\n this.lastSyncedAt = new Date();\n\n await this.save();\n return this;\n }\n\n /**\n * Get comments on this issue\n *\n * @returns Array of Comment objects (SMRT models)\n */\n async getComments(): Promise<Comment[]> {\n const client = await this.getClient();\n const comments: SDKComment[] = await client.listComments(this.number);\n\n const { Comment: CommentClass } = await import('./Comment');\n return comments.map(\n (c) =>\n new CommentClass({\n ...this.options,\n issueId: this.id ?? undefined,\n commentId: c.id,\n body: c.body,\n author: c.author.login,\n createdAt: c.createdAt,\n updatedAt: c.updatedAt,\n url: c.url,\n }),\n );\n }\n\n /**\n * Add a comment to this issue\n *\n * @param body - Comment body text\n * @returns Created Comment (SMRT model)\n */\n async addComment(body: string): Promise<Comment> {\n const client = await this.getClient();\n const created = await client.addComment(this.number, body);\n\n const { Comment: CommentClass } = await import('./Comment');\n const comment = new CommentClass({\n ...this.options,\n issueId: this.id ?? undefined,\n commentId: created.id,\n body: created.body,\n author: created.author.login,\n createdAt: created.createdAt,\n updatedAt: created.updatedAt,\n url: created.url,\n });\n\n await comment.save();\n this.commentsCount++;\n await this.save();\n\n return comment;\n }\n\n /**\n * Incorporate feedback from comments into the issue body\n *\n * This is the core \"Living Spec\" functionality:\n * 1. Reads all comments on the issue\n * 2. Uses AI to synthesize comments with the current body\n * 3. Optionally updates the issue with the synthesized content\n *\n * @param options - Feedback incorporation options\n * @returns Result with synthesized content and status\n */\n async incorporateFeedback(\n options: IncorporateFeedbackOptions = {},\n ): Promise<IncorporateFeedbackResult> {\n const comments = await this.getComments();\n\n // Filter comments by date if specified\n let relevantComments = comments;\n if (options.since) {\n const sinceDate = options.since;\n relevantComments = comments.filter(\n (c) => c.createdAt && c.createdAt > sinceDate,\n );\n }\n\n if (relevantComments.length === 0) {\n return {\n synthesized: this.body,\n applied: false,\n commentsAnalyzed: 0,\n };\n }\n\n const resolvedPrompt = await resolvePrompt(\n issueIncorporateFeedbackPrompt.key,\n {\n db: this.options.db ?? this.options.persistence,\n tenantId: this.tenantId,\n variables: {\n body: this.body,\n comments: relevantComments\n .map((c) => `- ${c.author}: ${c.body}`)\n .join('\\n'),\n },\n override: options.prompt ? { template: options.prompt } : undefined,\n },\n );\n\n const aiOptions = {\n ...resolvedPrompt.ai.params,\n ...(resolvedPrompt.ai.model ? { model: resolvedPrompt.ai.model } : {}),\n };\n\n let synthesized: string;\n\n if (resolvedPrompt.ai.provider) {\n synthesized = await this.runPromptWithResolvedAI(\n resolvedPrompt.text,\n resolvedPrompt.ai.provider,\n aiOptions,\n );\n } else {\n // The resolved prompt template already curates the issue body + comments,\n // so opt out of do()'s object-data injection to avoid duplicating the body.\n synthesized = await this.do(resolvedPrompt.text, {\n ...aiOptions,\n includeData: false,\n });\n }\n\n const result: IncorporateFeedbackResult = {\n synthesized,\n applied: false,\n commentsAnalyzed: relevantComments.length,\n previousBody: this.body,\n };\n\n // Apply changes if requested\n if (options.apply) {\n // Store original for rollback (only if first synthesis)\n if (this.synthesisCount === 0) {\n this.originalBody = this.body;\n }\n\n // Update the issue body\n const client = await this.getClient();\n await client.updateIssue(this.number, { body: synthesized });\n\n // Update local state\n this.body = synthesized;\n this.synthesisCount++;\n this.lastSyncedAt = new Date();\n await this.save();\n\n result.applied = true;\n }\n\n return result;\n }\n\n private async runPromptWithResolvedAI(\n instructions: string,\n provider: string,\n options: Record<string, unknown>,\n ): Promise<string> {\n const aiOption = this.options.ai as Record<string, unknown> | undefined;\n if (this.isExplicitAiClientOption(aiOption)) {\n const ai = await this.getAiClient();\n return this.sendPromptMessage(ai, instructions, options);\n }\n\n const globalAiConfig = smrtConfig.toJSON().ai || {};\n const instanceAiConfig = aiOption ?? {};\n const aiConfig = loadEnvConfig<any>(\n {\n ...globalAiConfig,\n ...instanceAiConfig,\n },\n {\n packageName: 'ai',\n prefix: 'SMRT',\n schema: {\n provider: 'string',\n model: 'string',\n apiKey: 'string',\n timeout: 'number',\n maxRetries: 'number',\n temperature: 'number',\n maxTokens: 'number',\n },\n },\n );\n\n const env = process.env;\n const apiKey =\n aiConfig.apiKey ||\n (provider === 'anthropic'\n ? env.ANTHROPIC_API_KEY\n : provider === 'gemini'\n ? env.GEMINI_API_KEY\n : env.OPENAI_API_KEY);\n\n const ai = await getAI({\n ...aiConfig,\n provider,\n type: provider,\n model: options.model ?? aiConfig.model,\n defaultModel: options.model ?? aiConfig.model,\n apiKey,\n } as any);\n\n return this.sendPromptMessage(ai, instructions, options);\n }\n\n /**\n * Sends a fully-resolved instruction string to the given AI client.\n *\n * `incorporateFeedback()` curates the entire prompt (issue body + comments)\n * via the resolved prompt template, so this path deliberately does NOT inject\n * the object's own field data — that would duplicate the body. The `this.do()`\n * fallback path passes `includeData: false` for the same reason, keeping both\n * `incorporateFeedback()` paths consistent (#1567).\n */\n private async sendPromptMessage(\n ai: { message: (prompt: string, options?: any) => Promise<string> },\n instructions: string,\n options: Record<string, unknown>,\n ): Promise<string> {\n const prompt = `--- Beginning of instructions ---\\n${instructions}\\n--- End of instructions ---\\nBased on the content body, please follow the instructions and provide a response. Never make use of codeblocks.`;\n const tools = this.getAvailableTools();\n\n return (await ai.message(prompt, {\n ...options,\n tools: tools.length > 0 ? tools : undefined,\n } as any)) as string;\n }\n\n private isExplicitAiClientOption(\n aiOption: Record<string, unknown> | undefined,\n ): boolean {\n return !!(\n aiOption &&\n typeof aiOption === 'object' &&\n typeof aiOption.embed === 'function' &&\n !aiOption.provider &&\n !aiOption.type\n );\n }\n\n /**\n * Rollback to the original body before AI synthesis\n *\n * @returns Result with success status\n */\n async rollback(): Promise<{ success: boolean; message: string }> {\n if (!this.originalBody) {\n return {\n success: false,\n message: 'No original body to rollback to',\n };\n }\n\n if (this.synthesisCount === 0) {\n return {\n success: false,\n message: 'No synthesis has been applied',\n };\n }\n\n // Update the issue body on the provider\n const client = await this.getClient();\n await client.updateIssue(this.number, { body: this.originalBody });\n\n // Update local state\n this.body = this.originalBody;\n this.originalBody = '';\n this.synthesisCount = 0;\n this.lastSyncedAt = new Date();\n await this.save();\n\n return {\n success: true,\n message: 'Successfully rolled back to original body',\n };\n }\n\n /**\n * AI-powered: Check if this issue needs review\n *\n * @returns True if the issue likely needs attention\n */\n async needsReview(): Promise<boolean> {\n return await this.is(\n `This issue needs review because one or more of the following:\n - It has been open for a long time without updates\n - There are unresolved questions in the comments\n - The requirements are unclear or incomplete\n - There is conflicting feedback that needs resolution`,\n );\n }\n\n /**\n * AI-powered: Check if the issue is a bug report\n */\n async isBugReport(): Promise<boolean> {\n return await this.is(\n 'This issue describes a bug, defect, or unexpected behavior',\n );\n }\n\n /**\n * AI-powered: Check if the issue is a feature request\n */\n async isFeatureRequest(): Promise<boolean> {\n return await this.is(\n 'This issue is a feature request or enhancement proposal',\n );\n }\n\n /**\n * AI-powered: Generate suggested labels based on content\n *\n * @returns Array of suggested label names\n */\n async suggestLabels(): Promise<string[]> {\n const suggestion = await this.do(\n `Based on the issue title and body, suggest appropriate labels.\n Consider:\n - Type: bug, feature, docs, chore, test\n - Priority: P0 (critical), P1 (high), P2 (medium), P3 (low)\n - Area: specific code areas or components\n\n Return only a comma-separated list of labels, nothing else.`,\n );\n\n return suggestion\n .split(',')\n .map((l) => l.trim())\n .filter(Boolean);\n }\n\n /**\n * Close this issue\n */\n async close(): Promise<void> {\n const client = await this.getClient();\n await client.closeIssue(this.number);\n this.state = 'closed';\n this.lastSyncedAt = new Date();\n await this.save();\n }\n\n /**\n * Add labels to this issue\n *\n * @param labels - Label names to add\n */\n async addLabels(labels: string[]): Promise<void> {\n const client = await this.getClient();\n await client.addLabels(this.number, labels);\n this.labels = [...new Set([...this.labels, ...labels])];\n await this.save();\n }\n\n /**\n * Remove a label from this issue\n *\n * @param label - Label name to remove\n */\n async removeLabel(label: string): Promise<void> {\n const client = await this.getClient();\n await client.removeLabel(this.number, label);\n this.labels = this.labels.filter((l) => l !== label);\n await this.save();\n }\n\n /**\n * Assign users to this issue\n *\n * @param assignees - User logins to assign\n */\n async assign(assignees: string[]): Promise<void> {\n const client = await this.getClient();\n await client.assignIssue(this.number, assignees);\n this.assignees = [...new Set([...this.assignees, ...assignees])];\n await this.save();\n }\n\n /**\n * Get issue URL\n */\n getUrl(): string {\n const repo = this._repository;\n if (repo) {\n return `https://github.com/${repo.owner}/${repo.name}/issues/${this.number}`;\n }\n return '';\n }\n}\n","/**\n * IssueCollection - Collection manager for Issue objects\n *\n * Provides querying and discovery operations for Issue entities.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Issue } from '../models/Issue';\nimport type { Repository } from '../models/Repository';\nimport type { SearchFilters } from '../types';\n\nexport class IssueCollection extends SmrtCollection<Issue> {\n static readonly _itemClass = Issue;\n\n /**\n * Discover issues from a repository and sync to database\n *\n * This method:\n * 1. Fetches issues from the provider via SDK\n * 2. Creates/updates SMRT Issue records in the database\n * 3. Returns the synced Issue objects\n *\n * @param options - Discovery options\n * @returns Array of Issue objects\n */\n async discover(options: {\n repository: Repository;\n filters?: SearchFilters;\n }): Promise<Issue[]> {\n const { repository, filters } = options;\n const repositoryId = repository.id ?? undefined;\n\n if (!repositoryId) {\n throw new Error('Repository must be saved before discovering issues');\n }\n\n const repoClient = await repository.getClient();\n\n // Fetch issues from provider\n const remoteIssues = await repoClient.searchIssues('', filters);\n\n const issues: Issue[] = [];\n\n for (const remote of remoteIssues) {\n // Find existing issue by repository + number\n let issue = await this.findOne({\n where: {\n repositoryId,\n number: remote.number,\n },\n });\n\n if (!issue) {\n // Create new issue\n issue = await this.create({\n repositoryId,\n number: remote.number,\n nodeId: remote.id,\n title: remote.title,\n body: remote.body,\n state: remote.state,\n author: remote.author.login,\n labels: remote.labels.map((l) => l.name),\n assignees: remote.assignees.map((a) => a.login),\n commentsCount: remote.commentsCount,\n lastSyncedAt: new Date(),\n });\n } else {\n // Update existing issue\n issue.nodeId = remote.id;\n issue.title = remote.title;\n issue.body = remote.body;\n issue.state = remote.state;\n issue.author = remote.author.login;\n issue.labels = remote.labels.map((l) => l.name);\n issue.assignees = remote.assignees.map((a) => a.login);\n issue.commentsCount = remote.commentsCount;\n issue.lastSyncedAt = new Date();\n }\n\n await issue.save();\n issues.push(issue);\n }\n\n return issues;\n }\n\n /**\n * Find issues by repository\n *\n * @param repositoryId - Repository ID\n * @returns Array of issues\n */\n async findByRepository(repositoryId: string): Promise<Issue[]> {\n return await this.list({\n where: { repositoryId },\n });\n }\n\n /**\n * Find open issues\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of open issues\n */\n async findOpen(repositoryId?: string): Promise<Issue[]> {\n const where: Record<string, any> = { state: 'open' };\n if (repositoryId) {\n where.repositoryId = repositoryId;\n }\n return await this.list({ where });\n }\n\n /**\n * Find issues by label\n *\n * @param label - Label name\n * @param repositoryId - Optional repository filter\n * @returns Array of issues with the label\n */\n async findByLabel(label: string, repositoryId?: string): Promise<Issue[]> {\n const issues = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n // Filter by label (JSON array search)\n return issues.filter((issue) => issue.labels.includes(label));\n }\n\n /**\n * Find issues by assignee\n *\n * @param assignee - Assignee login\n * @param repositoryId - Optional repository filter\n * @returns Array of issues assigned to the user\n */\n async findByAssignee(\n assignee: string,\n repositoryId?: string,\n ): Promise<Issue[]> {\n const issues = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n // Filter by assignee (JSON array search)\n return issues.filter((issue) => issue.assignees.includes(assignee));\n }\n\n /**\n * Find issues needing review (AI-powered)\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of issues that need review\n */\n async findNeedingReview(repositoryId?: string): Promise<Issue[]> {\n const openIssues = await this.findOpen(repositoryId);\n const needingReview: Issue[] = [];\n\n for (const issue of openIssues) {\n if (await issue.needsReview()) {\n needingReview.push(issue);\n }\n }\n\n return needingReview;\n }\n\n /**\n * Find issue by number in a repository\n *\n * @param repositoryId - Repository ID\n * @param number - Issue number\n * @returns Issue or null\n */\n async findByNumber(\n repositoryId: string,\n number: number,\n ): Promise<Issue | null> {\n const results = await this.list({\n where: { repositoryId, number },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Get issues with unincorporated feedback\n *\n * Issues that have comments but haven't had feedback incorporated\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of issues\n */\n async findWithUnincorporatedFeedback(\n repositoryId?: string,\n ): Promise<Issue[]> {\n const issues = await this.findOpen(repositoryId);\n\n return issues.filter(\n (issue) => issue.commentsCount > 0 && issue.synthesisCount === 0,\n );\n }\n\n /**\n * Batch sync issues from repository\n *\n * @param repository - Repository to sync from\n * @param options - Sync options\n * @returns Array of synced issues\n */\n async batchSync(\n repository: Repository,\n options: { force?: boolean } = {},\n ): Promise<Issue[]> {\n const issues = await this.findByRepository(repository.id as string);\n const synced: Issue[] = [];\n\n for (const issue of issues) {\n await issue.sync(options);\n synced.push(issue);\n }\n\n return synced;\n }\n\n /**\n * Find issues by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of issues for the tenant\n */\n async findByTenant(tenantId: string): Promise<Issue[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find global issues (no tenant)\n *\n * @returns Array of global issues\n */\n async findGlobal(): Promise<Issue[]> {\n return this.list({ where: { tenantId: null } });\n }\n\n /**\n * Find issues for a tenant including global issues\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global issues\n */\n async findWithGlobals(tenantId: string): Promise<Issue[]> {\n return this.query(\n `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,\n [tenantId],\n );\n }\n}\n","/**\n * Project model - SMRT wrapper for project board operations\n *\n * Provides persistent project tracking with provider-agnostic operations.\n * Uses @happyvertical/projects SDK for actual API calls.\n */\n\nimport { getProject } from '@happyvertical/projects';\nimport { getModuleConfig } from '@happyvertical/smrt-config';\nimport {\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport type {\n IProject,\n ItemFilters,\n ProjectField,\n ProjectItem,\n ProjectProviderType,\n ProjectStatus,\n SDKProject,\n SyncOptions,\n} from '../types';\nimport type { Issue } from './Issue';\nimport type { PullRequest } from './PullRequest';\n\nexport interface ProjectOptions extends SmrtObjectOptions {\n projectId?: string;\n projectNumber?: number;\n title?: string;\n description?: string;\n owner?: string;\n url?: string;\n providerType?: ProjectProviderType;\n tokenConfigKey?: string;\n statuses?: ProjectStatus[];\n fields?: ProjectField[];\n statusFieldId?: string;\n statusOptions?: Record<string, string>;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync', 'addItem', 'updateItemStatus'] },\n // sync/addItem/updateItemStatus/listItems are operator commands invoked\n // in-process via the CLI; they intentionally aren't exposed over HTTP today.\n cli: {\n include: [\n 'list',\n 'get',\n 'sync',\n 'addItem',\n 'updateItemStatus',\n 'listItems',\n ],\n skipApiCheck: true,\n },\n})\nexport class Project extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Provider-specific project ID (e.g., GitHub GraphQL node ID)\n */\n projectId: string = '';\n\n /**\n * Human-readable project number\n */\n projectNumber: number = 0;\n\n /**\n * Project title\n */\n title: string = '';\n\n /**\n * Project description\n */\n description: string = '';\n\n /**\n * Project owner (organization or user)\n */\n owner: string = '';\n\n /**\n * Project URL\n */\n url: string = '';\n\n /**\n * Project provider type\n */\n providerType: ProjectProviderType = 'github';\n\n /**\n * Environment variable name or config key for token resolution\n */\n tokenConfigKey: string = 'GITHUB_TOKEN';\n\n /**\n * Available statuses (columns) in the project\n */\n statuses: ProjectStatus[] = [];\n\n /**\n * Custom fields defined in the project\n */\n fields: ProjectField[] = [];\n\n /**\n * Status field ID for GitHub Projects V2\n */\n statusFieldId: string = '';\n\n /**\n * Maps status name to option ID (for GitHub Projects V2)\n */\n statusOptions: Record<string, string> = {};\n\n /**\n * Last sync timestamp\n */\n lastSyncedAt: Date | null = null;\n\n /**\n * Transient: Cached project client (not persisted)\n */\n private _client?: IProject;\n\n constructor(options: ProjectOptions = {}) {\n super(options);\n if (options.projectId !== undefined) this.projectId = options.projectId;\n if (options.projectNumber !== undefined)\n this.projectNumber = options.projectNumber;\n if (options.title !== undefined) this.title = options.title;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.owner !== undefined) this.owner = options.owner;\n if (options.url !== undefined) this.url = options.url;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.tokenConfigKey !== undefined)\n this.tokenConfigKey = options.tokenConfigKey;\n if (options.statuses !== undefined) this.statuses = options.statuses;\n if (options.fields !== undefined) this.fields = options.fields;\n if (options.statusFieldId !== undefined)\n this.statusFieldId = options.statusFieldId;\n if (options.statusOptions !== undefined)\n this.statusOptions = options.statusOptions;\n if (options.tenantId !== undefined)\n (this as any).tenantId = options.tenantId;\n }\n\n /**\n * Get the project client, resolving token from config\n *\n * @returns Project client for API operations\n * @throws Error if token cannot be resolved\n */\n async getClient(): Promise<IProject> {\n if (this._client) {\n return this._client;\n }\n\n // Resolve token from environment or config\n const token =\n process.env[this.tokenConfigKey] ||\n (getModuleConfig<Record<string, string>>('smrt-projects', {})[\n this.tokenConfigKey\n ] as string);\n\n if (!token) {\n throw new Error(\n `Token not found for key '${this.tokenConfigKey}'. ` +\n `Set the ${this.tokenConfigKey} environment variable or configure it in smrt.config.`,\n );\n }\n\n this._client = await getProject({\n type: this.providerType,\n projectId: this.projectId,\n token,\n statusFieldId: this.statusFieldId || undefined,\n statusOptions:\n Object.keys(this.statusOptions).length > 0\n ? this.statusOptions\n : undefined,\n });\n\n return this._client;\n }\n\n /**\n * Clear the cached client\n */\n clearClient(): void {\n this._client = undefined;\n }\n\n /**\n * Sync project metadata from the provider\n *\n * @param options - Sync options\n * @returns This project with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const projectData: SDKProject = await client.getProject();\n\n // Update fields from remote\n this.title = projectData.title;\n this.description = projectData.description || '';\n this.owner = projectData.owner;\n this.url = projectData.url;\n this.statuses = projectData.statuses;\n this.fields = projectData.fields;\n this.lastSyncedAt = new Date();\n\n await this.save();\n return this;\n }\n\n /**\n * Add an issue or PR to this project\n *\n * @param item - Issue or PullRequest to add\n * @returns Created ProjectItem\n */\n async addItem(item: Issue | PullRequest): Promise<ProjectItem> {\n if (!item.nodeId) {\n throw new Error('Item must have a nodeId (sync the item first)');\n }\n\n const client = await this.getClient();\n return await client.addItem(item.nodeId);\n }\n\n /**\n * Remove an item from this project\n *\n * @param itemId - Project item ID to remove\n */\n async removeItem(itemId: string): Promise<void> {\n const client = await this.getClient();\n await client.removeItem(itemId);\n }\n\n /**\n * Get a specific item from the project\n *\n * @param itemId - Project item ID\n * @returns ProjectItem or null\n */\n async getItem(itemId: string): Promise<ProjectItem | null> {\n const client = await this.getClient();\n return await client.getItem(itemId);\n }\n\n /**\n * List items in this project\n *\n * @param filters - Optional filters\n * @returns Array of ProjectItems\n */\n async listItems(filters?: ItemFilters): Promise<ProjectItem[]> {\n const client = await this.getClient();\n return await client.listItems(filters);\n }\n\n /**\n * Update an item's status (column)\n *\n * @param itemId - Project item ID\n * @param status - New status name\n */\n async updateItemStatus(itemId: string, status: string): Promise<void> {\n const client = await this.getClient();\n await client.updateItemStatus(itemId, status);\n }\n\n /**\n * Update an item's custom field\n *\n * @param itemId - Project item ID\n * @param fieldId - Field ID\n * @param value - New value\n */\n async updateItemField(\n itemId: string,\n fieldId: string,\n value: unknown,\n ): Promise<void> {\n const client = await this.getClient();\n await client.updateItemField(itemId, fieldId, value);\n }\n\n /**\n * Get available statuses\n *\n * @returns Array of status definitions\n */\n async getStatuses(): Promise<ProjectStatus[]> {\n if (this.statuses.length > 0) {\n return this.statuses;\n }\n\n const client = await this.getClient();\n this.statuses = await client.listStatuses();\n await this.save();\n return this.statuses;\n }\n\n /**\n * Get available fields\n *\n * @returns Array of field definitions\n */\n async getFields(): Promise<ProjectField[]> {\n if (this.fields.length > 0) {\n return this.fields;\n }\n\n const client = await this.getClient();\n this.fields = await client.listFields();\n await this.save();\n return this.fields;\n }\n\n /**\n * Get items in a specific status/column\n *\n * @param status - Status name\n * @returns Array of ProjectItems in that status\n */\n async getItemsByStatus(status: string): Promise<ProjectItem[]> {\n return await this.listItems({ status });\n }\n\n /**\n * Move an item to a new status\n *\n * @param item - Issue or PullRequest\n * @param status - Target status name\n */\n async moveItem(item: Issue | PullRequest, status: string): Promise<void> {\n // First, find the item in the project\n const items = await this.listItems();\n const projectItem = items.find((i) => i.contentId === item.nodeId);\n\n if (!projectItem) {\n throw new Error('Item not found in project');\n }\n\n await this.updateItemStatus(projectItem.id, status);\n }\n\n /**\n * AI-powered: Analyze project health and suggest improvements\n *\n * @returns Analysis of project status\n */\n async analyzeHealth(): Promise<string> {\n const items = await this.listItems();\n const statuses = await this.getStatuses();\n\n // Count items by status\n const statusCounts: Record<string, number> = {};\n for (const status of statuses) {\n statusCounts[status.name] = items.filter(\n (i) => i.status === status.name,\n ).length;\n }\n\n return await this.do(\n `Analyze the health of this project board and suggest improvements.\n\n Project: ${this.title}\n Description: ${this.description}\n\n Item distribution by status:\n ${Object.entries(statusCounts)\n .map(([status, count]) => `- ${status}: ${count} items`)\n .join('\\n')}\n\n Total items: ${items.length}\n\n Provide:\n 1. Overall health assessment\n 2. Potential bottlenecks\n 3. Suggestions for improvement`,\n // Title/description/status counts hand-rolled above; skip do()'s\n // object-data injection so the board context is not duplicated.\n { includeData: false },\n );\n }\n\n /**\n * Get project by title\n *\n * @param title - Project title\n * @param options - Additional options\n * @returns Project or null\n */\n static async getByTitle(\n title: string,\n options: SmrtObjectOptions = {},\n ): Promise<Project | null> {\n const { ProjectCollection } = await import('../collections/Projects');\n const collection = await (ProjectCollection as any).create(options);\n return await collection.findByTitle(title);\n }\n}\n","/**\n * ProjectCollection - Collection manager for Project objects\n *\n * Provides querying and discovery operations for Project entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Project } from '../models/Project';\nimport type { ProjectProviderType } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class ProjectCollection extends SmrtCollection<Project> {\n static readonly _itemClass = Project;\n\n /**\n * Find project by title\n *\n * @param title - Project title\n * @returns Project or null\n */\n async findByTitle(title: string): Promise<Project | null> {\n const results = await this.list({\n where: { title },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find projects by owner\n *\n * @param owner - Project owner (organization or user)\n * @returns Array of projects\n */\n async findByOwner(owner: string): Promise<Project[]> {\n return await this.list({\n where: { owner },\n });\n }\n\n /**\n * Find projects by provider type\n *\n * @param providerType - Provider type\n * @returns Array of projects\n */\n async findByProvider(providerType: ProjectProviderType): Promise<Project[]> {\n return await this.list({\n where: { providerType },\n });\n }\n\n /**\n * Get or create a project by ID\n *\n * @param projectId - Provider-specific project ID\n * @param options - Additional options for creation\n * @returns Project (existing or newly created)\n */\n async getOrCreate(\n projectId: string,\n options: {\n title?: string;\n owner?: string;\n providerType?: ProjectProviderType;\n tokenConfigKey?: string;\n statusFieldId?: string;\n statusOptions?: Record<string, string>;\n } = {},\n ): Promise<Project> {\n let project = await this.findOne({\n where: { projectId },\n });\n\n if (!project) {\n project = await this.create({\n projectId,\n title: options.title || '',\n owner: options.owner || '',\n providerType: options.providerType || 'github',\n tokenConfigKey: options.tokenConfigKey || 'GITHUB_TOKEN',\n statusFieldId: options.statusFieldId || '',\n statusOptions: options.statusOptions || {},\n });\n await project.save();\n\n // Sync to get full project data\n await project.sync({ force: true });\n }\n\n return project;\n }\n\n /**\n * Sync all projects\n *\n * @param options - Sync options\n * @returns Array of synced projects\n */\n async syncAll(options: { force?: boolean } = {}): Promise<Project[]> {\n const projects = await this.list({});\n const synced: Project[] = [];\n\n for (const project of projects) {\n await project.sync(options);\n synced.push(project);\n }\n\n return synced;\n }\n\n /**\n * Find projects with items in a specific status\n *\n * @param status - Status name\n * @returns Array of projects\n */\n async findWithItemsInStatus(status: string): Promise<Project[]> {\n const projects = await this.list({});\n const matching: Project[] = [];\n\n for (const project of projects) {\n try {\n const items = await project.getItemsByStatus(status);\n if (items.length > 0) {\n matching.push(project);\n }\n } catch (error) {\n // Log error and skip projects we can't access\n logger.warn(`Error accessing items for project ${project.projectId}`, {\n error: error instanceof Error ? error.message : error,\n });\n }\n }\n\n return matching;\n }\n\n /**\n * Get project statistics\n *\n * @param projectId - Project ID\n * @returns Statistics object\n */\n async getStatistics(projectId: string): Promise<{\n totalItems: number;\n itemsByStatus: Record<string, number>;\n itemsByType: Record<string, number>;\n }> {\n const project = await this.findOne({ where: { projectId } });\n if (!project) {\n throw new Error(`Project ${projectId} not found`);\n }\n\n const items = await project.listItems();\n const statuses = await project.getStatuses();\n\n const itemsByStatus: Record<string, number> = {};\n for (const status of statuses) {\n itemsByStatus[status.name] = 0;\n }\n\n const itemsByType: Record<string, number> = {\n Issue: 0,\n PullRequest: 0,\n DraftIssue: 0,\n };\n\n for (const item of items) {\n if (item.status && itemsByStatus[item.status] !== undefined) {\n itemsByStatus[item.status]++;\n }\n if (itemsByType[item.type] !== undefined) {\n itemsByType[item.type]++;\n }\n }\n\n return {\n totalItems: items.length,\n itemsByStatus,\n itemsByType,\n };\n }\n\n /**\n * Find projects by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of projects for the tenant\n */\n async findByTenant(tenantId: string): Promise<Project[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find global projects (no tenant)\n *\n * @returns Array of global projects\n */\n async findGlobal(): Promise<Project[]> {\n return this.list({ where: { tenantId: null } });\n }\n\n /**\n * Find projects for a tenant including global projects\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global projects\n */\n async findWithGlobals(tenantId: string): Promise<Project[]> {\n return this.query(\n `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,\n [tenantId],\n );\n }\n}\n","/**\n * PullRequest model - SMRT wrapper for pull request operations\n *\n * Extends Issue with PR-specific fields and methods.\n * Uses @happyvertical/repos SDK for actual API calls.\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped } from '@happyvertical/smrt-tenancy';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport type { MergeMethod, SyncOptions } from '../types';\nimport { Issue, type IssueOptions } from './Issue';\n\nexport interface PullRequestOptions extends IssueOptions {\n headRef?: string;\n baseRef?: string;\n merged?: boolean;\n mergedAt?: Date | null;\n mergeable?: boolean;\n draft?: boolean;\n additions?: number;\n deletions?: number;\n changedFiles?: number;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync', 'summarize', 'merge'] },\n // sync/summarize/merge/markReady are operator commands invoked in-process\n // via the CLI; they intentionally aren't exposed over HTTP today.\n cli: {\n include: ['list', 'get', 'sync', 'summarize', 'merge', 'markReady'],\n skipApiCheck: true,\n },\n})\nexport class PullRequest extends Issue {\n /**\n * Source branch ref\n */\n headRef: string = '';\n\n /**\n * Target branch ref\n */\n baseRef: string = '';\n\n /**\n * Whether the PR has been merged\n */\n merged: boolean = false;\n\n /**\n * When the PR was merged\n */\n mergedAt: Date | null = null;\n\n /**\n * Whether the PR can be merged\n */\n mergeable: boolean = true;\n\n /**\n * Whether this is a draft PR\n */\n draft: boolean = false;\n\n /**\n * Lines added\n */\n additions: number = 0;\n\n /**\n * Lines deleted\n */\n deletions: number = 0;\n\n /**\n * Number of files changed\n */\n changedFiles: number = 0;\n\n constructor(options: PullRequestOptions = {}) {\n super(options);\n if (options.headRef !== undefined) this.headRef = options.headRef;\n if (options.baseRef !== undefined) this.baseRef = options.baseRef;\n if (options.merged !== undefined) this.merged = options.merged;\n if (options.mergedAt !== undefined) this.mergedAt = options.mergedAt;\n if (options.mergeable !== undefined) this.mergeable = options.mergeable;\n if (options.draft !== undefined) this.draft = options.draft;\n if (options.additions !== undefined) this.additions = options.additions;\n if (options.deletions !== undefined) this.deletions = options.deletions;\n if (options.changedFiles !== undefined)\n this.changedFiles = options.changedFiles;\n }\n\n /**\n * Sync PR data from the provider\n *\n * @param options - Sync options\n * @returns This PR with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const prData = await client.getPullRequest(this.number);\n\n // Update base issue fields\n this.nodeId = prData.id;\n this.title = prData.title;\n this.body = prData.body;\n this.state = prData.state;\n this.author = prData.author.login;\n this.labels = prData.labels.map((l) => l.name);\n this.assignees = prData.assignees.map((a) => a.login);\n this.commentsCount = prData.commentsCount;\n\n // Update PR-specific fields\n this.headRef = prData.headRef;\n this.baseRef = prData.baseRef;\n this.merged = prData.merged;\n this.mergedAt = prData.mergedAt || null;\n this.mergeable = prData.mergeable;\n this.draft = prData.draft;\n\n this.lastSyncedAt = new Date();\n await this.save();\n return this;\n }\n\n /**\n * AI-powered: Generate a summary of PR changes\n *\n * @returns Summary of what this PR does\n */\n async summarize(): Promise<string> {\n return await this.do(\n `Summarize this pull request concisely.\n\n Title: ${this.title}\n Description: ${this.body}\n\n Changes: ${this.additions} additions, ${this.deletions} deletions across ${this.changedFiles} files\n Source: ${this.headRef} → ${this.baseRef}\n\n Provide a 2-3 sentence summary focusing on:\n 1. What the PR does\n 2. Why it matters\n 3. Any notable implementation details`,\n // Title/body/stats hand-rolled above; skip do()'s object-data injection.\n { includeData: false },\n );\n }\n\n /**\n * Merge this pull request\n *\n * @param method - Merge method (merge, squash, rebase)\n */\n async merge(method: MergeMethod = 'squash'): Promise<void> {\n if (this.merged) {\n throw new Error('Pull request is already merged');\n }\n\n if (this.draft) {\n throw new Error('Cannot merge a draft pull request');\n }\n\n if (!this.mergeable) {\n throw new Error('Pull request is not mergeable');\n }\n\n const client = await this.getClient();\n await client.mergePullRequest(this.number, method);\n\n this.merged = true;\n this.mergedAt = new Date();\n this.state = 'closed';\n this.lastSyncedAt = new Date();\n await this.save();\n }\n\n /**\n * Mark this draft PR as ready for review\n */\n async markReady(): Promise<void> {\n if (!this.draft) {\n throw new Error('Pull request is not a draft');\n }\n\n const client = await this.getClient();\n await client.markPRReady(this.number);\n\n this.draft = false;\n this.lastSyncedAt = new Date();\n await this.save();\n }\n\n /**\n * Convert this PR back to draft\n */\n async convertToDraft(): Promise<void> {\n if (this.draft) {\n throw new Error('Pull request is already a draft');\n }\n\n const client = await this.getClient();\n await client.convertPRToDraft(this.number);\n\n this.draft = true;\n this.lastSyncedAt = new Date();\n await this.save();\n }\n\n /**\n * Request review from specified users\n *\n * @param reviewers - User logins to request review from\n */\n async requestReviewers(reviewers: string[]): Promise<void> {\n const client = await this.getClient();\n await client.requestReview(this.number, reviewers);\n }\n\n /**\n * Find related issue for this PR\n *\n * @returns Related Issue or null\n */\n async findLinkedIssue(): Promise<Issue | null> {\n const client = await this.getClient();\n const issue = await client.findIssueForPR(this.number);\n\n if (!issue) {\n return null;\n }\n\n // Return as SMRT Issue\n const { IssueCollection } = await import('../collections/Issues');\n const collection = await (IssueCollection as any).create(this.options);\n return await collection.findOne({\n where: { repositoryId: this.repositoryId, number: issue.number },\n });\n }\n\n /**\n * AI-powered: Check if this PR is ready to merge\n *\n * @returns True if the PR appears ready\n */\n async isReadyToMerge(): Promise<boolean> {\n if (this.draft) return false;\n if (!this.mergeable) return false;\n if (this.state === 'closed') return false;\n\n return await this.is(\n `This pull request is ready to merge because:\n - It has a clear description of what it does\n - It addresses a specific issue or feature\n - The scope is appropriate (not too large)\n - There are no unresolved review comments`,\n );\n }\n\n /**\n * AI-powered: Suggest reviewers based on changed files\n *\n * @returns Array of suggested reviewer logins\n */\n async suggestReviewers(): Promise<string[]> {\n const suggestion = await this.do(\n `Based on this pull request's title, description, and scope,\n suggest who should review it.\n\n Title: ${this.title}\n Description: ${this.body}\n Changes: ${this.changedFiles} files changed\n\n Consider:\n - Code owners for the affected areas\n - Team members with relevant expertise\n - People who have previously worked on related code\n\n Return only a comma-separated list of GitHub usernames, nothing else.\n If you cannot determine reviewers, return an empty string.`,\n // Title/description hand-rolled above; skip do()'s object-data injection.\n { includeData: false },\n );\n\n return suggestion\n .split(',')\n .map((r) => r.trim())\n .filter(Boolean);\n }\n\n /**\n * Get PR URL\n */\n override getUrl(): string {\n const repo = this._repository;\n if (repo) {\n return `https://github.com/${repo.owner}/${repo.name}/pull/${this.number}`;\n }\n return '';\n }\n\n /**\n * Get the change size classification\n *\n * @returns Size classification (xs, s, m, l, xl)\n */\n getChangeSize(): 'xs' | 's' | 'm' | 'l' | 'xl' {\n const total = this.additions + this.deletions;\n\n if (total < 10) return 'xs';\n if (total < 50) return 's';\n if (total < 200) return 'm';\n if (total < 500) return 'l';\n return 'xl';\n }\n}\n","/**\n * PullRequestCollection - Collection manager for PullRequest objects\n *\n * Provides querying and discovery operations for PullRequest entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { PullRequest } from '../models/PullRequest';\nimport type { Repository } from '../models/Repository';\nimport type { SDKPullRequest, SearchFilters } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class PullRequestCollection extends SmrtCollection<PullRequest> {\n static readonly _itemClass = PullRequest;\n\n /**\n * Discover pull requests from a repository and sync to database\n *\n * @param options - Discovery options\n * @returns Array of PullRequest objects\n */\n async discover(options: {\n repository: Repository;\n filters?: SearchFilters;\n }): Promise<PullRequest[]> {\n const { repository, filters } = options;\n const repositoryId = repository.id ?? undefined;\n\n if (!repositoryId) {\n throw new Error(\n 'Repository must be saved before discovering pull requests',\n );\n }\n\n const repoClient = await repository.getClient();\n\n // Note: searchIssues with type filter would get PRs in GitHub\n // For now, we'll search for all and filter\n const remoteItems = await repoClient.searchIssues('is:pr', filters);\n\n const pullRequests: PullRequest[] = [];\n\n for (const remote of remoteItems) {\n // Get full PR data\n let prData: SDKPullRequest;\n try {\n prData = await repoClient.getPullRequest(remote.number);\n } catch (error) {\n // Log error and skip PR - could be rate limiting, auth, or access issues\n logger.warn(\n `Failed to fetch PR #${remote.number} from ${repository.owner}/${repository.name}`,\n { error: error instanceof Error ? error.message : error },\n );\n continue;\n }\n\n // Find existing PR by repository + number\n let pr = await this.findOne({\n where: {\n repositoryId,\n number: remote.number,\n },\n });\n\n if (!pr) {\n // Create new PR\n pr = await this.create({\n repositoryId,\n number: prData.number,\n nodeId: prData.id,\n title: prData.title,\n body: prData.body,\n state: prData.state,\n author: prData.author.login,\n labels: prData.labels.map((l) => l.name),\n assignees: prData.assignees.map((a) => a.login),\n commentsCount: prData.commentsCount,\n headRef: prData.headRef,\n baseRef: prData.baseRef,\n merged: prData.merged,\n mergedAt: prData.mergedAt || null,\n mergeable: prData.mergeable,\n draft: prData.draft,\n lastSyncedAt: new Date(),\n });\n } else {\n // Update existing PR\n pr.nodeId = prData.id;\n pr.title = prData.title;\n pr.body = prData.body;\n pr.state = prData.state;\n pr.author = prData.author.login;\n pr.labels = prData.labels.map((l) => l.name);\n pr.assignees = prData.assignees.map((a) => a.login);\n pr.commentsCount = prData.commentsCount;\n pr.headRef = prData.headRef;\n pr.baseRef = prData.baseRef;\n pr.merged = prData.merged;\n pr.mergedAt = prData.mergedAt || null;\n pr.mergeable = prData.mergeable;\n pr.draft = prData.draft;\n pr.lastSyncedAt = new Date();\n }\n\n await pr.save();\n pullRequests.push(pr);\n }\n\n return pullRequests;\n }\n\n /**\n * Find PRs by repository\n *\n * @param repositoryId - Repository ID\n * @returns Array of PRs\n */\n async findByRepository(repositoryId: string): Promise<PullRequest[]> {\n return await this.list({\n where: { repositoryId },\n });\n }\n\n /**\n * Find open PRs\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of open PRs\n */\n async findOpen(repositoryId?: string): Promise<PullRequest[]> {\n const where: Record<string, any> = { state: 'open' };\n if (repositoryId) {\n where.repositoryId = repositoryId;\n }\n return await this.list({ where });\n }\n\n /**\n * Find draft PRs\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of draft PRs\n */\n async findDrafts(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n return openPRs.filter((pr) => pr.draft);\n }\n\n /**\n * Find PRs ready to merge\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of mergeable PRs\n */\n async findReadyToMerge(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n return openPRs.filter((pr) => !pr.draft && pr.mergeable);\n }\n\n /**\n * Find PRs by branch\n *\n * @param branch - Branch name (head or base)\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs\n */\n async findByBranch(\n branch: string,\n repositoryId?: string,\n ): Promise<PullRequest[]> {\n const prs = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n return prs.filter((pr) => pr.headRef === branch || pr.baseRef === branch);\n }\n\n /**\n * Find PR by number in a repository\n *\n * @param repositoryId - Repository ID\n * @param number - PR number\n * @returns PullRequest or null\n */\n async findByNumber(\n repositoryId: string,\n number: number,\n ): Promise<PullRequest | null> {\n const results = await this.list({\n where: { repositoryId, number },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find PRs ready to merge (AI-powered)\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs that are ready\n */\n async findAIReadyToMerge(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n const ready: PullRequest[] = [];\n\n for (const pr of openPRs) {\n if (await pr.isReadyToMerge()) {\n ready.push(pr);\n }\n }\n\n return ready;\n }\n\n /**\n * Get PRs by change size\n *\n * @param size - Size classification\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs\n */\n async findBySize(\n size: 'xs' | 's' | 'm' | 'l' | 'xl',\n repositoryId?: string,\n ): Promise<PullRequest[]> {\n const prs = await this.findOpen(repositoryId);\n return prs.filter((pr) => pr.getChangeSize() === size);\n }\n\n /**\n * Batch sync PRs from repository\n *\n * @param repository - Repository to sync from\n * @param options - Sync options\n * @returns Array of synced PRs\n */\n async batchSync(\n repository: Repository,\n options: { force?: boolean } = {},\n ): Promise<PullRequest[]> {\n const prs = await this.findByRepository(repository.id as string);\n const synced: PullRequest[] = [];\n\n for (const pr of prs) {\n await pr.sync(options);\n synced.push(pr);\n }\n\n return synced;\n }\n\n /**\n * Find pull requests by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of pull requests for the tenant\n */\n async findByTenant(tenantId: string): Promise<PullRequest[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find global pull requests (no tenant)\n *\n * @returns Array of global pull requests\n */\n async findGlobal(): Promise<PullRequest[]> {\n return this.list({ where: { tenantId: null } });\n }\n\n /**\n * Find pull requests for a tenant including global pull requests\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global pull requests\n */\n async findWithGlobals(tenantId: string): Promise<PullRequest[]> {\n return this.query(\n `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,\n [tenantId],\n );\n }\n}\n","/**\n * Repository model - SMRT wrapper for repository operations\n *\n * Provides persistent repository tracking with provider-agnostic operations.\n * Uses @happyvertical/repos SDK for actual API calls.\n */\n\nimport { getRepository } from '@happyvertical/repos';\nimport { getModuleConfig } from '@happyvertical/smrt-config';\nimport {\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport type {\n CreateIssueInput,\n CreatePRInput,\n IRepository,\n RepositoryProviderType,\n SDKRepository,\n SearchFilters,\n SyncOptions,\n} from '../types';\nimport type { Issue } from './Issue';\nimport type { PullRequest } from './PullRequest';\n\nexport interface RepositoryOptions extends SmrtObjectOptions {\n owner?: string;\n name?: string;\n fullName?: string;\n description?: string;\n defaultBranch?: string;\n isPrivate?: boolean;\n providerType?: RepositoryProviderType;\n baseUrl?: string;\n tokenConfigKey?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync'] },\n // sync is an operator command invoked in-process via the CLI;\n // it intentionally isn't exposed over HTTP today.\n cli: { include: ['list', 'get', 'sync', 'create'], skipApiCheck: true },\n})\nexport class Repository extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Repository owner (organization or user)\n */\n owner: string = '';\n\n /**\n * Repository name\n */\n name: string = '';\n\n /**\n * Full name in owner/repo format\n */\n fullName: string = '';\n\n /**\n * Repository description\n */\n description: string = '';\n\n /**\n * Default branch name\n */\n defaultBranch: string = 'main';\n\n /**\n * Whether repository is private\n */\n isPrivate: boolean = false;\n\n /**\n * Repository provider type\n */\n providerType: RepositoryProviderType = 'github';\n\n /**\n * Base URL for self-hosted instances (GitHub Enterprise, GitLab self-hosted, etc.)\n */\n baseUrl: string = '';\n\n /**\n * Environment variable name or config key for token resolution\n * The token is NOT stored - only the key name is persisted\n */\n tokenConfigKey: string = 'GITHUB_TOKEN';\n\n /**\n * Last sync timestamp\n */\n lastSyncedAt: Date | null = null;\n\n /**\n * Transient: Cached repository client (not persisted)\n */\n private _client?: IRepository;\n\n constructor(options: RepositoryOptions = {}) {\n super(options);\n if (options.owner !== undefined) this.owner = options.owner;\n if (options.name !== undefined) this.name = options.name;\n if (options.fullName !== undefined) this.fullName = options.fullName;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.defaultBranch !== undefined)\n this.defaultBranch = options.defaultBranch;\n if (options.isPrivate !== undefined) this.isPrivate = options.isPrivate;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.baseUrl !== undefined) this.baseUrl = options.baseUrl;\n if (options.tokenConfigKey !== undefined)\n this.tokenConfigKey = options.tokenConfigKey;\n if (options.tenantId !== undefined)\n (this as any).tenantId = options.tenantId;\n }\n\n /**\n * Get the repository client, resolving token from config\n *\n * Token resolution order:\n * 1. Environment variable matching tokenConfigKey\n * 2. Module config value matching tokenConfigKey\n *\n * @returns Repository client for API operations\n * @throws Error if token cannot be resolved\n */\n async getClient(): Promise<IRepository> {\n if (this._client) {\n return this._client;\n }\n\n // Resolve token from environment or config\n const token =\n process.env[this.tokenConfigKey] ||\n (getModuleConfig<Record<string, string>>('smrt-projects', {})[\n this.tokenConfigKey\n ] as string);\n\n if (!token) {\n throw new Error(\n `Token not found for key '${this.tokenConfigKey}'. ` +\n `Set the ${this.tokenConfigKey} environment variable or configure it in smrt.config.`,\n );\n }\n\n this._client = await getRepository({\n type: this.providerType,\n owner: this.owner,\n repo: this.name,\n token,\n baseUrl: this.baseUrl || undefined,\n });\n\n return this._client;\n }\n\n /**\n * Clear the cached client (useful after token refresh)\n */\n clearClient(): void {\n this._client = undefined;\n }\n\n /**\n * Sync repository metadata from the provider\n *\n * @param options - Sync options\n * @returns This repository with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const repoData: SDKRepository = await client.getRepository();\n\n // Update fields from remote\n this.owner = repoData.owner;\n this.name = repoData.name;\n this.fullName = `${repoData.owner}/${repoData.name}`;\n this.description = repoData.description;\n this.defaultBranch = repoData.defaultBranch;\n this.isPrivate = repoData.isPrivate;\n this.lastSyncedAt = new Date();\n\n await this.save();\n return this;\n }\n\n /**\n * Get issues from this repository\n *\n * @param filters - Optional search filters\n * @returns Array of Issue objects (SMRT models)\n */\n async getIssues(filters?: SearchFilters): Promise<Issue[]> {\n const { IssueCollection } = await import('../collections/Issues');\n const collection = await (IssueCollection as any).create(this.options);\n return await collection.discover({ repository: this, filters });\n }\n\n /**\n * Get pull requests from this repository\n *\n * @param filters - Optional search filters\n * @returns Array of PullRequest objects (SMRT models)\n */\n async getPullRequests(filters?: SearchFilters): Promise<PullRequest[]> {\n const { PullRequestCollection } = await import(\n '../collections/PullRequests'\n );\n const collection = await (PullRequestCollection as any).create(\n this.options,\n );\n return await collection.discover({ repository: this, filters });\n }\n\n /**\n * Create a new issue in this repository\n *\n * @param data - Issue creation data\n * @returns Created Issue (SMRT model)\n */\n async createIssue(data: CreateIssueInput): Promise<Issue> {\n const repositoryId = this.id ?? undefined;\n if (!repositoryId) {\n throw new Error('Repository must be saved before creating issues');\n }\n\n const client = await this.getClient();\n const created = await client.createIssue(data);\n\n // Create SMRT Issue from remote data\n const { Issue } = await import('./Issue');\n const issue = new Issue({\n ...this.options,\n repositoryId,\n number: created.number,\n nodeId: created.id,\n title: created.title,\n body: created.body,\n state: created.state,\n author: created.author.login,\n labels: created.labels.map((l) => l.name),\n assignees: created.assignees.map((a) => a.login),\n commentsCount: created.commentsCount,\n lastSyncedAt: new Date(),\n });\n\n await issue.save();\n return issue;\n }\n\n /**\n * Create a new pull request in this repository\n *\n * @param data - PR creation data\n * @returns Created PullRequest (SMRT model)\n */\n async createPullRequest(data: CreatePRInput): Promise<PullRequest> {\n const repositoryId = this.id ?? undefined;\n if (!repositoryId) {\n throw new Error('Repository must be saved before creating pull requests');\n }\n\n const client = await this.getClient();\n const created = await client.createPullRequest(data);\n\n // Create SMRT PullRequest from remote data\n const { PullRequest } = await import('./PullRequest');\n const pr = new PullRequest({\n ...this.options,\n repositoryId,\n number: created.number,\n nodeId: created.id,\n title: created.title,\n body: created.body,\n state: created.state,\n author: created.author.login,\n labels: created.labels.map((l) => l.name),\n assignees: created.assignees.map((a) => a.login),\n commentsCount: created.commentsCount,\n headRef: created.headRef,\n baseRef: created.baseRef,\n merged: created.merged,\n draft: created.draft,\n lastSyncedAt: new Date(),\n });\n\n await pr.save();\n return pr;\n }\n\n /**\n * Check if this repository has any open issues matching criteria\n *\n * @param criteria - Natural language description of what to check\n * @returns True if matching issues exist\n */\n async hasOpenIssuesMatching(criteria: string): Promise<boolean> {\n const issues = await this.getIssues({ state: 'open' });\n if (issues.length === 0) return false;\n\n return await this.is(\n `This repository has open issues matching: ${criteria}. ` +\n `Current open issues: ${issues.map((i) => `#${i.number}: ${i.title}`).join(', ')}`,\n );\n }\n\n /**\n * Generate a summary of repository activity\n *\n * @returns AI-generated summary\n */\n async summarizeActivity(): Promise<string> {\n const issues = await this.getIssues({ state: 'open', limit: 10 });\n const prs = await this.getPullRequests({ state: 'open', limit: 10 });\n\n return await this.do(\n `Summarize the current activity in this repository. ` +\n `Open issues: ${issues.map((i) => `#${i.number}: ${i.title}`).join(', ')}. ` +\n `Open PRs: ${prs.map((p) => `#${p.number}: ${p.title}`).join(', ')}.`,\n );\n }\n\n /**\n * Get repository by owner and name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @param options - Additional options\n * @returns Repository or null if not found\n */\n static async getByFullName(\n owner: string,\n name: string,\n options: SmrtObjectOptions = {},\n ): Promise<Repository | null> {\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await (RepositoryCollection as any).create(options);\n return await collection.findByFullName(owner, name);\n }\n}\n","/**\n * RepositoryCollection - Collection manager for Repository objects\n *\n * Provides querying and discovery operations for Repository entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Repository } from '../models/Repository';\nimport type { RepositoryProviderType } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class RepositoryCollection extends SmrtCollection<Repository> {\n static readonly _itemClass = Repository;\n\n /**\n * Find a repository by owner and name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @returns Repository or null\n */\n async findByFullName(\n owner: string,\n name: string,\n ): Promise<Repository | null> {\n const results = await this.list({\n where: { owner, name },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find repositories by owner\n *\n * @param owner - Repository owner\n * @returns Array of repositories\n */\n async findByOwner(owner: string): Promise<Repository[]> {\n return await this.list({\n where: { owner },\n });\n }\n\n /**\n * Find repositories by provider type\n *\n * @param providerType - Provider type\n * @returns Array of repositories\n */\n async findByProvider(\n providerType: RepositoryProviderType,\n ): Promise<Repository[]> {\n return await this.list({\n where: { providerType },\n });\n }\n\n /**\n * Get or create a repository by owner/name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @param options - Additional options for creation\n * @returns Repository (existing or newly created)\n */\n async getOrCreate(\n owner: string,\n name: string,\n options: {\n providerType?: RepositoryProviderType;\n tokenConfigKey?: string;\n baseUrl?: string;\n } = {},\n ): Promise<Repository> {\n let repo = await this.findByFullName(owner, name);\n\n if (!repo) {\n repo = await this.create({\n owner,\n name,\n fullName: `${owner}/${name}`,\n providerType: options.providerType || 'github',\n tokenConfigKey: options.tokenConfigKey || 'GITHUB_TOKEN',\n baseUrl: options.baseUrl || '',\n });\n await repo.save();\n }\n\n return repo;\n }\n\n /**\n * Sync all repositories\n *\n * @param options - Sync options\n * @returns Array of synced repositories\n */\n async syncAll(options: { force?: boolean } = {}): Promise<Repository[]> {\n const repos = await this.list({});\n const synced: Repository[] = [];\n\n for (const repo of repos) {\n await repo.sync(options);\n synced.push(repo);\n }\n\n return synced;\n }\n\n /**\n * Find repositories with open issues\n *\n * @returns Array of repositories with at least one open issue\n */\n async findWithOpenIssues(): Promise<Repository[]> {\n const repos = await this.list({});\n const withIssues: Repository[] = [];\n\n for (const repo of repos) {\n try {\n const issues = await repo.getIssues({ state: 'open', limit: 1 });\n if (issues.length > 0) {\n withIssues.push(repo);\n }\n } catch (error) {\n // Log error and skip repos we can't access\n logger.warn(\n `Error accessing issues for repository ${repo.owner}/${repo.name}`,\n { error: error instanceof Error ? error.message : error },\n );\n }\n }\n\n return withIssues;\n }\n\n /**\n * Find repositories by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of repositories for the tenant\n */\n async findByTenant(tenantId: string): Promise<Repository[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find global repositories (no tenant)\n *\n * @returns Array of global repositories\n */\n async findGlobal(): Promise<Repository[]> {\n return this.list({ where: { tenantId: null } });\n }\n\n /**\n * Find repositories for a tenant including global repositories\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global repositories\n */\n async findWithGlobals(tenantId: string): Promise<Repository[]> {\n return this.query(\n `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,\n [tenantId],\n );\n }\n}\n","/**\n * Comment model - SMRT wrapper for issue/PR comments\n *\n * Represents a comment on an issue or pull request.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nconst logger = createLogger({ level: 'info' });\n\nexport interface CommentOptions extends SmrtObjectOptions {\n issueId?: string;\n commentId?: string;\n body?: string;\n author?: string;\n createdAt?: Date;\n updatedAt?: Date;\n url?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n})\nexport class Comment extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Issue this comment belongs to\n */\n @foreignKey('Issue')\n issueId?: string;\n\n /**\n * Provider-specific comment ID\n */\n commentId: string = '';\n\n /**\n * Comment body text\n */\n body: string = '';\n\n /**\n * Comment author's login\n */\n author: string = '';\n\n /**\n * When the comment was created\n */\n createdAt: Date | null = null;\n\n /**\n * When the comment was last updated\n */\n updatedAt: Date | null = null;\n\n /**\n * Comment URL\n */\n url: string = '';\n\n constructor(options: CommentOptions = {}) {\n super(options);\n if (options.issueId !== undefined) this.issueId = options.issueId;\n if (options.commentId !== undefined) this.commentId = options.commentId;\n if (options.body !== undefined) this.body = options.body;\n if (options.author !== undefined) this.author = options.author;\n if (options.createdAt !== undefined) this.createdAt = options.createdAt;\n if (options.updatedAt !== undefined) this.updatedAt = options.updatedAt;\n if (options.url !== undefined) this.url = options.url;\n if (options.tenantId !== undefined)\n (this as any).tenantId = options.tenantId;\n }\n\n /**\n * AI-powered: Check if this comment contains a question\n */\n async isQuestion(): Promise<boolean> {\n return await this.is(\n 'This comment contains a question or request for clarification',\n );\n }\n\n /**\n * AI-powered: Check if this comment contains approval\n */\n async isApproval(): Promise<boolean> {\n return await this.is(\n 'This comment expresses approval, agreement, or a positive response (LGTM, +1, approved, etc.)',\n );\n }\n\n /**\n * AI-powered: Check if this comment requests changes\n */\n async requestsChanges(): Promise<boolean> {\n return await this.is(\n 'This comment requests changes, modifications, or improvements to the issue/PR',\n );\n }\n\n /**\n * AI-powered: Extract action items from this comment\n *\n * @returns Array of action items\n */\n async extractActionItems(): Promise<string[]> {\n const result = await this.do(\n `Extract any action items, tasks, or requests from this comment.\n Return a JSON array of strings, each representing one action item.\n If no action items, return an empty array [].\n Only return the JSON array, nothing else.\n\n Comment: ${this.body}`,\n // Body is hand-rolled above; skip do()'s object-data injection (no dup).\n { includeData: false },\n );\n\n try {\n return JSON.parse(result);\n } catch (error) {\n logger.warn('Failed to parse action items JSON', {\n error: error instanceof Error ? error.message : error,\n response: result,\n });\n return [];\n }\n }\n\n /**\n * AI-powered: Summarize this comment\n *\n * @returns Brief summary\n */\n async summarize(): Promise<string> {\n return await this.do(\n `Summarize this comment in one sentence.\n Comment by ${this.author}: ${this.body}`,\n // Author + body hand-rolled above; skip do()'s object-data injection.\n { includeData: false },\n );\n }\n\n /**\n * Get the sentiment of this comment\n *\n * @returns Sentiment classification\n */\n async getSentiment(): Promise<'positive' | 'negative' | 'neutral'> {\n const result = await this.do(\n `Classify the sentiment of this comment as exactly one of: positive, negative, neutral\n Only return one word.\n Comment: ${this.body}`,\n // Body is hand-rolled above; skip do()'s object-data injection (no dup).\n { includeData: false },\n );\n\n const normalized = result.toLowerCase().trim();\n if (normalized.includes('positive')) return 'positive';\n if (normalized.includes('negative')) return 'negative';\n return 'neutral';\n }\n}\n","/**\n * Label model - SMRT wrapper for repository labels\n *\n * Represents a label that can be applied to issues and PRs.\n */\n\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\n\nexport interface LabelOptions extends SmrtObjectOptions {\n repositoryId?: string;\n name?: string;\n color?: string;\n description?: string;\n}\n\n@smrt({\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create'] },\n cli: { include: ['list', 'get', 'create', 'update', 'delete'] },\n})\nexport class Label extends SmrtObject {\n /**\n * Repository this label belongs to\n */\n @foreignKey('Repository')\n repositoryId?: string;\n\n /**\n * Label name\n */\n name: string = '';\n\n /**\n * Label color (hex without #)\n */\n color: string = '';\n\n /**\n * Label description\n */\n description: string = '';\n\n constructor(options: LabelOptions = {}) {\n super(options);\n if (options.repositoryId !== undefined)\n this.repositoryId = options.repositoryId;\n if (options.name !== undefined) this.name = options.name;\n if (options.color !== undefined) this.color = options.color;\n if (options.description !== undefined)\n this.description = options.description;\n }\n\n /**\n * Check if this is a type label (bug, feature, etc.)\n */\n isTypeLabel(): boolean {\n const typePatterns = [\n /^type:/i,\n /^kind:/i,\n /^bug$/i,\n /^feature$/i,\n /^enhancement$/i,\n /^docs$/i,\n /^chore$/i,\n ];\n return typePatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Check if this is a priority label\n */\n isPriorityLabel(): boolean {\n const priorityPatterns = [\n /^p[0-4]$/i,\n /^priority:/i,\n /^critical$/i,\n /^high$/i,\n /^medium$/i,\n /^low$/i,\n ];\n return priorityPatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Check if this is a status label\n */\n isStatusLabel(): boolean {\n const statusPatterns = [\n /^status:/i,\n /^wip$/i,\n /^in.?progress$/i,\n /^blocked$/i,\n /^needs.?review$/i,\n /^ready$/i,\n ];\n return statusPatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Get the label category\n *\n * @returns Category name\n */\n getCategory(): 'type' | 'priority' | 'status' | 'area' | 'other' {\n if (this.isTypeLabel()) return 'type';\n if (this.isPriorityLabel()) return 'priority';\n if (this.isStatusLabel()) return 'status';\n if (this.name.includes(':')) return 'area';\n return 'other';\n }\n\n /**\n * Parse priority level from label name\n *\n * @returns Priority level 0-4 or null\n */\n getPriorityLevel(): number | null {\n const match = this.name.match(/p([0-4])/i);\n if (match) {\n return parseInt(match[1], 10);\n }\n if (/critical/i.test(this.name)) return 0;\n if (/high/i.test(this.name)) return 1;\n if (/medium/i.test(this.name)) return 2;\n if (/low/i.test(this.name)) return 3;\n return null;\n }\n\n /**\n * Get label with # prefix for hex color\n */\n getHexColor(): string {\n return this.color.startsWith('#') ? this.color : `#${this.color}`;\n }\n\n /**\n * Create a label in the repository\n */\n async createInRepository(): Promise<void> {\n if (!this.repositoryId) {\n throw new Error('Label must have a repositoryId');\n }\n\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await (RepositoryCollection as any).create(this.options);\n const repo = await collection.get({ id: this.repositoryId });\n\n if (!repo) {\n throw new Error(`Repository ${this.repositoryId} not found`);\n }\n\n const client = await repo.getClient();\n await client.createLabel({\n name: this.name,\n color: this.color,\n description: this.description,\n });\n\n await this.save();\n }\n\n /**\n * Update this label in the repository\n */\n async updateInRepository(): Promise<void> {\n if (!this.repositoryId) {\n throw new Error('Label must have a repositoryId');\n }\n\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await (RepositoryCollection as any).create(this.options);\n const repo = await collection.get({ id: this.repositoryId });\n\n if (!repo) {\n throw new Error(`Repository ${this.repositoryId} not found`);\n }\n\n const client = await repo.getClient();\n await client.updateLabel(this.name, {\n name: this.name,\n color: this.color,\n description: this.description,\n });\n\n await this.save();\n }\n}\n"],"names":["RepositoryCollection","ai","smrtConfig","__decorateClass","tenantId","ProjectCollection","logger","IssueCollection","PullRequestCollection","Issue","PullRequest"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/__smrt-register__.ts","../src/constants.ts","../src/prompts.ts","../src/models/Issue.ts","../src/collections/Issues.ts","../src/models/Project.ts","../src/collections/Projects.ts","../src/models/PullRequest.ts","../src/collections/PullRequests.ts","../src/models/Repository.ts","../src/collections/Repositories.ts","../src/models/Comment.ts","../src/models/Label.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * Constants for smrt-projects package\n */\n\n/**\n * Default sync throttle duration in milliseconds (5 minutes)\n * Prevents excessive API calls by skipping sync if synced recently\n */\nexport const SYNC_THROTTLE_MS = 5 * 60 * 1000;\n","import { definePrompt } from '@happyvertical/smrt-prompts';\n\nexport const issueIncorporateFeedbackPrompt = definePrompt({\n key: 'projects.issue.incorporateFeedback',\n template: `You are updating a specification document based on team feedback.\n\nCurrent specification:\n{body}\n\nTeam comments and feedback:\n{comments}\n\nInstructions:\n1. Analyze the comments for consensus, changes, and new requirements\n2. Update the specification to reflect the agreed-upon changes\n3. Maintain the original structure and formatting where possible\n4. Mark any conflicting feedback that needs resolution\n5. Return ONLY the updated specification text, no additional commentary`,\n ai: {\n temperature: 0.2,\n },\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n","/**\n * Issue model - SMRT wrapper for issue tracking\n *\n * Provides persistent issue tracking with AI-powered feedback incorporation.\n * Uses @happyvertical/repos SDK for actual API calls.\n */\n\nimport { getAI } from '@happyvertical/ai';\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n config as smrtConfig,\n} from '@happyvertical/smrt-core';\nimport { resolvePrompt } from '@happyvertical/smrt-prompts';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { loadEnvConfig } from '@happyvertical/utils';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport { issueIncorporateFeedbackPrompt } from '../prompts';\nimport type {\n IncorporateFeedbackOptions,\n IncorporateFeedbackResult,\n IRepository,\n SDKComment,\n SyncOptions,\n} from '../types';\nimport type { Comment } from './Comment';\nimport type { Repository } from './Repository';\n\nexport interface IssueOptions extends SmrtObjectOptions {\n repositoryId?: string;\n number?: number;\n nodeId?: string;\n title?: string;\n body?: string;\n state?: 'open' | 'closed';\n author?: string;\n labels?: string[];\n assignees?: string[];\n commentsCount?: number;\n lastSyncedAt?: Date | null;\n originalBody?: string;\n synthesisCount?: number;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync', 'incorporateFeedback'] },\n // sync/incorporateFeedback/rollback are operator commands invoked in-process\n // via the CLI; they intentionally aren't exposed over HTTP today.\n cli: {\n include: ['list', 'get', 'sync', 'incorporateFeedback', 'rollback'],\n skipApiCheck: true,\n },\n})\nexport class Issue extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Repository this issue belongs to\n */\n @foreignKey('Repository', { required: true })\n repositoryId?: string;\n\n /**\n * Issue number (provider-specific)\n */\n number: number = 0;\n\n /**\n * Node ID for GraphQL operations (GitHub Projects API)\n */\n nodeId: string = '';\n\n /**\n * Issue title\n */\n title: string = '';\n\n /**\n * Issue body/description\n */\n body: string = '';\n\n /**\n * Issue state\n */\n state: 'open' | 'closed' = 'open';\n\n /**\n * Author's login/username\n */\n author: string = '';\n\n /**\n * Labels attached to the issue\n */\n labels: string[] = [];\n\n /**\n * Assignee logins\n */\n assignees: string[] = [];\n\n /**\n * Number of comments on the issue\n */\n commentsCount: number = 0;\n\n /**\n * Last sync timestamp\n */\n lastSyncedAt: Date | null = null;\n\n /**\n * Original body before any AI synthesis (for rollback)\n */\n originalBody: string = '';\n\n /**\n * Number of times feedback has been incorporated\n */\n synthesisCount: number = 0;\n\n /**\n * Transient: Cached repository (not persisted)\n * Protected so PullRequest can access it\n */\n protected _repository?: Repository;\n\n /**\n * Transient: Cached client (not persisted)\n */\n protected _client?: IRepository;\n\n constructor(options: IssueOptions = {}) {\n super(options);\n if (options.repositoryId !== undefined)\n this.repositoryId = options.repositoryId;\n if (options.number !== undefined) this.number = options.number;\n if (options.nodeId !== undefined) this.nodeId = options.nodeId;\n if (options.title !== undefined) this.title = options.title;\n if (options.body !== undefined) this.body = options.body;\n if (options.state !== undefined) this.state = options.state;\n if (options.author !== undefined) this.author = options.author;\n if (options.labels !== undefined) this.labels = options.labels;\n if (options.assignees !== undefined) this.assignees = options.assignees;\n if (options.commentsCount !== undefined)\n this.commentsCount = options.commentsCount;\n if (options.lastSyncedAt !== undefined)\n this.lastSyncedAt = options.lastSyncedAt;\n if (options.originalBody !== undefined)\n this.originalBody = options.originalBody;\n if (options.synthesisCount !== undefined)\n this.synthesisCount = options.synthesisCount;\n if (options.tenantId !== undefined)\n (this as any).tenantId = options.tenantId;\n }\n\n /**\n * Get the repository this issue belongs to\n */\n async getRepository(): Promise<Repository> {\n if (this._repository) {\n return this._repository;\n }\n\n if (!this.repositoryId) {\n throw new Error('Issue has no repositoryId set');\n }\n\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await (RepositoryCollection as any).create(this.options);\n const repo = await collection.get({ id: this.repositoryId });\n\n if (!repo) {\n throw new Error(`Repository ${this.repositoryId} not found`);\n }\n\n this._repository = repo;\n return repo;\n }\n\n /**\n * Get the repository client for API operations\n */\n async getClient(): Promise<IRepository> {\n if (this._client) {\n return this._client;\n }\n\n const repo = await this.getRepository();\n this._client = await repo.getClient();\n return this._client;\n }\n\n /**\n * Clear cached repository and client\n */\n clearCache(): void {\n this._repository = undefined;\n this._client = undefined;\n }\n\n /**\n * Sync issue data from the provider\n *\n * @param options - Sync options\n * @returns This issue with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const issueData = await client.getIssue(this.number);\n\n // Update fields from remote\n this.nodeId = issueData.id;\n this.title = issueData.title;\n this.body = issueData.body;\n this.state = issueData.state;\n this.author = issueData.author.login;\n this.labels = issueData.labels.map((l) => l.name);\n this.assignees = issueData.assignees.map((a) => a.login);\n this.commentsCount = issueData.commentsCount;\n this.lastSyncedAt = new Date();\n\n await this.save();\n return this;\n }\n\n /**\n * Get comments on this issue\n *\n * @returns Array of Comment objects (SMRT models)\n */\n async getComments(): Promise<Comment[]> {\n const client = await this.getClient();\n const comments: SDKComment[] = await client.listComments(this.number);\n\n const { Comment: CommentClass } = await import('./Comment');\n return comments.map(\n (c) =>\n new CommentClass({\n ...this.options,\n issueId: this.id ?? undefined,\n commentId: c.id,\n body: c.body,\n author: c.author.login,\n createdAt: c.createdAt,\n updatedAt: c.updatedAt,\n url: c.url,\n }),\n );\n }\n\n /**\n * Add a comment to this issue\n *\n * @param body - Comment body text\n * @returns Created Comment (SMRT model)\n */\n async addComment(body: string): Promise<Comment> {\n const client = await this.getClient();\n const created = await client.addComment(this.number, body);\n\n const { Comment: CommentClass } = await import('./Comment');\n const comment = new CommentClass({\n ...this.options,\n issueId: this.id ?? undefined,\n commentId: created.id,\n body: created.body,\n author: created.author.login,\n createdAt: created.createdAt,\n updatedAt: created.updatedAt,\n url: created.url,\n });\n\n await comment.save();\n this.commentsCount++;\n await this.save();\n\n return comment;\n }\n\n /**\n * Incorporate feedback from comments into the issue body\n *\n * This is the core \"Living Spec\" functionality:\n * 1. Reads all comments on the issue\n * 2. Uses AI to synthesize comments with the current body\n * 3. Optionally updates the issue with the synthesized content\n *\n * @param options - Feedback incorporation options\n * @returns Result with synthesized content and status\n */\n async incorporateFeedback(\n options: IncorporateFeedbackOptions = {},\n ): Promise<IncorporateFeedbackResult> {\n const comments = await this.getComments();\n\n // Filter comments by date if specified\n let relevantComments = comments;\n if (options.since) {\n const sinceDate = options.since;\n relevantComments = comments.filter(\n (c) => c.createdAt && c.createdAt > sinceDate,\n );\n }\n\n if (relevantComments.length === 0) {\n return {\n synthesized: this.body,\n applied: false,\n commentsAnalyzed: 0,\n };\n }\n\n const resolvedPrompt = await resolvePrompt(\n issueIncorporateFeedbackPrompt.key,\n {\n db: this.options.db ?? this.options.persistence,\n tenantId: this.tenantId,\n variables: {\n body: this.body,\n comments: relevantComments\n .map((c) => `- ${c.author}: ${c.body}`)\n .join('\\n'),\n },\n override: options.prompt ? { template: options.prompt } : undefined,\n },\n );\n\n const aiOptions = {\n ...resolvedPrompt.ai.params,\n ...(resolvedPrompt.ai.model ? { model: resolvedPrompt.ai.model } : {}),\n };\n\n let synthesized: string;\n\n if (resolvedPrompt.ai.provider) {\n synthesized = await this.runPromptWithResolvedAI(\n resolvedPrompt.text,\n resolvedPrompt.ai.provider,\n aiOptions,\n );\n } else {\n // The resolved prompt template already curates the issue body + comments,\n // so opt out of do()'s object-data injection to avoid duplicating the body.\n synthesized = await this.do(resolvedPrompt.text, {\n ...aiOptions,\n includeData: false,\n });\n }\n\n const result: IncorporateFeedbackResult = {\n synthesized,\n applied: false,\n commentsAnalyzed: relevantComments.length,\n previousBody: this.body,\n };\n\n // Apply changes if requested\n if (options.apply) {\n // Store original for rollback (only if first synthesis)\n if (this.synthesisCount === 0) {\n this.originalBody = this.body;\n }\n\n // Update the issue body\n const client = await this.getClient();\n await client.updateIssue(this.number, { body: synthesized });\n\n // Update local state\n this.body = synthesized;\n this.synthesisCount++;\n this.lastSyncedAt = new Date();\n await this.save();\n\n result.applied = true;\n }\n\n return result;\n }\n\n private async runPromptWithResolvedAI(\n instructions: string,\n provider: string,\n options: Record<string, unknown>,\n ): Promise<string> {\n const aiOption = this.options.ai as Record<string, unknown> | undefined;\n if (this.isExplicitAiClientOption(aiOption)) {\n const ai = await this.getAiClient();\n return this.sendPromptMessage(ai, instructions, options);\n }\n\n const globalAiConfig = smrtConfig.toJSON().ai || {};\n const instanceAiConfig = aiOption ?? {};\n const aiConfig = loadEnvConfig<any>(\n {\n ...globalAiConfig,\n ...instanceAiConfig,\n },\n {\n packageName: 'ai',\n prefix: 'SMRT',\n schema: {\n provider: 'string',\n model: 'string',\n apiKey: 'string',\n timeout: 'number',\n maxRetries: 'number',\n temperature: 'number',\n maxTokens: 'number',\n },\n },\n );\n\n const env = process.env;\n const apiKey =\n aiConfig.apiKey ||\n (provider === 'anthropic'\n ? env.ANTHROPIC_API_KEY\n : provider === 'gemini'\n ? env.GEMINI_API_KEY\n : env.OPENAI_API_KEY);\n\n const ai = await getAI({\n ...aiConfig,\n provider,\n type: provider,\n model: options.model ?? aiConfig.model,\n defaultModel: options.model ?? aiConfig.model,\n apiKey,\n } as any);\n\n return this.sendPromptMessage(ai, instructions, options);\n }\n\n /**\n * Sends a fully-resolved instruction string to the given AI client.\n *\n * `incorporateFeedback()` curates the entire prompt (issue body + comments)\n * via the resolved prompt template, so this path deliberately does NOT inject\n * the object's own field data — that would duplicate the body. The `this.do()`\n * fallback path passes `includeData: false` for the same reason, keeping both\n * `incorporateFeedback()` paths consistent (#1567).\n */\n private async sendPromptMessage(\n ai: { message: (prompt: string, options?: any) => Promise<string> },\n instructions: string,\n options: Record<string, unknown>,\n ): Promise<string> {\n const prompt = `--- Beginning of instructions ---\\n${instructions}\\n--- End of instructions ---\\nBased on the content body, please follow the instructions and provide a response. Never make use of codeblocks.`;\n const tools = this.getAvailableTools();\n\n return (await ai.message(prompt, {\n ...options,\n tools: tools.length > 0 ? tools : undefined,\n } as any)) as string;\n }\n\n private isExplicitAiClientOption(\n aiOption: Record<string, unknown> | undefined,\n ): boolean {\n return !!(\n aiOption &&\n typeof aiOption === 'object' &&\n typeof aiOption.embed === 'function' &&\n !aiOption.provider &&\n !aiOption.type\n );\n }\n\n /**\n * Rollback to the original body before AI synthesis\n *\n * @returns Result with success status\n */\n async rollback(): Promise<{ success: boolean; message: string }> {\n if (!this.originalBody) {\n return {\n success: false,\n message: 'No original body to rollback to',\n };\n }\n\n if (this.synthesisCount === 0) {\n return {\n success: false,\n message: 'No synthesis has been applied',\n };\n }\n\n // Update the issue body on the provider\n const client = await this.getClient();\n await client.updateIssue(this.number, { body: this.originalBody });\n\n // Update local state\n this.body = this.originalBody;\n this.originalBody = '';\n this.synthesisCount = 0;\n this.lastSyncedAt = new Date();\n await this.save();\n\n return {\n success: true,\n message: 'Successfully rolled back to original body',\n };\n }\n\n /**\n * AI-powered: Check if this issue needs review\n *\n * @returns True if the issue likely needs attention\n */\n async needsReview(): Promise<boolean> {\n return await this.is(\n `This issue needs review because one or more of the following:\n - It has been open for a long time without updates\n - There are unresolved questions in the comments\n - The requirements are unclear or incomplete\n - There is conflicting feedback that needs resolution`,\n );\n }\n\n /**\n * AI-powered: Check if the issue is a bug report\n */\n async isBugReport(): Promise<boolean> {\n return await this.is(\n 'This issue describes a bug, defect, or unexpected behavior',\n );\n }\n\n /**\n * AI-powered: Check if the issue is a feature request\n */\n async isFeatureRequest(): Promise<boolean> {\n return await this.is(\n 'This issue is a feature request or enhancement proposal',\n );\n }\n\n /**\n * AI-powered: Generate suggested labels based on content\n *\n * @returns Array of suggested label names\n */\n async suggestLabels(): Promise<string[]> {\n const suggestion = await this.do(\n `Based on the issue title and body, suggest appropriate labels.\n Consider:\n - Type: bug, feature, docs, chore, test\n - Priority: P0 (critical), P1 (high), P2 (medium), P3 (low)\n - Area: specific code areas or components\n\n Return only a comma-separated list of labels, nothing else.`,\n );\n\n return suggestion\n .split(',')\n .map((l) => l.trim())\n .filter(Boolean);\n }\n\n /**\n * Close this issue\n */\n async close(): Promise<void> {\n const client = await this.getClient();\n await client.closeIssue(this.number);\n this.state = 'closed';\n this.lastSyncedAt = new Date();\n await this.save();\n }\n\n /**\n * Add labels to this issue\n *\n * @param labels - Label names to add\n */\n async addLabels(labels: string[]): Promise<void> {\n const client = await this.getClient();\n await client.addLabels(this.number, labels);\n this.labels = [...new Set([...this.labels, ...labels])];\n await this.save();\n }\n\n /**\n * Remove a label from this issue\n *\n * @param label - Label name to remove\n */\n async removeLabel(label: string): Promise<void> {\n const client = await this.getClient();\n await client.removeLabel(this.number, label);\n this.labels = this.labels.filter((l) => l !== label);\n await this.save();\n }\n\n /**\n * Assign users to this issue\n *\n * @param assignees - User logins to assign\n */\n async assign(assignees: string[]): Promise<void> {\n const client = await this.getClient();\n await client.assignIssue(this.number, assignees);\n this.assignees = [...new Set([...this.assignees, ...assignees])];\n await this.save();\n }\n\n /**\n * Get issue URL\n */\n getUrl(): string {\n const repo = this._repository;\n if (repo) {\n return `https://github.com/${repo.owner}/${repo.name}/issues/${this.number}`;\n }\n return '';\n }\n}\n","/**\n * IssueCollection - Collection manager for Issue objects\n *\n * Provides querying and discovery operations for Issue entities.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Issue } from '../models/Issue';\nimport type { Repository } from '../models/Repository';\nimport type { SearchFilters } from '../types';\n\nexport class IssueCollection extends SmrtCollection<Issue> {\n static readonly _itemClass = Issue;\n\n /**\n * Discover issues from a repository and sync to database\n *\n * This method:\n * 1. Fetches issues from the provider via SDK\n * 2. Creates/updates SMRT Issue records in the database\n * 3. Returns the synced Issue objects\n *\n * @param options - Discovery options\n * @returns Array of Issue objects\n */\n async discover(options: {\n repository: Repository;\n filters?: SearchFilters;\n }): Promise<Issue[]> {\n const { repository, filters } = options;\n const repositoryId = repository.id ?? undefined;\n\n if (!repositoryId) {\n throw new Error('Repository must be saved before discovering issues');\n }\n\n const repoClient = await repository.getClient();\n\n // Fetch issues from provider\n const remoteIssues = await repoClient.searchIssues('', filters);\n\n const issues: Issue[] = [];\n\n for (const remote of remoteIssues) {\n // Find existing issue by repository + number\n let issue = await this.findOne({\n where: {\n repositoryId,\n number: remote.number,\n },\n });\n\n if (!issue) {\n // Create new issue\n issue = await this.create({\n repositoryId,\n number: remote.number,\n nodeId: remote.id,\n title: remote.title,\n body: remote.body,\n state: remote.state,\n author: remote.author.login,\n labels: remote.labels.map((l) => l.name),\n assignees: remote.assignees.map((a) => a.login),\n commentsCount: remote.commentsCount,\n lastSyncedAt: new Date(),\n });\n } else {\n // Update existing issue\n issue.nodeId = remote.id;\n issue.title = remote.title;\n issue.body = remote.body;\n issue.state = remote.state;\n issue.author = remote.author.login;\n issue.labels = remote.labels.map((l) => l.name);\n issue.assignees = remote.assignees.map((a) => a.login);\n issue.commentsCount = remote.commentsCount;\n issue.lastSyncedAt = new Date();\n }\n\n await issue.save();\n issues.push(issue);\n }\n\n return issues;\n }\n\n /**\n * Find issues by repository\n *\n * @param repositoryId - Repository ID\n * @returns Array of issues\n */\n async findByRepository(repositoryId: string): Promise<Issue[]> {\n return await this.list({\n where: { repositoryId },\n });\n }\n\n /**\n * Find open issues\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of open issues\n */\n async findOpen(repositoryId?: string): Promise<Issue[]> {\n const where: Record<string, any> = { state: 'open' };\n if (repositoryId) {\n where.repositoryId = repositoryId;\n }\n return await this.list({ where });\n }\n\n /**\n * Find issues by label\n *\n * @param label - Label name\n * @param repositoryId - Optional repository filter\n * @returns Array of issues with the label\n */\n async findByLabel(label: string, repositoryId?: string): Promise<Issue[]> {\n const issues = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n // Filter by label (JSON array search)\n return issues.filter((issue) => issue.labels.includes(label));\n }\n\n /**\n * Find issues by assignee\n *\n * @param assignee - Assignee login\n * @param repositoryId - Optional repository filter\n * @returns Array of issues assigned to the user\n */\n async findByAssignee(\n assignee: string,\n repositoryId?: string,\n ): Promise<Issue[]> {\n const issues = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n // Filter by assignee (JSON array search)\n return issues.filter((issue) => issue.assignees.includes(assignee));\n }\n\n /**\n * Find issues needing review (AI-powered)\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of issues that need review\n */\n async findNeedingReview(repositoryId?: string): Promise<Issue[]> {\n const openIssues = await this.findOpen(repositoryId);\n const needingReview: Issue[] = [];\n\n for (const issue of openIssues) {\n if (await issue.needsReview()) {\n needingReview.push(issue);\n }\n }\n\n return needingReview;\n }\n\n /**\n * Find issue by number in a repository\n *\n * @param repositoryId - Repository ID\n * @param number - Issue number\n * @returns Issue or null\n */\n async findByNumber(\n repositoryId: string,\n number: number,\n ): Promise<Issue | null> {\n const results = await this.list({\n where: { repositoryId, number },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Get issues with unincorporated feedback\n *\n * Issues that have comments but haven't had feedback incorporated\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of issues\n */\n async findWithUnincorporatedFeedback(\n repositoryId?: string,\n ): Promise<Issue[]> {\n const issues = await this.findOpen(repositoryId);\n\n return issues.filter(\n (issue) => issue.commentsCount > 0 && issue.synthesisCount === 0,\n );\n }\n\n /**\n * Batch sync issues from repository\n *\n * @param repository - Repository to sync from\n * @param options - Sync options\n * @returns Array of synced issues\n */\n async batchSync(\n repository: Repository,\n options: { force?: boolean } = {},\n ): Promise<Issue[]> {\n const issues = await this.findByRepository(repository.id as string);\n const synced: Issue[] = [];\n\n for (const issue of issues) {\n await issue.sync(options);\n synced.push(issue);\n }\n\n return synced;\n }\n\n /**\n * Find issues by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of issues for the tenant\n */\n async findByTenant(tenantId: string): Promise<Issue[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global issues (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global issues\n */\n async findGlobal(): Promise<Issue[]> {\n return queryGlobal<Issue>(this);\n }\n\n /**\n * Find issues for a tenant plus all global issues.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global issues\n */\n async findWithGlobals(tenantId: string): Promise<Issue[]> {\n return queryWithGlobals<Issue>(this, tenantId, 'Issue.findWithGlobals');\n }\n}\n","/**\n * Project model - SMRT wrapper for project board operations\n *\n * Provides persistent project tracking with provider-agnostic operations.\n * Uses @happyvertical/projects SDK for actual API calls.\n */\n\nimport { getProject } from '@happyvertical/projects';\nimport { getModuleConfig } from '@happyvertical/smrt-config';\nimport {\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport type {\n IProject,\n ItemFilters,\n ProjectField,\n ProjectItem,\n ProjectProviderType,\n ProjectStatus,\n SDKProject,\n SyncOptions,\n} from '../types';\nimport type { Issue } from './Issue';\nimport type { PullRequest } from './PullRequest';\n\nexport interface ProjectOptions extends SmrtObjectOptions {\n projectId?: string;\n projectNumber?: number;\n title?: string;\n description?: string;\n owner?: string;\n url?: string;\n providerType?: ProjectProviderType;\n tokenConfigKey?: string;\n statuses?: ProjectStatus[];\n fields?: ProjectField[];\n statusFieldId?: string;\n statusOptions?: Record<string, string>;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync', 'addItem', 'updateItemStatus'] },\n // sync/addItem/updateItemStatus/listItems are operator commands invoked\n // in-process via the CLI; they intentionally aren't exposed over HTTP today.\n cli: {\n include: [\n 'list',\n 'get',\n 'sync',\n 'addItem',\n 'updateItemStatus',\n 'listItems',\n ],\n skipApiCheck: true,\n },\n})\nexport class Project extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Provider-specific project ID (e.g., GitHub GraphQL node ID)\n */\n projectId: string = '';\n\n /**\n * Human-readable project number\n */\n projectNumber: number = 0;\n\n /**\n * Project title\n */\n title: string = '';\n\n /**\n * Project description\n */\n description: string = '';\n\n /**\n * Project owner (organization or user)\n */\n owner: string = '';\n\n /**\n * Project URL\n */\n url: string = '';\n\n /**\n * Project provider type\n */\n providerType: ProjectProviderType = 'github';\n\n /**\n * Environment variable name or config key for token resolution\n */\n tokenConfigKey: string = 'GITHUB_TOKEN';\n\n /**\n * Available statuses (columns) in the project\n */\n statuses: ProjectStatus[] = [];\n\n /**\n * Custom fields defined in the project\n */\n fields: ProjectField[] = [];\n\n /**\n * Status field ID for GitHub Projects V2\n */\n statusFieldId: string = '';\n\n /**\n * Maps status name to option ID (for GitHub Projects V2)\n */\n statusOptions: Record<string, string> = {};\n\n /**\n * Last sync timestamp\n */\n lastSyncedAt: Date | null = null;\n\n /**\n * Transient: Cached project client (not persisted)\n */\n private _client?: IProject;\n\n constructor(options: ProjectOptions = {}) {\n super(options);\n if (options.projectId !== undefined) this.projectId = options.projectId;\n if (options.projectNumber !== undefined)\n this.projectNumber = options.projectNumber;\n if (options.title !== undefined) this.title = options.title;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.owner !== undefined) this.owner = options.owner;\n if (options.url !== undefined) this.url = options.url;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.tokenConfigKey !== undefined)\n this.tokenConfigKey = options.tokenConfigKey;\n if (options.statuses !== undefined) this.statuses = options.statuses;\n if (options.fields !== undefined) this.fields = options.fields;\n if (options.statusFieldId !== undefined)\n this.statusFieldId = options.statusFieldId;\n if (options.statusOptions !== undefined)\n this.statusOptions = options.statusOptions;\n if (options.tenantId !== undefined)\n (this as any).tenantId = options.tenantId;\n }\n\n /**\n * Get the project client, resolving token from config\n *\n * @returns Project client for API operations\n * @throws Error if token cannot be resolved\n */\n async getClient(): Promise<IProject> {\n if (this._client) {\n return this._client;\n }\n\n // Resolve token from environment or config\n const token =\n process.env[this.tokenConfigKey] ||\n (getModuleConfig<Record<string, string>>('smrt-projects', {})[\n this.tokenConfigKey\n ] as string);\n\n if (!token) {\n throw new Error(\n `Token not found for key '${this.tokenConfigKey}'. ` +\n `Set the ${this.tokenConfigKey} environment variable or configure it in smrt.config.`,\n );\n }\n\n this._client = await getProject({\n type: this.providerType,\n projectId: this.projectId,\n token,\n statusFieldId: this.statusFieldId || undefined,\n statusOptions:\n Object.keys(this.statusOptions).length > 0\n ? this.statusOptions\n : undefined,\n });\n\n return this._client;\n }\n\n /**\n * Clear the cached client\n */\n clearClient(): void {\n this._client = undefined;\n }\n\n /**\n * Sync project metadata from the provider\n *\n * @param options - Sync options\n * @returns This project with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const projectData: SDKProject = await client.getProject();\n\n // Update fields from remote\n this.title = projectData.title;\n this.description = projectData.description || '';\n this.owner = projectData.owner;\n this.url = projectData.url;\n this.statuses = projectData.statuses;\n this.fields = projectData.fields;\n this.lastSyncedAt = new Date();\n\n await this.save();\n return this;\n }\n\n /**\n * Add an issue or PR to this project\n *\n * @param item - Issue or PullRequest to add\n * @returns Created ProjectItem\n */\n async addItem(item: Issue | PullRequest): Promise<ProjectItem> {\n if (!item.nodeId) {\n throw new Error('Item must have a nodeId (sync the item first)');\n }\n\n const client = await this.getClient();\n return await client.addItem(item.nodeId);\n }\n\n /**\n * Remove an item from this project\n *\n * @param itemId - Project item ID to remove\n */\n async removeItem(itemId: string): Promise<void> {\n const client = await this.getClient();\n await client.removeItem(itemId);\n }\n\n /**\n * Get a specific item from the project\n *\n * @param itemId - Project item ID\n * @returns ProjectItem or null\n */\n async getItem(itemId: string): Promise<ProjectItem | null> {\n const client = await this.getClient();\n return await client.getItem(itemId);\n }\n\n /**\n * List items in this project\n *\n * @param filters - Optional filters\n * @returns Array of ProjectItems\n */\n async listItems(filters?: ItemFilters): Promise<ProjectItem[]> {\n const client = await this.getClient();\n return await client.listItems(filters);\n }\n\n /**\n * Update an item's status (column)\n *\n * @param itemId - Project item ID\n * @param status - New status name\n */\n async updateItemStatus(itemId: string, status: string): Promise<void> {\n const client = await this.getClient();\n await client.updateItemStatus(itemId, status);\n }\n\n /**\n * Update an item's custom field\n *\n * @param itemId - Project item ID\n * @param fieldId - Field ID\n * @param value - New value\n */\n async updateItemField(\n itemId: string,\n fieldId: string,\n value: unknown,\n ): Promise<void> {\n const client = await this.getClient();\n await client.updateItemField(itemId, fieldId, value);\n }\n\n /**\n * Get available statuses\n *\n * @returns Array of status definitions\n */\n async getStatuses(): Promise<ProjectStatus[]> {\n if (this.statuses.length > 0) {\n return this.statuses;\n }\n\n const client = await this.getClient();\n this.statuses = await client.listStatuses();\n await this.save();\n return this.statuses;\n }\n\n /**\n * Get available fields\n *\n * @returns Array of field definitions\n */\n async getFields(): Promise<ProjectField[]> {\n if (this.fields.length > 0) {\n return this.fields;\n }\n\n const client = await this.getClient();\n this.fields = await client.listFields();\n await this.save();\n return this.fields;\n }\n\n /**\n * Get items in a specific status/column\n *\n * @param status - Status name\n * @returns Array of ProjectItems in that status\n */\n async getItemsByStatus(status: string): Promise<ProjectItem[]> {\n return await this.listItems({ status });\n }\n\n /**\n * Move an item to a new status\n *\n * @param item - Issue or PullRequest\n * @param status - Target status name\n */\n async moveItem(item: Issue | PullRequest, status: string): Promise<void> {\n // First, find the item in the project\n const items = await this.listItems();\n const projectItem = items.find((i) => i.contentId === item.nodeId);\n\n if (!projectItem) {\n throw new Error('Item not found in project');\n }\n\n await this.updateItemStatus(projectItem.id, status);\n }\n\n /**\n * AI-powered: Analyze project health and suggest improvements\n *\n * @returns Analysis of project status\n */\n async analyzeHealth(): Promise<string> {\n const items = await this.listItems();\n const statuses = await this.getStatuses();\n\n // Count items by status\n const statusCounts: Record<string, number> = {};\n for (const status of statuses) {\n statusCounts[status.name] = items.filter(\n (i) => i.status === status.name,\n ).length;\n }\n\n return await this.do(\n `Analyze the health of this project board and suggest improvements.\n\n Project: ${this.title}\n Description: ${this.description}\n\n Item distribution by status:\n ${Object.entries(statusCounts)\n .map(([status, count]) => `- ${status}: ${count} items`)\n .join('\\n')}\n\n Total items: ${items.length}\n\n Provide:\n 1. Overall health assessment\n 2. Potential bottlenecks\n 3. Suggestions for improvement`,\n // Title/description/status counts hand-rolled above; skip do()'s\n // object-data injection so the board context is not duplicated.\n { includeData: false },\n );\n }\n\n /**\n * Get project by title\n *\n * @param title - Project title\n * @param options - Additional options\n * @returns Project or null\n */\n static async getByTitle(\n title: string,\n options: SmrtObjectOptions = {},\n ): Promise<Project | null> {\n const { ProjectCollection } = await import('../collections/Projects');\n const collection = await (ProjectCollection as any).create(options);\n return await collection.findByTitle(title);\n }\n}\n","/**\n * ProjectCollection - Collection manager for Project objects\n *\n * Provides querying and discovery operations for Project entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Project } from '../models/Project';\nimport type { ProjectProviderType } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class ProjectCollection extends SmrtCollection<Project> {\n static readonly _itemClass = Project;\n\n /**\n * Find project by title\n *\n * @param title - Project title\n * @returns Project or null\n */\n async findByTitle(title: string): Promise<Project | null> {\n const results = await this.list({\n where: { title },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find projects by owner\n *\n * @param owner - Project owner (organization or user)\n * @returns Array of projects\n */\n async findByOwner(owner: string): Promise<Project[]> {\n return await this.list({\n where: { owner },\n });\n }\n\n /**\n * Find projects by provider type\n *\n * @param providerType - Provider type\n * @returns Array of projects\n */\n async findByProvider(providerType: ProjectProviderType): Promise<Project[]> {\n return await this.list({\n where: { providerType },\n });\n }\n\n /**\n * Get or create a project by ID\n *\n * @param projectId - Provider-specific project ID\n * @param options - Additional options for creation\n * @returns Project (existing or newly created)\n */\n async getOrCreate(\n projectId: string,\n options: {\n title?: string;\n owner?: string;\n providerType?: ProjectProviderType;\n tokenConfigKey?: string;\n statusFieldId?: string;\n statusOptions?: Record<string, string>;\n } = {},\n ): Promise<Project> {\n let project = await this.findOne({\n where: { projectId },\n });\n\n if (!project) {\n project = await this.create({\n projectId,\n title: options.title || '',\n owner: options.owner || '',\n providerType: options.providerType || 'github',\n tokenConfigKey: options.tokenConfigKey || 'GITHUB_TOKEN',\n statusFieldId: options.statusFieldId || '',\n statusOptions: options.statusOptions || {},\n });\n await project.save();\n\n // Sync to get full project data\n await project.sync({ force: true });\n }\n\n return project;\n }\n\n /**\n * Sync all projects\n *\n * @param options - Sync options\n * @returns Array of synced projects\n */\n async syncAll(options: { force?: boolean } = {}): Promise<Project[]> {\n const projects = await this.list({});\n const synced: Project[] = [];\n\n for (const project of projects) {\n await project.sync(options);\n synced.push(project);\n }\n\n return synced;\n }\n\n /**\n * Find projects with items in a specific status\n *\n * @param status - Status name\n * @returns Array of projects\n */\n async findWithItemsInStatus(status: string): Promise<Project[]> {\n const projects = await this.list({});\n const matching: Project[] = [];\n\n for (const project of projects) {\n try {\n const items = await project.getItemsByStatus(status);\n if (items.length > 0) {\n matching.push(project);\n }\n } catch (error) {\n // Log error and skip projects we can't access\n logger.warn(`Error accessing items for project ${project.projectId}`, {\n error: error instanceof Error ? error.message : error,\n });\n }\n }\n\n return matching;\n }\n\n /**\n * Get project statistics\n *\n * @param projectId - Project ID\n * @returns Statistics object\n */\n async getStatistics(projectId: string): Promise<{\n totalItems: number;\n itemsByStatus: Record<string, number>;\n itemsByType: Record<string, number>;\n }> {\n const project = await this.findOne({ where: { projectId } });\n if (!project) {\n throw new Error(`Project ${projectId} not found`);\n }\n\n const items = await project.listItems();\n const statuses = await project.getStatuses();\n\n const itemsByStatus: Record<string, number> = {};\n for (const status of statuses) {\n itemsByStatus[status.name] = 0;\n }\n\n const itemsByType: Record<string, number> = {\n Issue: 0,\n PullRequest: 0,\n DraftIssue: 0,\n };\n\n for (const item of items) {\n if (item.status && itemsByStatus[item.status] !== undefined) {\n itemsByStatus[item.status]++;\n }\n if (itemsByType[item.type] !== undefined) {\n itemsByType[item.type]++;\n }\n }\n\n return {\n totalItems: items.length,\n itemsByStatus,\n itemsByType,\n };\n }\n\n /**\n * Find projects by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of projects for the tenant\n */\n async findByTenant(tenantId: string): Promise<Project[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global projects (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global projects\n */\n async findGlobal(): Promise<Project[]> {\n return queryGlobal<Project>(this);\n }\n\n /**\n * Find projects for a tenant plus all global projects.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global projects\n */\n async findWithGlobals(tenantId: string): Promise<Project[]> {\n return queryWithGlobals<Project>(this, tenantId, 'Project.findWithGlobals');\n }\n}\n","/**\n * PullRequest model - SMRT wrapper for pull request operations\n *\n * Extends Issue with PR-specific fields and methods.\n * Uses @happyvertical/repos SDK for actual API calls.\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped } from '@happyvertical/smrt-tenancy';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport type { MergeMethod, SyncOptions } from '../types';\nimport { Issue, type IssueOptions } from './Issue';\n\nexport interface PullRequestOptions extends IssueOptions {\n headRef?: string;\n baseRef?: string;\n merged?: boolean;\n mergedAt?: Date | null;\n mergeable?: boolean;\n draft?: boolean;\n additions?: number;\n deletions?: number;\n changedFiles?: number;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync', 'summarize', 'merge'] },\n // sync/summarize/merge/markReady are operator commands invoked in-process\n // via the CLI; they intentionally aren't exposed over HTTP today.\n cli: {\n include: ['list', 'get', 'sync', 'summarize', 'merge', 'markReady'],\n skipApiCheck: true,\n },\n})\nexport class PullRequest extends Issue {\n /**\n * Source branch ref\n */\n headRef: string = '';\n\n /**\n * Target branch ref\n */\n baseRef: string = '';\n\n /**\n * Whether the PR has been merged\n */\n merged: boolean = false;\n\n /**\n * When the PR was merged\n */\n mergedAt: Date | null = null;\n\n /**\n * Whether the PR can be merged\n */\n mergeable: boolean = true;\n\n /**\n * Whether this is a draft PR\n */\n draft: boolean = false;\n\n /**\n * Lines added\n */\n additions: number = 0;\n\n /**\n * Lines deleted\n */\n deletions: number = 0;\n\n /**\n * Number of files changed\n */\n changedFiles: number = 0;\n\n constructor(options: PullRequestOptions = {}) {\n super(options);\n if (options.headRef !== undefined) this.headRef = options.headRef;\n if (options.baseRef !== undefined) this.baseRef = options.baseRef;\n if (options.merged !== undefined) this.merged = options.merged;\n if (options.mergedAt !== undefined) this.mergedAt = options.mergedAt;\n if (options.mergeable !== undefined) this.mergeable = options.mergeable;\n if (options.draft !== undefined) this.draft = options.draft;\n if (options.additions !== undefined) this.additions = options.additions;\n if (options.deletions !== undefined) this.deletions = options.deletions;\n if (options.changedFiles !== undefined)\n this.changedFiles = options.changedFiles;\n }\n\n /**\n * Sync PR data from the provider\n *\n * @param options - Sync options\n * @returns This PR with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const prData = await client.getPullRequest(this.number);\n\n // Update base issue fields\n this.nodeId = prData.id;\n this.title = prData.title;\n this.body = prData.body;\n this.state = prData.state;\n this.author = prData.author.login;\n this.labels = prData.labels.map((l) => l.name);\n this.assignees = prData.assignees.map((a) => a.login);\n this.commentsCount = prData.commentsCount;\n\n // Update PR-specific fields\n this.headRef = prData.headRef;\n this.baseRef = prData.baseRef;\n this.merged = prData.merged;\n this.mergedAt = prData.mergedAt || null;\n this.mergeable = prData.mergeable;\n this.draft = prData.draft;\n\n this.lastSyncedAt = new Date();\n await this.save();\n return this;\n }\n\n /**\n * AI-powered: Generate a summary of PR changes\n *\n * @returns Summary of what this PR does\n */\n async summarize(): Promise<string> {\n return await this.do(\n `Summarize this pull request concisely.\n\n Title: ${this.title}\n Description: ${this.body}\n\n Changes: ${this.additions} additions, ${this.deletions} deletions across ${this.changedFiles} files\n Source: ${this.headRef} → ${this.baseRef}\n\n Provide a 2-3 sentence summary focusing on:\n 1. What the PR does\n 2. Why it matters\n 3. Any notable implementation details`,\n // Title/body/stats hand-rolled above; skip do()'s object-data injection.\n { includeData: false },\n );\n }\n\n /**\n * Merge this pull request\n *\n * @param method - Merge method (merge, squash, rebase)\n */\n async merge(method: MergeMethod = 'squash'): Promise<void> {\n if (this.merged) {\n throw new Error('Pull request is already merged');\n }\n\n if (this.draft) {\n throw new Error('Cannot merge a draft pull request');\n }\n\n if (!this.mergeable) {\n throw new Error('Pull request is not mergeable');\n }\n\n const client = await this.getClient();\n await client.mergePullRequest(this.number, method);\n\n this.merged = true;\n this.mergedAt = new Date();\n this.state = 'closed';\n this.lastSyncedAt = new Date();\n await this.save();\n }\n\n /**\n * Mark this draft PR as ready for review\n */\n async markReady(): Promise<void> {\n if (!this.draft) {\n throw new Error('Pull request is not a draft');\n }\n\n const client = await this.getClient();\n await client.markPRReady(this.number);\n\n this.draft = false;\n this.lastSyncedAt = new Date();\n await this.save();\n }\n\n /**\n * Convert this PR back to draft\n */\n async convertToDraft(): Promise<void> {\n if (this.draft) {\n throw new Error('Pull request is already a draft');\n }\n\n const client = await this.getClient();\n await client.convertPRToDraft(this.number);\n\n this.draft = true;\n this.lastSyncedAt = new Date();\n await this.save();\n }\n\n /**\n * Request review from specified users\n *\n * @param reviewers - User logins to request review from\n */\n async requestReviewers(reviewers: string[]): Promise<void> {\n const client = await this.getClient();\n await client.requestReview(this.number, reviewers);\n }\n\n /**\n * Find related issue for this PR\n *\n * @returns Related Issue or null\n */\n async findLinkedIssue(): Promise<Issue | null> {\n const client = await this.getClient();\n const issue = await client.findIssueForPR(this.number);\n\n if (!issue) {\n return null;\n }\n\n // Return as SMRT Issue\n const { IssueCollection } = await import('../collections/Issues');\n const collection = await (IssueCollection as any).create(this.options);\n return await collection.findOne({\n where: { repositoryId: this.repositoryId, number: issue.number },\n });\n }\n\n /**\n * AI-powered: Check if this PR is ready to merge\n *\n * @returns True if the PR appears ready\n */\n async isReadyToMerge(): Promise<boolean> {\n if (this.draft) return false;\n if (!this.mergeable) return false;\n if (this.state === 'closed') return false;\n\n return await this.is(\n `This pull request is ready to merge because:\n - It has a clear description of what it does\n - It addresses a specific issue or feature\n - The scope is appropriate (not too large)\n - There are no unresolved review comments`,\n );\n }\n\n /**\n * AI-powered: Suggest reviewers based on changed files\n *\n * @returns Array of suggested reviewer logins\n */\n async suggestReviewers(): Promise<string[]> {\n const suggestion = await this.do(\n `Based on this pull request's title, description, and scope,\n suggest who should review it.\n\n Title: ${this.title}\n Description: ${this.body}\n Changes: ${this.changedFiles} files changed\n\n Consider:\n - Code owners for the affected areas\n - Team members with relevant expertise\n - People who have previously worked on related code\n\n Return only a comma-separated list of GitHub usernames, nothing else.\n If you cannot determine reviewers, return an empty string.`,\n // Title/description hand-rolled above; skip do()'s object-data injection.\n { includeData: false },\n );\n\n return suggestion\n .split(',')\n .map((r) => r.trim())\n .filter(Boolean);\n }\n\n /**\n * Get PR URL\n */\n override getUrl(): string {\n const repo = this._repository;\n if (repo) {\n return `https://github.com/${repo.owner}/${repo.name}/pull/${this.number}`;\n }\n return '';\n }\n\n /**\n * Get the change size classification\n *\n * @returns Size classification (xs, s, m, l, xl)\n */\n getChangeSize(): 'xs' | 's' | 'm' | 'l' | 'xl' {\n const total = this.additions + this.deletions;\n\n if (total < 10) return 'xs';\n if (total < 50) return 's';\n if (total < 200) return 'm';\n if (total < 500) return 'l';\n return 'xl';\n }\n}\n","/**\n * PullRequestCollection - Collection manager for PullRequest objects\n *\n * Provides querying and discovery operations for PullRequest entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { PullRequest } from '../models/PullRequest';\nimport type { Repository } from '../models/Repository';\nimport type { SDKPullRequest, SearchFilters } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class PullRequestCollection extends SmrtCollection<PullRequest> {\n static readonly _itemClass = PullRequest;\n\n /**\n * Discover pull requests from a repository and sync to database\n *\n * @param options - Discovery options\n * @returns Array of PullRequest objects\n */\n async discover(options: {\n repository: Repository;\n filters?: SearchFilters;\n }): Promise<PullRequest[]> {\n const { repository, filters } = options;\n const repositoryId = repository.id ?? undefined;\n\n if (!repositoryId) {\n throw new Error(\n 'Repository must be saved before discovering pull requests',\n );\n }\n\n const repoClient = await repository.getClient();\n\n // Note: searchIssues with type filter would get PRs in GitHub\n // For now, we'll search for all and filter\n const remoteItems = await repoClient.searchIssues('is:pr', filters);\n\n const pullRequests: PullRequest[] = [];\n\n for (const remote of remoteItems) {\n // Get full PR data\n let prData: SDKPullRequest;\n try {\n prData = await repoClient.getPullRequest(remote.number);\n } catch (error) {\n // Log error and skip PR - could be rate limiting, auth, or access issues\n logger.warn(\n `Failed to fetch PR #${remote.number} from ${repository.owner}/${repository.name}`,\n { error: error instanceof Error ? error.message : error },\n );\n continue;\n }\n\n // Find existing PR by repository + number\n let pr = await this.findOne({\n where: {\n repositoryId,\n number: remote.number,\n },\n });\n\n if (!pr) {\n // Create new PR\n pr = await this.create({\n repositoryId,\n number: prData.number,\n nodeId: prData.id,\n title: prData.title,\n body: prData.body,\n state: prData.state,\n author: prData.author.login,\n labels: prData.labels.map((l) => l.name),\n assignees: prData.assignees.map((a) => a.login),\n commentsCount: prData.commentsCount,\n headRef: prData.headRef,\n baseRef: prData.baseRef,\n merged: prData.merged,\n mergedAt: prData.mergedAt || null,\n mergeable: prData.mergeable,\n draft: prData.draft,\n lastSyncedAt: new Date(),\n });\n } else {\n // Update existing PR\n pr.nodeId = prData.id;\n pr.title = prData.title;\n pr.body = prData.body;\n pr.state = prData.state;\n pr.author = prData.author.login;\n pr.labels = prData.labels.map((l) => l.name);\n pr.assignees = prData.assignees.map((a) => a.login);\n pr.commentsCount = prData.commentsCount;\n pr.headRef = prData.headRef;\n pr.baseRef = prData.baseRef;\n pr.merged = prData.merged;\n pr.mergedAt = prData.mergedAt || null;\n pr.mergeable = prData.mergeable;\n pr.draft = prData.draft;\n pr.lastSyncedAt = new Date();\n }\n\n await pr.save();\n pullRequests.push(pr);\n }\n\n return pullRequests;\n }\n\n /**\n * Find PRs by repository\n *\n * @param repositoryId - Repository ID\n * @returns Array of PRs\n */\n async findByRepository(repositoryId: string): Promise<PullRequest[]> {\n return await this.list({\n where: { repositoryId },\n });\n }\n\n /**\n * Find open PRs\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of open PRs\n */\n async findOpen(repositoryId?: string): Promise<PullRequest[]> {\n const where: Record<string, any> = { state: 'open' };\n if (repositoryId) {\n where.repositoryId = repositoryId;\n }\n return await this.list({ where });\n }\n\n /**\n * Find draft PRs\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of draft PRs\n */\n async findDrafts(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n return openPRs.filter((pr) => pr.draft);\n }\n\n /**\n * Find PRs ready to merge\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of mergeable PRs\n */\n async findReadyToMerge(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n return openPRs.filter((pr) => !pr.draft && pr.mergeable);\n }\n\n /**\n * Find PRs by branch\n *\n * @param branch - Branch name (head or base)\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs\n */\n async findByBranch(\n branch: string,\n repositoryId?: string,\n ): Promise<PullRequest[]> {\n const prs = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n return prs.filter((pr) => pr.headRef === branch || pr.baseRef === branch);\n }\n\n /**\n * Find PR by number in a repository\n *\n * @param repositoryId - Repository ID\n * @param number - PR number\n * @returns PullRequest or null\n */\n async findByNumber(\n repositoryId: string,\n number: number,\n ): Promise<PullRequest | null> {\n const results = await this.list({\n where: { repositoryId, number },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find PRs ready to merge (AI-powered)\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs that are ready\n */\n async findAIReadyToMerge(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n const ready: PullRequest[] = [];\n\n for (const pr of openPRs) {\n if (await pr.isReadyToMerge()) {\n ready.push(pr);\n }\n }\n\n return ready;\n }\n\n /**\n * Get PRs by change size\n *\n * @param size - Size classification\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs\n */\n async findBySize(\n size: 'xs' | 's' | 'm' | 'l' | 'xl',\n repositoryId?: string,\n ): Promise<PullRequest[]> {\n const prs = await this.findOpen(repositoryId);\n return prs.filter((pr) => pr.getChangeSize() === size);\n }\n\n /**\n * Batch sync PRs from repository\n *\n * @param repository - Repository to sync from\n * @param options - Sync options\n * @returns Array of synced PRs\n */\n async batchSync(\n repository: Repository,\n options: { force?: boolean } = {},\n ): Promise<PullRequest[]> {\n const prs = await this.findByRepository(repository.id as string);\n const synced: PullRequest[] = [];\n\n for (const pr of prs) {\n await pr.sync(options);\n synced.push(pr);\n }\n\n return synced;\n }\n\n /**\n * Find pull requests by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of pull requests for the tenant\n */\n async findByTenant(tenantId: string): Promise<PullRequest[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global pull requests (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global pull requests\n */\n async findGlobal(): Promise<PullRequest[]> {\n return queryGlobal<PullRequest>(this);\n }\n\n /**\n * Find pull requests for a tenant plus all global pull requests.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global pull requests\n */\n async findWithGlobals(tenantId: string): Promise<PullRequest[]> {\n return queryWithGlobals<PullRequest>(\n this,\n tenantId,\n 'PullRequest.findWithGlobals',\n );\n }\n}\n","/**\n * Repository model - SMRT wrapper for repository operations\n *\n * Provides persistent repository tracking with provider-agnostic operations.\n * Uses @happyvertical/repos SDK for actual API calls.\n */\n\nimport { getRepository } from '@happyvertical/repos';\nimport { getModuleConfig } from '@happyvertical/smrt-config';\nimport {\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport type {\n CreateIssueInput,\n CreatePRInput,\n IRepository,\n RepositoryProviderType,\n SDKRepository,\n SearchFilters,\n SyncOptions,\n} from '../types';\nimport type { Issue } from './Issue';\nimport type { PullRequest } from './PullRequest';\n\nexport interface RepositoryOptions extends SmrtObjectOptions {\n owner?: string;\n name?: string;\n fullName?: string;\n description?: string;\n defaultBranch?: string;\n isPrivate?: boolean;\n providerType?: RepositoryProviderType;\n baseUrl?: string;\n tokenConfigKey?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync'] },\n // sync is an operator command invoked in-process via the CLI;\n // it intentionally isn't exposed over HTTP today.\n cli: { include: ['list', 'get', 'sync', 'create'], skipApiCheck: true },\n})\nexport class Repository extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Repository owner (organization or user)\n */\n owner: string = '';\n\n /**\n * Repository name\n */\n name: string = '';\n\n /**\n * Full name in owner/repo format\n */\n fullName: string = '';\n\n /**\n * Repository description\n */\n description: string = '';\n\n /**\n * Default branch name\n */\n defaultBranch: string = 'main';\n\n /**\n * Whether repository is private\n */\n isPrivate: boolean = false;\n\n /**\n * Repository provider type\n */\n providerType: RepositoryProviderType = 'github';\n\n /**\n * Base URL for self-hosted instances (GitHub Enterprise, GitLab self-hosted, etc.)\n */\n baseUrl: string = '';\n\n /**\n * Environment variable name or config key for token resolution\n * The token is NOT stored - only the key name is persisted\n */\n tokenConfigKey: string = 'GITHUB_TOKEN';\n\n /**\n * Last sync timestamp\n */\n lastSyncedAt: Date | null = null;\n\n /**\n * Transient: Cached repository client (not persisted)\n */\n private _client?: IRepository;\n\n constructor(options: RepositoryOptions = {}) {\n super(options);\n if (options.owner !== undefined) this.owner = options.owner;\n if (options.name !== undefined) this.name = options.name;\n if (options.fullName !== undefined) this.fullName = options.fullName;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.defaultBranch !== undefined)\n this.defaultBranch = options.defaultBranch;\n if (options.isPrivate !== undefined) this.isPrivate = options.isPrivate;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.baseUrl !== undefined) this.baseUrl = options.baseUrl;\n if (options.tokenConfigKey !== undefined)\n this.tokenConfigKey = options.tokenConfigKey;\n if (options.tenantId !== undefined)\n (this as any).tenantId = options.tenantId;\n }\n\n /**\n * Get the repository client, resolving token from config\n *\n * Token resolution order:\n * 1. Environment variable matching tokenConfigKey\n * 2. Module config value matching tokenConfigKey\n *\n * @returns Repository client for API operations\n * @throws Error if token cannot be resolved\n */\n async getClient(): Promise<IRepository> {\n if (this._client) {\n return this._client;\n }\n\n // Resolve token from environment or config\n const token =\n process.env[this.tokenConfigKey] ||\n (getModuleConfig<Record<string, string>>('smrt-projects', {})[\n this.tokenConfigKey\n ] as string);\n\n if (!token) {\n throw new Error(\n `Token not found for key '${this.tokenConfigKey}'. ` +\n `Set the ${this.tokenConfigKey} environment variable or configure it in smrt.config.`,\n );\n }\n\n this._client = await getRepository({\n type: this.providerType,\n owner: this.owner,\n repo: this.name,\n token,\n baseUrl: this.baseUrl || undefined,\n });\n\n return this._client;\n }\n\n /**\n * Clear the cached client (useful after token refresh)\n */\n clearClient(): void {\n this._client = undefined;\n }\n\n /**\n * Sync repository metadata from the provider\n *\n * @param options - Sync options\n * @returns This repository with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const repoData: SDKRepository = await client.getRepository();\n\n // Update fields from remote\n this.owner = repoData.owner;\n this.name = repoData.name;\n this.fullName = `${repoData.owner}/${repoData.name}`;\n this.description = repoData.description;\n this.defaultBranch = repoData.defaultBranch;\n this.isPrivate = repoData.isPrivate;\n this.lastSyncedAt = new Date();\n\n await this.save();\n return this;\n }\n\n /**\n * Get issues from this repository\n *\n * @param filters - Optional search filters\n * @returns Array of Issue objects (SMRT models)\n */\n async getIssues(filters?: SearchFilters): Promise<Issue[]> {\n const { IssueCollection } = await import('../collections/Issues');\n const collection = await (IssueCollection as any).create(this.options);\n return await collection.discover({ repository: this, filters });\n }\n\n /**\n * Get pull requests from this repository\n *\n * @param filters - Optional search filters\n * @returns Array of PullRequest objects (SMRT models)\n */\n async getPullRequests(filters?: SearchFilters): Promise<PullRequest[]> {\n const { PullRequestCollection } = await import(\n '../collections/PullRequests'\n );\n const collection = await (PullRequestCollection as any).create(\n this.options,\n );\n return await collection.discover({ repository: this, filters });\n }\n\n /**\n * Create a new issue in this repository\n *\n * @param data - Issue creation data\n * @returns Created Issue (SMRT model)\n */\n async createIssue(data: CreateIssueInput): Promise<Issue> {\n const repositoryId = this.id ?? undefined;\n if (!repositoryId) {\n throw new Error('Repository must be saved before creating issues');\n }\n\n const client = await this.getClient();\n const created = await client.createIssue(data);\n\n // Create SMRT Issue from remote data\n const { Issue } = await import('./Issue');\n const issue = new Issue({\n ...this.options,\n repositoryId,\n number: created.number,\n nodeId: created.id,\n title: created.title,\n body: created.body,\n state: created.state,\n author: created.author.login,\n labels: created.labels.map((l) => l.name),\n assignees: created.assignees.map((a) => a.login),\n commentsCount: created.commentsCount,\n lastSyncedAt: new Date(),\n });\n\n // Directly-constructed models must be initialized before save() can access\n // the database connection (SmrtCollection.create() does this internally).\n await issue.initialize();\n await issue.save();\n return issue;\n }\n\n /**\n * Create a new pull request in this repository\n *\n * @param data - PR creation data\n * @returns Created PullRequest (SMRT model)\n */\n async createPullRequest(data: CreatePRInput): Promise<PullRequest> {\n const repositoryId = this.id ?? undefined;\n if (!repositoryId) {\n throw new Error('Repository must be saved before creating pull requests');\n }\n\n const client = await this.getClient();\n const created = await client.createPullRequest(data);\n\n // Create SMRT PullRequest from remote data\n const { PullRequest } = await import('./PullRequest');\n const pr = new PullRequest({\n ...this.options,\n repositoryId,\n number: created.number,\n nodeId: created.id,\n title: created.title,\n body: created.body,\n state: created.state,\n author: created.author.login,\n labels: created.labels.map((l) => l.name),\n assignees: created.assignees.map((a) => a.login),\n commentsCount: created.commentsCount,\n headRef: created.headRef,\n baseRef: created.baseRef,\n merged: created.merged,\n draft: created.draft,\n lastSyncedAt: new Date(),\n });\n\n // Directly-constructed models must be initialized before save() can access\n // the database connection (SmrtCollection.create() does this internally).\n await pr.initialize();\n await pr.save();\n return pr;\n }\n\n /**\n * Check if this repository has any open issues matching criteria\n *\n * @param criteria - Natural language description of what to check\n * @returns True if matching issues exist\n */\n async hasOpenIssuesMatching(criteria: string): Promise<boolean> {\n const issues = await this.getIssues({ state: 'open' });\n if (issues.length === 0) return false;\n\n return await this.is(\n `This repository has open issues matching: ${criteria}. ` +\n `Current open issues: ${issues.map((i) => `#${i.number}: ${i.title}`).join(', ')}`,\n );\n }\n\n /**\n * Generate a summary of repository activity\n *\n * @returns AI-generated summary\n */\n async summarizeActivity(): Promise<string> {\n const issues = await this.getIssues({ state: 'open', limit: 10 });\n const prs = await this.getPullRequests({ state: 'open', limit: 10 });\n\n return await this.do(\n `Summarize the current activity in this repository. ` +\n `Open issues: ${issues.map((i) => `#${i.number}: ${i.title}`).join(', ')}. ` +\n `Open PRs: ${prs.map((p) => `#${p.number}: ${p.title}`).join(', ')}.`,\n );\n }\n\n /**\n * Get repository by owner and name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @param options - Additional options\n * @returns Repository or null if not found\n */\n static async getByFullName(\n owner: string,\n name: string,\n options: SmrtObjectOptions = {},\n ): Promise<Repository | null> {\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await (RepositoryCollection as any).create(options);\n return await collection.findByFullName(owner, name);\n }\n}\n","/**\n * RepositoryCollection - Collection manager for Repository objects\n *\n * Provides querying and discovery operations for Repository entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Repository } from '../models/Repository';\nimport type { RepositoryProviderType } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class RepositoryCollection extends SmrtCollection<Repository> {\n static readonly _itemClass = Repository;\n\n /**\n * Find a repository by owner and name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @returns Repository or null\n */\n async findByFullName(\n owner: string,\n name: string,\n ): Promise<Repository | null> {\n const results = await this.list({\n where: { owner, name },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find repositories by owner\n *\n * @param owner - Repository owner\n * @returns Array of repositories\n */\n async findByOwner(owner: string): Promise<Repository[]> {\n return await this.list({\n where: { owner },\n });\n }\n\n /**\n * Find repositories by provider type\n *\n * @param providerType - Provider type\n * @returns Array of repositories\n */\n async findByProvider(\n providerType: RepositoryProviderType,\n ): Promise<Repository[]> {\n return await this.list({\n where: { providerType },\n });\n }\n\n /**\n * Get or create a repository by owner/name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @param options - Additional options for creation\n * @returns Repository (existing or newly created)\n */\n async getOrCreate(\n owner: string,\n name: string,\n options: {\n providerType?: RepositoryProviderType;\n tokenConfigKey?: string;\n baseUrl?: string;\n } = {},\n ): Promise<Repository> {\n let repo = await this.findByFullName(owner, name);\n\n if (!repo) {\n repo = await this.create({\n owner,\n name,\n fullName: `${owner}/${name}`,\n providerType: options.providerType || 'github',\n tokenConfigKey: options.tokenConfigKey || 'GITHUB_TOKEN',\n baseUrl: options.baseUrl || '',\n });\n await repo.save();\n }\n\n return repo;\n }\n\n /**\n * Sync all repositories\n *\n * @param options - Sync options\n * @returns Array of synced repositories\n */\n async syncAll(options: { force?: boolean } = {}): Promise<Repository[]> {\n const repos = await this.list({});\n const synced: Repository[] = [];\n\n for (const repo of repos) {\n await repo.sync(options);\n synced.push(repo);\n }\n\n return synced;\n }\n\n /**\n * Find repositories with open issues\n *\n * @returns Array of repositories with at least one open issue\n */\n async findWithOpenIssues(): Promise<Repository[]> {\n const repos = await this.list({});\n const withIssues: Repository[] = [];\n\n for (const repo of repos) {\n try {\n const issues = await repo.getIssues({ state: 'open', limit: 1 });\n if (issues.length > 0) {\n withIssues.push(repo);\n }\n } catch (error) {\n // Log error and skip repos we can't access\n logger.warn(\n `Error accessing issues for repository ${repo.owner}/${repo.name}`,\n { error: error instanceof Error ? error.message : error },\n );\n }\n }\n\n return withIssues;\n }\n\n /**\n * Find repositories by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of repositories for the tenant\n */\n async findByTenant(tenantId: string): Promise<Repository[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global repositories (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global repositories\n */\n async findGlobal(): Promise<Repository[]> {\n return queryGlobal<Repository>(this);\n }\n\n /**\n * Find repositories for a tenant plus all global repositories.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global repositories\n */\n async findWithGlobals(tenantId: string): Promise<Repository[]> {\n return queryWithGlobals<Repository>(\n this,\n tenantId,\n 'Repository.findWithGlobals',\n );\n }\n}\n","/**\n * Comment model - SMRT wrapper for issue/PR comments\n *\n * Represents a comment on an issue or pull request.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nconst logger = createLogger({ level: 'info' });\n\nexport interface CommentOptions extends SmrtObjectOptions {\n issueId?: string;\n commentId?: string;\n body?: string;\n author?: string;\n createdAt?: Date;\n updatedAt?: Date;\n url?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n})\nexport class Comment extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Issue this comment belongs to\n */\n @foreignKey('Issue')\n issueId?: string;\n\n /**\n * Provider-specific comment ID\n */\n commentId: string = '';\n\n /**\n * Comment body text\n */\n body: string = '';\n\n /**\n * Comment author's login\n */\n author: string = '';\n\n /**\n * When the comment was created\n */\n createdAt: Date | null = null;\n\n /**\n * When the comment was last updated\n */\n updatedAt: Date | null = null;\n\n /**\n * Comment URL\n */\n url: string = '';\n\n constructor(options: CommentOptions = {}) {\n super(options);\n if (options.issueId !== undefined) this.issueId = options.issueId;\n if (options.commentId !== undefined) this.commentId = options.commentId;\n if (options.body !== undefined) this.body = options.body;\n if (options.author !== undefined) this.author = options.author;\n if (options.createdAt !== undefined) this.createdAt = options.createdAt;\n if (options.updatedAt !== undefined) this.updatedAt = options.updatedAt;\n if (options.url !== undefined) this.url = options.url;\n if (options.tenantId !== undefined)\n (this as any).tenantId = options.tenantId;\n }\n\n /**\n * AI-powered: Check if this comment contains a question\n */\n async isQuestion(): Promise<boolean> {\n return await this.is(\n 'This comment contains a question or request for clarification',\n );\n }\n\n /**\n * AI-powered: Check if this comment contains approval\n */\n async isApproval(): Promise<boolean> {\n return await this.is(\n 'This comment expresses approval, agreement, or a positive response (LGTM, +1, approved, etc.)',\n );\n }\n\n /**\n * AI-powered: Check if this comment requests changes\n */\n async requestsChanges(): Promise<boolean> {\n return await this.is(\n 'This comment requests changes, modifications, or improvements to the issue/PR',\n );\n }\n\n /**\n * AI-powered: Extract action items from this comment\n *\n * @returns Array of action items\n */\n async extractActionItems(): Promise<string[]> {\n const result = await this.do(\n `Extract any action items, tasks, or requests from this comment.\n Return a JSON array of strings, each representing one action item.\n If no action items, return an empty array [].\n Only return the JSON array, nothing else.\n\n Comment: ${this.body}`,\n // Body is hand-rolled above; skip do()'s object-data injection (no dup).\n { includeData: false },\n );\n\n try {\n return JSON.parse(result);\n } catch (error) {\n logger.warn('Failed to parse action items JSON', {\n error: error instanceof Error ? error.message : error,\n response: result,\n });\n return [];\n }\n }\n\n /**\n * AI-powered: Summarize this comment\n *\n * @returns Brief summary\n */\n async summarize(): Promise<string> {\n return await this.do(\n `Summarize this comment in one sentence.\n Comment by ${this.author}: ${this.body}`,\n // Author + body hand-rolled above; skip do()'s object-data injection.\n { includeData: false },\n );\n }\n\n /**\n * Get the sentiment of this comment\n *\n * @returns Sentiment classification\n */\n async getSentiment(): Promise<'positive' | 'negative' | 'neutral'> {\n const result = await this.do(\n `Classify the sentiment of this comment as exactly one of: positive, negative, neutral\n Only return one word.\n Comment: ${this.body}`,\n // Body is hand-rolled above; skip do()'s object-data injection (no dup).\n { includeData: false },\n );\n\n const normalized = result.toLowerCase().trim();\n if (normalized.includes('positive')) return 'positive';\n if (normalized.includes('negative')) return 'negative';\n return 'neutral';\n }\n}\n","/**\n * Label model - SMRT wrapper for repository labels\n *\n * Represents a label that can be applied to issues and PRs.\n */\n\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\n\nexport interface LabelOptions extends SmrtObjectOptions {\n repositoryId?: string;\n name?: string;\n color?: string;\n description?: string;\n}\n\n@smrt({\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create'] },\n cli: { include: ['list', 'get', 'create', 'update', 'delete'] },\n})\nexport class Label extends SmrtObject {\n /**\n * Repository this label belongs to\n */\n @foreignKey('Repository')\n repositoryId?: string;\n\n /**\n * Label name\n */\n name: string = '';\n\n /**\n * Label color (hex without #)\n */\n color: string = '';\n\n /**\n * Label description\n */\n description: string = '';\n\n constructor(options: LabelOptions = {}) {\n super(options);\n if (options.repositoryId !== undefined)\n this.repositoryId = options.repositoryId;\n if (options.name !== undefined) this.name = options.name;\n if (options.color !== undefined) this.color = options.color;\n if (options.description !== undefined)\n this.description = options.description;\n }\n\n /**\n * Check if this is a type label (bug, feature, etc.)\n */\n isTypeLabel(): boolean {\n const typePatterns = [\n /^type:/i,\n /^kind:/i,\n /^bug$/i,\n /^feature$/i,\n /^enhancement$/i,\n /^docs$/i,\n /^chore$/i,\n ];\n return typePatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Check if this is a priority label\n */\n isPriorityLabel(): boolean {\n const priorityPatterns = [\n /^p[0-4]$/i,\n /^priority:/i,\n /^critical$/i,\n /^high$/i,\n /^medium$/i,\n /^low$/i,\n ];\n return priorityPatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Check if this is a status label\n */\n isStatusLabel(): boolean {\n const statusPatterns = [\n /^status:/i,\n /^wip$/i,\n /^in.?progress$/i,\n /^blocked$/i,\n /^needs.?review$/i,\n /^ready$/i,\n ];\n return statusPatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Get the label category\n *\n * @returns Category name\n */\n getCategory(): 'type' | 'priority' | 'status' | 'area' | 'other' {\n if (this.isTypeLabel()) return 'type';\n if (this.isPriorityLabel()) return 'priority';\n if (this.isStatusLabel()) return 'status';\n if (this.name.includes(':')) return 'area';\n return 'other';\n }\n\n /**\n * Parse priority level from label name\n *\n * @returns Priority level 0-4 or null\n */\n getPriorityLevel(): number | null {\n const match = this.name.match(/p([0-4])/i);\n if (match) {\n return parseInt(match[1], 10);\n }\n if (/critical/i.test(this.name)) return 0;\n if (/high/i.test(this.name)) return 1;\n if (/medium/i.test(this.name)) return 2;\n if (/low/i.test(this.name)) return 3;\n return null;\n }\n\n /**\n * Get label with # prefix for hex color\n */\n getHexColor(): string {\n return this.color.startsWith('#') ? this.color : `#${this.color}`;\n }\n\n /**\n * Create a label in the repository\n */\n async createInRepository(): Promise<void> {\n if (!this.repositoryId) {\n throw new Error('Label must have a repositoryId');\n }\n\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await (RepositoryCollection as any).create(this.options);\n const repo = await collection.get({ id: this.repositoryId });\n\n if (!repo) {\n throw new Error(`Repository ${this.repositoryId} not found`);\n }\n\n const client = await repo.getClient();\n await client.createLabel({\n name: this.name,\n color: this.color,\n description: this.description,\n });\n\n await this.save();\n }\n\n /**\n * Update this label in the repository\n */\n async updateInRepository(): Promise<void> {\n if (!this.repositoryId) {\n throw new Error('Label must have a repositoryId');\n }\n\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await (RepositoryCollection as any).create(this.options);\n const repo = await collection.get({ id: this.repositoryId });\n\n if (!repo) {\n throw new Error(`Repository ${this.repositoryId} not found`);\n }\n\n const client = await repo.getClient();\n await client.updateLabel(this.name, {\n name: this.name,\n color: this.color,\n description: this.description,\n });\n\n await this.save();\n }\n}\n"],"names":["RepositoryCollection","ai","smrtConfig","__decorateClass","tenantId","ProjectCollection","logger","IssueCollection","PullRequestCollection","Issue","PullRequest"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": "1.0.0",
3
- "timestamp": 1782241041924,
3
+ "timestamp": 1782251571366,
4
4
  "packageName": "@happyvertical/smrt-projects",
5
- "packageVersion": "0.34.0",
5
+ "packageVersion": "0.34.2",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-projects:IssueCollection": {
8
8
  "name": "issuecollection",
@@ -1 +1 @@
1
- {"version":3,"file":"Repository.d.ts","sourceRoot":"","sources":["../../src/models/Repository.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EACL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,sBAAsB,EAEtB,aAAa,EACb,WAAW,EACZ,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,qBAQa,UAAW,SAAQ,UAAU;IACxC;;OAEG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAM;IAEnB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAM;IAElB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAM;IAEtB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAM;IAEzB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAU;IAE/B;;OAEG;IACH,SAAS,EAAE,OAAO,CAAS;IAE3B;;OAEG;IACH,YAAY,EAAE,sBAAsB,CAAY;IAEhD;;OAEG;IACH,OAAO,EAAE,MAAM,CAAM;IAErB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAkB;IAExC;;OAEG;IACH,YAAY,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEjC;;OAEG;IACH,OAAO,CAAC,OAAO,CAAC,CAAc;gBAElB,OAAO,GAAE,iBAAsB;IAmB3C;;;;;;;;;OASG;IACG,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC;IA8BvC;;OAEG;IACH,WAAW,IAAI,IAAI;IAInB;;;;;OAKG;IACG,IAAI,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BpD;;;;;OAKG;IACG,SAAS,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAM1D;;;;;OAKG;IACG,eAAe,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAUtE;;;;;OAKG;IACG,WAAW,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,KAAK,CAAC;IA8BzD;;;;;OAKG;IACG,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAkClE;;;;;OAKG;IACG,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU/D;;;;OAIG;IACG,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAW1C;;;;;;;OAOG;WACU,aAAa,CACxB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;CAO9B"}
1
+ {"version":3,"file":"Repository.d.ts","sourceRoot":"","sources":["../../src/models/Repository.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EACL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,sBAAsB,EAEtB,aAAa,EACb,WAAW,EACZ,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,qBAQa,UAAW,SAAQ,UAAU;IACxC;;OAEG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAM;IAEnB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAM;IAElB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAM;IAEtB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAM;IAEzB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAU;IAE/B;;OAEG;IACH,SAAS,EAAE,OAAO,CAAS;IAE3B;;OAEG;IACH,YAAY,EAAE,sBAAsB,CAAY;IAEhD;;OAEG;IACH,OAAO,EAAE,MAAM,CAAM;IAErB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAkB;IAExC;;OAEG;IACH,YAAY,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEjC;;OAEG;IACH,OAAO,CAAC,OAAO,CAAC,CAAc;gBAElB,OAAO,GAAE,iBAAsB;IAmB3C;;;;;;;;;OASG;IACG,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC;IA8BvC;;OAEG;IACH,WAAW,IAAI,IAAI;IAInB;;;;;OAKG;IACG,IAAI,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BpD;;;;;OAKG;IACG,SAAS,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAM1D;;;;;OAKG;IACG,eAAe,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAUtE;;;;;OAKG;IACG,WAAW,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,KAAK,CAAC;IAiCzD;;;;;OAKG;IACG,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAqClE;;;;;OAKG;IACG,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU/D;;;;OAIG;IACG,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAW1C;;;;;;;OAOG;WACU,aAAa,CACxB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;CAO9B"}
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-06-23T18:57:22.293Z",
3
+ "generatedAt": "2026-06-23T21:52:51.727Z",
4
4
  "packageName": "@happyvertical/smrt-projects",
5
- "packageVersion": "0.34.0",
5
+ "packageVersion": "0.34.2",
6
6
  "sourceManifestPath": "dist/manifest.json",
7
7
  "agentDocPath": "AGENTS.md",
8
8
  "sourceHashes": {
9
- "manifest": "cc1beede9139aea8840f482f36c911f6e562042d578906ea017f05e1290c05d1",
10
- "packageJson": "393fddac45a7d9b9d0a3479d8ceefb1e3a2c61f97d9be7e4d20f0369cadcb968",
9
+ "manifest": "32892ed0b60cce783a3540c4d09833301c1174932cf82a1eb68292ccf9b64057",
10
+ "packageJson": "7f3c4e39da4aa9195fd5bfe30de332cfe99a65dc498d8baef81d65f69fb29de0",
11
11
  "agents": "31de38c962634d69c728bab8dff270448a49718fc36ee20b9cd12216cdbed95c"
12
12
  },
13
13
  "exports": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-projects",
3
- "version": "0.34.0",
3
+ "version": "0.34.2",
4
4
  "description": "Provider-agnostic project management models (Issues, PRs, Repositories, Projects) for SMRT framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,12 +38,12 @@
38
38
  "@happyvertical/repos": "^0.74.7",
39
39
  "@happyvertical/sql": "^0.74.7",
40
40
  "@happyvertical/utils": "^0.74.7",
41
- "@happyvertical/smrt-config": "0.34.0",
42
- "@happyvertical/smrt-prompts": "0.34.0",
43
- "@happyvertical/smrt-tenancy": "0.34.0",
44
- "@happyvertical/smrt-core": "0.34.0",
45
- "@happyvertical/smrt-types": "0.34.0",
46
- "@happyvertical/smrt-ui": "0.34.0"
41
+ "@happyvertical/smrt-config": "0.34.2",
42
+ "@happyvertical/smrt-core": "0.34.2",
43
+ "@happyvertical/smrt-prompts": "0.34.2",
44
+ "@happyvertical/smrt-tenancy": "0.34.2",
45
+ "@happyvertical/smrt-types": "0.34.2",
46
+ "@happyvertical/smrt-ui": "0.34.2"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "svelte": "^5.18.0"
@@ -63,8 +63,8 @@
63
63
  "typescript": "^5.9.3",
64
64
  "vite": "^7.3.1",
65
65
  "vitest": "^4.0.17",
66
- "@happyvertical/smrt-cli": "0.34.0",
67
- "@happyvertical/smrt-vitest": "0.34.0"
66
+ "@happyvertical/smrt-cli": "0.34.2",
67
+ "@happyvertical/smrt-vitest": "0.34.2"
68
68
  },
69
69
  "keywords": [
70
70
  "ai",