@codified/cli 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +3 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -256,7 +256,7 @@ ${c}`}).join(`
256
256
 
257
257
  ${r}
258
258
 
259
- Respond with JSON only. No markdown, no explanation.`,n=await this.anthropic.messages.create({model:"claude-sonnet-4-6-20250610",max_tokens:16384,system:C$,messages:[{role:"user",content:i}]});if(n.stop_reason==="max_tokens"){console.warn("[git-miner] Response truncated (hit max_tokens). Retrying with higher limit...");let s=await this.anthropic.messages.create({model:"claude-sonnet-4-6-20250610",max_tokens:65536,system:C$,messages:[{role:"user",content:i}]}),a=s.content.find(c=>c.type==="text");if(a&&a.type==="text")return s.stop_reason==="max_tokens"&&console.warn("[git-miner] Response still truncated after retry. Processing partial results."),this.parseResponse(a.text,e)}let o=n.content.find(s=>s.type==="text");return!o||o.type!=="text"?(console.error("[git-miner] No text response from Claude"),{nodes:[],edges:[]}):this.parseResponse(o.text,e)}parseResponse(e,r){let i=e.replace(/^```json?\n?/,"").replace(/\n?```$/,"").trim(),n;try{n=JSON.parse(i)}catch(u){return console.error("[git-miner] Failed to parse Claude response:",u),console.error("[git-miner] Raw response:",e.slice(0,500)),{nodes:[],edges:[]}}let o=r[0]?.connectorId??"unknown",s=u=>({...O3,reference:`${o}:${u}`}),a=(n.nodes??[]).map(u=>{let l=u;return{type:l.type??"CodeArtifact",sourceRef:l.sourceRef??"",properties:l.properties??{},confidence:Math.max(0,Math.min(1,l.confidence??.5)),tags:Array.isArray(l.tags)?l.tags:[],source:s(l.sourceRef??"")}}),c=(n.edges??[]).map(u=>{let l=u;return{type:l.type??"relates_to",fromRef:l.fromRef??"",toRef:l.toRef??"",confidence:Math.max(0,Math.min(1,l.confidence??.5)),evidence:l.evidence??null,source:s(`${l.fromRef}\u2192${l.toRef}`)}});return console.log(`[git-miner] Extracted ${a.length} nodes and ${c.length} edges from ${r.length} artifact(s)`),{nodes:a,edges:c}}}});var Fs,Xy=m(()=>{"use strict";Ne();Ne();Ne();Ne();Fs=class{constructor(e){this.config=e}async process(e){let r={created:[],merged:[],conflicted:[],rejected:[]},i=new Map;for(let n of e.nodes)try{let o=await this.processNode(n);switch(o.action){case"created":r.created.push(o.nodeId),i.set(n.sourceRef,o.nodeId);break;case"merged":r.merged.push(o.nodeId),i.set(n.sourceRef,o.nodeId);break;case"conflicted":r.conflicted.push(o.nodeId),i.set(n.sourceRef,o.nodeId);break}}catch(o){console.error(`[pipeline] Failed to process node ${n.sourceRef}:`,o),r.rejected.push(n.sourceRef)}for(let n of e.edges)try{await this.processEdge(n,i)}catch(o){console.error(`[pipeline] Failed to process edge ${n.fromRef}\u2192${n.toRef}:`,o)}for(let n of r.created)try{await this.maybePromote(n)}catch(o){console.error(`[pipeline] Failed to auto-promote ${n}:`,o)}return console.log(`[pipeline] Processed: ${r.created.length} created, ${r.merged.length} merged, ${r.conflicted.length} conflicted, ${r.rejected.length} rejected`),r}async processNode(e){if(this.config.enableDedup){let i=await this.findBySourceRef(e.sourceRef);if(i)return await lr(i,{properties:e.properties,tags:e.tags,confidence:e.confidence}),{action:"merged",nodeId:i}}if(!this.isValidNodeType(e.type))throw new Error(`Invalid node type: ${e.type}`);return{action:"created",nodeId:(await qr({type:e.type,layer:"draft",confidence:e.confidence,source:e.source,properties:{...e.properties,_sourceRef:e.sourceRef},tags:e.tags})).id}}async processEdge(e,r){let i=r.get(e.fromRef)??await this.resolveRef(e.fromRef),n=r.get(e.toRef)??await this.resolveRef(e.toRef);if(!i||!n){console.warn(`[pipeline] Skipping edge ${e.fromRef}\u2192${e.toRef}: unresolved refs`);return}(await wr({type:e.type,sourceId:i,targetId:n,limit:1})).length>0||await Ir({type:e.type,sourceId:i,targetId:n,confidence:e.confidence,evidence:e.evidence??void 0,source:e.source})}async maybePromote(e){let r=await Ze(e,{layers:["draft"]});r&&r.confidence>=this.config.autoPromoteThreshold&&(await ho(e,"permanent"),console.log(`[pipeline] Auto-promoted node ${e} (confidence: ${r.confidence.toFixed(2)})`))}async findBySourceRef(e){let r=await ae(`SELECT id FROM nodes
259
+ Respond with JSON only. No markdown, no explanation.`,n=await this.anthropic.messages.create({model:"claude-sonnet-4-6",max_tokens:16384,system:C$,messages:[{role:"user",content:i}]});if(n.stop_reason==="max_tokens"){console.warn("[git-miner] Response truncated (hit max_tokens). Retrying with higher limit...");let s=await this.anthropic.messages.create({model:"claude-sonnet-4-6",max_tokens:65536,system:C$,messages:[{role:"user",content:i}]}),a=s.content.find(c=>c.type==="text");if(a&&a.type==="text")return s.stop_reason==="max_tokens"&&console.warn("[git-miner] Response still truncated after retry. Processing partial results."),this.parseResponse(a.text,e)}let o=n.content.find(s=>s.type==="text");return!o||o.type!=="text"?(console.error("[git-miner] No text response from Claude"),{nodes:[],edges:[]}):this.parseResponse(o.text,e)}parseResponse(e,r){let i=e.replace(/^```json?\n?/,"").replace(/\n?```$/,"").trim(),n;try{n=JSON.parse(i)}catch(u){return console.error("[git-miner] Failed to parse Claude response:",u),console.error("[git-miner] Raw response:",e.slice(0,500)),{nodes:[],edges:[]}}let o=r[0]?.connectorId??"unknown",s=u=>({...O3,reference:`${o}:${u}`}),a=(n.nodes??[]).map(u=>{let l=u;return{type:l.type??"CodeArtifact",sourceRef:l.sourceRef??"",properties:l.properties??{},confidence:Math.max(0,Math.min(1,l.confidence??.5)),tags:Array.isArray(l.tags)?l.tags:[],source:s(l.sourceRef??"")}}),c=(n.edges??[]).map(u=>{let l=u;return{type:l.type??"relates_to",fromRef:l.fromRef??"",toRef:l.toRef??"",confidence:Math.max(0,Math.min(1,l.confidence??.5)),evidence:l.evidence??null,source:s(`${l.fromRef}\u2192${l.toRef}`)}});return console.log(`[git-miner] Extracted ${a.length} nodes and ${c.length} edges from ${r.length} artifact(s)`),{nodes:a,edges:c}}}});var Fs,Xy=m(()=>{"use strict";Ne();Ne();Ne();Ne();Fs=class{constructor(e){this.config=e}async process(e){let r={created:[],merged:[],conflicted:[],rejected:[]},i=new Map;for(let n of e.nodes)try{let o=await this.processNode(n);switch(o.action){case"created":r.created.push(o.nodeId),i.set(n.sourceRef,o.nodeId);break;case"merged":r.merged.push(o.nodeId),i.set(n.sourceRef,o.nodeId);break;case"conflicted":r.conflicted.push(o.nodeId),i.set(n.sourceRef,o.nodeId);break}}catch(o){console.error(`[pipeline] Failed to process node ${n.sourceRef}:`,o),r.rejected.push(n.sourceRef)}for(let n of e.edges)try{await this.processEdge(n,i)}catch(o){console.error(`[pipeline] Failed to process edge ${n.fromRef}\u2192${n.toRef}:`,o)}for(let n of r.created)try{await this.maybePromote(n)}catch(o){console.error(`[pipeline] Failed to auto-promote ${n}:`,o)}return console.log(`[pipeline] Processed: ${r.created.length} created, ${r.merged.length} merged, ${r.conflicted.length} conflicted, ${r.rejected.length} rejected`),r}async processNode(e){if(this.config.enableDedup){let i=await this.findBySourceRef(e.sourceRef);if(i)return await lr(i,{properties:e.properties,tags:e.tags,confidence:e.confidence}),{action:"merged",nodeId:i}}if(!this.isValidNodeType(e.type))throw new Error(`Invalid node type: ${e.type}`);return{action:"created",nodeId:(await qr({type:e.type,layer:"draft",confidence:e.confidence,source:e.source,properties:{...e.properties,_sourceRef:e.sourceRef},tags:e.tags})).id}}async processEdge(e,r){let i=r.get(e.fromRef)??await this.resolveRef(e.fromRef),n=r.get(e.toRef)??await this.resolveRef(e.toRef);if(!i||!n){console.warn(`[pipeline] Skipping edge ${e.fromRef}\u2192${e.toRef}: unresolved refs`);return}(await wr({type:e.type,sourceId:i,targetId:n,limit:1})).length>0||await Ir({type:e.type,sourceId:i,targetId:n,confidence:e.confidence,evidence:e.evidence??void 0,source:e.source})}async maybePromote(e){let r=await Ze(e,{layers:["draft"]});r&&r.confidence>=this.config.autoPromoteThreshold&&(await ho(e,"permanent"),console.log(`[pipeline] Auto-promoted node ${e} (confidence: ${r.confidence.toFixed(2)})`))}async findBySourceRef(e){let r=await ae(`SELECT id FROM nodes
260
260
  WHERE properties->>'_sourceRef' = $1
261
261
  AND superseded_by IS NULL
262
262
  LIMIT 1`,[e]);return r.rows.length===0?null:r.rows[0].id}async resolveRef(e){let r=await Ze(e,{layers:["permanent","draft"]});return r?r.id:this.findBySourceRef(e)}isValidNodeType(e){return["Decision","Feature","Metric","CustomerSignal","CodeArtifact","Discussion","Gap","Study","Person"].includes(e)}}});var Us,eb=m(()=>{"use strict";Us=class{constructor(e,r,i,n,o){this.registry=e;this.miner=r;this.pipeline=i;this.config=n;this.eventBus=o}async run(e){let r=this.registry.get(e);if(!r)throw new Error(`Connector "${e}" not found`);let i=this.registry.getConnection(e);if(!i)throw new Error(`Connector "${e}" is not connected. Call connect() first.`);let n=Date.now();console.log(`[bootstrap] Starting full sync for connector: ${r.name}`),this.registry.updateSyncState(e,{status:"syncing"});let o={created:[],merged:[],conflicted:[],rejected:[]},s=0,a=0,c=[];try{for await(let l of r.fullSync(i))if(c.push(l),s++,c.length>=this.config.minerBatchSize){a++,console.log(`[bootstrap] Batch ${a}: mining ${c.length} artifacts (${s} total)...`);let d=await this.processBatch(c);this.mergeResults(o,d),console.log(`[bootstrap] Batch ${a} done: +${d.created.length} created, +${d.merged.length} merged (running total: ${o.created.length} nodes, ${o.merged.length} merged)`),c=[]}if(c.length>0){a++,console.log(`[bootstrap] Batch ${a}: mining ${c.length} artifacts (${s} total)...`);let l=await this.processBatch(c);this.mergeResults(o,l),console.log(`[bootstrap] Batch ${a} done: +${l.created.length} created, +${l.merged.length} merged (running total: ${o.created.length} nodes, ${o.merged.length} merged)`)}this.registry.updateSyncState(e,{status:"idle",lastSyncAt:new Date,artifactCount:s});let u=Date.now()-n;return console.log(`[bootstrap] Completed for ${r.name}: ${s} artifacts, ${o.created.length} nodes created, ${o.merged.length} merged (${(u/1e3).toFixed(1)}s)`),{connectorId:e,totalArtifacts:s,pipeline:o,durationMs:u}}catch(u){throw this.registry.updateSyncState(e,{status:"error",error:u instanceof Error?u.message:String(u)}),u}}async incrementalSync(e){let r=this.registry.get(e);if(!r)throw new Error(`Connector "${e}" not found`);let i=this.registry.getConnection(e);if(!i)throw new Error(`Connector "${e}" is not connected`);let n=this.registry.getSyncState(e);if(!n?.lastSyncAt)return console.log(`[bootstrap] No previous sync found for ${e}, running full sync`),this.run(e);let o=Date.now(),s=n.lastSyncAt;console.log(`[bootstrap] Incremental sync for ${r.name} since ${s.toISOString()}`),this.registry.updateSyncState(e,{status:"syncing"});let a={created:[],merged:[],conflicted:[],rejected:[]},c=0,u=[];try{for await(let d of r.incrementalSync(i,s))if(u.push(d),c++,u.length>=this.config.minerBatchSize){let p=await this.processBatch(u);this.mergeResults(a,p),u=[]}if(u.length>0){let d=await this.processBatch(u);this.mergeResults(a,d)}this.registry.updateSyncState(e,{status:"idle",lastSyncAt:new Date,artifactCount:(n.artifactCount??0)+c});let l=Date.now()-o;return console.log(`[bootstrap] Incremental sync completed for ${r.name}: ${c} new artifacts (${(l/1e3).toFixed(1)}s)`),{connectorId:e,totalArtifacts:c,pipeline:a,durationMs:l}}catch(l){throw this.registry.updateSyncState(e,{status:"error",error:l instanceof Error?l.message:String(l)}),l}}async processBatch(e){let r=await this.miner.mine(e);return this.pipeline.process(r)}mergeResults(e,r){e.created.push(...r.created),e.merged.push(...r.merged),e.conflicted.push(...r.conflicted),e.rejected.push(...r.rejected)}}});var tb,rb=m(()=>{"use strict";tb={minerBatchSize:10,enableDedup:!0,autoPromoteThreshold:.7}});function k3(t,e){let r={...tb,...t},i=new As,n=new js,o=new Fs(r),s=new Us(i,n,o,r,e);return i.register(new Cs),i.register(new Ls),console.log("[ingest] Service initialized"),{registry:i,miner:n,pipeline:o,bootstrap:s}}var L$=m(()=>{"use strict";Hy();Zy();Jy();Yy();Xy();eb();rb();Hy();Zy();Jy();Yy();Xy();eb();rb()});var j$,F$,U$=m(()=>{"use strict";j$={missing_data:["customer_interview","team_dm","document_request"],stale:["customer_interview","market_signal"],contradiction:["customer_interview","team_dm"],untested_assumption:["customer_interview","micro_survey"],missing_validation:["customer_interview","micro_survey"],coverage_gap:["tribal_knowledge_mining","team_dm","document_request"]},F$={missing_data:"discovery",stale:"discovery",contradiction:"concept-test",untested_assumption:"concept-test",missing_validation:"sentiment",coverage_gap:"discovery"}});import{randomUUID as M$}from"node:crypto";var Ms,Wd,Gs,nb=m(()=>{"use strict";Ne();U$();Ms=new Map,Wd=new Map,Gs=class{constructor(e){this.eventBus=e}async start(){this.eventBus.subscriber.subscribe("gap.detected.>",async e=>{await this.handleGapDetected(e)},{group:"collection-planner"})}async handleGapDetected(e){let r=await Ze(e.gapNodeId,{layers:["permanent","draft"]});if(!r)return;let i=r.metadata?.gapType??"missing_data",n=this.computeBatchKey(r),o=Wd.get(n);if(o&&o.length>0){let a=Ms.get(o[0]);if(a&&a.status==="planned"){a.gapIds.push(e.gapNodeId);let c=this.generateQuestions(r);a.questions.push(...c);return}}let s=await this.createPlan(e.gapNodeId,i,r);Wd.has(n)||Wd.set(n,[]),Wd.get(n).push(s.id)}async createPlan(e,r,i){i||(i=await Ze(e,{layers:["permanent","draft"]}));let n=this.selectMethod(r,i),o=this.generateQuestions(i),s=this.generateSuccessCriteria(r,i),a={id:M$(),gapIds:[e],method:n,questions:o,successCriteria:s,priority:this.computePriority(i),batchId:null,status:"planned",externalStudyId:null,createdAt:new Date().toISOString(),completedAt:null};return Ms.set(a.id,a),a}async approvePlan(e){let r=Ms.get(e);return!r||r.status!=="planned"?null:(r.status="approved",r)}getPlan(e){return Ms.get(e)??null}listPlans(e){let r=Array.from(Ms.values());e?.status&&(r=r.filter(o=>e.status.includes(o.status))),e?.batchId&&(r=r.filter(o=>o.batchId===e.batchId)),e?.gapId&&(r=r.filter(o=>o.gapIds.includes(e.gapId))),r.sort((o,s)=>s.priority-o.priority);let i=e?.offset??0,n=e?.limit??50;return r.slice(i,i+n)}updatePlanStatus(e,r){let i=Ms.get(e);i&&(i.status=r,(r==="completed"||r==="failed")&&(i.completedAt=new Date().toISOString()))}selectMethod(e,r){let n=(j$[e]??["customer_interview"])[0],o=r?.metadata?.description??"";switch(n){case"customer_interview":return{type:"customer_interview",studyType:F$[e]??"discovery",segment:r?.metadata?.customerSegment??void 0};case"micro_survey":return{type:"micro_survey",trigger:"contextual",question:o};case"market_signal":return{type:"market_signal",sources:["web","competitors"],query:o};case"team_dm":return{type:"team_dm",targetRole:this.inferTargetRole(r),channel:"slack"};case"document_request":return{type:"document_request",targetPerson:"",topic:o};case"tribal_knowledge_mining":return{type:"tribal_knowledge_mining",targetTeam:this.inferTargetTeam(r),topic:o};default:return{type:"customer_interview",studyType:"discovery"}}}generateQuestions(e){if(!e)return["What can you tell us about this topic?"];let r=e.metadata?.description??"";switch(e.metadata?.gapType??"missing_data"){case"missing_data":return[`We're missing data on: ${r}. What has been your experience?`,"What factors are most important to you in this area?"];case"stale":return[`Our information about "${r}" may be outdated. Has anything changed recently?`,"What's different now compared to 3-6 months ago?"];case"contradiction":return[`We're seeing conflicting signals about: ${r}. What's your perspective?`,"In what context is this true vs. not true?"];case"untested_assumption":return[`We've assumed: ${r}. Does this match your experience?`,"What would change your mind about this?"];case"missing_validation":return[`We'd like to validate: ${r}. How accurate is this?`,"What's missing from this picture?"];default:return[`Tell us about your experience with: ${r}`]}}generateSuccessCriteria(e,r){let i=r?.metadata?.description??"this topic";switch(e){case"missing_data":return`Obtain at least 3 independent data points about: ${i}`;case"stale":return`Get current information (< 30 days old) about: ${i}`;case"contradiction":return"Identify which perspective is more accurate, or under what conditions each is true";case"untested_assumption":return"Validate or invalidate the assumption with at least 5 data points";case"missing_validation":return"Confirm or deny with direct evidence from users/stakeholders";case"coverage_gap":return"Document the missing context with source attribution";default:return"Resolve the gap with supporting evidence"}}computeBatchKey(e){if(!e)return M$();let r=e.metadata?.gapType??"unknown",i=e.tags[0]??r;return`${r}:${i}`}computePriority(e){if(!e)return .5;let r={critical:1,high:.75,medium:.5,low:.25},i=e.metadata?.severity??"medium";return r[i]??.5}inferTargetRole(e){if(!e)return"engineering";let r=e.metadata?.gapType??"";return r==="missing_data"||r==="missing_validation"?"product":"engineering"}inferTargetTeam(e){if(!e)return"engineering";let r=e.tags;return r.includes("pricing")||r.includes("business")?"product":r.includes("customer")||r.includes("churn")?"sales":"engineering"}}});function G$(t){return{system:"codify-interviews",reference:t,agentId:null,reliability:.85}}function P3(t){let e=t.match(/(?:on|about|validate):\s*(.+?)(?:\.|What|How|$)/i);if(e)return e[1].trim();let r=t.match(/"([^"]+)"/);return r?r[1].trim():t.replace(/^(Tell us about|What can you tell us about)\s*/i,"").slice(0,50).trim()||null}var $3,Bs,ib=m(()=>{"use strict";$3={progressPollIntervalMs:6e4,minInterviewsForSynthesis:3},Bs=class{constructor(e,r,i,n){this.mcp=e;this.planner=r;this.eventBus=i;this.config={...$3,...n}}config;activeStudies=new Map;pollTimers=new Map;async execute(e){if(e.method.type!=="customer_interview")return null;let r=e.method,i=await this.mcp.runStudy({type:r.studyType,description:e.questions.join(`
@@ -653,7 +653,7 @@ builder.objectType('MyObject', {
653
653
  `),Qk(i);try{await Kk(i)}catch(E){console.error(" \u2717 Failed to start Docker services:",E.message),process.exit(1)}console.log(" \u2713 PostgreSQL on :5432"),console.log(" \u2713 NATS on :4222"),console.log(" Waiting for PostgreSQL to accept connections..."),await Hk(i)||(console.error(` \u2717 PostgreSQL did not become ready within 120s
654
654
  `),process.exit(1)),console.log(" \u2713 PostgreSQL is ready")}console.log(`
655
655
  [4/6] Database migrations`);try{let y=Fk(),E=await Wk(s,y),x=E.applied.length+E.skipped.length;E.applied.length>0?console.log(` \u2713 Schema applied (${E.applied.length} migration${E.applied.length>1?"s":""} applied, ${E.skipped.length} already up-to-date)`):console.log(` \u2713 Schema up-to-date (${x} migration${x>1?"s":""})`)}catch(y){console.error(" \u2717 Migration failed:",y.message),process.exit(1)}console.log(`
656
- [5/6] Project config`),Jk(r,{recursive:!0});let c=xs(r,"config.json"),u={version:"0.1.0",database:s,nats:a,anthropicApiKey:o,projectRoot:e,createdAt:new Date().toISOString()};jd(c,JSON.stringify(u,null,2)+`
656
+ [5/6] Project config`),Jk(r,{recursive:!0});let c=xs(r,"config.json"),u={version:"0.1.5",database:s,nats:a,anthropicApiKey:o,projectRoot:e,createdAt:new Date().toISOString()};jd(c,JSON.stringify(u,null,2)+`
657
657
  `,"utf-8"),console.log(" \u2713 .codify/config.json created");let l=xs(e,".gitignore");if(Zk(l)){let y=Yk(l,"utf-8");y.includes(".codify")||(jd(l,y.trimEnd()+`
658
658
  .codify/
659
659
  `,"utf-8"),console.log(" \u2713 .codify/ added to .gitignore"))}else jd(l,`.codify/
@@ -721,7 +721,7 @@ builder.objectType('MyObject', {
721
721
  ERROR: ANTHROPIC_API_KEY not set.`),console.error(` Export your API key: export ANTHROPIC_API_KEY=sk-...
722
722
  `)):console.error(`
723
723
  ERROR: ${e}
724
- `),process.exit(1)}});var $c=new gn;$c.name("codify").description("Codify \u2014 Living Context Graph for AI-Native Teams").version("0.1.0").addHelpText("after",`
724
+ `),process.exit(1)}});var $c=new gn;$c.name("codify").description("Codify \u2014 Living Context Graph for AI-Native Teams").version("0.1.5").addHelpText("after",`
725
725
  Quick Start:
726
726
  codify init Set up infrastructure and configure project
727
727
  codify bootstrap Mine git history into the context graph
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codified/cli",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "description": "Codify — Living Context Graph for AI-Native Teams",
6
6
  "repository": {