@zibby/skills 0.1.70 β 0.1.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +5 -1
- package/dist/review.d.ts +2 -0
- package/dist/review.js +4 -0
- package/dist/reviewMemoryIo.d.ts +43 -0
- package/dist/reviewMemoryIo.js +1 -0
- package/dist/reviewRecord.d.ts +120 -0
- package/dist/reviewRecord.js +4 -0
- package/package.json +5 -1
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/skills",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.71",
|
|
4
4
|
"description": "Built-in skill definitions for the Zibby agent-workflow framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -69,6 +69,10 @@
|
|
|
69
69
|
"./sentry": {
|
|
70
70
|
"types": "./dist/sentry.d.ts",
|
|
71
71
|
"default": "./dist/sentry.js"
|
|
72
|
+
},
|
|
73
|
+
"./review": {
|
|
74
|
+
"types": "./dist/review.d.ts",
|
|
75
|
+
"default": "./dist/review.js"
|
|
72
76
|
}
|
|
73
77
|
},
|
|
74
78
|
"scripts": {
|
package/dist/review.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { REVIEW_RECORD_SCHEMA_VERSION, REVIEW_RECORD_KIND, CONTENT_MAX_BYTES, FIELD_MAX_CHARS, SEVERITY_TIERS, FINDING_STATUSES, normalizeSeverity, buildReviewRecord, upsertReplyOutcome, serializeReviewRecord, parseReviewMemory, summarizeForPrompt } from "./reviewRecord.js";
|
|
2
|
+
export { scopeForReviewMemory, storeReviewRecord, recallReviewRecord } from "./reviewMemoryIo.js";
|
package/dist/review.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
var A=1,l="review-record",O=204800,T=2e3,I=["blocker","should-fix","nit"],_={blocker:0,"should-fix":1,nit:2},g=["open","conceded","held","resolved"];function v(e){let r=String(e??"").trim().toLowerCase();return r?r.includes("\u{1F534}")||r.includes("blocker")||r.includes("critical")||r.includes("high")?"blocker":r.includes("\u{1F7E2}")||r.includes("nit")||r.includes("minor")||r.includes("low")||r.includes("info")?"nit":(r.includes("\u{1F7E1}")||r.includes("should")||r.includes("medium")||r.includes("warn"),"should-fix"):"should-fix"}var c=(e,r)=>{let n=e==null?"":String(e);return n.length>r?n.slice(0,r):n},E=e=>typeof Buffer<"u"&&typeof Buffer.byteLength=="function"?Buffer.byteLength(e,"utf8"):new TextEncoder().encode(e).length;function k({headSha:e=null,verdict:r="COMMENT",objectivesChecked:n=!1,findings:i=[],nowIso:t=null}={}){let s=Array.isArray(i)?i:[];return{schemaVersion:1,kind:l,headSha:e||null,verdict:String(r||"COMMENT"),objectivesChecked:!!n,reviewedAt:t||null,findings:s.map((o,u)=>({id:`f${u+1}`,file:c(o?.file,512),line:o?.line==null?null:o.line,severity:v(o?.severity),category:c(o?.category,64),claim:c(o?.claim,2e3),evidence:c(o?.evidence,2e3),suggestion:c(o?.suggestion,2e3),confidence:typeof o?.confidence=="number"?o.confidence:null,status:"open"}))}}function C(e,{findingId:r,status:n,note:i}={}){if(!e||!Array.isArray(e.findings))return e;let t=g.includes(n)?n:"held";return{...e,findings:e.findings.map(s=>s.id===r?{...s,status:t,replyNote:c(i,2e3)}:s)}}function a(e){if(!e)return"";let r=[...e.findings||[]].sort((s,o)=>{let u=(_[s.severity]??9)-(_[o.severity]??9);if(u!==0)return u;let y=s.file||"",p=o.file||"";if(y!==p)return y<p?-1:1;let m=Number(s.line)||0,R=Number(o.line)||0;return m!==R?m-R:(s.id||"")<(o.id||"")?-1:1}),n={...e,findings:r},i=JSON.stringify(n);if(E(i)<=204800)return i;let t=[...r];for(n={...e,findings:t,truncated:!0};t.length>0&&E(JSON.stringify(n))>204800;)t.pop(),n={...e,findings:t,truncated:!0};return JSON.stringify(n)}var S=e=>e&&typeof e=="object"&&!Array.isArray(e)&&e.kind===l;function d(e){if(e==null)return{kind:"empty"};if(typeof e=="object"){if(!Array.isArray(e)&&typeof e.error=="string")return{kind:"empty"};if(S(e)){let i=Number(e.schemaVersion)>1;return{kind:"record",record:e,future:i}}return{kind:"legacy",legacyNote:h(e)}}if(typeof e!="string")return{kind:"empty"};let r=e.trim();if(!r)return{kind:"empty"};let n;try{n=JSON.parse(r)}catch{return{kind:"legacy",legacyNote:r}}if(n&&typeof n=="object"&&typeof n.error=="string")return{kind:"empty"};if(S(n)){let i=Number(n.schemaVersion)>1;return{kind:"record",record:n,future:i}}return{kind:"legacy",legacyNote:r}}function h(e){try{return JSON.stringify(e)}catch{return String(e)}}function w(e){if(!e||e.kind==="empty")return"";if(e.kind==="legacy")return`Prior review memory (legacy note, advisory only):
|
|
2
|
+
${e.legacyNote}`;let r=e.record||{};if(e.future)return`Prior review memory (newer format ${r.schemaVersion} \u2014 advisory; verify against the live thread):
|
|
3
|
+
${h(r).slice(0,2e3)}`;let n=[`Prior review of this change (verdict: ${r.verdict||"COMMENT"}${r.headSha?`, commit ${r.headSha}`:""}):`],i=(r.findings||[]).map(t=>{let s=t.file?`${t.file}${t.line!=null?`:${t.line}`:""}`:"(general)",o=t.status&&t.status!=="open"?` [${t.status}]`:"";return`- [${t.severity}] ${s} \u2014 ${t.claim||""}${o}`});return r.truncated&&i.push("- (\u2026older/lower-severity findings were truncated to fit memory)"),[...n,...i].join(`
|
|
4
|
+
`)}import{existsSync as M,readFileSync as x}from"node:fs";import{homedir as $}from"node:os";import{join as b}from"node:path";function B(){if(process.env.PROJECT_API_TOKEN)return process.env.PROJECT_API_TOKEN;if(process.env.ZIBBY_USER_TOKEN)return process.env.ZIBBY_USER_TOKEN;try{let e=b($(),".zibby","config.json");return M(e)&&JSON.parse(x(e,"utf-8")).sessionToken||null}catch{return null}}function V(){return process.env.ZIBBY_ACCOUNT_API_URL?process.env.ZIBBY_ACCOUNT_API_URL.replace(/\/$/,""):(process.env.ZIBBY_ENV||"prod")==="local"?"http://localhost:3001":process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://api-prod.zibby.app"}function D(){return(typeof process.env.WORKFLOW_TYPE=="string"?process.env.WORKFLOW_TYPE.trim():"")||"agent"}function f(e){return`${D()}:${e}`}async function N(e,r){let n=B();if(!n)return{__noToken:!0};let i=`${V()}/credits/review-memory`,t=await fetch(i,{method:"POST",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"},body:JSON.stringify({op:e,...r})});if(!t.ok){let s=await t.text().catch(()=>"");throw new Error(`review-memory ${e} failed (${t.status}): ${s.slice(0,300)}`)}return t.json()}async function F(e,r){try{let n=a(r);if(!n)return{ok:!1,reason:"empty-record"};let i=await N("store",{scope:f(e),content:n});return i&&i.__noToken?{ok:!1,reason:"no-token"}:{ok:!0}}catch(n){return{ok:!1,reason:n?.message||"store-error"}}}async function L(e){try{let r=await N("recall",{scope:f(e)});if(!r||r.__noToken)return{kind:"empty"};let n=r.found&&r.memory?r.memory:null;if(!n)return{kind:"empty"};let i=n.content!=null?n.content:n.metadata!=null?n.metadata:null;return d(i)}catch{return{kind:"empty"}}}export{O as CONTENT_MAX_BYTES,T as FIELD_MAX_CHARS,g as FINDING_STATUSES,l as REVIEW_RECORD_KIND,A as REVIEW_RECORD_SCHEMA_VERSION,I as SEVERITY_TIERS,k as buildReviewRecord,v as normalizeSeverity,d as parseReviewMemory,L as recallReviewRecord,f as scopeForReviewMemory,a as serializeReviewRecord,F as storeReviewRecord,w as summarizeForPrompt,C as upsertReplyOutcome};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** Effective backend scope for a plain per-PR/MR key. IDENTICAL to kvMemory scopeFor. */
|
|
2
|
+
export function scopeForReviewMemory(key: any): string;
|
|
3
|
+
/**
|
|
4
|
+
* Store a review record under a plain per-PR/MR key. Serializes via
|
|
5
|
+
* serializeReviewRecord (deterministic, byte-capped 200KB) and POSTs
|
|
6
|
+
* { op:'store', scope, content }.
|
|
7
|
+
*
|
|
8
|
+
* BEST-EFFORT: never throws. { ok:true } on success; { ok:false, reason:'no-token' }
|
|
9
|
+
* with no backend credential (local dev / self-host); { ok:false, reason } otherwise.
|
|
10
|
+
* The caller must treat a false result as a no-op β memory NEVER blocks a run.
|
|
11
|
+
*/
|
|
12
|
+
export function storeReviewRecord(key: any, record: any): Promise<{
|
|
13
|
+
ok: boolean;
|
|
14
|
+
reason?: undefined;
|
|
15
|
+
} | {
|
|
16
|
+
ok: boolean;
|
|
17
|
+
reason: any;
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Recall the review record stored under a plain per-PR/MR key. POSTs
|
|
21
|
+
* { op:'recall', scope } and hands the returned `content` to the tolerant
|
|
22
|
+
* parseReviewMemory (which never throws over any input).
|
|
23
|
+
*
|
|
24
|
+
* BEST-EFFORT: never throws. Returns parseReviewMemory's result
|
|
25
|
+
* ({ kind:'empty' | 'record' | 'legacy', ... }); { kind:'empty' } on missing
|
|
26
|
+
* token or ANY failure, so the caller degrades to "no prior memory".
|
|
27
|
+
*/
|
|
28
|
+
export function recallReviewRecord(key: any): Promise<{
|
|
29
|
+
kind: string;
|
|
30
|
+
record?: undefined;
|
|
31
|
+
future?: undefined;
|
|
32
|
+
legacyNote?: undefined;
|
|
33
|
+
} | {
|
|
34
|
+
kind: string;
|
|
35
|
+
record: any;
|
|
36
|
+
future: boolean;
|
|
37
|
+
legacyNote?: undefined;
|
|
38
|
+
} | {
|
|
39
|
+
kind: string;
|
|
40
|
+
legacyNote: string;
|
|
41
|
+
record?: undefined;
|
|
42
|
+
future?: undefined;
|
|
43
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{existsSync as S,readFileSync as v}from"node:fs";import{homedir as N}from"node:os";import{join as A}from"node:path";var R="review-record";var d={blocker:0,"should-fix":1,nit:2};var y=e=>typeof Buffer<"u"&&typeof Buffer.byteLength=="function"?Buffer.byteLength(e,"utf8"):new TextEncoder().encode(e).length;function m(e){if(!e)return"";let t=[...e.findings||[]].sort((o,s)=>{let c=(d[o.severity]??9)-(d[s.severity]??9);if(c!==0)return c;let u=o.file||"",l=s.file||"";if(u!==l)return u<l?-1:1;let a=Number(o.line)||0,f=Number(s.line)||0;return a!==f?a-f:(o.id||"")<(s.id||"")?-1:1}),n={...e,findings:t},r=JSON.stringify(n);if(y(r)<=204800)return r;let i=[...t];for(n={...e,findings:i,truncated:!0};i.length>0&&y(JSON.stringify(n))>204800;)i.pop(),n={...e,findings:i,truncated:!0};return JSON.stringify(n)}var p=e=>e&&typeof e=="object"&&!Array.isArray(e)&&e.kind===R;function _(e){if(e==null)return{kind:"empty"};if(typeof e=="object"){if(!Array.isArray(e)&&typeof e.error=="string")return{kind:"empty"};if(p(e)){let r=Number(e.schemaVersion)>1;return{kind:"record",record:e,future:r}}return{kind:"legacy",legacyNote:h(e)}}if(typeof e!="string")return{kind:"empty"};let t=e.trim();if(!t)return{kind:"empty"};let n;try{n=JSON.parse(t)}catch{return{kind:"legacy",legacyNote:t}}if(n&&typeof n=="object"&&typeof n.error=="string")return{kind:"empty"};if(p(n)){let r=Number(n.schemaVersion)>1;return{kind:"record",record:n,future:r}}return{kind:"legacy",legacyNote:t}}function h(e){try{return JSON.stringify(e)}catch{return String(e)}}function O(){if(process.env.PROJECT_API_TOKEN)return process.env.PROJECT_API_TOKEN;if(process.env.ZIBBY_USER_TOKEN)return process.env.ZIBBY_USER_TOKEN;try{let e=A(N(),".zibby","config.json");return S(e)&&JSON.parse(v(e,"utf-8")).sessionToken||null}catch{return null}}function k(){return process.env.ZIBBY_ACCOUNT_API_URL?process.env.ZIBBY_ACCOUNT_API_URL.replace(/\/$/,""):(process.env.ZIBBY_ENV||"prod")==="local"?"http://localhost:3001":process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://api-prod.zibby.app"}function T(){return(typeof process.env.WORKFLOW_TYPE=="string"?process.env.WORKFLOW_TYPE.trim():"")||"agent"}function E(e){return`${T()}:${e}`}async function g(e,t){let n=O();if(!n)return{__noToken:!0};let r=`${k()}/credits/review-memory`,i=await fetch(r,{method:"POST",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"},body:JSON.stringify({op:e,...t})});if(!i.ok){let o=await i.text().catch(()=>"");throw new Error(`review-memory ${e} failed (${i.status}): ${o.slice(0,300)}`)}return i.json()}async function $(e,t){try{let n=m(t);if(!n)return{ok:!1,reason:"empty-record"};let r=await g("store",{scope:E(e),content:n});return r&&r.__noToken?{ok:!1,reason:"no-token"}:{ok:!0}}catch(n){return{ok:!1,reason:n?.message||"store-error"}}}async function b(e){try{let t=await g("recall",{scope:E(e)});if(!t||t.__noToken)return{kind:"empty"};let n=t.found&&t.memory?t.memory:null;if(!n)return{kind:"empty"};let r=n.content!=null?n.content:n.metadata!=null?n.metadata:null;return _(r)}catch{return{kind:"empty"}}}export{b as recallReviewRecord,E as scopeForReviewMemory,$ as storeReviewRecord};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize the review's free-form / emoji severity into a stable tier.
|
|
3
|
+
* The real review schema defaults severity to 'π‘'; reviews also emit π΄/π’ and
|
|
4
|
+
* words. Anything unrecognized falls back to 'should-fix' (never throws).
|
|
5
|
+
*/
|
|
6
|
+
export function normalizeSeverity(raw: any): "should-fix" | "blocker" | "nit";
|
|
7
|
+
/**
|
|
8
|
+
* Build a fresh review record from the review node's (post-verification)
|
|
9
|
+
* findings. `findings` is the REAL review shape:
|
|
10
|
+
* { file, line?, severity, category, claim, evidence, suggestion?, confidence? }
|
|
11
|
+
* Assigns stable ids (f1..fN), normalizes severity, caps long text, status:'open'.
|
|
12
|
+
* `nowIso` is injected (callers pass new Date().toISOString()) so this stays pure.
|
|
13
|
+
*/
|
|
14
|
+
export function buildReviewRecord({ headSha, verdict, objectivesChecked, findings, nowIso, }?: {
|
|
15
|
+
headSha?: any;
|
|
16
|
+
verdict?: string;
|
|
17
|
+
objectivesChecked?: boolean;
|
|
18
|
+
findings?: any[];
|
|
19
|
+
nowIso?: any;
|
|
20
|
+
}): {
|
|
21
|
+
schemaVersion: number;
|
|
22
|
+
kind: string;
|
|
23
|
+
headSha: any;
|
|
24
|
+
verdict: string;
|
|
25
|
+
objectivesChecked: boolean;
|
|
26
|
+
reviewedAt: any;
|
|
27
|
+
findings: {
|
|
28
|
+
id: string;
|
|
29
|
+
file: string;
|
|
30
|
+
line: any;
|
|
31
|
+
severity: string;
|
|
32
|
+
category: string;
|
|
33
|
+
claim: string;
|
|
34
|
+
evidence: string;
|
|
35
|
+
suggestion: string;
|
|
36
|
+
confidence: any;
|
|
37
|
+
status: string;
|
|
38
|
+
}[];
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Record the OUTCOME of a comment_reply against a finding. IDEMPOTENT: it SETS
|
|
42
|
+
* findings[id].status (and an optional one-line note) β running the same reply
|
|
43
|
+
* twice (webhook redelivery) yields the identical record, no double-append.
|
|
44
|
+
* Returns a NEW record (does not mutate the input). If findingId is unknown, the
|
|
45
|
+
* record is returned unchanged (best-effort, never throws).
|
|
46
|
+
*/
|
|
47
|
+
export function upsertReplyOutcome(record: any, { findingId, status, note }?: {}): any;
|
|
48
|
+
/**
|
|
49
|
+
* Serialize a record to a string that FITS CONTENT_MAX_BYTES. Deterministic:
|
|
50
|
+
* findings are stably sorted by (severityRank, file, line, id); if still over
|
|
51
|
+
* budget, the LOWEST-priority findings are dropped until it fits and
|
|
52
|
+
* `truncated:true` is set. Text fields are already capped by buildReviewRecord.
|
|
53
|
+
*/
|
|
54
|
+
export function serializeReviewRecord(record: any): string;
|
|
55
|
+
/**
|
|
56
|
+
* Tolerant reader β NEVER throws. Accepts whatever kv_recall returns for the
|
|
57
|
+
* value (a JSON string, an already-parsed metadata object, a legacy prose
|
|
58
|
+
* string, an {error} envelope, null/'').
|
|
59
|
+
* Returns one of:
|
|
60
|
+
* { kind:'empty' } β nothing usable
|
|
61
|
+
* { kind:'record', record, future?:bool } β a structured record (future=newer schemaVersion)
|
|
62
|
+
* { kind:'legacy', legacyNote:string } β an old freeform note; advisory only
|
|
63
|
+
*/
|
|
64
|
+
export function parseReviewMemory(raw: any): {
|
|
65
|
+
kind: string;
|
|
66
|
+
record?: undefined;
|
|
67
|
+
future?: undefined;
|
|
68
|
+
legacyNote?: undefined;
|
|
69
|
+
} | {
|
|
70
|
+
kind: string;
|
|
71
|
+
record: any;
|
|
72
|
+
future: boolean;
|
|
73
|
+
legacyNote?: undefined;
|
|
74
|
+
} | {
|
|
75
|
+
kind: string;
|
|
76
|
+
legacyNote: string;
|
|
77
|
+
record?: undefined;
|
|
78
|
+
future?: undefined;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Render a parsed memory into prompt text for the review/reply LLM. Compact,
|
|
82
|
+
* human-readable, and it NEVER assumes a shape it didn't verify (a future
|
|
83
|
+
* schemaVersion is surfaced as advisory). Empty β '' (caller omits the block).
|
|
84
|
+
*/
|
|
85
|
+
export function summarizeForPrompt(parsed: any): string;
|
|
86
|
+
/**
|
|
87
|
+
* reviewRecord β a GENERIC, provider-agnostic structured record for the
|
|
88
|
+
* code-review β comment_reply memory (shared by gitlab-code-review and
|
|
89
|
+
* github-code-review). Replaces the freeform prose kv note with a versioned,
|
|
90
|
+
* queryable record.
|
|
91
|
+
*
|
|
92
|
+
* DELIBERATELY TRANSPORT-AGNOSTIC. This module does NO I/O: it only builds,
|
|
93
|
+
* serializes, parses and renders the record. WHO stores/recalls it (the JS node
|
|
94
|
+
* vs the LLM via kv_store/kv_recall) is a separate wiring decision β these pure
|
|
95
|
+
* functions are correct either way. The per-PR/MR KEY stays provider-specific
|
|
96
|
+
* (reviewMemoryScopeFor in each review-node.js); the record BODY here carries
|
|
97
|
+
* zero provider fields (identity lives in the key, not the body).
|
|
98
|
+
*
|
|
99
|
+
* Contract facts this module mirrors (source of truth = backend
|
|
100
|
+
* src/handlers/review-memory.js + packages/skills/src/kvMemory.js):
|
|
101
|
+
* - kv `content` is a STRING, hard-capped at 200KB (CONTENT_MAX). We serialize
|
|
102
|
+
* to a string and truncate deterministically to fit β an over-cap store is
|
|
103
|
+
* rejected (HTTP 400) and SILENTLY lost, so truncation must happen here,
|
|
104
|
+
* before the write.
|
|
105
|
+
* - kv also has an optional `metadata` OBJECT channel; parseReviewMemory
|
|
106
|
+
* therefore accepts an already-parsed object too, so the record can ride in
|
|
107
|
+
* either channel without changing this code.
|
|
108
|
+
*
|
|
109
|
+
* Reviewed by two adversarial design agents (2026-07-04): schema aligned to the
|
|
110
|
+
* REAL finding shape ({file,line,severity,category,claim,evidence,suggestion,
|
|
111
|
+
* confidence}); replies modeled as an IDEMPOTENT findingIdβstatus set (NOT an
|
|
112
|
+
* append log, which double-appends on webhook redelivery); headSha carried but
|
|
113
|
+
* treated as advisory (its plumbing is deferred β today it is undefined).
|
|
114
|
+
*/
|
|
115
|
+
export const REVIEW_RECORD_SCHEMA_VERSION: 1;
|
|
116
|
+
export const REVIEW_RECORD_KIND: "review-record";
|
|
117
|
+
export const CONTENT_MAX_BYTES: number;
|
|
118
|
+
export const FIELD_MAX_CHARS: 2000;
|
|
119
|
+
export const SEVERITY_TIERS: string[];
|
|
120
|
+
export const FINDING_STATUSES: string[];
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
var h=1,m="review-record",_=204800,N=2e3,A=["blocker","should-fix","nit"],a={blocker:0,"should-fix":1,nit:2},S=["open","conceded","held","resolved"];function R(e){let n=String(e??"").trim().toLowerCase();return n?n.includes("\u{1F534}")||n.includes("blocker")||n.includes("critical")||n.includes("high")?"blocker":n.includes("\u{1F7E2}")||n.includes("nit")||n.includes("minor")||n.includes("low")||n.includes("info")?"nit":(n.includes("\u{1F7E1}")||n.includes("should")||n.includes("medium")||n.includes("warn"),"should-fix"):"should-fix"}var u=(e,n)=>{let t=e==null?"":String(e);return t.length>n?t.slice(0,n):t},g=e=>typeof Buffer<"u"&&typeof Buffer.byteLength=="function"?Buffer.byteLength(e,"utf8"):new TextEncoder().encode(e).length;function v({headSha:e=null,verdict:n="COMMENT",objectivesChecked:t=!1,findings:o=[],nowIso:i=null}={}){let s=Array.isArray(o)?o:[];return{schemaVersion:1,kind:m,headSha:e||null,verdict:String(n||"COMMENT"),objectivesChecked:!!t,reviewedAt:i||null,findings:s.map((r,c)=>({id:`f${c+1}`,file:u(r?.file,512),line:r?.line==null?null:r.line,severity:R(r?.severity),category:u(r?.category,64),claim:u(r?.claim,2e3),evidence:u(r?.evidence,2e3),suggestion:u(r?.suggestion,2e3),confidence:typeof r?.confidence=="number"?r.confidence:null,status:"open"}))}}function k(e,{findingId:n,status:t,note:o}={}){if(!e||!Array.isArray(e.findings))return e;let i=S.includes(t)?t:"held";return{...e,findings:e.findings.map(s=>s.id===n?{...s,status:i,replyNote:u(o,2e3)}:s)}}function C(e){if(!e)return"";let n=[...e.findings||[]].sort((s,r)=>{let c=(a[s.severity]??9)-(a[r.severity]??9);if(c!==0)return c;let l=s.file||"",d=r.file||"";if(l!==d)return l<d?-1:1;let f=Number(s.line)||0,y=Number(r.line)||0;return f!==y?f-y:(s.id||"")<(r.id||"")?-1:1}),t={...e,findings:n},o=JSON.stringify(t);if(g(o)<=204800)return o;let i=[...n];for(t={...e,findings:i,truncated:!0};i.length>0&&g(JSON.stringify(t))>204800;)i.pop(),t={...e,findings:i,truncated:!0};return JSON.stringify(t)}var E=e=>e&&typeof e=="object"&&!Array.isArray(e)&&e.kind===m;function I(e){if(e==null)return{kind:"empty"};if(typeof e=="object"){if(!Array.isArray(e)&&typeof e.error=="string")return{kind:"empty"};if(E(e)){let o=Number(e.schemaVersion)>1;return{kind:"record",record:e,future:o}}return{kind:"legacy",legacyNote:p(e)}}if(typeof e!="string")return{kind:"empty"};let n=e.trim();if(!n)return{kind:"empty"};let t;try{t=JSON.parse(n)}catch{return{kind:"legacy",legacyNote:n}}if(t&&typeof t=="object"&&typeof t.error=="string")return{kind:"empty"};if(E(t)){let o=Number(t.schemaVersion)>1;return{kind:"record",record:t,future:o}}return{kind:"legacy",legacyNote:n}}function p(e){try{return JSON.stringify(e)}catch{return String(e)}}function O(e){if(!e||e.kind==="empty")return"";if(e.kind==="legacy")return`Prior review memory (legacy note, advisory only):
|
|
2
|
+
${e.legacyNote}`;let n=e.record||{};if(e.future)return`Prior review memory (newer format ${n.schemaVersion} \u2014 advisory; verify against the live thread):
|
|
3
|
+
${p(n).slice(0,2e3)}`;let t=[`Prior review of this change (verdict: ${n.verdict||"COMMENT"}${n.headSha?`, commit ${n.headSha}`:""}):`],o=(n.findings||[]).map(i=>{let s=i.file?`${i.file}${i.line!=null?`:${i.line}`:""}`:"(general)",r=i.status&&i.status!=="open"?` [${i.status}]`:"";return`- [${i.severity}] ${s} \u2014 ${i.claim||""}${r}`});return n.truncated&&o.push("- (\u2026older/lower-severity findings were truncated to fit memory)"),[...t,...o].join(`
|
|
4
|
+
`)}export{_ as CONTENT_MAX_BYTES,N as FIELD_MAX_CHARS,S as FINDING_STATUSES,m as REVIEW_RECORD_KIND,h as REVIEW_RECORD_SCHEMA_VERSION,A as SEVERITY_TIERS,v as buildReviewRecord,R as normalizeSeverity,I as parseReviewMemory,C as serializeReviewRecord,O as summarizeForPrompt,k as upsertReplyOutcome};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/skills",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.71",
|
|
4
4
|
"description": "Built-in skill definitions for the Zibby agent-workflow framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -69,6 +69,10 @@
|
|
|
69
69
|
"./sentry": {
|
|
70
70
|
"types": "./dist/sentry.d.ts",
|
|
71
71
|
"default": "./dist/sentry.js"
|
|
72
|
+
},
|
|
73
|
+
"./review": {
|
|
74
|
+
"types": "./dist/review.d.ts",
|
|
75
|
+
"default": "./dist/review.js"
|
|
72
76
|
}
|
|
73
77
|
},
|
|
74
78
|
"scripts": {
|