@cleocode/core 2026.4.27 → 2026.4.29

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.
@@ -1 +1 @@
1
- {"version":3,"file":"mvi-helpers.d.ts","sourceRoot":"","sources":["../src/mvi-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEpD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAM3D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAI/D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAKrE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,cAAc,CAKjD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAIjE"}
1
+ {"version":3,"file":"mvi-helpers.d.ts","sourceRoot":"","sources":["../src/mvi-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEpD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAM3D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAI/D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAIrE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,cAAc,CAKjD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAIjE"}
@@ -19,6 +19,10 @@ export declare function getLinkByExternalId(providerId: string, externalId: stri
19
19
  export declare function getLinksByTaskId(taskId: string, cwd?: string): Promise<ExternalTaskLink[]>;
20
20
  /**
21
21
  * Create a new external task link.
22
+ *
23
+ * Ensures the external_task_links table exists before inserting, providing
24
+ * graceful degradation for older project databases that predate the
25
+ * wave0-schema-hardening migration.
22
26
  */
23
27
  export declare function createLink(params: {
24
28
  taskId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"link-store.d.ts","sourceRoot":"","sources":["../../src/reconciliation/link-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAS5D;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAO7B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAYlC;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAOhG;AAMD;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE;IACN,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACvC,aAAa,CAAC,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAC;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,EACD,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,CAAC,CAgC3B;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,EACD,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM7F"}
1
+ {"version":3,"file":"link-store.d.ts","sourceRoot":"","sources":["../../src/reconciliation/link-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAY5D;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAO7B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAYlC;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAOhG;AA0DD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE;IACN,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACvC,aAAa,CAAC,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAC;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,EACD,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,CAAC,CAiC3B;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,EACD,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM7F"}
@@ -1 +1 @@
1
- {"version":3,"file":"input-sanitization.d.ts","sourceRoot":"","sources":["../../src/security/input-sanitization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAG7B,IAAI,EAAE,MAAM;IACZ,KAAK,CAAC,EAAE,MAAM;gBAFrB,OAAO,EAAE,MAAM,EACR,IAAI,GAAE,MAA+B,EACrC,KAAK,CAAC,EAAE,MAAM,YAAA;CAKxB;AAiBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAoBrD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CA2CtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAmC,GAC7C,MAAM,CAcR;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAgBxF;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,wGAShB,CAAC;AAEX,eAAO,MAAM,cAAc,8BAA+B,CAAC;AAE3D,eAAO,MAAM,uBAAuB,0DAAoB,CAAC;AAEzD,eAAO,MAAM,8BAA8B,sFAA2B,CAAC;AAEvE,eAAO,MAAM,kBAAkB,2HAAoD,CAAC;AAEpF,eAAO,MAAM,gBAAgB,gDAAkB,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAI/D,CAAC;AAEF;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,OAAO,CAA2C;gBAE9C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;IAOrD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IA8BnC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAMzB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IASrC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAQzB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAInD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI;CAGtD;AAsBD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,SAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CASjF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAkGrC"}
1
+ {"version":3,"file":"input-sanitization.d.ts","sourceRoot":"","sources":["../../src/security/input-sanitization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAG7B,IAAI,EAAE,MAAM;IACZ,KAAK,CAAC,EAAE,MAAM;gBAFrB,OAAO,EAAE,MAAM,EACR,IAAI,GAAE,MAA+B,EACrC,KAAK,CAAC,EAAE,MAAM,YAAA;CAKxB;AAiBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAoBrD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CA2CtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAmC,GAC7C,MAAM,CAcR;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAgBxF;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,wGAShB,CAAC;AAEX,eAAO,MAAM,cAAc,8BAA+B,CAAC;AAE3D,eAAO,MAAM,uBAAuB,0DAAoB,CAAC;AAEzD,eAAO,MAAM,8BAA8B,sFAA2B,CAAC;AAEvE,eAAO,MAAM,kBAAkB,2HAAoD,CAAC;AAEpF,eAAO,MAAM,gBAAgB,gDAAkB,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAI/D,CAAC;AAEF;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,OAAO,CAA2C;gBAE9C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;IAOrD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IA8BnC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAMzB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IASrC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAQzB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAInD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI;CAGtD;AAsBD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,SAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CASjF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAwGrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/sticky/list.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAoBjE;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,kBAAkB,EAC1B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,EAAE,CAAC,CAWvB"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/sticky/list.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAoBjE;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,kBAAkB,EAC1B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,EAAE,CAAC,CA2BvB"}
@@ -70,6 +70,8 @@ export interface ListStickiesParams {
70
70
  status?: StickyNoteStatus;
71
71
  color?: StickyNoteColor;
72
72
  priority?: StickyNotePriority;
73
+ /** Filter to notes containing ALL of the specified tags. */
74
+ tags?: string[];
73
75
  limit?: number;
74
76
  }
75
77
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sticky/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE7E;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE3D;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,QAAQ,GAAG,cAAc,GAAG,WAAW,CAAC;AAEnF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,qBAAqB;IACrB,MAAM,EAAE,gBAAgB,CAAC;IACzB,qCAAqC;IACrC,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,mBAAmB;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,mBAAmB,CAAC;IAChC,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sticky/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE7E;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE3D;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,QAAQ,GAAG,cAAc,GAAG,WAAW,CAAC;AAEnF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,qBAAqB;IACrB,MAAM,EAAE,gBAAgB,CAAC;IACzB,qCAAqC;IACrC,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,mBAAmB;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,mBAAmB,CAAC;IAChC,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleocode/core",
3
- "version": "2026.4.27",
3
+ "version": "2026.4.29",
4
4
  "description": "CLEO core business logic kernel — tasks, sessions, memory, orchestration, lifecycle, with bundled SQLite store",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -36,12 +36,12 @@
36
36
  "write-file-atomic": "^7.0.1",
37
37
  "yaml": "^2.8.3",
38
38
  "zod": "^4.3.6",
39
- "@cleocode/adapters": "2026.4.27",
40
- "@cleocode/agents": "2026.4.27",
41
- "@cleocode/caamp": "2026.4.27",
42
- "@cleocode/contracts": "2026.4.27",
43
- "@cleocode/lafs": "2026.4.27",
44
- "@cleocode/skills": "2026.4.27"
39
+ "@cleocode/adapters": "2026.4.29",
40
+ "@cleocode/agents": "2026.4.29",
41
+ "@cleocode/caamp": "2026.4.29",
42
+ "@cleocode/lafs": "2026.4.29",
43
+ "@cleocode/contracts": "2026.4.29",
44
+ "@cleocode/skills": "2026.4.29"
45
45
  },
46
46
  "optionalDependencies": {
47
47
  "tree-sitter-c": "^0.24.1",
package/src/adrs/sync.ts CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
16
16
  import { join } from 'node:path';
17
- import { adrTaskLinks, architectureDecisions } from '../store/tasks-schema.js';
17
+ import { adrTaskLinks, architectureDecisions, tasks } from '../store/tasks-schema.js';
18
18
  import { parseAdrFile } from './parse.js';
19
19
  import type { AdrSyncResult } from './types.js';
20
20
 
@@ -68,7 +68,7 @@ function collectAdrFiles(dir: string): Array<{ file: string; relPath: string }>
68
68
  */
69
69
  export async function syncAdrsToDb(projectRoot: string): Promise<AdrSyncResult> {
70
70
  const adrsDir = join(projectRoot, '.cleo', 'adrs');
71
- const result: AdrSyncResult = { inserted: 0, updated: 0, skipped: 0, errors: [] };
71
+ const result: AdrSyncResult = { inserted: 0, updated: 0, skipped: 0, errors: [], warnings: [] };
72
72
 
73
73
  if (!existsSync(adrsDir)) {
74
74
  return result;
@@ -93,9 +93,50 @@ export async function syncAdrsToDb(projectRoot: string): Promise<AdrSyncResult>
93
93
  const dbRelPath = `.cleo/adrs/${relPath}`;
94
94
  const content = readFileSync(filePath, 'utf-8');
95
95
 
96
- const supersedesId = fm.Supersedes ? extractAdrIdFromRef(fm.Supersedes) : null;
97
- const supersededById = fm['Superseded By'] ? extractAdrIdFromRef(fm['Superseded By']) : null;
98
- const amendsId = fm.Amends ? extractAdrIdFromRef(fm.Amends) : null;
96
+ let supersedesId = fm.Supersedes ? extractAdrIdFromRef(fm.Supersedes) : null;
97
+ let supersededById = fm['Superseded By'] ? extractAdrIdFromRef(fm['Superseded By']) : null;
98
+ let amendsId = fm.Amends ? extractAdrIdFromRef(fm.Amends) : null;
99
+
100
+ // Validate FK references exist before insert/update to avoid constraint violations
101
+ if (supersedesId) {
102
+ const exists = await db
103
+ .select({ id: architectureDecisions.id })
104
+ .from(architectureDecisions)
105
+ .where(eq(architectureDecisions.id, supersedesId))
106
+ .all();
107
+ if (exists.length === 0) {
108
+ result.warnings.push(
109
+ `${record.id}: supersedes target ${supersedesId} not found in DB, setting to null`,
110
+ );
111
+ supersedesId = null;
112
+ }
113
+ }
114
+ if (supersededById) {
115
+ const exists = await db
116
+ .select({ id: architectureDecisions.id })
117
+ .from(architectureDecisions)
118
+ .where(eq(architectureDecisions.id, supersededById))
119
+ .all();
120
+ if (exists.length === 0) {
121
+ result.warnings.push(
122
+ `${record.id}: supersededBy target ${supersededById} not found in DB, setting to null`,
123
+ );
124
+ supersededById = null;
125
+ }
126
+ }
127
+ if (amendsId) {
128
+ const exists = await db
129
+ .select({ id: architectureDecisions.id })
130
+ .from(architectureDecisions)
131
+ .where(eq(architectureDecisions.id, amendsId))
132
+ .all();
133
+ if (exists.length === 0) {
134
+ result.warnings.push(
135
+ `${record.id}: amends target ${amendsId} not found in DB, setting to null`,
136
+ );
137
+ amendsId = null;
138
+ }
139
+ }
99
140
 
100
141
  const rowBase = {
101
142
  id: record.id,
@@ -136,6 +177,18 @@ export async function syncAdrsToDb(projectRoot: string): Promise<AdrSyncResult>
136
177
  await db.delete(adrTaskLinks).where(eq(adrTaskLinks.adrId, record.id));
137
178
  if (fm['Related Tasks']) {
138
179
  for (const taskId of parseTaskIds(fm['Related Tasks'])) {
180
+ // Validate task exists before inserting link to avoid FK constraint violation
181
+ const taskExists = await db
182
+ .select({ id: tasks.id })
183
+ .from(tasks)
184
+ .where(eq(tasks.id, taskId))
185
+ .all();
186
+ if (taskExists.length === 0) {
187
+ result.warnings.push(
188
+ `${record.id}: related task ${taskId} not found in DB, skipping link`,
189
+ );
190
+ continue;
191
+ }
139
192
  await db.insert(adrTaskLinks).values({ adrId: record.id, taskId, linkType: 'related' });
140
193
  }
141
194
  }
package/src/adrs/types.ts CHANGED
@@ -37,6 +37,7 @@ export interface AdrSyncResult {
37
37
  updated: number;
38
38
  skipped: number;
39
39
  errors: Array<{ file: string; error: string }>;
40
+ warnings: string[];
40
41
  }
41
42
 
42
43
  export interface AdrListResult {
@@ -52,7 +52,6 @@ export function taskListItemNext(taskId: string): NextDirectives {
52
52
  export function sessionListItemNext(sessionId: string): NextDirectives {
53
53
  return {
54
54
  show: `cleo session show ${sessionId}`,
55
- serialize: `cleo session serialize ${sessionId}`,
56
55
  };
57
56
  }
58
57
 
@@ -169,54 +169,64 @@ async function executeTransferInternal(params: TransferParams): Promise<Transfer
169
169
  }
170
170
 
171
171
  // Step 6: Create bidirectional external_task_links
172
- // Only create links for tasks that were actually imported (verify they exist in target)
172
+ // Only create links for tasks that were actually imported (verify they exist in target).
173
+ // Wrapped in try-catch: link creation is non-critical — the transfer itself has already
174
+ // succeeded by this point. If the target DB predates the wave0-schema-hardening migration
175
+ // and table creation fails, we log a warning and continue rather than aborting the transfer.
173
176
  let linksCreated = 0;
174
- const targetAccessor = await getAccessor(targetProject.path);
175
- const { tasks: targetTasks } = await targetAccessor.queryTasks({});
176
- const targetTaskIds = new Set(targetTasks.map((t) => t.id));
177
-
178
- for (const entry of entries) {
179
- if (importResult.idRemap[entry.sourceId] && targetTaskIds.has(entry.targetId)) {
180
- // Link in target: points back to source
181
- await createLink(
182
- {
183
- taskId: entry.targetId,
184
- providerId: `nexus:${sourceProject.name}`,
185
- externalId: entry.sourceId,
186
- externalTitle: entry.title,
187
- linkType: 'transferred',
188
- syncDirection: 'inbound',
189
- metadata: {
190
- transferMode: mode,
191
- transferScope: scope,
192
- sourceProject: sourceProject.name,
193
- transferredAt: new Date().toISOString(),
177
+ try {
178
+ const targetAccessor = await getAccessor(targetProject.path);
179
+ const { tasks: targetTasks } = await targetAccessor.queryTasks({});
180
+ const targetTaskIds = new Set(targetTasks.map((t) => t.id));
181
+
182
+ for (const entry of entries) {
183
+ if (importResult.idRemap[entry.sourceId] && targetTaskIds.has(entry.targetId)) {
184
+ // Link in target: points back to source
185
+ await createLink(
186
+ {
187
+ taskId: entry.targetId,
188
+ providerId: `nexus:${sourceProject.name}`,
189
+ externalId: entry.sourceId,
190
+ externalTitle: entry.title,
191
+ linkType: 'transferred',
192
+ syncDirection: 'inbound',
193
+ metadata: {
194
+ transferMode: mode,
195
+ transferScope: scope,
196
+ sourceProject: sourceProject.name,
197
+ transferredAt: new Date().toISOString(),
198
+ },
194
199
  },
195
- },
196
- targetProject.path,
197
- );
198
- linksCreated++;
199
-
200
- // Link in source: points to target
201
- await createLink(
202
- {
203
- taskId: entry.sourceId,
204
- providerId: `nexus:${targetProject.name}`,
205
- externalId: entry.targetId,
206
- externalTitle: entry.title,
207
- linkType: 'transferred',
208
- syncDirection: 'outbound',
209
- metadata: {
210
- transferMode: mode,
211
- transferScope: scope,
212
- targetProject: targetProject.name,
213
- transferredAt: new Date().toISOString(),
200
+ targetProject.path,
201
+ );
202
+ linksCreated++;
203
+
204
+ // Link in source: points to target
205
+ await createLink(
206
+ {
207
+ taskId: entry.sourceId,
208
+ providerId: `nexus:${targetProject.name}`,
209
+ externalId: entry.targetId,
210
+ externalTitle: entry.title,
211
+ linkType: 'transferred',
212
+ syncDirection: 'outbound',
213
+ metadata: {
214
+ transferMode: mode,
215
+ transferScope: scope,
216
+ targetProject: targetProject.name,
217
+ transferredAt: new Date().toISOString(),
218
+ },
214
219
  },
215
- },
216
- sourceProject.path,
217
- );
218
- linksCreated++;
220
+ sourceProject.path,
221
+ );
222
+ linksCreated++;
223
+ }
219
224
  }
225
+ } catch (err) {
226
+ log.warn(
227
+ { err, linksCreated },
228
+ 'Failed to create external_task_links during transfer — tasks were transferred successfully but provenance links could not be written',
229
+ );
220
230
  }
221
231
  result.linksCreated = linksCreated;
222
232
 
@@ -7,10 +7,13 @@
7
7
 
8
8
  import { randomUUID } from 'node:crypto';
9
9
  import type { ExternalTaskLink } from '@cleocode/contracts';
10
- import { and, eq } from 'drizzle-orm';
10
+ import { and, eq, sql } from 'drizzle-orm';
11
+ import { getLogger } from '../logger.js';
11
12
  import { getDb } from '../store/sqlite.js';
12
13
  import { externalTaskLinks } from '../store/tasks-schema.js';
13
14
 
15
+ const log = getLogger('link-store');
16
+
14
17
  // ---------------------------------------------------------------------------
15
18
  // Read operations
16
19
  // ---------------------------------------------------------------------------
@@ -63,12 +66,68 @@ export async function getLinksByTaskId(taskId: string, cwd?: string): Promise<Ex
63
66
  return rows.map(rowToLink);
64
67
  }
65
68
 
69
+ // ---------------------------------------------------------------------------
70
+ // Table safety
71
+ // ---------------------------------------------------------------------------
72
+
73
+ /**
74
+ * Ensure the external_task_links table exists in the given database.
75
+ *
76
+ * Older project databases (created before the wave0-schema-hardening migration)
77
+ * may lack this table. Rather than aborting operations like nexus transfer,
78
+ * we create the table on demand using CREATE TABLE IF NOT EXISTS.
79
+ *
80
+ * This is idempotent — safe to call on every write operation.
81
+ */
82
+ async function ensureExternalTaskLinksTable(cwd?: string): Promise<void> {
83
+ const db = await getDb(cwd);
84
+ try {
85
+ db.run(
86
+ sql.raw(`
87
+ CREATE TABLE IF NOT EXISTS external_task_links (
88
+ id text PRIMARY KEY NOT NULL,
89
+ task_id text NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
90
+ provider_id text NOT NULL,
91
+ external_id text NOT NULL,
92
+ external_url text,
93
+ external_title text,
94
+ link_type text NOT NULL,
95
+ sync_direction text NOT NULL DEFAULT 'inbound',
96
+ metadata_json text DEFAULT '{}',
97
+ linked_at text NOT NULL DEFAULT (datetime('now')),
98
+ last_sync_at text
99
+ )
100
+ `),
101
+ );
102
+ db.run(
103
+ sql.raw(
104
+ `CREATE UNIQUE INDEX IF NOT EXISTS uq_ext_links_task_provider_external ON external_task_links(task_id, provider_id, external_id)`,
105
+ ),
106
+ );
107
+ db.run(
108
+ sql.raw(`CREATE INDEX IF NOT EXISTS idx_ext_links_task_id ON external_task_links(task_id)`),
109
+ );
110
+ db.run(
111
+ sql.raw(
112
+ `CREATE INDEX IF NOT EXISTS idx_ext_links_provider_id ON external_task_links(provider_id)`,
113
+ ),
114
+ );
115
+ } catch (err) {
116
+ log.warn({ err }, 'Failed to ensure external_task_links table exists');
117
+ throw err;
118
+ }
119
+ }
120
+
66
121
  // ---------------------------------------------------------------------------
67
122
  // Write operations
68
123
  // ---------------------------------------------------------------------------
69
124
 
70
125
  /**
71
126
  * Create a new external task link.
127
+ *
128
+ * Ensures the external_task_links table exists before inserting, providing
129
+ * graceful degradation for older project databases that predate the
130
+ * wave0-schema-hardening migration.
72
131
  */
73
132
  export async function createLink(
74
133
  params: {
@@ -83,6 +142,7 @@ export async function createLink(
83
142
  },
84
143
  cwd?: string,
85
144
  ): Promise<ExternalTaskLink> {
145
+ await ensureExternalTaskLinksTable(cwd);
86
146
  const db = await getDb(cwd);
87
147
  const now = new Date().toISOString();
88
148
  const id = randomUUID();
@@ -379,8 +379,14 @@ export function sanitizeParams(
379
379
  }
380
380
 
381
381
  if (typeof value === 'string' && (key === 'path' || key === 'file') && projectRoot) {
382
- sanitized[key] = sanitizePath(value, projectRoot);
383
- continue;
382
+ // Skip path sanitization for operations that intentionally accept external paths
383
+ const allowExternalPath =
384
+ context?.domain === 'nexus' &&
385
+ (context?.operation === 'register' || context?.operation === 'reconcile');
386
+ if (!allowExternalPath) {
387
+ sanitized[key] = sanitizePath(value, projectRoot);
388
+ continue;
389
+ }
384
390
  }
385
391
 
386
392
  if (
@@ -42,12 +42,28 @@ export async function listStickies(
42
42
  ): Promise<StickyNote[]> {
43
43
  const accessor = await getBrainAccessor(projectRoot);
44
44
 
45
+ // Tags are stored as JSON in a text column, so we filter in-memory after
46
+ // the SQL query. Request extra rows (no limit) when tag filtering is active
47
+ // so we don't inadvertently clip the result set before filtering.
48
+ const hasTagFilter = params.tags && params.tags.length > 0;
49
+
45
50
  const rows = await accessor.findStickyNotes({
46
51
  status: params.status,
47
52
  color: params.color,
48
53
  priority: params.priority,
49
- limit: params.limit,
54
+ limit: hasTagFilter ? undefined : params.limit,
50
55
  });
51
56
 
52
- return rows.map(rowToStickyNote);
57
+ let notes = rows.map(rowToStickyNote);
58
+
59
+ // In-memory tag filter: keep notes that contain ALL requested tags.
60
+ if (hasTagFilter) {
61
+ const requiredTags = params.tags!;
62
+ notes = notes.filter((note) => requiredTags.every((t) => note.tags.includes(t)));
63
+ if (params.limit && notes.length > params.limit) {
64
+ notes = notes.slice(0, params.limit);
65
+ }
66
+ }
67
+
68
+ return notes;
53
69
  }
@@ -78,6 +78,8 @@ export interface ListStickiesParams {
78
78
  status?: StickyNoteStatus;
79
79
  color?: StickyNoteColor;
80
80
  priority?: StickyNotePriority;
81
+ /** Filter to notes containing ALL of the specified tags. */
82
+ tags?: string[];
81
83
  limit?: number;
82
84
  }
83
85