@sudocode-ai/cli 0.1.0 → 0.1.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.
Files changed (112) hide show
  1. package/dist/cli/feedback-commands.d.ts.map +1 -0
  2. package/dist/cli/feedback-commands.js +274 -0
  3. package/dist/cli/feedback-commands.js.map +1 -0
  4. package/dist/cli/init-commands.d.ts.map +1 -0
  5. package/dist/cli/init-commands.js +148 -0
  6. package/dist/cli/init-commands.js.map +1 -0
  7. package/dist/cli/issue-commands.d.ts.map +1 -0
  8. package/dist/cli/issue-commands.js +310 -0
  9. package/dist/cli/issue-commands.js.map +1 -0
  10. package/dist/cli/query-commands.d.ts.map +1 -0
  11. package/dist/cli/query-commands.js +61 -0
  12. package/dist/cli/query-commands.js.map +1 -0
  13. package/dist/cli/reference-commands.d.ts.map +1 -0
  14. package/dist/cli/reference-commands.js +136 -0
  15. package/dist/cli/reference-commands.js.map +1 -0
  16. package/dist/cli/relationship-commands.d.ts.map +1 -0
  17. package/dist/cli/relationship-commands.js +76 -0
  18. package/dist/cli/relationship-commands.js.map +1 -0
  19. package/dist/cli/server-commands.d.ts.map +1 -0
  20. package/dist/cli/server-commands.js +99 -0
  21. package/dist/cli/server-commands.js.map +1 -0
  22. package/dist/cli/spec-commands.d.ts.map +1 -0
  23. package/dist/cli/spec-commands.js +321 -0
  24. package/dist/cli/spec-commands.js.map +1 -0
  25. package/dist/cli/status-commands.d.ts.map +1 -0
  26. package/dist/cli/status-commands.js +131 -0
  27. package/dist/cli/status-commands.js.map +1 -0
  28. package/dist/cli/sync-commands.d.ts.map +1 -0
  29. package/dist/cli/sync-commands.js +416 -0
  30. package/dist/cli/sync-commands.js.map +1 -0
  31. package/dist/cli/update-commands.d.ts.map +1 -0
  32. package/dist/cli/update-commands.js +78 -0
  33. package/dist/cli/update-commands.js.map +1 -0
  34. package/dist/cli.d.ts.map +1 -0
  35. package/dist/cli.js +425 -195
  36. package/dist/cli.js.map +1 -0
  37. package/dist/db.d.ts.map +1 -0
  38. package/dist/db.js +54 -0
  39. package/dist/db.js.map +1 -0
  40. package/dist/export.d.ts.map +1 -0
  41. package/dist/export.js +195 -0
  42. package/dist/export.js.map +1 -0
  43. package/dist/filename-generator.d.ts.map +1 -0
  44. package/dist/filename-generator.js +93 -0
  45. package/dist/filename-generator.js.map +1 -0
  46. package/dist/id-generator.d.ts.map +1 -0
  47. package/dist/id-generator.js +123 -0
  48. package/dist/id-generator.js.map +1 -0
  49. package/dist/import.d.ts.map +1 -0
  50. package/dist/import.js +608 -0
  51. package/dist/import.js.map +1 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +13 -189
  54. package/dist/index.js.map +1 -0
  55. package/dist/jsonl.d.ts.map +1 -0
  56. package/dist/jsonl.js +333 -0
  57. package/dist/jsonl.js.map +1 -0
  58. package/dist/markdown.d.ts.map +1 -0
  59. package/dist/markdown.js +357 -0
  60. package/dist/markdown.js.map +1 -0
  61. package/dist/migrations.d.ts.map +1 -0
  62. package/dist/migrations.js +57 -0
  63. package/dist/migrations.js.map +1 -0
  64. package/dist/operations/events.d.ts.map +1 -0
  65. package/dist/operations/events.js +108 -0
  66. package/dist/operations/events.js.map +1 -0
  67. package/dist/operations/feedback-anchors.d.ts.map +1 -0
  68. package/dist/operations/feedback-anchors.js +444 -0
  69. package/dist/operations/feedback-anchors.js.map +1 -0
  70. package/dist/operations/feedback.d.ts.map +1 -0
  71. package/dist/operations/feedback.js +234 -0
  72. package/dist/operations/feedback.js.map +1 -0
  73. package/dist/operations/index.d.ts.map +1 -0
  74. package/dist/operations/index.js +10 -0
  75. package/dist/operations/index.js.map +1 -0
  76. package/dist/operations/issues.d.ts.map +1 -0
  77. package/dist/operations/issues.js +411 -0
  78. package/dist/operations/issues.js.map +1 -0
  79. package/dist/operations/references.d.ts.map +1 -0
  80. package/dist/operations/references.js +117 -0
  81. package/dist/operations/references.js.map +1 -0
  82. package/dist/operations/relationships.d.ts.map +1 -0
  83. package/dist/operations/relationships.js +236 -0
  84. package/dist/operations/relationships.js.map +1 -0
  85. package/dist/operations/specs.d.ts.map +1 -0
  86. package/dist/operations/specs.js +290 -0
  87. package/dist/operations/specs.js.map +1 -0
  88. package/dist/operations/tags.d.ts.map +1 -0
  89. package/dist/operations/tags.js +127 -0
  90. package/dist/operations/tags.js.map +1 -0
  91. package/dist/operations/transactions.d.ts.map +1 -0
  92. package/dist/operations/transactions.js +111 -0
  93. package/dist/operations/transactions.js.map +1 -0
  94. package/dist/sync.d.ts.map +1 -0
  95. package/dist/sync.js +442 -0
  96. package/dist/sync.js.map +1 -0
  97. package/dist/test-schema.d.ts.map +1 -0
  98. package/dist/test-schema.js +46 -0
  99. package/dist/test-schema.js.map +1 -0
  100. package/dist/types.d.ts.map +1 -0
  101. package/dist/types.js +7 -0
  102. package/dist/types.js.map +1 -0
  103. package/dist/update-checker.d.ts.map +1 -0
  104. package/dist/update-checker.js +151 -0
  105. package/dist/update-checker.js.map +1 -0
  106. package/dist/version.d.ts.map +1 -0
  107. package/dist/version.js +23 -0
  108. package/dist/version.js.map +1 -0
  109. package/dist/watcher.d.ts.map +1 -0
  110. package/dist/watcher.js +438 -0
  111. package/dist/watcher.js.map +1 -0
  112. package/package.json +4 -7
package/dist/cli.js CHANGED
@@ -1,196 +1,426 @@
1
1
  #!/usr/bin/env node
2
- var Tt=Object.defineProperty;var un=Object.getOwnPropertyDescriptor;var fn=Object.getOwnPropertyNames;var gn=Object.prototype.hasOwnProperty;var ce=(t,e)=>()=>(t&&(e=t(t=0)),e);var rt=(t,e)=>{for(var s in e)Tt(t,s,{get:e[s],enumerable:!0})},mn=(t,e,s,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of fn(e))!gn.call(t,o)&&o!==s&&Tt(t,o,{get:()=>e[o],enumerable:!(n=un(e,o))||n.enumerable});return t};var hn=t=>mn(Tt({},"__esModule",{value:!0}),t);import*as Xt from"fs";import*as it from"path";import{fileURLToPath as Dn}from"url";function xn(){let t=it.join(En,"..","package.json");return JSON.parse(Xt.readFileSync(t,"utf8")).version}var wn,En,re,Ye=ce(()=>{"use strict";wn=Dn(import.meta.url),En=it.dirname(wn);re=xn()});import*as Ne from"fs";import*as It from"path";import*as es from"crypto";function at(t,e){let s=vt(e),n=On(t);return`${s.id_prefix.spec}-${String(n).padStart(3,"0")}`}function ct(t,e){let s=vt(e),n=Tn(t);return`${s.id_prefix.issue}-${String(n).padStart(3,"0")}`}function On(t){let s=t.prepare(`
3
- SELECT id FROM specs
4
- ORDER BY created_at DESC
5
- LIMIT 1
6
- `).get();if(s){let r=s.id.match(/(\d+)$/);if(r)return parseInt(r[1],10)+1}return t.prepare("SELECT COUNT(*) as count FROM specs").get().count+1}function Tn(t){let s=t.prepare(`
7
- SELECT id FROM issues
8
- ORDER BY created_at DESC
9
- LIMIT 1
10
- `).get();if(s){let r=s.id.match(/(\d+)$/);if(r)return parseInt(r[1],10)+1}return t.prepare("SELECT COUNT(*) as count FROM issues").get().count+1}function vt(t){let e=It.join(t,"config.json");if(!Ne.existsSync(e)){let n={version:re,id_prefix:{spec:"SPEC",issue:"ISSUE"}};return In(t,n),n}let s=Ne.readFileSync(e,"utf8");return JSON.parse(s)}function In(t,e){let s=It.join(t,"config.json");Ne.writeFileSync(s,JSON.stringify(e,null,2),"utf8")}function ts(t){return vt(t)}function dt(){return es.randomUUID()}var xe=ce(()=>{"use strict";Ye()});var $t={};rt($t,{createSpec:()=>Oe,deleteSpec:()=>Ge,getSpec:()=>T,getSpecByFilePath:()=>Ve,listSpecs:()=>P,searchSpecs:()=>kt,updateSpec:()=>_e});function Oe(t,e){let s=null;if(e.parent_id){let i=T(t,e.parent_id);if(!i)throw new Error(`Parent spec not found: ${e.parent_id}`);s=i.uuid}let n=e.uuid||dt(),o=["id","uuid","title","file_path","content","priority","parent_id","parent_uuid","archived"],r=["@id","@uuid","@title","@file_path","@content","@priority","@parent_id","@parent_uuid","@archived"];e.created_at&&(o.push("created_at"),r.push("@created_at")),e.updated_at&&(o.push("updated_at"),r.push("@updated_at")),e.archived_at!==void 0&&(o.push("archived_at"),r.push("@archived_at"));let a=t.prepare(`
11
- INSERT INTO specs (
12
- ${o.join(", ")}
13
- ) VALUES (
14
- ${r.join(", ")}
15
- )
16
- ON CONFLICT(id) DO UPDATE SET
17
- uuid = excluded.uuid,
18
- title = excluded.title,
19
- file_path = excluded.file_path,
20
- content = excluded.content,
21
- priority = excluded.priority,
22
- parent_id = excluded.parent_id,
23
- parent_uuid = excluded.parent_uuid,
24
- archived = excluded.archived,
25
- archived_at = excluded.archived_at,
26
- ${e.created_at?"created_at = excluded.created_at,":""}
27
- ${e.updated_at?"updated_at = excluded.updated_at":"updated_at = CURRENT_TIMESTAMP"}
28
- `);try{let i={id:e.id,uuid:n,title:e.title,file_path:e.file_path,content:e.content||"",priority:e.priority??2,parent_id:e.parent_id??null,parent_uuid:s,archived:e.archived?1:0};e.created_at&&(i.created_at=e.created_at),e.updated_at&&(i.updated_at=e.updated_at),e.archived_at!==void 0&&(i.archived_at=e.archived_at),a.run(i);let d=T(t,e.id);if(!d)throw new Error(`Failed to create spec ${e.id}`);return d}catch(i){throw i.code&&i.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${i.message}`):i}}function T(t,e){return t.prepare(`
29
- SELECT * FROM specs WHERE id = ?
30
- `).get(e)??null}function Ve(t,e){return t.prepare(`
31
- SELECT * FROM specs WHERE file_path = ?
32
- `).get(e)??null}function _e(t,e,s){let n=T(t,e);if(!n)throw new Error(`Spec not found: ${e}`);if(s.parent_id&&!T(t,s.parent_id))throw new Error(`Parent spec not found: ${s.parent_id}`);let o=[],r={id:e};if(s.title!==void 0&&s.title!==n.title&&(o.push("title = @title"),r.title=s.title),s.file_path!==void 0&&s.file_path!==n.file_path&&(o.push("file_path = @file_path"),r.file_path=s.file_path),s.content!==void 0&&s.content!==n.content&&(o.push("content = @content"),r.content=s.content),s.priority!==void 0&&s.priority!==n.priority&&(o.push("priority = @priority"),r.priority=s.priority),s.parent_id!==void 0&&s.parent_id!==n.parent_id&&(o.push("parent_id = @parent_id"),r.parent_id=s.parent_id),s.archived!==void 0&&s.archived!==n.archived?(o.push("archived = @archived"),r.archived=s.archived?1:0,s.archived_at!==void 0?(o.push("archived_at = @archived_at"),r.archived_at=s.archived_at):s.archived&&!n.archived?o.push("archived_at = CURRENT_TIMESTAMP"):!s.archived&&n.archived&&o.push("archived_at = NULL")):s.archived_at!==void 0&&s.archived_at!==n.archived_at&&(o.push("archived_at = @archived_at"),r.archived_at=s.archived_at),s.updated_at!==void 0?(o.push("updated_at = @updated_at"),r.updated_at=s.updated_at):o.length>0&&o.push("updated_at = CURRENT_TIMESTAMP"),o.length===0)return n;let a=t.prepare(`
33
- UPDATE specs SET ${o.join(", ")} WHERE id = @id
34
- `);try{a.run(r);let i=T(t,e);if(!i)throw new Error(`Failed to update spec ${e}`);return i}catch(i){throw i.code&&i.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${i.message}`):i}}function Ge(t,e){return t.prepare("DELETE FROM specs WHERE id = ?").run(e).changes>0}function P(t,e={}){let s=[],n={};e.priority!==void 0&&(s.push("priority = @priority"),n.priority=e.priority),e.parent_id!==void 0&&(s.push("parent_id = @parent_id"),n.parent_id=e.parent_id),e.archived!==void 0&&(s.push("archived = @archived"),n.archived=e.archived?1:0);let o="SELECT * FROM specs";return s.length>0&&(o+=" WHERE "+s.join(" AND ")),o+=" ORDER BY priority DESC, created_at DESC",e.limit!==void 0&&(o+=" LIMIT @limit",n.limit=e.limit),e.offset!==void 0&&(o+=" OFFSET @offset",n.offset=e.offset),t.prepare(o).all(n)}function kt(t,e,s={}){let n=["(title LIKE @query OR content LIKE @query)"],o={query:`%${e}%`};s.priority!==void 0&&(n.push("priority = @priority"),o.priority=s.priority),s.parent_id!==void 0&&(n.push("parent_id = @parent_id"),o.parent_id=s.parent_id),s.archived!==void 0&&(n.push("archived = @archived"),o.archived=s.archived?1:0);let r=`SELECT * FROM specs WHERE ${n.join(" AND ")} ORDER BY priority DESC, created_at DESC`;return s.limit!==void 0?(r+=" LIMIT @limit",o.limit=s.limit):r+=" LIMIT 50",t.prepare(r).all(o)}var K=ce(()=>{"use strict";xe()});var ss={};rt(ss,{closeIssue:()=>lt,createIssue:()=>Te,deleteIssue:()=>Ct,getBlockedIssues:()=>Ae,getIssue:()=>O,getReadyIssues:()=>Le,listIssues:()=>U,reopenIssue:()=>$n,searchIssues:()=>Rt,updateIssue:()=>ee});function Te(t,e){let s=null;if(e.parent_id){let i=O(t,e.parent_id);if(!i)throw new Error(`Parent issue not found: ${e.parent_id}`);s=i.uuid}let n=e.uuid||dt(),o=["id","uuid","title","content","status","priority","assignee","parent_id","parent_uuid","archived"],r=["@id","@uuid","@title","@content","@status","@priority","@assignee","@parent_id","@parent_uuid","@archived"];e.created_at&&(o.push("created_at"),r.push("@created_at")),e.updated_at&&(o.push("updated_at"),r.push("@updated_at")),e.closed_at!==void 0&&(o.push("closed_at"),r.push("@closed_at")),e.archived_at!==void 0&&(o.push("archived_at"),r.push("@archived_at"));let a=t.prepare(`
35
- INSERT INTO issues (
36
- ${o.join(", ")}
37
- ) VALUES (
38
- ${r.join(", ")}
39
- )
40
- ON CONFLICT(id) DO UPDATE SET
41
- uuid = excluded.uuid,
42
- title = excluded.title,
43
- content = excluded.content,
44
- status = excluded.status,
45
- priority = excluded.priority,
46
- assignee = excluded.assignee,
47
- parent_id = excluded.parent_id,
48
- parent_uuid = excluded.parent_uuid,
49
- archived = excluded.archived,
50
- archived_at = excluded.archived_at,
51
- ${e.created_at?"created_at = excluded.created_at,":""}
52
- ${e.updated_at?"updated_at = excluded.updated_at":"updated_at = CURRENT_TIMESTAMP"}
53
- `);try{let i={id:e.id,uuid:n,title:e.title,content:e.content||"",status:e.status||"open",priority:e.priority??2,assignee:e.assignee??null,parent_id:e.parent_id??null,parent_uuid:s,archived:e.archived?1:0};e.created_at&&(i.created_at=e.created_at),e.updated_at&&(i.updated_at=e.updated_at),e.closed_at!==void 0&&(i.closed_at=e.closed_at),e.archived_at!==void 0&&(i.archived_at=e.archived_at),a.run(i);let d=O(t,e.id);if(!d)throw new Error(`Failed to create issue ${e.id}`);return d}catch(i){throw i.code&&i.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${i.message}`):i}}function O(t,e){return t.prepare(`
54
- SELECT * FROM issues WHERE id = ?
55
- `).get(e)??null}function ee(t,e,s){let n=O(t,e);if(!n)throw new Error(`Issue not found: ${e}`);if(s.parent_id&&!O(t,s.parent_id))throw new Error(`Parent issue not found: ${s.parent_id}`);let o=[],r={id:e};if(s.title!==void 0&&s.title!==n.title&&(o.push("title = @title"),r.title=s.title),s.content!==void 0&&s.content!==n.content&&(o.push("content = @content"),r.content=s.content),s.status!==void 0&&s.status!==n.status?(o.push("status = @status"),r.status=s.status,s.closed_at!==void 0?(o.push("closed_at = @closed_at"),r.closed_at=s.closed_at):s.status==="closed"&&n.status!=="closed"?o.push("closed_at = CURRENT_TIMESTAMP"):s.status!=="closed"&&n.status==="closed"&&o.push("closed_at = NULL")):s.closed_at!==void 0&&s.closed_at!==n.closed_at&&(o.push("closed_at = @closed_at"),r.closed_at=s.closed_at),s.priority!==void 0&&s.priority!==n.priority&&(o.push("priority = @priority"),r.priority=s.priority),s.assignee!==void 0&&s.assignee!==n.assignee&&(o.push("assignee = @assignee"),r.assignee=s.assignee),s.parent_id!==void 0&&s.parent_id!==n.parent_id&&(o.push("parent_id = @parent_id"),r.parent_id=s.parent_id),s.archived!==void 0&&(s.archived?1:0)!==n.archived?(o.push("archived = @archived"),r.archived=s.archived?1:0,s.archived_at!==void 0?(o.push("archived_at = @archived_at"),r.archived_at=s.archived_at):s.archived&&!n.archived?o.push("archived_at = CURRENT_TIMESTAMP"):!s.archived&&n.archived&&o.push("archived_at = NULL")):s.archived_at!==void 0&&s.archived_at!==n.archived_at&&(o.push("archived_at = @archived_at"),r.archived_at=s.archived_at),s.updated_at!==void 0?(o.push("updated_at = @updated_at"),r.updated_at=s.updated_at):o.length>0&&o.push("updated_at = CURRENT_TIMESTAMP"),o.length===0)return n;let a=t.prepare(`
56
- UPDATE issues SET ${o.join(", ")} WHERE id = @id
57
- `);try{a.run(r);let i=O(t,e);if(!i)throw new Error(`Failed to update issue ${e}`);return s.status==="closed"&&n.status!=="closed"&&vn(t,e),i}catch(i){throw i.code&&i.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${i.message}`):i}}function vn(t,e){let s=ue(t,e,"issue","blocks");for(let n of s){let o=n.from_id,r=O(t,o);if(!r||r.status!=="blocked")continue;kn(t,o,e)||t.prepare(`
58
- UPDATE issues
59
- SET status = 'open', updated_at = CURRENT_TIMESTAMP
60
- WHERE id = ?
61
- `).run(o)}}function kn(t,e,s){let n=t.prepare(`
62
- SELECT COUNT(*) as count
63
- FROM relationships r
64
- JOIN issues blocker ON r.to_id = blocker.id AND r.to_type = 'issue'
65
- WHERE r.from_id = ?
66
- AND r.from_type = 'issue'
67
- AND r.relationship_type = 'blocks'
68
- AND blocker.status IN ('open', 'in_progress', 'blocked')
69
- ${s?"AND blocker.id != ?":""}
70
- `),o=s?[e,s]:[e];return n.get(...o).count>0}function Ct(t,e){return t.prepare("DELETE FROM issues WHERE id = ?").run(e).changes>0}function lt(t,e){return ee(t,e,{status:"closed"})}function $n(t,e){return ee(t,e,{status:"open"})}function U(t,e={}){let s=[],n={};e.status!==void 0&&(s.push("status = @status"),n.status=e.status),e.priority!==void 0&&(s.push("priority = @priority"),n.priority=e.priority),e.assignee!==void 0&&(s.push("assignee = @assignee"),n.assignee=e.assignee),e.parent_id!==void 0&&(s.push("parent_id = @parent_id"),n.parent_id=e.parent_id),e.archived!==void 0&&(s.push("archived = @archived"),n.archived=e.archived?1:0);let o="SELECT * FROM issues";return s.length>0&&(o+=" WHERE "+s.join(" AND ")),o+=" ORDER BY priority DESC, created_at DESC",e.limit!==void 0&&(o+=" LIMIT @limit",n.limit=e.limit),e.offset!==void 0&&(o+=" OFFSET @offset",n.offset=e.offset),t.prepare(o).all(n)}function Le(t){return t.prepare("SELECT * FROM ready_issues ORDER BY priority DESC, created_at DESC").all()}function Ae(t){return t.prepare("SELECT * FROM blocked_issues ORDER BY priority DESC, created_at DESC").all()}function Rt(t,e,s={}){let n=["(title LIKE @query OR content LIKE @query)"],o={query:`%${e}%`};s.status!==void 0&&(n.push("status = @status"),o.status=s.status),s.priority!==void 0&&(n.push("priority = @priority"),o.priority=s.priority),s.assignee!==void 0&&(n.push("assignee = @assignee"),o.assignee=s.assignee),s.parent_id!==void 0&&(n.push("parent_id = @parent_id"),o.parent_id=s.parent_id),s.archived!==void 0&&(n.push("archived = @archived"),o.archived=s.archived?1:0);let r=`SELECT * FROM issues WHERE ${n.join(" AND ")} ORDER BY priority DESC, created_at DESC`;return s.limit!==void 0?(r+=" LIMIT @limit",o.limit=s.limit):r+=" LIMIT 50",t.prepare(r).all(o)}var W=ce(()=>{"use strict";xe();ie()});var ut={};rt(ut,{addRelationship:()=>Y,getAllRelationships:()=>jn,getDependencies:()=>Ln,getDependents:()=>An,getIncomingRelationships:()=>ue,getOutgoingRelationships:()=>de,getRelationship:()=>pt,relationshipExists:()=>Mn,removeAllRelationships:()=>je,removeRelationship:()=>Rn});function Y(t,e){let s=e.from_type==="spec"?"specs":"issues",n=t.prepare(`SELECT id, uuid FROM ${s} WHERE id = ?`).get(e.from_id);if(!n)throw new Error(`${e.from_type==="spec"?"Spec":"Issue"} not found: ${e.from_id}`);let o=e.to_type==="spec"?"specs":"issues",r=t.prepare(`SELECT id, uuid FROM ${o} WHERE id = ?`).get(e.to_id);if(!r)throw new Error(`${e.to_type==="spec"?"Spec":"Issue"} not found: ${e.to_id}`);let a=pt(t,e.from_id,e.from_type,e.to_id,e.to_type,e.relationship_type);if(a)return a;let i=t.prepare(`
71
- INSERT INTO relationships (
72
- from_id, from_uuid, from_type, to_id, to_uuid, to_type, relationship_type, metadata
73
- ) VALUES (
74
- @from_id, @from_uuid, @from_type, @to_id, @to_uuid, @to_type, @relationship_type, @metadata
75
- )
76
- `);try{i.run({from_id:e.from_id,from_uuid:n.uuid,from_type:e.from_type,to_id:e.to_id,to_uuid:r.uuid,to_type:e.to_type,relationship_type:e.relationship_type,metadata:e.metadata??null});let d=pt(t,e.from_id,e.from_type,e.to_id,e.to_type,e.relationship_type);if(!d)throw new Error("Failed to create relationship");return e.relationship_type==="blocks"&&e.from_type==="issue"&&e.to_type==="issue"&&Cn(t,e.from_id,e.to_id),d}catch(d){throw d.code&&d.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Relationship already exists: ${e.from_id} (${e.from_type}) --[${e.relationship_type}]--> ${e.to_id} (${e.to_type})`):d}}function Cn(t,e,s){let n=O(t,s);if(n&&n.status!=="closed"){let o=O(t,e);o&&(o.status==="open"||o.status==="in_progress")&&t.prepare(`
77
- UPDATE issues
78
- SET status = 'blocked', updated_at = CURRENT_TIMESTAMP
79
- WHERE id = ?
80
- `).run(e)}}function pt(t,e,s,n,o,r){return t.prepare(`
81
- SELECT * FROM relationships
82
- WHERE from_id = ? AND from_type = ?
83
- AND to_id = ? AND to_type = ?
84
- AND relationship_type = ?
85
- `).get(e,s,n,o,r)??null}function Rn(t,e,s,n,o,r){let d=t.prepare(`
86
- DELETE FROM relationships
87
- WHERE from_id = ? AND from_type = ?
88
- AND to_id = ? AND to_type = ?
89
- AND relationship_type = ?
90
- `).run(e,s,n,o,r).changes>0;return d&&r==="blocks"&&s==="issue"&&o==="issue"&&Fn(t,e),d}function Fn(t,e){let s=O(t,e);s&&s.status==="blocked"&&(Nn(t,e)||t.prepare(`
91
- UPDATE issues
92
- SET status = 'open', updated_at = CURRENT_TIMESTAMP
93
- WHERE id = ?
94
- `).run(e))}function Nn(t,e){return t.prepare(`
95
- SELECT COUNT(*) as count
96
- FROM relationships r
97
- JOIN issues blocker ON r.to_id = blocker.id AND r.to_type = 'issue'
98
- WHERE r.from_id = ?
99
- AND r.from_type = 'issue'
100
- AND r.relationship_type = 'blocks'
101
- AND blocker.status IN ('open', 'in_progress', 'blocked')
102
- `).get(e).count>0}function de(t,e,s,n){let o=`
103
- SELECT * FROM relationships
104
- WHERE from_id = @entity_id AND from_type = @entity_type
105
- `,r={entity_id:e,entity_type:s};return n!==void 0&&(o+=" AND relationship_type = @relationship_type",r.relationship_type=n),o+=" ORDER BY created_at DESC",t.prepare(o).all(r)}function ue(t,e,s,n){let o=`
106
- SELECT * FROM relationships
107
- WHERE to_id = @entity_id AND to_type = @entity_type
108
- `,r={entity_id:e,entity_type:s};return n!==void 0&&(o+=" AND relationship_type = @relationship_type",r.relationship_type=n),o+=" ORDER BY created_at DESC",t.prepare(o).all(r)}function Ln(t,e,s){return de(t,e,s,"blocks")}function An(t,e,s){return ue(t,e,s,"blocks")}function jn(t,e,s){return{outgoing:de(t,e,s),incoming:ue(t,e,s)}}function Mn(t,e,s,n,o,r){return pt(t,e,s,n,o,r)!==null}function je(t,e,s){return t.prepare(`
109
- DELETE FROM relationships
110
- WHERE (from_id = ? AND from_type = ?)
111
- OR (to_id = ? AND to_type = ?)
112
- `).run(e,s,e,s).changes}var ie=ce(()=>{"use strict";W()});function Jn(t,e,s,n){let o=s==="spec"?"specs":"issues",r=t.prepare(`SELECT uuid FROM ${o} WHERE id = ?`).get(e);if(!r)throw new Error(`${s==="spec"?"Spec":"Issue"} not found: ${e}`);let a=t.prepare(`
113
- INSERT INTO tags (entity_id, entity_uuid, entity_type, tag)
114
- VALUES (@entity_id, @entity_uuid, @entity_type, @tag)
115
- `);try{return a.run({entity_id:e,entity_uuid:r.uuid,entity_type:s,tag:n}),{entity_id:e,entity_uuid:r.uuid,entity_type:s,tag:n}}catch(i){if(i.code&&i.code.startsWith("SQLITE_CONSTRAINT"))return{entity_id:e,entity_uuid:r.uuid,entity_type:s,tag:n};throw i}}function Pn(t,e,s,n){let o=[];for(let r of n)o.push(Jn(t,e,s,r));return o}function te(t,e,s){return t.prepare(`
116
- SELECT tag FROM tags
117
- WHERE entity_id = ? AND entity_type = ?
118
- ORDER BY tag
119
- `).all(e,s).map(r=>r.tag)}function Un(t,e,s){return t.prepare(`
120
- DELETE FROM tags
121
- WHERE entity_id = ? AND entity_type = ?
122
- `).run(e,s).changes}function Z(t,e,s,n){return Un(t,e,s),n.length>0&&Pn(t,e,s,n),n}var Ie=ce(()=>{"use strict"});function ns(t){return{...t,dismissed:t.dismissed===1}}function Wn(t){let s=t.prepare(`
123
- SELECT id FROM issue_feedback ORDER BY id DESC LIMIT 1
124
- `).get();if(!s)return"FB-001";let n=s.id.match(/^FB-(\d+)$/);if(!n)return"FB-001";let o=parseInt(n[1],10)+1;return`FB-${String(o).padStart(3,"0")}`}function ft(t,e){let s=e.id||Wn(t),n=e.anchor?JSON.stringify(e.anchor):null,o=e.agent||"user",r=t.prepare("SELECT uuid FROM issues WHERE id = ?").get(e.issue_id);if(!r)throw new Error(`Issue not found: ${e.issue_id}`);let a=t.prepare("SELECT uuid FROM specs WHERE id = ?").get(e.spec_id);if(!a)throw new Error(`Spec not found: ${e.spec_id}`);let i=t.prepare(`
125
- INSERT INTO issue_feedback (
126
- id, issue_id, issue_uuid, spec_id, spec_uuid, feedback_type, content, agent, anchor, dismissed
127
- ) VALUES (
128
- @id, @issue_id, @issue_uuid, @spec_id, @spec_uuid, @feedback_type, @content, @agent, @anchor, @dismissed
129
- )
130
- `);try{i.run({id:s,issue_id:e.issue_id,issue_uuid:r.uuid,spec_id:e.spec_id,spec_uuid:a.uuid,feedback_type:e.feedback_type,content:e.content,agent:o,anchor:n,dismissed:e.dismissed!==void 0&&e.dismissed?1:0});let d=Me(t,s);if(!d)throw new Error(`Failed to create feedback ${s}`);return d}catch(d){throw d.code&&d.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${d.message}`):d}}function Me(t,e){let n=t.prepare(`
131
- SELECT * FROM issue_feedback WHERE id = ?
132
- `).get(e);return n?ns(n):null}function Ke(t,e,s){let n=Me(t,e);if(!n)throw new Error(`Feedback not found: ${e}`);let o=[],r={id:e};if(s.content!==void 0&&(o.push("content = @content"),r.content=s.content),s.dismissed!==void 0&&(o.push("dismissed = @dismissed"),r.dismissed=s.dismissed?1:0),s.anchor!==void 0&&(o.push("anchor = @anchor"),r.anchor=JSON.stringify(s.anchor)),o.push("updated_at = CURRENT_TIMESTAMP"),o.length===1)return n;let a=t.prepare(`
133
- UPDATE issue_feedback SET ${o.join(", ")} WHERE id = @id
134
- `);try{a.run(r);let i=Me(t,e);if(!i)throw new Error(`Failed to update feedback ${e}`);return i}catch(i){throw i.code&&i.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${i.message}`):i}}function os(t,e){return t.prepare("DELETE FROM issue_feedback WHERE id = ?").run(e).changes>0}function rs(t,e){return Ke(t,e,{dismissed:!0})}function V(t,e={}){let s=[],n={};e.issue_id!==void 0&&(s.push("issue_id = @issue_id"),n.issue_id=e.issue_id),e.spec_id!==void 0&&(s.push("spec_id = @spec_id"),n.spec_id=e.spec_id),e.feedback_type!==void 0&&(s.push("feedback_type = @feedback_type"),n.feedback_type=e.feedback_type),e.dismissed!==void 0&&(s.push("dismissed = @dismissed"),n.dismissed=e.dismissed?1:0);let o="SELECT * FROM issue_feedback";return s.length>0&&(o+=" WHERE "+s.join(" AND ")),o+=" ORDER BY created_at DESC",e.limit!==void 0&&(o+=" LIMIT @limit",n.limit=e.limit),e.offset!==void 0&&(o+=" OFFSET @offset",n.offset=e.offset),t.prepare(o).all(n).map(ns)}var be=ce(()=>{"use strict"});import*as B from"fs";import*as is from"readline";import*as as from"path";async function Ft(t,e={}){let{skipErrors:s=!1,onError:n}=e;if(!B.existsSync(t))return[];let o=[],r=B.createReadStream(t,{encoding:"utf8"}),a=is.createInterface({input:r,crlfDelay:1/0}),i=0;for await(let d of a)if(i++,d.trim()!=="")try{let c=JSON.parse(d);o.push(c)}catch(c){let l=c;if(n&&n(i,d,l),!s)throw new Error(`Failed to parse JSON at line ${i}: ${l.message}`)}return o}async function Nt(t,e,s={}){let{atomic:n=!0}=s,o=as.dirname(t);B.existsSync(o)||B.mkdirSync(o,{recursive:!0});let r=n?`${t}.tmp`:t,a=[...e].sort((c,l)=>{let p=c.created_at,y=l.created_at;if(!p&&!y){let v=c.id||"",x=l.id||"";return v<x?-1:v>x?1:0}if(!p)return 1;if(!y||p<y)return-1;if(p>y)return 1;let g=c.id||"",L=l.id||"";return g<L?-1:g>L?1:0}),d=a.map(c=>JSON.stringify(c)).join(`
135
- `)+`
136
- `;if(!(B.existsSync(t)&&B.readFileSync(t,"utf8")===d)&&(B.writeFileSync(r,d,"utf8"),n&&B.renameSync(r,t),a.length>0)){let c=a.map(l=>l.updated_at).filter(l=>l!=null).map(l=>{let p=String(l),g=p.endsWith("Z")||p.includes("+")||/[+-]\d{2}:\d{2}$/.test(p)?p:p.replace(" ","T")+"Z";return new Date(g).getTime()});if(c.length>0){let l=Math.max(...c),p=new Date(l);B.utimesSync(t,p,p)}}}var Lt=ce(()=>{"use strict"});function Cs(t,e){return t.inTransaction?e(t):t.transaction(e)(t)}var Rs=ce(()=>{"use strict"});var Ls={};rt(Ls,{countReferences:()=>go,detectChanges:()=>qt,detectCollisions:()=>Ht,importFromJSONL:()=>st,importIssues:()=>Yt,importSpecs:()=>zt,resolveCollisions:()=>Ns,updateTextReferences:()=>ho});import*as Bt from"path";function qt(t,e){let s=new Map(t.map(d=>[d.uuid,d])),n=new Set(e.map(d=>d.uuid)),o=e.filter(d=>!s.has(d.uuid)).map(d=>d.id),r=t.filter(d=>!n.has(d.uuid)).map(d=>d.id),a=[],i=[];for(let d of e){let c=s.get(d.uuid);c&&(fo(c,d)?a.push(d.id):i.push(d.id))}return{added:o,updated:a,deleted:r,unchanged:i}}function fo(t,e){return t.updated_at!==e.updated_at}function Ht(t,e){let s=[],n=new Map(t.map(r=>[r.id,r]));for(let r of e){let a=n.get(r.id);a&&a.uuid!==r.uuid&&s.push({id:r.id,uuid:r.uuid,type:"spec",reason:"Same ID but different UUID (different entities)",localContent:a.title,incomingContent:r.title,localCreatedAt:a.created_at,incomingCreatedAt:r.created_at})}let o=new Map;for(let r of e){let a=o.get(r.id)||[];a.push(r),o.set(r.id,a)}for(let[r,a]of o.entries())if(a.length>1&&new Set(a.map(d=>d.uuid)).size>1)for(let d=1;d<a.length;d++)s.push({id:a[d].id,uuid:a[d].uuid,type:"spec",reason:"Duplicate ID in incoming data with different UUID",localContent:a[0].title,incomingContent:a[d].title,localCreatedAt:a[0].created_at,incomingCreatedAt:a[d].created_at});return s}function go(t,e,s){let n=0,o=P(t);for(let a of o){let i=new RegExp(`\\b${e}\\b`,"g"),d=a.content.match(i);d&&(n+=d.length)}let r=U(t);for(let a of r){let i=new RegExp(`\\b${e}\\b`,"g"),d=a.content.match(i);d&&(n+=d.length)}return n}function Ns(t,e){let s=[],n=new Map;for(let o of e){let r=!0;if(o.localCreatedAt){let i=new Date(o.localCreatedAt).getTime(),d=new Date(o.incomingCreatedAt).getTime();d>i?r=!0:i>d?r=!1:r=o.uuid>o.localContent}let a=n.get(o.uuid);a||(a=mo(t,o.id,o.type),n.set(o.uuid,a)),s.push({...o,resolution:"renumber",newId:a,...r&&{note:"incoming is newer - correctly renumbered"},...!r&&{note:"local is newer - incoming (older) being renumbered"}})}return s}function mo(t,e,s){let n=e.match(/^([a-z]+-)?(\d+)$/i);if(!n)return`${s}-${Date.now()}`;let o=n[1]||`${s}-`,r=parseInt(n[2],10),a=`${o}${r+1e3}`,i=0;for(;i<1e3;){if(!(s==="spec"?T(t,a)!==null:O(t,a)!==null))return a;r++,a=`${o}${r+1e3}`,i++}return`${o}${Date.now()}`}function ho(t,e,s){let n=0,o=P(t);for(let a of o){let i=new RegExp(`\\b${e}\\b`,"g");if(i.test(a.content)){let d=a.content.replace(i,s);_e(t,a.id,{content:d}),n++}}let r=U(t);for(let a of r){let i=new RegExp(`\\b${e}\\b`,"g"),d=!1,c=a.content;i.test(a.content)&&(c=a.content.replace(i,s),d=!0),d&&(ee(t,a.id,{content:c}),n++)}return n}function zt(t,e,s,n=!1,o=!1){if(n)return{added:s.added.length,updated:s.updated.length,deleted:s.deleted.length};let r=0,a=0,i=0;for(let d of s.added){let c=e.find(l=>l.id===d);c&&(Oe(t,{id:c.id,uuid:c.uuid,title:c.title,file_path:c.file_path,content:c.content,priority:c.priority,parent_id:c.parent_id,archived:c.archived,archived_at:c.archived_at,created_at:c.created_at,updated_at:c.updated_at}),Z(t,c.id,"spec",c.tags||[]),r++)}if(!o)for(let d of s.added){let c=e.find(l=>l.id===d);if(c&&c.relationships&&c.relationships.length>0)for(let l of c.relationships)Y(t,{from_id:l.from,from_type:l.from_type,to_id:l.to,to_type:l.to_type,relationship_type:l.type})}for(let d of s.updated){let c=e.find(l=>l.id===d);c&&(_e(t,c.id,{title:c.title,file_path:c.file_path,content:c.content,priority:c.priority,parent_id:c.parent_id,archived:c.archived,archived_at:c.archived_at,updated_at:c.updated_at}),Z(t,c.id,"spec",c.tags||[]),a++)}if(!o)for(let d of s.updated){let c=e.find(l=>l.id===d);if(c){je(t,c.id,"spec");for(let l of c.relationships||[])Y(t,{from_id:l.from,from_type:l.from_type,to_id:l.to,to_type:l.to_type,relationship_type:l.type})}}for(let d of s.deleted)Ge(t,d),i++;return{added:r,updated:a,deleted:i}}function Fs(t,e,s){let n=V(t,{issue_id:e});for(let o of n)os(t,o.id);if(s&&s.length>0)for(let o of s)ft(t,{id:o.id,issue_id:o.issue_id,spec_id:o.spec_id,feedback_type:o.feedback_type,content:o.content,agent:o.agent,anchor:o.anchor,dismissed:o.dismissed})}function Yt(t,e,s,n=!1,o=!1){if(n)return{added:s.added.length,updated:s.updated.length,deleted:s.deleted.length};let r=0,a=0,i=0;for(let d of s.added){let c=e.find(l=>l.id===d);c&&(Te(t,{id:c.id,uuid:c.uuid,title:c.title,content:c.content,status:c.status,priority:c.priority,assignee:c.assignee,parent_id:c.parent_id,archived:c.archived,archived_at:c.archived_at,created_at:c.created_at,updated_at:c.updated_at,closed_at:c.closed_at}),Z(t,c.id,"issue",c.tags||[]),Fs(t,c.id,c.feedback),r++)}if(!o)for(let d of s.added){let c=e.find(l=>l.id===d);if(c)for(let l of c.relationships||[])Y(t,{from_id:l.from,from_type:l.from_type,to_id:l.to,to_type:l.to_type,relationship_type:l.type})}for(let d of s.updated){let c=e.find(l=>l.id===d);c&&(ee(t,c.id,{title:c.title,content:c.content,status:c.status,priority:c.priority,assignee:c.assignee,parent_id:c.parent_id,archived:c.archived,archived_at:c.archived_at,updated_at:c.updated_at,closed_at:c.closed_at}),Z(t,c.id,"issue",c.tags||[]),Fs(t,c.id,c.feedback),a++)}if(!o)for(let d of s.updated){let c=e.find(l=>l.id===d);if(c){je(t,c.id,"issue");for(let l of c.relationships||[])Y(t,{from_id:l.from,from_type:l.from_type,to_id:l.to,to_type:l.to_type,relationship_type:l.type})}}for(let d of s.deleted)Ct(t,d),i++;return{added:r,updated:a,deleted:i}}async function st(t,e={}){let{inputDir:s=".sudocode",specsFile:n="specs.jsonl",issuesFile:o="issues.jsonl",dryRun:r=!1,resolveCollisions:a=!0}=e,i=Bt.join(s,n),d=Bt.join(s,o),c=await Ft(i,{skipErrors:!0}),l=await Ft(d,{skipErrors:!0}),p=P(t),y=U(t),g=Ht(p,c),L=Ht(y,l),v=[...g.map(D=>({...D,type:"spec"})),...L.map(D=>({...D,type:"issue"}))],x=[];if(a&&v.length>0){x=Ns(t,v);for(let D of x)if(D.resolution==="renumber"&&D.newId){if(D.type==="spec"){let S=c.find(m=>m.id===D.id&&m.uuid===D.uuid);S&&(S.id=D.newId)}else if(D.type==="issue"){let S=l.find(m=>m.id===D.id&&m.uuid===D.uuid);S&&(S.id=D.newId)}}}let b=qt(p,c),C=qt(y,l),_={specs:{added:0,updated:0,deleted:0},issues:{added:0,updated:0,deleted:0},collisions:x.length>0?x:v};return r?(_.specs=zt(t,c,b,r),_.issues=Yt(t,l,C,r)):Cs(t,()=>{_.specs=zt(t,c,b,r,!0),_.issues=Yt(t,l,C,r,!0);for(let D of b.added){let S=c.find(m=>m.id===D);if(S&&S.relationships&&S.relationships.length>0)for(let m of S.relationships)Y(t,{from_id:m.from,from_type:m.from_type,to_id:m.to,to_type:m.to_type,relationship_type:m.type})}for(let D of b.updated){let S=c.find(m=>m.id===D);if(S){je(t,S.id,"spec");for(let m of S.relationships||[])Y(t,{from_id:m.from,from_type:m.from_type,to_id:m.to,to_type:m.to_type,relationship_type:m.type})}}for(let D of C.added){let S=l.find(m=>m.id===D);if(S&&S.relationships&&S.relationships.length>0)for(let m of S.relationships)Y(t,{from_id:m.from,from_type:m.from_type,to_id:m.to,to_type:m.to_type,relationship_type:m.type})}for(let D of C.updated){let S=l.find(m=>m.id===D);if(S){je(t,S.id,"issue");for(let m of S.relationships||[])Y(t,{from_id:m.from,from_type:m.from_type,to_id:m.to,to_type:m.to_type,relationship_type:m.type})}}}),_}var yt=ce(()=>{"use strict";Lt();K();W();ie();Ie();be();Rs()});import{Command as Io}from"commander";import Qt from"chalk";import*as le from"path";import*as Et from"fs";import Sn from"better-sqlite3";import*as ye from"@sudocode-ai/types/schema";var yn=[];function _n(t){return t.exec(`
137
- CREATE TABLE IF NOT EXISTS migrations (
138
- version INTEGER PRIMARY KEY,
139
- name TEXT NOT NULL,
140
- applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
141
- )
142
- `),t.prepare("SELECT MAX(version) as version FROM migrations").get().version??0}function bn(t,e){t.prepare(`
143
- INSERT OR REPLACE INTO migrations (version, name)
144
- VALUES (?, ?)
145
- `).run(e.version,e.name)}function Zt(t){let e=_n(t),s=yn.filter(n=>n.version>e);if(s.length!==0){console.log(`Running ${s.length} pending migration(s)...`);for(let n of s){console.log(` Applying migration ${n.version}: ${n.name}`);try{n.up(t),bn(t,n),console.log(` \u2713 Migration ${n.version} applied successfully`)}catch(o){throw console.error(` \u2717 Migration ${n.version} failed:`,o),o}}}}function ze(t){let e=new Sn(t.path,{verbose:t.verbose?console.log:void 0});e.exec(ye.DB_CONFIG);for(let s of ye.ALL_TABLES)e.exec(s);for(let s of ye.ALL_INDEXES)e.exec(s);for(let s of ye.ALL_VIEWS)e.exec(s);return Zt(e),e}xe();K();ie();Ie();be();import h from"chalk";import*as ve from"path";import*as ge from"fs";K();W();ie();Ie();be();Lt();function Bn(t,e){let n=de(t,e.id,"spec").map(r=>({from:r.from_id,from_type:r.from_type,to:r.to_id,to_type:r.to_type,type:r.relationship_type})),o=te(t,e.id,"spec");return{...e,relationships:n,tags:o}}function qn(t,e){let n=de(t,e.id,"issue").map(i=>({from:i.from_id,from_type:i.from_type,to:i.to_id,to_type:i.to_type,type:i.relationship_type})),o=te(t,e.id,"issue"),a=V(t,{issue_id:e.id}).map(i=>({id:i.id,issue_id:i.issue_id,spec_id:i.spec_id,feedback_type:i.feedback_type,content:i.content,agent:i.agent,anchor:i.anchor&&typeof i.anchor=="string"?JSON.parse(i.anchor):i.anchor,dismissed:i.dismissed,created_at:i.created_at,updated_at:i.updated_at}));return{...e,relationships:n,tags:o,feedback:a.length>0?a:void 0}}function Hn(t,e={}){let{since:s}=e,n=P(t);return(s?n.filter(r=>new Date(r.updated_at)>s):n).map(r=>Bn(t,r))}function zn(t,e={}){let{since:s}=e,n=U(t);return(s?n.filter(r=>new Date(r.updated_at)>s):n).map(r=>qn(t,r))}async function R(t,e={}){let{outputDir:s=".sudocode",specsFile:n="specs.jsonl",issuesFile:o="issues.jsonl"}=e,r=`${s}/${n}`,a=`${s}/${o}`,i=Hn(t,e);await Nt(r,i);let d=zn(t,e);return await Nt(a,d),{specsCount:i.length,issuesCount:d.length}}K();W();xe();import mt from"gray-matter";import*as Je from"fs";import*as cs from"crypto";function fe(t,e,s){let n=t.split(`
146
- `);if(e<1||e>n.length)throw new Error(`Line number ${e} is out of range (1-${n.length})`);let o=n[e-1],r=Yn(n,e),a=ls(o,s,50),i=gt(n,e,-50),d=gt(n,e,50),c=r?e-r.startLine:void 0,l=ps(a);return{section_heading:r?.heading,section_level:r?.level,line_number:e,line_offset:c,text_snippet:a,context_before:i,context_after:d,content_hash:l,anchor_status:"valid",last_verified_at:new Date().toISOString(),original_location:{line_number:e,section_heading:r?.heading}}}function ds(t,e){let s=t.split(`
147
- `);for(let n=0;n<s.length;n++){let r=s[n].indexOf(e);if(r!==-1){let a=n+1;return fe(t,a,r)}}return null}function Yn(t,e){for(let s=e-1;s>=0;s--){let o=t[s].match(/^(#{1,6})\s+(.+?)(\r)?$/);if(o){let r=o[1].length;return{heading:o[2].trim(),level:r,startLine:s+1}}}return null}function ls(t,e,s=50){if(!t||t.trim()==="")return"";let n=t.trim(),o=0,r=n.length;if(e!==void 0){let i=t.length-t.trimStart().length,d=Math.max(0,e-i),c=Math.floor(s/2);o=Math.max(0,d-c),r=Math.min(n.length,d+c)}else r=Math.min(n.length,s);let a=n.substring(o,r);return o>0&&(a="..."+a),r<n.length&&(a=a+"..."),a}function gt(t,e,s){if(s===0)return"";let n=s>0?1:-1,o=Math.abs(s),r="",a=e-1;for(n>0?a+=1:a-=1;a>=0&&a<t.length&&r.length<o;){let i=t[a],d=o-r.length;if(n>0)r.length>0&&(r+=" "),r+=i.substring(0,d);else{let c=Math.max(0,i.length-d),l=i.substring(c);r.length>0?r=l+" "+r:r=l}a+=n}return r.trim()}function ps(t){return cs.createHash("sha256").update(t).digest("hex").substring(0,16)}function Vn(t,e){if(!e.line_number)return!1;let s=t.split(`
148
- `);if(e.line_number<1||e.line_number>s.length)return!1;let n=s[e.line_number-1];if(e.text_snippet&&e.text_snippet.trim()){let o=e.text_snippet.replace(/\.\.\./g,"").trim();if(o&&!n.includes(o))return!1}if(e.content_hash&&e.text_snippet&&e.text_snippet.trim()){let o=ls(n,void 0,50);if(o&&ps(o)!==e.content_hash)return!1}return!0}function us(t){let e=t.split(`
149
- `),s=[];for(let n=0;n<e.length;n++){let r=e[n].match(/^(#{1,6})\s+(.+?)(\r)?$/);r&&s.push({heading:r[2].trim(),level:r[1].length,startLine:n+1})}return s}function Gn(t,e,s,n){if(!e)return[];let o=t.split(`
150
- `),r=[],a=e.replace(/\.\.\./g,"").trim();for(let i=0;i<o.length;i++)if(o[i].includes(a)){let c=.5;s&&gt(o,i+1,-50).includes(s.substring(0,20))&&(c+=.25),n&&gt(o,i+1,50).includes(n.substring(0,20))&&(c+=.25),r.push({lineNumber:i+1,confidence:Math.min(c,1)})}return r.sort((i,d)=>d.confidence-i.confidence)}function Kn(t,e){let s=t.length,n=e.length,o=Array(s+1).fill(null).map(()=>Array(n+1).fill(0));for(let r=0;r<=s;r++)o[r][0]=r;for(let r=0;r<=n;r++)o[0][r]=r;for(let r=1;r<=s;r++)for(let a=1;a<=n;a++){let i=t[r-1]===e[a-1]?0:1;o[r][a]=Math.min(o[r-1][a]+1,o[r][a-1]+1,o[r-1][a-1]+i)}return o[s][n]}function Qn(t,e,s=5){let n=us(t);if(n.length===0)return null;let o=e.toLowerCase().trim(),r=null,a=1/0;for(let i of n){let d=i.heading.toLowerCase().trim(),c=Kn(o,d);c<a&&c<=s&&(a=c,r=i)}return r}function fs(t,e,s){if(Vn(e,s))return{...s,anchor_status:"valid",last_verified_at:new Date().toISOString()};if(s.section_heading&&s.line_offset!==void 0){let o=us(e).find(r=>r.heading===s.section_heading);if(o){let r=o.startLine+s.line_offset,a=e.split(`
151
- `);if(r>0&&r<=a.length){let i=a[r-1];if(s.text_snippet){let d=s.text_snippet.replace(/\.\.\./g,"").trim();if(d&&i.includes(d))return{...fe(e,r),anchor_status:"relocated",last_verified_at:new Date().toISOString(),original_location:s.original_location||{line_number:s.line_number||0,section_heading:s.section_heading}}}}}}if(s.text_snippet){let n=Gn(e,s.text_snippet,s.context_before,s.context_after);if(n.length>0&&n[0].confidence>=.7)return{...fe(e,n[0].lineNumber),anchor_status:"relocated",last_verified_at:new Date().toISOString(),original_location:s.original_location||{line_number:s.line_number||0,section_heading:s.section_heading}}}if(s.section_heading&&s.line_offset!==void 0){let n=Qn(e,s.section_heading,5);if(n){let o=n.startLine+s.line_offset,r=e.split(`
152
- `);if(o>0&&o<=r.length)return{...fe(e,o),anchor_status:"relocated",last_verified_at:new Date().toISOString(),original_location:s.original_location||{line_number:s.line_number||0,section_heading:s.section_heading}}}}return{...s,anchor_status:"stale",last_verified_at:new Date().toISOString(),original_location:s.original_location||{line_number:s.line_number||0,section_heading:s.section_heading}}}function At(t,e,s){let n=mt(t),o;if(s&&e)try{o=ts(s)}catch{}let r=eo(n.content,e,o);return{data:n.data,content:n.content,raw:t,references:r}}function Qe(t,e,s){let n=Je.readFileSync(t,"utf8");return At(n,e,s)}function Zn(t,e){return t.substring(0,e).split(`
153
- `).length}function Xn(t){return{section_heading:t.section_heading,section_level:t.section_level,line_number:t.line_number,line_offset:t.line_offset,text_snippet:t.text_snippet,context_before:t.context_before,context_after:t.context_after,content_hash:t.content_hash}}function eo(t,e,s){let n=[],o=/\[\[(@)?([a-z]+-\d+)(?:\|([^\]]+))?\]\](?:\{\s*(?:type:\s*)?([a-z-]+)\s*\})?/gi,r;for(;(r=o.exec(t))!==null;){let a=r[1]==="@",i=r[2],d=r[3]?.trim(),c=r[4]?.trim(),l;try{let p=Zn(t,r.index),y=fe(t,p,r.index);l=Xn(y)}catch{l=void 0}if(e){let p=null;try{T(e,i)&&(p="spec")}catch{}if(!p)try{O(e,i)&&(p="issue")}catch{}p&&n.push({match:r[0],id:i,type:p,index:r.index,displayText:d,relationshipType:c,anchor:l})}else{let p;if(s){let y=s.id_prefix.spec.toLowerCase(),g=s.id_prefix.issue.toLowerCase();a||i.toLowerCase().startsWith(g+"-")?p="issue":(i.toLowerCase().startsWith(y+"-"),p="spec")}else p=a||i.startsWith("issue-")?"issue":"spec";n.push({match:r[0],id:i,type:p,index:r.index,displayText:d,relationshipType:c,anchor:l})}}return n}function jt(t,e){return mt.stringify(e,t)}function to(t,e){let s=mt(t),n={...s.data,...e},o=Object.fromEntries(Object.entries(n).filter(([r,a])=>a!==void 0));return mt.stringify(s.content,o)}function Mt(t,e){let s=Je.readFileSync(t,"utf8"),n=to(s,e);Je.writeFileSync(t,n,"utf8")}function so(t,e){return jt(t,e)}function Ze(t,e,s){let n=so(e,s);Je.writeFileSync(t,n,"utf8")}import*as Se from"fs";import*as Xe from"path";function Jt(t,e=50){return t.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,"").slice(0,e)}function ht(t,e,s,n=".md"){let o=Jt(t),r=o+n,a=Xe.join(s,r);if(!Se.existsSync(a))return r;try{let c=Se.readFileSync(a,"utf8").match(/^---\s*\n[\s\S]*?^id:\s*['"]?([^'"\n]+)['"]?\s*$/m);if(c&&c[1]===e)return r}catch{}return`${o}_${e}${n}`}function gs(t,e,s){let n=Xe.join(e,`${t}.md`);if(Se.existsSync(n))return n;if(s){let o=Xe.join(e,`${Jt(s)}.md`);if(Se.existsSync(o))try{let i=Se.readFileSync(o,"utf8").match(/^---\s*\n[\s\S]*?^id:\s*['"]?([^'"\n]+)['"]?\s*$/m);if(i&&i[1]===t)return o}catch{}let r=Xe.join(e,`${Jt(s)}_${t}.md`);if(Se.existsSync(r))return r}return null}async function ms(t,e,s){try{let n=at(t.db,t.outputDir),o=ve.join(t.outputDir,"specs");ge.mkdirSync(o,{recursive:!0});let a=`specs/${s.filePath?ve.basename(s.filePath):ht(e,n,o)}`,i=s.description||"",d=Oe(t.db,{id:n,title:e,file_path:a,content:i,priority:parseInt(s.priority),parent_id:s.parent||void 0});if(s.tags){let l=s.tags.split(",").map(p=>p.trim());Z(t.db,n,"spec",l)}let c={id:n,title:e,priority:parseInt(s.priority),created_at:d.created_at,...s.parent&&{parent_id:s.parent},...s.tags&&{tags:s.tags.split(",").map(l=>l.trim())}};Ze(ve.join(t.outputDir,a),c,i),await R(t.db,{outputDir:t.outputDir}),t.jsonOutput?console.log(JSON.stringify({id:n,title:e,file_path:a},null,2)):(console.log(h.green("\u2713 Created spec"),h.cyan(n)),console.log(h.gray(` Title: ${e}`)),console.log(h.gray(` File: ${a}`)))}catch(n){console.error(h.red("\u2717 Failed to create spec")),console.error(n instanceof Error?n.message:String(n)),process.exit(1)}}async function hs(t,e){try{let s=e.grep?kt(t.db,e.grep,{priority:e.priority?parseInt(e.priority):void 0,archived:e.archived!==void 0?e.archived==="true":!1,limit:parseInt(e.limit)}):P(t.db,{priority:e.priority?parseInt(e.priority):void 0,archived:e.archived!==void 0?e.archived==="true":!1,limit:parseInt(e.limit)});if(t.jsonOutput)console.log(JSON.stringify(s,null,2));else{if(s.length===0){console.log(h.gray("No specs found"));return}console.log(h.bold(`
154
- Found ${s.length} spec(s):
155
- `));for(let n of s)console.log(h.cyan(n.id),n.title),console.log(h.gray(` Priority: ${n.priority} | ${n.file_path}`));console.log()}}catch(s){console.error(h.red("\u2717 Failed to list specs")),console.error(s instanceof Error?s.message:String(s)),process.exit(1)}}async function ys(t,e){try{let s=T(t.db,e);s||(console.error(h.red(`\u2717 Spec not found: ${e}`)),process.exit(1));let n=de(t.db,e,"spec"),o=ue(t.db,e,"spec"),r=te(t.db,e,"spec"),a=V(t.db,{spec_id:e});if(t.jsonOutput)console.log(JSON.stringify({...s,relationships:{outgoing:n,incoming:o},tags:r,feedback:a},null,2));else{if(console.log(),console.log(h.bold.cyan(s.id),h.bold(s.title)),console.log(h.gray("\u2500".repeat(60))),console.log(h.gray("Priority:"),s.priority),console.log(h.gray("File:"),s.file_path),s.parent_id&&console.log(h.gray("Parent:"),s.parent_id),console.log(h.gray("Created:"),s.created_at),console.log(h.gray("Updated:"),s.updated_at),r.length>0&&console.log(h.gray("Tags:"),r.join(", ")),s.content&&(console.log(),console.log(h.bold("Content:")),console.log(s.content)),n.length>0){console.log(),console.log(h.bold("Outgoing Relationships:"));for(let i of n)console.log(` ${h.yellow(i.relationship_type)} \u2192 ${h.cyan(i.to_id)} (${i.to_type})`)}if(o.length>0){console.log(),console.log(h.bold("Incoming Relationships:"));for(let i of o)console.log(` ${h.cyan(i.from_id)} (${i.from_type}) \u2192 ${h.yellow(i.relationship_type)}`)}if(a.length>0){console.log(),console.log(h.bold("Feedback Received:"));for(let i of a){let d=typeof i.anchor=="string"?JSON.parse(i.anchor):i.anchor,c=i.dismissed?h.gray:h.white,l=d.anchor_status==="valid"?h.green:d.anchor_status==="relocated"?h.yellow:h.red;console.log(` ${h.cyan(i.id)} \u2190 ${h.cyan(i.issue_id)}`,c(`[${i.dismissed?"dismissed":"active"}]`),l(`[${d.anchor_status}]`)),console.log(h.gray(` Type: ${i.feedback_type} | ${d.section_heading||"No section"} (line ${d.line_number})`));let p=i.content.substring(0,60)+(i.content.length>60?"...":"");console.log(h.gray(` ${p}`))}}console.log()}}catch(s){console.error(h.red("\u2717 Failed to show spec")),console.error(s instanceof Error?s.message:String(s)),process.exit(1)}}async function _s(t,e,s){try{let n=T(t.db,e);n||(console.error(h.red(`\u2717 Spec not found: ${e}`)),process.exit(1));let{updateSpec:o}=await Promise.resolve().then(()=>(K(),$t)),r={};s.title&&(r.title=s.title),s.priority&&(r.priority=parseInt(s.priority)),s.description!==void 0&&(r.content=s.description),s.parent!==void 0&&(r.parent_id=s.parent||void 0),s.archived!==void 0&&(r.archived=s.archived==="true");let a=o(t.db,e,r);if(s.tags!==void 0){let i=s.tags.split(",").map(d=>d.trim());Z(t.db,e,"spec",i)}if(s.description!==void 0||s.title||s.priority||s.parent||s.tags){let i=ve.join(t.outputDir,n.file_path),d="";if(ge.existsSync(i)){d=ge.readFileSync(i,"utf8");let y=d.match(/^---\n[\s\S]*?\n---\n([\s\S]*)$/);y&&(d=y[1])}let c=te(t.db,e,"spec"),l={id:a.id,title:a.title,priority:a.priority,created_at:a.created_at,...a.parent_id&&{parent_id:a.parent_id},...c.length>0&&{tags:c}},p=s.description!==void 0?s.description:d;Ze(i,l,p)}await R(t.db,{outputDir:t.outputDir}),t.jsonOutput?console.log(JSON.stringify(a,null,2)):(console.log(h.green("\u2713 Updated spec"),h.cyan(e)),s.title&&console.log(h.gray(` Title: ${a.title}`)),s.priority&&console.log(h.gray(` Priority: ${a.priority}`)))}catch(n){console.error(h.red("\u2717 Failed to update spec")),console.error(n instanceof Error?n.message:String(n)),process.exit(1)}}async function bs(t,e,s){try{let n=[];for(let o of e)try{let r=T(t.db,o);if(!r){n.push({id:o,success:!1,error:"Spec not found"}),t.jsonOutput||console.error(h.red("\u2717 Spec not found:"),h.cyan(o));continue}let a=ve.join(t.outputDir,r.file_path),{deleteSpec:i}=await Promise.resolve().then(()=>(K(),$t));i(t.db,o)?(ge.existsSync(a)&&ge.unlinkSync(a),n.push({id:o,success:!0}),t.jsonOutput||console.log(h.green("\u2713 Deleted spec"),h.cyan(o))):(n.push({id:o,success:!1,error:"Delete failed"}),t.jsonOutput||console.error(h.red("\u2717 Failed to delete spec"),h.cyan(o)))}catch(r){let a=r instanceof Error?r.message:String(r);n.push({id:o,success:!1,error:a}),t.jsonOutput||console.error(h.red("\u2717 Failed to process"),h.cyan(o),":",a)}await R(t.db,{outputDir:t.outputDir}),t.jsonOutput&&console.log(JSON.stringify(n,null,2))}catch(n){console.error(h.red("\u2717 Failed to delete specs")),console.error(n instanceof Error?n.message:String(n)),process.exit(1)}}xe();W();ie();Ie();be();import u from"chalk";async function Ss(t,e,s){try{let n=ct(t.db,t.outputDir),o=Te(t.db,{id:n,title:e,content:s.description||"",status:"open",priority:parseInt(s.priority),assignee:s.assignee||void 0,parent_id:s.parent||void 0});if(s.tags){let r=s.tags.split(",").map(a=>a.trim());Z(t.db,n,"issue",r)}await R(t.db,{outputDir:t.outputDir}),t.jsonOutput?console.log(JSON.stringify({id:n,title:e,status:"open"},null,2)):(console.log(u.green("\u2713 Created issue"),u.cyan(n)),console.log(u.gray(` Title: ${e}`)),s.assignee&&console.log(u.gray(` Assignee: ${s.assignee}`)))}catch(n){console.error(u.red("\u2717 Failed to create issue")),console.error(n instanceof Error?n.message:String(n)),process.exit(1)}}async function Ds(t,e){try{let s=e.grep?Rt(t.db,e.grep,{status:e.status,assignee:e.assignee,priority:e.priority?parseInt(e.priority):void 0,archived:e.archived!==void 0?e.archived==="true":!1,limit:parseInt(e.limit)}):U(t.db,{status:e.status,assignee:e.assignee,priority:e.priority?parseInt(e.priority):void 0,archived:e.archived!==void 0?e.archived==="true":!1,limit:parseInt(e.limit)});if(t.jsonOutput)console.log(JSON.stringify(s,null,2));else{if(s.length===0){console.log(u.gray("No issues found"));return}console.log(u.bold(`
156
- Found ${s.length} issue(s):
157
- `));for(let n of s){let o=n.status==="closed"?u.green:n.status==="in_progress"?u.yellow:n.status==="blocked"?u.red:u.gray,r=n.assignee?u.gray(`@${n.assignee}`):"";console.log(u.cyan(n.id),o(`[${n.status}]`),n.title,r),console.log(u.gray(` Priority: ${n.priority}`))}console.log()}}catch(s){console.error(u.red("\u2717 Failed to list issues")),console.error(s instanceof Error?s.message:String(s)),process.exit(1)}}async function ws(t,e){try{let s=O(t.db,e);s||(console.error(u.red(`\u2717 Issue not found: ${e}`)),process.exit(1));let n=de(t.db,e,"issue"),o=ue(t.db,e,"issue"),r=te(t.db,e,"issue"),a=V(t.db,{issue_id:e});if(t.jsonOutput)console.log(JSON.stringify({...s,relationships:{outgoing:n,incoming:o},tags:r,feedback:a},null,2));else{if(console.log(),console.log(u.bold.cyan(s.id),u.bold(s.title)),console.log(u.gray("\u2500".repeat(60))),console.log(u.gray("Status:"),s.status),console.log(u.gray("Priority:"),s.priority),s.assignee&&console.log(u.gray("Assignee:"),s.assignee),s.parent_id&&console.log(u.gray("Parent:"),s.parent_id),console.log(u.gray("Created:"),s.created_at),console.log(u.gray("Updated:"),s.updated_at),s.closed_at&&console.log(u.gray("Closed:"),s.closed_at),r.length>0&&console.log(u.gray("Tags:"),r.join(", ")),s.content&&(console.log(),console.log(u.bold("Content:")),console.log(s.content)),s.content&&(console.log(),console.log(u.bold("Content:")),console.log(s.content)),n.length>0){console.log(),console.log(u.bold("Outgoing Relationships:"));for(let i of n)console.log(` ${u.yellow(i.relationship_type)} \u2192 ${u.cyan(i.to_id)} (${i.to_type})`)}if(o.length>0){console.log(),console.log(u.bold("Incoming Relationships:"));for(let i of o)console.log(` ${u.cyan(i.from_id)} (${i.from_type}) \u2192 ${u.yellow(i.relationship_type)}`)}if(a.length>0){console.log(),console.log(u.bold("Feedback Provided:"));for(let i of a){let d=typeof i.anchor=="string"?JSON.parse(i.anchor):i.anchor,c=i.dismissed?u.gray:u.white,l=d.anchor_status==="valid"?u.green:d.anchor_status==="relocated"?u.yellow:u.red;console.log(` ${u.cyan(i.id)} \u2192 ${u.cyan(i.spec_id)}`,c(`[${i.dismissed?"dismissed":"active"}]`),l(`[${d.anchor_status}]`)),console.log(u.gray(` Type: ${i.feedback_type} | ${d.section_heading||"No section"} (line ${d.line_number})`));let p=i.content.substring(0,60)+(i.content.length>60?"...":"");console.log(u.gray(` ${p}`))}}console.log()}}catch(s){console.error(u.red("\u2717 Failed to show issue")),console.error(s instanceof Error?s.message:String(s)),process.exit(1)}}async function Es(t,e,s){try{let n={};s.status&&(n.status=s.status),s.priority&&(n.priority=parseInt(s.priority)),s.assignee&&(n.assignee=s.assignee),s.title&&(n.title=s.title),s.description&&(n.description=s.description),s.archived!==void 0&&(n.archived=s.archived==="true");let o=ee(t.db,e,n);await R(t.db,{outputDir:t.outputDir}),t.jsonOutput?console.log(JSON.stringify(o,null,2)):(console.log(u.green("\u2713 Updated issue"),u.cyan(e)),Object.keys(n).forEach(r=>{console.log(u.gray(` ${r}: ${n[r]}`))}))}catch(n){console.error(u.red("\u2717 Failed to update issue")),console.error(n instanceof Error?n.message:String(n)),process.exit(1)}}async function xs(t,e,s){try{let n=[];for(let o of e)try{lt(t.db,o),n.push({id:o,success:!0}),t.jsonOutput||console.log(u.green("\u2713 Closed issue"),u.cyan(o))}catch(r){n.push({id:o,success:!1,error:r instanceof Error?r.message:String(r)}),t.jsonOutput||console.error(u.red("\u2717 Failed to close"),u.cyan(o),":",r instanceof Error?r.message:String(r))}await R(t.db,{outputDir:t.outputDir}),t.jsonOutput&&console.log(JSON.stringify(n,null,2))}catch(n){console.error(u.red("\u2717 Failed to close issues")),console.error(n instanceof Error?n.message:String(n)),process.exit(1)}}async function Os(t,e,s){try{let n=[];for(let o of e)try{if(!O(t.db,o)){n.push({id:o,success:!1,error:"Issue not found"}),t.jsonOutput||console.error(u.red("\u2717 Issue not found:"),u.cyan(o));continue}if(s.hard){let{deleteIssue:a}=await Promise.resolve().then(()=>(W(),ss));a(t.db,o)?(n.push({id:o,success:!0,action:"hard_delete"}),t.jsonOutput||console.log(u.green("\u2713 Permanently deleted issue"),u.cyan(o))):(n.push({id:o,success:!1,error:"Delete failed"}),t.jsonOutput||console.error(u.red("\u2717 Failed to delete issue"),u.cyan(o)))}else lt(t.db,o),n.push({id:o,success:!0,action:"soft_delete",status:"closed"}),t.jsonOutput||console.log(u.green("\u2713 Closed issue"),u.cyan(o))}catch(r){let a=r instanceof Error?r.message:String(r);n.push({id:o,success:!1,error:a}),t.jsonOutput||console.error(u.red("\u2717 Failed to process"),u.cyan(o),":",a)}await R(t.db,{outputDir:t.outputDir}),t.jsonOutput&&console.log(JSON.stringify(n,null,2))}catch(n){console.error(u.red("\u2717 Failed to delete issues")),console.error(n instanceof Error?n.message:String(n)),process.exit(1)}}ie();import ke from"chalk";import*as Pt from"path";import*as Pe from"fs";import*as et from"path";K();W();ie();Ie();be();xe();function no(t){let{file_path:e,entity_type:s,...n}=t;return n}function oo(t,e,s,n,o,r){let a=new Date().toISOString(),i={...e};if(i.id||(i.id=s==="spec"?at(t,o):ct(t,o)),!i.title){let c=Pe.readFileSync(n,"utf8").match(/^#\s+(.+)$/m);i.title=c?c[1]:et.basename(n,".md")}return i.created_at||(i.created_at=a),i.updated_at||(i.updated_at=a),s==="spec"||i.status||(i.status="open"),!i.priority&&i.priority!==0&&(i.priority=2),i}async function tt(t,e,s={}){let{outputDir:n=".sudocode",autoExport:o=!0,user:r="system",autoInitialize:a=!0,writeBackFrontmatter:i=!0}=s;try{let d=Qe(e,t,n),{data:c,content:l,references:p}=d,y=ro(c,e),g=c.id,L=g,v=et.relative(n,e),x=v.startsWith("..")?et.relative(process.cwd(),e):v,b=null,C=null;if(y==="spec"){if(c.file_path=x,L&&(C=T(t,L)),b=Ve(t,x),C)g=C.id,C.file_path!==x&&(console.log(`[sync] File renamed: ${C.file_path} \u2192 ${x}`),b&&b.id!==C.id&&console.warn(`[sync] Warning: File path conflict! Spec ${b.id} already exists at ${x}. Keeping ${C.id} and updating path.`));else if(b)g=b.id,c.id=g;else if(L&&b){let w=b.id;console.warn(`[sync] Warning: ID in frontmatter (${L}) differs from existing spec ID (${w}) for ${x}. Using existing ID.`),g=w,c.id=g}}if(!g)if(a){if(c=oo(t,c,y,e,n,r),g=c.id,i){let w=no(c);Mt(e,w)}}else return{success:!1,action:"no-change",entityId:"",entityType:y,error:"Missing id in frontmatter (auto-initialization disabled)"};let D=!(y==="spec"?T(t,g):O(t,g)),S=Pe.statSync(e),m=new Date(S.mtimeMs).toISOString();return y==="spec"?await io(t,g,c,l,p,D,r,m):await ao(t,g,c,l,p,D,r,m),o&&await R(t,{outputDir:n}),{success:!0,action:D?"created":"updated",entityId:g,entityType:y}}catch(d){return{success:!1,action:"no-change",entityId:"",entityType:"spec",error:d instanceof Error?d.message:String(d)}}}async function me(t,e,s,n){try{let o=s==="spec"?T(t,e):O(t,e);if(!o)return{success:!1,action:"no-change",entityId:e,entityType:s,error:`${s} not found: ${e}`};let{getOutgoingRelationships:r}=await Promise.resolve().then(()=>(ie(),ut)),a=r(t,e,s),i=te(t,e,s),d=co(o,s,a,i),c=Pe.existsSync(n);if(c)Mt(n,d);else{let l=o.content||"";Ze(n,d,l)}return{success:!0,action:c?"updated":"created",entityId:e,entityType:s}}catch(o){return{success:!1,action:"no-change",entityId:e,entityType:s,error:o instanceof Error?o.message:String(o)}}}function ro(t,e){return t.entity_type==="issue"?"issue":t.entity_type==="spec"?"spec":e.includes("/issues/")||e.includes("/issue-")?"issue":(e.includes("/specs/")||e.includes("/spec-"),"spec")}async function io(t,e,s,n,o,r,a,i){let d=r?null:T(t,e),c=d?.content||"",l={id:e,title:s.title||"Untitled",file_path:s.file_path||"",content:n,priority:s.priority??2,parent_id:s.parent_id||void 0};if(r)Oe(t,{...l,updated_at:i});else{let p=d?.title!==l.title||d?.content!==l.content||d?.priority!==l.priority||d?.parent_id!==l.parent_id||d?.file_path!==l.file_path;if(_e(t,e,{...l,...p&&i?{updated_at:i}:{}}),c!==n){let y=V(t,{spec_id:e});if(y.length>0)for(let g of y){let L=typeof g.anchor=="string"?JSON.parse(g.anchor):g.anchor,v=fs(c,n,L);Ke(t,g.id,{anchor:v})}}}s.tags&&Array.isArray(s.tags)&&Z(t,e,"spec",s.tags),await Ts(t,e,"spec",o,s.relationships,a)}async function ao(t,e,s,n,o,r,a,i){let d=r?null:O(t,e),c={id:e,title:s.title||"Untitled",content:n,status:s.status||"open",priority:s.priority??2,assignee:s.assignee||void 0,parent_id:s.parent_id||void 0};if(r)Te(t,{...c,updated_at:i});else{let l=d?.title!==c.title||d?.content!==c.content||d?.status!==c.status||d?.priority!==c.priority||d?.assignee!==c.assignee||d?.parent_id!==c.parent_id;ee(t,e,{...c,...l&&i?{updated_at:i}:{}})}s.tags&&Array.isArray(s.tags)&&Z(t,e,"issue",s.tags),await Ts(t,e,"issue",o,s.relationships,a)}async function Ts(t,e,s,n,o,r="system"){let{getOutgoingRelationships:a}=await Promise.resolve().then(()=>(ie(),ut)),i=a(t,e,s),d=new Set(i.map(c=>`${c.relationship_type}:${c.to_type}:${c.to_id}`));for(let c of n){let l=c.relationshipType||"references",p=`${l}:${c.type}:${c.id}`;if(!d.has(p))try{Y(t,{from_id:e,from_type:s,to_id:c.id,to_type:c.type,relationship_type:l,metadata:c.anchor?JSON.stringify({anchor:c.anchor}):void 0})}catch{}}if(o&&Array.isArray(o))for(let c of o){let l=`${c.relationship_type}:${c.target_type}:${c.target_id}`;if(!d.has(l))try{Y(t,{from_id:e,from_type:s,to_id:c.target_id,to_type:c.target_type,relationship_type:c.relationship_type})}catch{}}}function co(t,e,s,n){let o={id:t.id,title:t.title,priority:t.priority,created_at:t.created_at};if(t.parent_id&&(o.parent_id=t.parent_id),n.length>0&&(o.tags=n),s.length>0&&(o.relationships=s),e==="spec")return o;{let r=t,a={...o,status:r.status};return r.assignee&&(a.assignee=r.assignee),r.closed_at&&(a.closed_at=r.closed_at),a}}K();W();async function Is(t,e,s,n){try{let o,r;if(T(t.db,e)?o="spec":O(t.db,e)?o="issue":(console.error(ke.red(`\u2717 Entity not found: ${e}`)),process.exit(1)),T(t.db,s)?r="spec":O(t.db,s)?r="issue":(console.error(ke.red(`\u2717 Entity not found: ${s}`)),process.exit(1)),Y(t.db,{from_id:e,from_type:o,to_id:s,to_type:r,relationship_type:n.type}),await R(t.db,{outputDir:t.outputDir}),o==="spec"){let a=T(t.db,e);if(a){let i=Pt.join(t.outputDir,a.file_path);await me(t.db,e,"spec",i)}}else if(O(t.db,e)){let i=Pt.join(t.outputDir,"issues",`${e}.md`);await me(t.db,e,"issue",i)}t.jsonOutput?console.log(JSON.stringify({from:e,to:s,type:n.type,success:!0},null,2)):(console.log(ke.green("\u2713 Created relationship")),console.log(ke.cyan(e),ke.yellow(n.type),"\u2192",ke.cyan(s)))}catch(o){console.error(ke.red("\u2717 Failed to create relationship")),console.error(o instanceof Error?o.message:String(o)),process.exit(1)}}import q from"chalk";import*as Ue from"fs";import*as Ut from"path";function lo(t,e,s){let n=`[[${t}`;return e&&(n+=`|${e}`),n+="]]",s&&(n+=`{ ${s} }`),n}function po(t,e){let s=t.split(`
158
- `);if(e<1||e>s.length)throw new Error(`Line number ${e} is out of bounds (content has ${s.length} lines)`);let n=0;for(let o=0;o<e-1;o++)n+=s[o].length+1;return n}function uo(t,e){let s=t.indexOf(e);if(s===-1)throw new Error(`Text not found: "${e}"`);return s}function vs(t,e,s){let{referenceId:n,displayText:o,relationshipType:r,format:a="inline",position:i="after"}=s;if(!e.line&&!e.text)throw new Error("Either line or text must be specified");if(e.line&&e.text)throw new Error("Cannot specify both line and text");let d=lo(n,o,r),c;if(e.line){if(c=po(t,e.line),i==="after"){let y=t.indexOf(`
159
- `,c);c=y===-1?t.length:y}}else if(e.text)c=uo(t,e.text),i==="after"&&(c+=e.text.length);else throw new Error("Location must specify line or text");let l;return a==="newline"?i==="before"?l=`${d}
160
- `:l=`
161
- ${d}`:i==="before"?l=`${d} `:l=` ${d}`,t.slice(0,c)+l+t.slice(c)}K();W();async function Wt(t,e,s,n){try{!n.line&&!n.text&&(console.error(q.red("\u2717 Either --line or --text must be specified")),process.exit(1)),n.line&&n.text&&(console.error(q.red("\u2717 Cannot specify both --line and --text")),process.exit(1));let o,r,a;o=T(t.db,e),o?(r="spec",a=Ut.join(t.outputDir,o.file_path)):(o=O(t.db,e),o?(r="issue",a=Ut.join(t.outputDir,"issues",`${e}.md`)):(console.error(q.red(`\u2717 Entity not found: ${e}`)),process.exit(1))),Ue.existsSync(a)||(console.error(q.red(`\u2717 File not found: ${a}`)),process.exit(1));let i=Ue.readFileSync(a,"utf8"),d=At(i),c={};if(n.line){let l=parseInt(n.line);(isNaN(l)||l<1)&&(console.error(q.red("\u2717 Invalid line number")),process.exit(1)),c.line=l}else n.text&&(c.text=n.text);try{let l=vs(d.content,c,{referenceId:s,displayText:n.display,relationshipType:n.type,format:n.format||"inline",position:n.position||"after"}),p=jt(d.data,l);Ue.writeFileSync(a,p,"utf8"),r==="spec"?_e(t.db,e,{content:l}):ee(t.db,e,{content:l}),await R(t.db,{outputDir:t.outputDir}),t.jsonOutput?console.log(JSON.stringify({entity_id:e,reference_id:s,location:c.line?`line ${c.line}`:`text: "${c.text}"`,success:!0},null,2)):(console.log(q.green("\u2713 Added reference to"),q.cyan(e)),console.log(q.gray(` Reference: [[${s}${n.display?`|${n.display}`:""}]]`)),n.type&&console.log(q.gray(` Type: ${n.type}`)),c.line?console.log(q.gray(` Location: line ${c.line} (${n.position||"after"})`)):c.text&&console.log(q.gray(` Location: after "${c.text}"`)),console.log(q.gray(` Format: ${n.format||"inline"}`)))}catch(l){l instanceof Error&&(l.message.includes("not found")?console.error(q.red(`\u2717 ${l.message}`)):l.message.includes("out of bounds")?console.error(q.red(`\u2717 ${l.message}`)):(console.error(q.red("\u2717 Failed to add reference")),console.error(l.message))),process.exit(1)}}catch(o){console.error(q.red("\u2717 Failed to add reference")),console.error(o instanceof Error?o.message:String(o)),process.exit(1)}}W();import ae from"chalk";async function ks(t,e){try{let s={};if(s.issues=Le(t.db),t.jsonOutput)console.log(JSON.stringify(s,null,2));else{if(s.issues.length===0)console.log(ae.gray(`
162
- No ready issues`));else{console.log(ae.bold(`
163
- Ready Issues (${s.issues.length}):
164
- `));for(let n of s.issues){let o=n.assignee?ae.gray(`@${n.assignee}`):"";console.log(ae.cyan(n.id),n.title,o),console.log(ae.gray(` Priority: ${n.priority}`))}}console.log()}}catch(s){console.error(ae.red("\u2717 Failed to get ready items")),console.error(s instanceof Error?s.message:String(s)),process.exit(1)}}async function $s(t,e){try{let s={};if(s.issues=Ae(t.db),t.jsonOutput)console.log(JSON.stringify(s,null,2));else{if(s.issues.length===0)console.log(ae.gray(`
165
- No blocked issues`));else{console.log(ae.bold(`
166
- Blocked Issues (${s.issues.length}):
167
- `));for(let n of s.issues)console.log(ae.cyan(n.id),n.title),console.log(ae.gray(` Reason: ${n.status}`))}console.log()}}catch(s){console.error(ae.red("\u2717 Failed to get blocked items")),console.error(s instanceof Error?s.message:String(s)),process.exit(1)}}import E from"chalk";import*as Q from"fs";import*as j from"path";yt();import yo from"chokidar";import*as A from"path";import*as $e from"fs";yt();K();W();be();Ie();function As(t){let{db:e,baseDir:s,debounceDelay:n=2e3,onLog:o=console.log,onError:r=console.error,ignoreInitial:a=!0,syncJSONLToMarkdown:i=!1}=t,d={filesWatched:0,changesPending:0,changesProcessed:0,errors:0},c=new Map;function l(_,D,S){try{if(!$e.existsSync(_))return!1;let m=Qe(_,e,s),{data:w,content:M}=m,J=S==="spec"?T(e,D):O(e,D);if(!J||w.title!==J.title||M.trim()!==(J.content||"").trim())return!1;if(S==="spec"){if(w.priority!==J.priority)return!1}else{let k=J;if(w.status!==k.status||w.priority!==k.priority)return!1}return!0}catch{return!1}}function p(_){try{if(!$e.existsSync(_))return!1;let S=$e.readFileSync(_,"utf8").trim().split(`
168
- `).filter(m=>m.trim());for(let m of S){let w=JSON.parse(m),M=w.id,J=_.includes("specs.jsonl")?"spec":"issue",k=J==="spec"?T(e,M):O(e,M);if(!k||w.title!==k.title||(w.content||"").trim()!==(k.content||"").trim()||w.priority!==k.priority||w.parent_id!==k.parent_id||w.archived!==k.archived||w.archived_at!==k.archived_at)return!0;if(J==="spec"){let oe=k;if(w.file_path!==oe.file_path)return!0}else if(J==="issue"){let oe=k;if(w.status!==oe.status||w.assignee!==oe.assignee||w.closed_at!==oe.closed_at)return!0;let Ot=V(e,{issue_id:M}),Re=w.feedback||[];if(Re.length!==Ot.length)return!0;for(let Fe of Re){let pe=Ot.find(pn=>pn.id===Fe.id);if(!pe||Fe.content!==pe.content||Fe.feedback_type!==pe.feedback_type||Fe.spec_id!==pe.spec_id||Fe.dismissed!==pe.dismissed)return!0;let dn=JSON.stringify(Fe.anchor||null),ln=JSON.stringify(pe.anchor&&typeof pe.anchor=="string"?JSON.parse(pe.anchor):pe.anchor||null);if(dn!==ln)return!0}}let F=te(e,M,J),ne=w.tags||[];if(ne.length!==F.length)return!0;let X=new Set(F);if(ne.some(oe=>!X.has(oe)))return!0;let{getOutgoingRelationships:Ee}=(ie(),hn(ut)),ot=Ee(e,M,J),xt=w.relationships||[];if(xt.length!==ot.length)return!0;for(let oe of xt)if(!ot.find(Re=>Re.to_id===oe.to&&Re.to_type===oe.to_type&&Re.relationship_type===oe.type))return!0;if(w.updated_at&&new Date(w.updated_at).getTime()>new Date(k.updated_at).getTime())return!0}return!1}catch{return!0}}let y=A.join(s,"specs"),g=A.join(s,"issues"),L=A.join(s,"specs.jsonl"),v=A.join(s,"issues.jsonl"),x=yo.watch([y,g,L,v],{persistent:!0,ignoreInitial:a,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}});o(`[watch] Watching directories: ${y}, ${g} and JSONL files`);async function b(_,D){try{let S=A.extname(_),m=A.basename(_);if(S===".md")if(o(`[watch] ${D} ${A.relative(s,_)}`),D==="unlink"){let w=A.relative(s,_),M=Ve(e,w);M?Ge(e,M.id)&&(o(`[watch] Deleted spec ${M.id} (file removed)`),await R(e,{outputDir:s})):o(`[watch] File deleted but no spec found: ${w}`)}else{try{let M=Qe(_,e,s),{data:J}=M,k=J.id,F=A.relative(s,_),ne=F.startsWith("specs/")||F.startsWith("specs\\")?"spec":"issue";if(k&&l(_,k,ne))return;if(k){let X=ne==="spec"?T(e,k):O(e,k);if(X){let ot=$e.statSync(_).mtimeMs;if(new Date(X.updated_at).getTime()>ot){o(`[watch] Skipping sync for ${ne} ${k} (database is newer)`);return}}}}catch{}let w=await tt(e,_,{outputDir:s,autoExport:!0,autoInitialize:!0,writeBackFrontmatter:!0});w.success?o(`[watch] Synced ${w.entityType} ${w.entityId} (${w.action})`):(r(new Error(`Failed to sync ${_}: ${w.error}`)),d.errors++)}else if((m==="specs.jsonl"||m==="issues.jsonl")&&(o(`[watch] ${D} ${A.relative(s,_)}`),D!=="unlink"&&(p(_)&&(await st(e,{inputDir:s}),o("[watch] Imported JSONL changes to database")),i))){o("[watch] Checking for entities that need markdown updates...");let w=0,M=P(e);for(let F of M)if(F.file_path){let ne=A.join(s,F.file_path);if(l(ne,F.id,"spec"))continue;let X=await me(e,F.id,"spec",ne);X.success?(w++,o(`[watch] Synced spec ${F.id} to ${F.file_path} (${X.action})`)):X.error&&r(new Error(`Failed to sync spec ${F.id}: ${X.error}`))}let J=U(e),k=A.join(s,"issues");for(let F of J){let ne=`${F.id}.md`,X=A.join(k,ne);if(l(X,F.id,"issue"))continue;let Ee=await me(e,F.id,"issue",X);Ee.success?(w++,o(`[watch] Synced issue ${F.id} to markdown (${Ee.action})`)):Ee.error&&r(new Error(`Failed to sync issue ${F.id}: ${Ee.error}`))}w>0?o(`[watch] Synced ${w} entities to markdown`):o("[watch] All markdown files are up to date")}d.changesProcessed++}catch(S){let m=S instanceof Error?S.message:String(S);r(new Error(`Error processing ${_}: ${m}`)),d.errors++}}function C(_,D){let S=c.get(_);S&&(clearTimeout(S),d.changesPending--),d.changesPending++;let m=setTimeout(()=>{c.delete(_),d.changesPending--,b(_,D)},n);c.set(_,m)}return x.on("add",_=>C(_,"add")),x.on("change",_=>C(_,"change")),x.on("unlink",_=>C(_,"unlink")),x.on("ready",()=>{let _=x.getWatched();d.filesWatched=Object.keys(_).reduce((D,S)=>D+_[S].length,0),o(`[watch] Watching ${d.filesWatched} files in ${s}`)}),x.on("error",_=>{r(_),d.errors++}),{stop:async()=>{o("[watch] Stopping watcher...");for(let _ of c.values())clearTimeout(_);c.clear(),d.changesPending=0,await x.close(),o("[watch] Watcher stopped")},getStats:()=>({...d})}}function js(t){let e=!1,s=async n=>{if(!e){e=!0,console.log(`
169
- [watch] Received ${n}, shutting down gracefully...`);try{await t.stop(),process.exit(0)}catch(o){console.error("[watch] Error during shutdown:",o),process.exit(1)}}};process.on("SIGINT",()=>s("SIGINT")),process.on("SIGTERM",()=>s("SIGTERM")),process.on("unhandledRejection",(n,o)=>{console.error("[watch] Unhandled Rejection at:",o,"reason:",n)})}K();W();import se from"chalk";import*as $ from"fs";import*as G from"path";Ye();function Ms(t){let e=G.join(t,"config.json"),s=G.join(t,"cache.db"),n=G.join(t,"specs"),o=G.join(t,"issues");return $.existsSync(e)&&$.existsSync(s)&&$.existsSync(n)&&$.existsSync(o)}async function Vt(t={}){let e=t.specPrefix||"SPEC",s=t.issuePrefix||"ISSUE",n=t.dir||G.join(process.cwd(),".sudocode"),o=t.jsonOutput||!1;$.mkdirSync(n,{recursive:!0}),$.mkdirSync(G.join(n,"specs"),{recursive:!0}),$.mkdirSync(G.join(n,"issues"),{recursive:!0});let r=[],a=G.join(n,"cache.db"),i=$.existsSync(a),d;i?(r.push("cache.db"),d=ze({path:a})):($.mkdirSync(G.dirname(a),{recursive:!0}),d=ze({path:a}));let c={version:re,id_prefix:{spec:e,issue:s},worktree:{worktreeStoragePath:".sudocode/worktrees",autoCreateBranches:!0,autoDeleteBranches:!1,enableSparseCheckout:!1,branchPrefix:"sudocode",cleanupOrphanedWorktreesOnStartup:!0}};$.writeFileSync(G.join(n,"config.json"),JSON.stringify(c,null,2),"utf8");let l=!1,p=!1,y=G.join(n,"specs.jsonl");$.existsSync(y)?(r.push("specs.jsonl"),l=$.readFileSync(y,"utf8").trim().length>0):$.writeFileSync(y,"","utf8");let g=G.join(n,"issues.jsonl");if($.existsSync(g)?(r.push("issues.jsonl"),p=$.readFileSync(g,"utf8").trim().length>0):$.writeFileSync(g,"","utf8"),l||p)try{o||console.log(se.blue("Importing from existing JSONL files..."));let{importFromJSONL:v}=await Promise.resolve().then(()=>(yt(),Ls)),x=await v(d,{inputDir:n,resolveCollisions:!0});o||((x.specs.added>0||x.specs.updated>0)&&console.log(se.gray(` Specs: ${x.specs.added} added, ${x.specs.updated} updated`)),(x.issues.added>0||x.issues.updated>0)&&console.log(se.gray(` Issues: ${x.issues.added} added, ${x.issues.updated} updated`)),x.collisions.length>0&&console.log(se.yellow(` Resolved ${x.collisions.length} ID collisions`)))}catch(v){o||console.log(se.yellow(` Warning: Failed to import JSONL data - ${v instanceof Error?v.message:String(v)}`))}$.writeFileSync(G.join(n,".gitignore"),`cache.db*
170
- issues/
171
- specs/
172
- worktrees/`,"utf8"),d.close(),o||(console.log(se.green("\u2713 Initialized sudocode in"),se.cyan(n)),console.log(se.gray(` Spec prefix: ${e}`)),console.log(se.gray(` Issue prefix: ${s}`)),console.log(se.gray(` Database: ${a}`)),r.length>0&&console.log(se.yellow(` Preserved existing: ${r.join(", ")}`)))}async function Js(t){try{await Vt(t)}catch(e){console.error(se.red("\u2717 Initialization failed")),console.error(e instanceof Error?e.message:String(e)),process.exit(1)}}async function qs(t,e){if(!Ms(t.outputDir)){console.log(E.blue("Initializing sudocode...")),console.log();try{await Vt({specPrefix:"SPEC",issuePrefix:"ISSUE",dir:t.outputDir,jsonOutput:t.jsonOutput})}catch(s){console.error(E.red("\u2717 Auto-initialization failed")),console.error(s instanceof Error?s.message:String(s)),process.exit(1)}console.log()}if(e.watch){console.log(E.blue("Starting file watcher...")),console.log(E.gray(` Watching: ${t.outputDir}`)),console.log(E.gray(" Press Ctrl+C to stop"));let s=As({db:t.db,baseDir:t.outputDir,debounceDelay:2e3,syncJSONLToMarkdown:!0,onLog:n=>{t.jsonOutput||console.log(E.gray(n))},onError:n=>{console.error(E.red(`[watch] Error: ${n.message}`))}});js(s),await new Promise(()=>{})}else if(e.fromMarkdown)await Ps(t);else if(e.toMarkdown)await Us(t);else{let{direction:s,reason:n}=_o(t);console.log(E.blue("Detecting sync direction...")),console.log(E.gray(` ${n}`)),console.log(),s==="no-sync"?(console.log(E.green("\u2713 Everything is in sync")),console.log(E.gray(" Use --from-markdown or --to-markdown to force a specific direction"))):s==="from-markdown"?(console.log(E.blue("\u2192 Syncing FROM markdown TO database (markdown is newer)")),console.log(),await Ps(t)):s==="to-markdown"&&(console.log(E.blue("\u2192 Syncing FROM database TO markdown (database is newer)")),console.log(),await Us(t))}}async function Hs(t,e){try{await R(t.db,{outputDir:e.output}),t.jsonOutput?console.log(JSON.stringify({success:!0,outputDir:e.output},null,2)):(console.log(E.green("\u2713 Exported to JSONL")),console.log(E.gray(` Output: ${e.output}`)))}catch(s){console.error(E.red("\u2717 Failed to export")),console.error(s instanceof Error?s.message:String(s)),process.exit(1)}}async function zs(t,e){try{await st(t.db,{inputDir:e.input}),t.jsonOutput?console.log(JSON.stringify({success:!0,inputDir:e.input},null,2)):(console.log(E.green("\u2713 Imported from JSONL")),console.log(E.gray(` Input: ${e.input}`)))}catch(s){console.error(E.red("\u2717 Failed to import")),console.error(s instanceof Error?s.message:String(s)),process.exit(1)}}async function Ps(t){console.log(E.blue("Syncing from markdown to database..."));let e=j.join(t.outputDir,"specs"),s=j.join(t.outputDir,"issues"),n=0,o=0,r={outputDir:t.outputDir,autoExport:!1,autoInitialize:!0,writeBackFrontmatter:!0};if(Q.existsSync(e)){let a=_t(e);console.log(E.gray(` Found ${a.length} spec files`));for(let i of a){let d=await tt(t.db,i,r);d.success?(n++,console.log(E.gray(` \u2713 ${d.action} ${d.entityType} ${d.entityId}`))):(o++,console.log(E.red(` \u2717 Failed to sync ${j.basename(i)}: ${d.error}`)))}}if(Q.existsSync(s)){let a=_t(s);console.log(E.gray(` Found ${a.length} issue files`));for(let i of a){let d=await tt(t.db,i,r);d.success?(n++,console.log(E.gray(` \u2713 ${d.action} ${d.entityType} ${d.entityId}`))):(o++,console.log(E.red(` \u2717 Failed to sync ${j.basename(i)}: ${d.error}`)))}}n>0&&await R(t.db,{outputDir:t.outputDir}),console.log(),console.log(E.green(`\u2713 Synced ${n} files to database`)),o>0&&console.log(E.yellow(` ${o} errors`))}async function Us(t){console.log(E.blue("Syncing from database to markdown..."));let e=j.join(t.outputDir,"specs"),s=j.join(t.outputDir,"issues");Q.mkdirSync(e,{recursive:!0}),Q.mkdirSync(s,{recursive:!0});let n=0,o=0,r=P(t.db,{});console.log(E.gray(` Found ${r.length} specs in database`));for(let i of r){let d=j.join(t.outputDir,i.file_path);if(!Q.existsSync(d)){let l=gs(i.id,e,i.title);if(l)d=l;else{let p=ht(i.title,i.id,e);d=j.join(e,p)}}let c=await me(t.db,i.id,"spec",d);c.success?(n++,console.log(E.gray(` \u2713 ${c.action} spec ${i.id} \u2192 ${j.basename(d)}`))):(o++,console.log(E.red(` \u2717 Failed to sync spec ${i.id}: ${c.error}`)))}let a=U(t.db,{});console.log(E.gray(` Found ${a.length} issues in database`));for(let i of a){let d=`${i.id}.md`,c=j.join(s,d),l=await me(t.db,i.id,"issue",c);l.success?(n++,console.log(E.gray(` \u2713 ${l.action} issue ${i.id}`))):(o++,console.log(E.red(` \u2717 Failed to sync issue ${i.id}: ${l.error}`)))}console.log(),console.log(E.green(`\u2713 Synced ${n} entities to markdown`)),o>0&&console.log(E.yellow(` ${o} errors`))}function _t(t){let e=[];function s(n){let o=Q.readdirSync(n,{withFileTypes:!0});for(let r of o){let a=j.join(n,r.name);r.isDirectory()?s(a):r.isFile()&&r.name.endsWith(".md")&&e.push(a)}}return s(t),e}function Ws(t){if(t.length===0)return null;let e=null;for(let s of t)try{let o=Q.statSync(s).mtime;(!e||o>e)&&(e=o)}catch{continue}return e}function Bs(t){try{return Q.statSync(t).mtime}catch{return null}}function _o(t){let e=j.join(t.outputDir,"specs"),s=j.join(t.outputDir,"issues"),n=j.join(t.outputDir,"specs.jsonl"),o=j.join(t.outputDir,"issues.jsonl"),r=Bs(n),a=Bs(o),i=[],d=[];Q.existsSync(e)&&(i=_t(e)),Q.existsSync(s)&&(d=_t(s));let c=Ws(i),l=Ws(d),p=!1,y=!1,g=[];return!r&&!c?g.push("No spec files or JSONL found"):!r&&c?(y=!0,g.push("Specs JSONL missing, markdown exists")):r&&!c?(p=!0,g.push("Spec markdown files missing, JSONL exists")):r&&c&&(c>r?(y=!0,g.push(`Spec markdown files are newer (${De(c)} > ${De(r)})`)):r>c?(p=!0,g.push(`Specs JSONL is newer (${De(r)} > ${De(c)})`)):g.push("Specs are in sync")),!a&&!l?g.push("No issue files or JSONL found"):!a&&l?(y=!0,g.push("Issues JSONL missing, markdown exists")):a&&!l?(p=!0,g.push("Issue markdown files missing, JSONL exists")):a&&l&&(l>a?(y=!0,g.push(`Issue markdown files are newer (${De(l)} > ${De(a)})`)):a>l?(p=!0,g.push(`Issues JSONL is newer (${De(a)} > ${De(l)})`)):g.push("Issues are in sync")),y&&p?{direction:"from-markdown",reason:g.join("; ")+" (choosing markdown as source)"}:y?{direction:"from-markdown",reason:g.join("; ")}:p?{direction:"to-markdown",reason:g.join("; ")}:{direction:"no-sync",reason:g.join("; ")}}function De(t){return t.toISOString().replace("T"," ").substring(0,19)}K();W();W();import N from"chalk";async function Ys(t,e){let s=P(t.db,{}),n=U(t.db,{}),o=Le(t.db),r=Ae(t.db),a={open:n.filter(i=>i.status==="open").length,in_progress:n.filter(i=>i.status==="in_progress").length,blocked:n.filter(i=>i.status==="blocked").length,needs_review:n.filter(i=>i.status==="needs_review").length,closed:n.filter(i=>i.status==="closed").length};if(t.jsonOutput){console.log(JSON.stringify({specs:{total:s.length},issues:{total:n.length,by_status:a,ready:o.length,blocked:r.length}},null,2));return}console.log(N.bold(`
173
- Sudocode Status
174
- `)),console.log(N.blue("Specs:")),console.log(` ${N.cyan(s.length)} total`),console.log(),console.log(N.blue("Issues:")),console.log(` ${N.cyan(n.length)} total (${a.open} open, ${a.in_progress} in_progress, ${a.blocked} blocked, ${a.needs_review} needs_review, ${a.closed} closed)`),console.log(` ${N.green(o.length)} ready to work on`),console.log(` ${N.yellow(r.length)} blocked`),console.log(),console.log(N.gray("Sync status: All files in sync")),console.log()}async function Vs(t,e){let s=P(t.db,{}),n=U(t.db,{}),o=Le(t.db),r=Ae(t.db),a={open:n.filter(b=>b.status==="open").length,in_progress:n.filter(b=>b.status==="in_progress").length,blocked:n.filter(b=>b.status==="blocked").length,needs_review:n.filter(b=>b.status==="needs_review").length,closed:n.filter(b=>b.status==="closed").length},i=t.db.prepare(`
175
- SELECT relationship_type, COUNT(*) as count
176
- FROM relationships
177
- GROUP BY relationship_type
178
- `),d={},c=i.all();for(let b of c)d[b.relationship_type]=b.count;let l=c.reduce((b,C)=>b+C.count,0),p=new Date;p.setDate(p.getDate()-7);let y=s.filter(b=>new Date(b.updated_at)>p).length,g=n.filter(b=>new Date(b.updated_at)>p).length,L=n.filter(b=>new Date(b.created_at)>p).length,v=n.filter(b=>b.closed_at&&new Date(b.closed_at)>p).length;if(t.jsonOutput){console.log(JSON.stringify({specs:{total:s.length},issues:{total:n.length,by_status:a,ready:o.length,blocked:r.length},relationships:{total:l,by_type:d},recent_activity:{specs_updated:y,issues_updated:g,issues_created:L,issues_closed:v}},null,2));return}console.log(N.bold(`
179
- Project Statistics
180
- `)),console.log(N.blue("Specs:")),console.log(` Total: ${N.cyan(s.length)}`),console.log(),console.log(N.blue("Issues:")),console.log(` Total: ${N.cyan(n.length)}`),console.log(` By Status: ${a.open} open, ${a.in_progress} in_progress, ${a.blocked} blocked, ${a.needs_review} needs_review, ${a.closed} closed`),console.log(` Ready: ${N.green(o.length)}`),console.log(` Blocked: ${N.yellow(r.length)}`),console.log(),console.log(N.blue("Relationships:")),console.log(` Total: ${N.cyan(l)}`);let x=Object.entries(d).map(([b,C])=>`${C} ${b}`).join(", ");x&&console.log(` ${x}`),console.log(),console.log(N.blue("Recent Activity (last 7 days):")),console.log(` ${y} specs updated`),console.log(` ${g} issues updated`),console.log(` ${L} issues created`),console.log(` ${v} issues closed`),console.log()}be();K();W();import f from"chalk";async function Gs(t,e,s,n){try{O(t.db,e)||(console.error(f.red(`\u2717 Issue not found: ${e}`)),process.exit(1));let r=T(t.db,s);r||(console.error(f.red(`\u2717 Spec not found: ${s}`)),process.exit(1));let a=r.content,i;if(n.line){let c=parseInt(n.line);(isNaN(c)||c<1)&&(console.error(f.red("\u2717 Invalid line number")),process.exit(1)),i=fe(a,c)}else n.text?(i=ds(a,n.text),i||(console.error(f.red(`\u2717 Text not found in spec: "${n.text}"`)),process.exit(1))):(console.error(f.red("\u2717 Either --line or --text must be specified")),process.exit(1));let d=ft(t.db,{issue_id:e,spec_id:s,feedback_type:n.type,content:n.content,agent:n.agent||process.env.USER||"cli",anchor:i,dismissed:!1});t.jsonOutput?console.log(JSON.stringify(d,null,2)):(console.log(f.green("\u2713 Created feedback"),f.cyan(d.id)),console.log(f.gray(` Issue: ${e}`)),console.log(f.gray(` Spec: ${s}`)),console.log(f.gray(` Type: ${n.type}`)),console.log(f.gray(` Location: ${i.section_heading||"Unknown"} (line ${i.line_number})`)))}catch(o){console.error(f.red("\u2717 Failed to create feedback")),console.error(o instanceof Error?o.message:String(o)),process.exit(1)}}async function Ks(t,e){try{let s={issue_id:e.issue,spec_id:e.spec,feedback_type:e.type,dismissed:e.dismissed!==void 0?e.dismissed==="true":void 0,limit:parseInt(e.limit)},n=V(t.db,s);if(t.jsonOutput)console.log(JSON.stringify(n,null,2));else{if(n.length===0){console.log(f.gray("No feedback found"));return}console.log(f.bold(`
181
- Found ${n.length} feedback item(s):
182
- `));for(let o of n){let r=typeof o.anchor=="string"?JSON.parse(o.anchor):o.anchor,a=o.dismissed?f.gray:f.white,i=r.anchor_status==="valid"?f.green:r.anchor_status==="relocated"?f.yellow:f.red;console.log(f.cyan(o.id),a(`[${o.dismissed?"dismissed":"active"}]`),i(`[${r.anchor_status}]`),f.gray(`${o.issue_id} \u2192 ${o.spec_id}`)),console.log(f.gray(` Type: ${o.feedback_type} | ${r.section_heading||"No section"} (line ${r.line_number})`)),console.log(f.gray(` ${o.content.substring(0,80)}${o.content.length>80?"...":""}`))}console.log()}}catch(s){console.error(f.red("\u2717 Failed to list feedback")),console.error(s instanceof Error?s.message:String(s)),process.exit(1)}}async function Qs(t,e){try{let s=Me(t.db,e);s||(console.error(f.red(`\u2717 Feedback not found: ${e}`)),process.exit(1));let n=typeof s.anchor=="string"?JSON.parse(s.anchor):s.anchor;if(t.jsonOutput)console.log(JSON.stringify({...s,anchor:n},null,2));else{console.log(),console.log(f.bold.cyan(s.id),f.bold(s.feedback_type)),console.log(f.gray("\u2500".repeat(60))),console.log(f.gray("Issue:"),s.issue_id),console.log(f.gray("Spec:"),s.spec_id),console.log(f.gray("Status:"),s.dismissed?"Dismissed":"Active"),console.log(f.gray("Agent:"),s.agent),console.log(f.gray("Created:"),s.created_at),console.log(f.gray("Updated:"),s.updated_at),console.log(),console.log(f.bold("Content:")),console.log(s.content),console.log(),console.log(f.bold("Anchor Location:"));let o=n.anchor_status==="valid"?f.green:n.anchor_status==="relocated"?f.yellow:f.red;console.log(f.gray(" Status:"),o(n.anchor_status)),console.log(f.gray(" Section:"),n.section_heading||"None"),console.log(f.gray(" Line:"),n.line_number||"Unknown"),n.text_snippet&&console.log(f.gray(" Snippet:"),`"${n.text_snippet}"`),n.original_location&&n.anchor_status!=="valid"&&(console.log(),console.log(f.bold("Original Location:")),console.log(f.gray(" Line:"),n.original_location.line_number),console.log(f.gray(" Section:"),n.original_location.section_heading||"None")),console.log()}}catch(s){console.error(f.red("\u2717 Failed to show feedback")),console.error(s instanceof Error?s.message:String(s)),process.exit(1)}}async function Zs(t,e,s){try{let n=rs(t.db,e);t.jsonOutput?console.log(JSON.stringify(n,null,2)):console.log(f.green("\u2713 Dismissed feedback"),f.cyan(e))}catch(n){console.error(f.red("\u2717 Failed to dismiss feedback")),console.error(n instanceof Error?n.message:String(n)),process.exit(1)}}async function Xs(t){try{let s=V(t.db,{}).filter(n=>(typeof n.anchor=="string"?JSON.parse(n.anchor):n.anchor).anchor_status==="stale");if(t.jsonOutput)console.log(JSON.stringify(s,null,2));else{if(s.length===0){console.log(f.green("\u2713 No stale anchors found"));return}console.log(f.bold.red(`
183
- Found ${s.length} stale anchor(s):
184
- `));for(let n of s){let o=typeof n.anchor=="string"?JSON.parse(n.anchor):n.anchor;console.log(f.cyan(n.id),f.red("[stale]"),f.gray(`${n.issue_id} \u2192 ${n.spec_id}`)),console.log(f.gray(` Original: ${o.original_location?.section_heading||"Unknown"} (line ${o.original_location?.line_number})`)),o.text_snippet&&console.log(f.gray(` Snippet: "${o.text_snippet}"`))}console.log(),console.log(f.yellow("Tip: Use `sg feedback relocate <id> --line <number>` to manually relocate anchors"))}}catch(e){console.error(f.red("\u2717 Failed to list stale feedback")),console.error(e instanceof Error?e.message:String(e)),process.exit(1)}}async function en(t,e,s){try{let n=Me(t.db,e);n||(console.error(f.red(`\u2717 Feedback not found: ${e}`)),process.exit(1));let o=T(t.db,n.spec_id);o||(console.error(f.red(`\u2717 Spec not found: ${n.spec_id}`)),process.exit(1));let r=parseInt(s.line);(isNaN(r)||r<1)&&(console.error(f.red("\u2717 Invalid line number")),process.exit(1));let a=fe(o.content,r),i=typeof n.anchor=="string"?JSON.parse(n.anchor):n.anchor;a.original_location=i.original_location||{line_number:i.line_number||0,section_heading:i.section_heading},a.anchor_status="relocated";let d=Ke(t.db,e,{anchor:a});t.jsonOutput?console.log(JSON.stringify(d,null,2)):(console.log(f.green("\u2713 Relocated feedback anchor"),f.cyan(e)),console.log(f.gray(` New location: ${a.section_heading||"Unknown"} (line ${r})`)))}catch(n){console.error(f.red("\u2717 Failed to relocate feedback")),console.error(n instanceof Error?n.message:String(n)),process.exit(1)}}import{spawn as xo}from"child_process";import*as Dt from"path";import{fileURLToPath as Oo}from"url";import we from"chalk";Ye();import*as he from"fs";import*as Kt from"path";import*as tn from"os";var sn="@sudocode-ai/cli",nn=Kt.join(tn.tmpdir(),"sudocode-cli"),Gt=Kt.join(nn,"update-cache.json"),bo=1e3*60*60*24;async function So(){try{let t=await fetch(`https://registry.npmjs.org/${sn}/latest`,{headers:{Accept:"application/json"}});return t.ok&&(await t.json()).version||null}catch{return null}}function Do(){try{if(!he.existsSync(Gt))return null;let t=he.readFileSync(Gt,"utf-8"),e=JSON.parse(t);return Date.now()-e.timestamp>bo?null:e}catch{return null}}function wo(t){try{he.mkdirSync(nn,{recursive:!0});let e={timestamp:Date.now(),latest:t};he.writeFileSync(Gt,JSON.stringify(e,null,2),"utf-8")}catch{}}async function bt(){let t=Do();if(t)return{current:re,latest:t.latest,updateAvailable:re!==t.latest};let e=await So();return e?(wo(e),{current:re,latest:e,updateAvailable:re!==e}):null}function Eo(t,e){let s=t.split(".").map(Number),n=e.split(".").map(Number);for(let o=0;o<3;o++){let r=s[o]||0,a=n[o]||0;if(r<a)return!0;if(r>a)return!1}return!1}async function St(){let t=await bt();return!t||!t.updateAvailable||!Eo(t.current,t.latest)?null:`
185
- \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E
186
- \u2502 \u2502
187
- \u2502 Update available: ${t.current} \u2192 ${t.latest} \u2502
188
- \u2502 \u2502
189
- \u2502 Run: npm install -g ${sn} \u2502
190
- \u2502 Or: sudocode update \u2502
191
- \u2502 \u2502
192
- \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F
193
- `.trim()}async function on(t,e){try{let i=await St();i&&(console.log(),console.log(we.yellow(i)),console.log())}catch{}let s=Oo(import.meta.url),n=Dt.dirname(s),o=Dt.resolve(n,"../../../server/dist/src/index.js"),r={...process.env,SUDOCODE_DIR:t.outputDir,PORT:e.port||process.env.PORT||"3000"};console.log(we.blue("Starting sudocode local server...")),e.port&&console.log(we.gray(`Port: ${e.port}`));let a=xo("node",[o],{detached:e.detach||!1,stdio:e.detach?"ignore":"inherit",env:r});e.detach?(a.unref(),console.log(we.green(`\u2713 Server started in background on http://localhost:${r.PORT}`)),console.log(we.gray(` Process ID: ${a.pid}`)),console.log(we.gray(` Health check: http://localhost:${r.PORT}/health`))):(process.on("SIGINT",()=>{console.log(we.yellow(`
194
-
195
- Shutting down server...`)),a.kill(),process.exit(0)}),a.on("exit",i=>{i!==0&&i!==null&&(console.error(we.red(`Server exited with code ${i}`)),process.exit(i))}))}import H from"chalk";import{execSync as To}from"child_process";var nt="@sudocode-ai/cli";async function rn(){console.log(H.cyan("Checking for updates..."));let t=await bt();if(!t){console.log(H.yellow("Unable to check for updates")),console.log("Please try again later or check manually:"),console.log(` npm view ${nt} version`);return}console.log(`Current version: ${H.cyan(t.current)}`),console.log(`Latest version: ${H.cyan(t.latest)}`),t.updateAvailable?(console.log(),console.log(H.green("\u2713 Update available!")),console.log(),console.log("To update, run:"),console.log(H.yellow(` npm install -g ${nt}`)),console.log(H.yellow(" sudocode update"))):(console.log(),console.log(H.green("\u2713 You are using the latest version")))}async function an(){console.log(H.cyan("Checking for updates..."));let t=await bt();if(!t)console.log(H.yellow("Unable to check for updates")),console.log("Attempting to update anyway...");else if(t.updateAvailable)console.log(`Updating from ${t.current} to ${t.latest}...`);else{console.log(H.green("\u2713 Already on latest version:"),t.current);return}try{console.log(),console.log(H.cyan("Running: npm install -g "+nt)),console.log(),To(`npm install -g ${nt}`,{stdio:"inherit"}),console.log(),console.log(H.green("\u2713 Update completed successfully!")),console.log(),console.log("Run 'sudocode --version' to verify the new version")}catch(e){console.log(),console.error(H.red("\u2717 Update failed")),console.log(),console.log("Please try updating manually:"),console.log(H.yellow(` npm install -g ${nt}`)),console.log(),e instanceof Error&&(console.log("Error details:"),console.log(H.dim(e.message))),process.exit(1)}}Ye();var Be=null,We="",wt=".sudocode",cn=!1;function vo(){let t=process.cwd(),e=le.parse(t).root;for(;t!==e;){let s=le.join(t,".sudocode","cache.db");if(Et.existsSync(s))return s;t=le.dirname(t)}return null}function ko(){if(!We){let t=vo();t?(We=t,wt=le.dirname(t)):(wt=le.join(process.cwd(),".sudocode"),We=le.join(wt,"cache.db"))}try{Et.mkdirSync(le.dirname(We),{recursive:!0}),Be=ze({path:We})}catch(t){console.error(Qt.red("Error: Failed to open database")),console.error(t instanceof Error?t.message:String(t)),process.exit(1)}}function I(){return Be||(console.error(Qt.red("Error: Database not initialized")),process.exit(1)),{db:Be,outputDir:wt,jsonOutput:cn}}var z=new Io;z.name("sudocode").description("sudocode - git-native agentic context management").version(re).option("--db <path>","Database path (default: auto-discover)").option("--json","Output in JSON format").hook("preAction",t=>{let e=t.optsWithGlobals();e.db&&(We=e.db),e.json&&(cn=!0),t.name()!=="init"&&ko()}).hook("postAction",()=>{Be&&(Be.close(),Be=null)});z.command("init").description("Initialize .sudocode directory structure").option("--spec-prefix <prefix>","ID prefix for specs","SPEC").option("--issue-prefix <prefix>","ID prefix for issues","ISSUE").action(async t=>{await Js({specPrefix:t.specPrefix,issuePrefix:t.issuePrefix})});var qe=z.command("spec").alias("specs").description("Manage specifications");qe.command("create <title>").description("Create a new spec").option("-p, --priority <priority>","Priority (0-4)","2").option("-d, --description <desc>","Description").option("--file-path <path>","File path for markdown").option("--parent <id>","Parent spec ID").option("--tags <tags>","Comma-separated tags").action(async(t,e)=>{await ms(I(),t,e)});qe.command("list").description("List all specs").option("-p, --priority <priority>","Filter by priority").option("-g, --grep <query>","Search by title or content").option("--archived <bool>","Filter by archive status (true/false)").option("--limit <num>","Limit results","50").action(async t=>{await hs(I(),t)});qe.command("show <id>").description("Show spec details").action(async t=>{await ys(I(),t)});qe.command("update <id>").description("Update a spec").option("-p, --priority <priority>","New priority").option("--title <title>","New title").option("-d, --description <desc>","New description").option("--parent <id>","New parent spec ID").option("--tags <tags>","New comma-separated tags").option("--archived <bool>","Archive status (true/false)").action(async(t,e)=>{await _s(I(),t,e)});qe.command("delete <id...>").description("Delete one or more specs").action(async(t,e)=>{await bs(I(),t,e)});qe.command("add-ref <entity-id> <reference-id>").description("Add a reference to a spec").option("-l, --line <number>","Line number to insert reference").option("-t, --text <text>","Text to search for insertion point").option("--display <text>","Display text for reference").option("--type <type>","Relationship type (blocks, implements, etc.)").option("--format <format>","Format: inline or newline","inline").action(async(t,e,s)=>{await Wt(I(),t,e,s)});var Ce=z.command("issue").alias("issues").description("Manage issues");Ce.command("create <title>").description("Create a new issue").option("-p, --priority <priority>","Priority (0-4)","2").option("-d, --description <desc>","Description").option("-a, --assignee <assignee>","Assignee").option("--parent <id>","Parent issue ID").option("--tags <tags>","Comma-separated tags").action(async(t,e)=>{await Ss(I(),t,e)});Ce.command("list").description("List all issues").option("-s, --status <status>","Filter by status").option("-a, --assignee <assignee>","Filter by assignee").option("-p, --priority <priority>","Filter by priority").option("-g, --grep <query>","Search by title or content").option("--archived <bool>","Filter by archive status (true/false)").option("--limit <num>","Limit results","50").action(async t=>{await Ds(I(),t)});Ce.command("show <id>").description("Show issue details").action(async t=>{await ws(I(),t)});Ce.command("update <id>").description("Update an issue").option("-s, --status <status>","New status").option("-p, --priority <priority>","New priority").option("-a, --assignee <assignee>","New assignee").option("--title <title>","New title").option("--description <desc>","New description").option("--archived <bool>","Archive status (true/false)").action(async(t,e)=>{await Es(I(),t,e)});Ce.command("close <id...>").description("Close one or more issues").option("-r, --reason <reason>","Reason for closing").action(async(t,e)=>{await xs(I(),t,e)});Ce.command("delete <id...>").description("Delete one or more issues").option("--hard","Permanently delete from database (default: close the issue)").action(async(t,e)=>{await Os(I(),t,e)});Ce.command("add-ref <entity-id> <reference-id>").description("Add a reference to an issue").option("-l, --line <number>","Line number to insert reference").option("-t, --text <text>","Text to search for insertion point").option("--display <text>","Display text for reference").option("--type <type>","Relationship type (blocks, implements, etc.)").option("--format <format>","Format: inline or newline","inline").option("--position <position>","Position: before or after","after").action(async(t,e,s)=>{await Wt(I(),t,e,s)});z.command("link <from> <to>").description("Create a relationship between entities").option("-t, --type <type>","Relationship type","references").action(async(t,e,s)=>{await Is(I(),t,e,s)});z.command("ready").description("Show ready issues (no blockers)").action(async t=>{await ks(I(),t)});z.command("blocked").description("Show blocked issues").action(async t=>{await $s(I(),t)});z.command("status").description("Show project status summary").option("-v, --verbose","Show detailed status").action(async t=>{await Ys(I(),t)});z.command("stats").description("Show detailed project statistics").action(async t=>{await Vs(I(),t)});var He=z.command("feedback").description("Manage spec feedback from issues");He.command("add <issue-id> <spec-id>").description("Add feedback to a spec from an issue").option("-l, --line <number>","Line number in spec").option("-t, --text <text>","Text to search for anchor").option("--type <type>","Feedback type (comment, suggestion, request)","comment").option("-c, --content <text>","Feedback content (required)").option("-a, --agent <name>","Agent name").action(async(t,e,s)=>{await Gs(I(),t,e,s)});He.command("list").description("List all feedback").option("-i, --issue <id>","Filter by issue ID").option("-s, --spec <id>","Filter by spec ID").option("-t, --type <type>","Filter by feedback type").option("--status <status>","Filter by status (open, acknowledged, resolved, wont_fix)").option("--limit <num>","Limit results","50").action(async t=>{await Ks(I(),t)});He.command("show <id>").description("Show detailed feedback information").action(async t=>{await Qs(I(),t)});He.command("dismiss <id>").description("Dismiss feedback").option("-c, --comment <text>","Optional comment").action(async(t,e)=>{await Zs(I(),t,e)});He.command("stale").description("List all stale feedback anchors").action(async()=>{await Xs(I())});He.command("relocate <id>").description("Manually relocate a stale anchor").option("-l, --line <number>","New line number (required)").action(async(t,e)=>{await en(I(),t,e)});z.command("sync").description("Sync between markdown, JSONL, and database").option("--watch","Watch for changes and auto-sync").option("--from-markdown","Sync from markdown to database").option("--to-markdown","Sync from database to markdown").action(async t=>{await qs(I(),t)});z.command("export").description("Export database to JSONL").option("-o, --output <dir>","Output directory",".sudocode").action(async t=>{await Hs(I(),t)});z.command("import").description("Import from JSONL to database").option("-i, --input <dir>","Input directory",".sudocode").action(async t=>{await zs(I(),t)});z.command("server").description("Start the sudocode local server").option("-p, --port <port>","Port to run server on","3000").option("-d, --detach","Run server in background").action(async t=>{await on(I(),t)});z.command("update").description("Update sudocode to the latest version").option("--check","Check for updates without installing").action(async t=>{t.check?await rn():await an()});z.parse();var $o=process.argv.includes("update"),Co=process.argv.includes("server");!$o&&!Co&&St().then(t=>{t&&(console.log(),console.log(Qt.yellow(t)),console.log())}).catch(()=>{});
196
- //# sourceMappingURL=cli.js.map
2
+ /**
3
+ * sudocode CLI - Git-native spec and issue management
4
+ */
5
+ import { Command } from "commander";
6
+ import chalk from "chalk";
7
+ import * as path from "path";
8
+ import * as fs from "fs";
9
+ import { initDatabase } from "./db.js";
10
+ // Import command handlers
11
+ import { handleSpecCreate, handleSpecList, handleSpecShow, handleSpecUpdate, handleSpecDelete, } from "./cli/spec-commands.js";
12
+ import { handleIssueCreate, handleIssueList, handleIssueShow, handleIssueUpdate, handleIssueClose, handleIssueDelete, } from "./cli/issue-commands.js";
13
+ import { handleLink } from "./cli/relationship-commands.js";
14
+ import { handleAddReference } from "./cli/reference-commands.js";
15
+ import { handleReady, handleBlocked } from "./cli/query-commands.js";
16
+ import { handleSync, handleExport, handleImport } from "./cli/sync-commands.js";
17
+ import { handleStatus, handleStats } from "./cli/status-commands.js";
18
+ import { handleFeedbackAdd, handleFeedbackList, handleFeedbackShow, handleFeedbackDismiss, handleFeedbackStale, handleFeedbackRelocate, } from "./cli/feedback-commands.js";
19
+ import { handleServerStart } from "./cli/server-commands.js";
20
+ import { handleInit } from "./cli/init-commands.js";
21
+ import { handleUpdate, handleUpdateCheck } from "./cli/update-commands.js";
22
+ import { getUpdateNotification } from "./update-checker.js";
23
+ import { VERSION } from "./version.js";
24
+ // Global state
25
+ let db = null;
26
+ let dbPath = "";
27
+ let outputDir = ".sudocode";
28
+ let jsonOutput = false;
29
+ /**
30
+ * Find database path
31
+ * Searches for .sudocode/cache.db in current directory and parent directories
32
+ */
33
+ function findDatabasePath() {
34
+ let currentDir = process.cwd();
35
+ const root = path.parse(currentDir).root;
36
+ while (currentDir !== root) {
37
+ const potentialPath = path.join(currentDir, ".sudocode", "cache.db");
38
+ if (fs.existsSync(potentialPath)) {
39
+ return potentialPath;
40
+ }
41
+ currentDir = path.dirname(currentDir);
42
+ }
43
+ return null;
44
+ }
45
+ /**
46
+ * Initialize database connection
47
+ */
48
+ function initDB() {
49
+ if (!dbPath) {
50
+ const found = findDatabasePath();
51
+ if (found) {
52
+ dbPath = found;
53
+ outputDir = path.dirname(found);
54
+ }
55
+ else {
56
+ // Default location
57
+ outputDir = path.join(process.cwd(), ".sudocode");
58
+ dbPath = path.join(outputDir, "cache.db");
59
+ }
60
+ }
61
+ try {
62
+ // Ensure the database directory exists before opening/creating the database
63
+ fs.mkdirSync(path.dirname(dbPath), { recursive: true });
64
+ db = initDatabase({ path: dbPath });
65
+ }
66
+ catch (error) {
67
+ console.error(chalk.red("Error: Failed to open database"));
68
+ console.error(error instanceof Error ? error.message : String(error));
69
+ process.exit(1);
70
+ }
71
+ }
72
+ /**
73
+ * Get command context
74
+ */
75
+ function getContext() {
76
+ if (!db) {
77
+ console.error(chalk.red("Error: Database not initialized"));
78
+ process.exit(1);
79
+ }
80
+ return { db, outputDir, jsonOutput };
81
+ }
82
+ // Create main program
83
+ const program = new Command();
84
+ program
85
+ .name("sudocode")
86
+ .description("sudocode - git-native agentic context management")
87
+ .version(VERSION)
88
+ .option("--db <path>", "Database path (default: auto-discover)")
89
+ .option("--json", "Output in JSON format")
90
+ .hook("preAction", (thisCommand) => {
91
+ // Get global options
92
+ const opts = thisCommand.optsWithGlobals();
93
+ if (opts.db)
94
+ dbPath = opts.db;
95
+ if (opts.json)
96
+ jsonOutput = true;
97
+ // Skip DB init for init command
98
+ if (thisCommand.name() !== "init") {
99
+ initDB();
100
+ }
101
+ })
102
+ .hook("postAction", () => {
103
+ // Close database after command completes
104
+ if (db) {
105
+ db.close();
106
+ db = null;
107
+ }
108
+ });
109
+ // ============================================================================
110
+ // INIT COMMAND
111
+ // ============================================================================
112
+ program
113
+ .command("init")
114
+ .description("Initialize .sudocode directory structure")
115
+ .option("--spec-prefix <prefix>", "ID prefix for specs", "SPEC")
116
+ .option("--issue-prefix <prefix>", "ID prefix for issues", "ISSUE")
117
+ .action(async (options) => {
118
+ await handleInit({
119
+ specPrefix: options.specPrefix,
120
+ issuePrefix: options.issuePrefix,
121
+ });
122
+ });
123
+ // ============================================================================
124
+ // SPEC COMMANDS
125
+ // ============================================================================
126
+ const spec = program
127
+ .command("spec")
128
+ .alias("specs")
129
+ .description("Manage specifications");
130
+ spec
131
+ .command("create <title>")
132
+ .description("Create a new spec")
133
+ .option("-p, --priority <priority>", "Priority (0-4)", "2")
134
+ .option("-d, --description <desc>", "Description")
135
+ .option("--file-path <path>", "File path for markdown")
136
+ .option("--parent <id>", "Parent spec ID")
137
+ .option("--tags <tags>", "Comma-separated tags")
138
+ .action(async (title, options) => {
139
+ await handleSpecCreate(getContext(), title, options);
140
+ });
141
+ spec
142
+ .command("list")
143
+ .description("List all specs")
144
+ .option("-p, --priority <priority>", "Filter by priority")
145
+ .option("-g, --grep <query>", "Search by title or content")
146
+ .option("--archived <bool>", "Filter by archive status (true/false)")
147
+ .option("--limit <num>", "Limit results", "50")
148
+ .action(async (options) => {
149
+ await handleSpecList(getContext(), options);
150
+ });
151
+ spec
152
+ .command("show <id>")
153
+ .description("Show spec details")
154
+ .action(async (id) => {
155
+ await handleSpecShow(getContext(), id);
156
+ });
157
+ spec
158
+ .command("update <id>")
159
+ .description("Update a spec")
160
+ .option("-p, --priority <priority>", "New priority")
161
+ .option("--title <title>", "New title")
162
+ .option("-d, --description <desc>", "New description")
163
+ .option("--parent <id>", "New parent spec ID")
164
+ .option("--tags <tags>", "New comma-separated tags")
165
+ .option("--archived <bool>", "Archive status (true/false)")
166
+ .action(async (id, options) => {
167
+ await handleSpecUpdate(getContext(), id, options);
168
+ });
169
+ spec
170
+ .command("delete <id...>")
171
+ .description("Delete one or more specs")
172
+ .action(async (ids, options) => {
173
+ await handleSpecDelete(getContext(), ids, options);
174
+ });
175
+ spec
176
+ .command("add-ref <entity-id> <reference-id>")
177
+ .description("Add a reference to a spec")
178
+ .option("-l, --line <number>", "Line number to insert reference")
179
+ .option("-t, --text <text>", "Text to search for insertion point")
180
+ .option("--display <text>", "Display text for reference")
181
+ .option("--type <type>", "Relationship type (blocks, implements, etc.)")
182
+ .option("--format <format>", "Format: inline or newline", "inline")
183
+ .action(async (entityId, referenceId, options) => {
184
+ await handleAddReference(getContext(), entityId, referenceId, options);
185
+ });
186
+ // ============================================================================
187
+ // ISSUE COMMANDS
188
+ // ============================================================================
189
+ const issue = program
190
+ .command("issue")
191
+ .alias("issues")
192
+ .description("Manage issues");
193
+ issue
194
+ .command("create <title>")
195
+ .description("Create a new issue")
196
+ .option("-p, --priority <priority>", "Priority (0-4)", "2")
197
+ .option("-d, --description <desc>", "Description")
198
+ .option("-a, --assignee <assignee>", "Assignee")
199
+ .option("--parent <id>", "Parent issue ID")
200
+ .option("--tags <tags>", "Comma-separated tags")
201
+ .action(async (title, options) => {
202
+ await handleIssueCreate(getContext(), title, options);
203
+ });
204
+ issue
205
+ .command("list")
206
+ .description("List all issues")
207
+ .option("-s, --status <status>", "Filter by status")
208
+ .option("-a, --assignee <assignee>", "Filter by assignee")
209
+ .option("-p, --priority <priority>", "Filter by priority")
210
+ .option("-g, --grep <query>", "Search by title or content")
211
+ .option("--archived <bool>", "Filter by archive status (true/false)")
212
+ .option("--limit <num>", "Limit results", "50")
213
+ .action(async (options) => {
214
+ await handleIssueList(getContext(), options);
215
+ });
216
+ issue
217
+ .command("show <id>")
218
+ .description("Show issue details")
219
+ .action(async (id) => {
220
+ await handleIssueShow(getContext(), id);
221
+ });
222
+ issue
223
+ .command("update <id>")
224
+ .description("Update an issue")
225
+ .option("-s, --status <status>", "New status")
226
+ .option("-p, --priority <priority>", "New priority")
227
+ .option("-a, --assignee <assignee>", "New assignee")
228
+ .option("--title <title>", "New title")
229
+ .option("--description <desc>", "New description")
230
+ .option("--archived <bool>", "Archive status (true/false)")
231
+ .action(async (id, options) => {
232
+ await handleIssueUpdate(getContext(), id, options);
233
+ });
234
+ issue
235
+ .command("close <id...>")
236
+ .description("Close one or more issues")
237
+ .option("-r, --reason <reason>", "Reason for closing")
238
+ .action(async (ids, options) => {
239
+ await handleIssueClose(getContext(), ids, options);
240
+ });
241
+ issue
242
+ .command("delete <id...>")
243
+ .description("Delete one or more issues")
244
+ .option("--hard", "Permanently delete from database (default: close the issue)")
245
+ .action(async (ids, options) => {
246
+ await handleIssueDelete(getContext(), ids, options);
247
+ });
248
+ issue
249
+ .command("add-ref <entity-id> <reference-id>")
250
+ .description("Add a reference to an issue")
251
+ .option("-l, --line <number>", "Line number to insert reference")
252
+ .option("-t, --text <text>", "Text to search for insertion point")
253
+ .option("--display <text>", "Display text for reference")
254
+ .option("--type <type>", "Relationship type (blocks, implements, etc.)")
255
+ .option("--format <format>", "Format: inline or newline", "inline")
256
+ .option("--position <position>", "Position: before or after", "after")
257
+ .action(async (entityId, referenceId, options) => {
258
+ await handleAddReference(getContext(), entityId, referenceId, options);
259
+ });
260
+ // ============================================================================
261
+ // RELATIONSHIP COMMANDS
262
+ // ============================================================================
263
+ program
264
+ .command("link <from> <to>")
265
+ .description("Create a relationship between entities")
266
+ .option("-t, --type <type>", "Relationship type", "references")
267
+ .action(async (from, to, options) => {
268
+ await handleLink(getContext(), from, to, options);
269
+ });
270
+ // ============================================================================
271
+ // READY & BLOCKED COMMANDS
272
+ // ============================================================================
273
+ program
274
+ .command("ready")
275
+ .description("Show ready issues (no blockers)")
276
+ .action(async (options) => {
277
+ await handleReady(getContext(), options);
278
+ });
279
+ program
280
+ .command("blocked")
281
+ .description("Show blocked issues")
282
+ .action(async (options) => {
283
+ await handleBlocked(getContext(), options);
284
+ });
285
+ // ============================================================================
286
+ // STATUS & STATS COMMANDS
287
+ // ============================================================================
288
+ program
289
+ .command("status")
290
+ .description("Show project status summary")
291
+ .option("-v, --verbose", "Show detailed status")
292
+ .action(async (options) => {
293
+ await handleStatus(getContext(), options);
294
+ });
295
+ program
296
+ .command("stats")
297
+ .description("Show detailed project statistics")
298
+ .action(async (options) => {
299
+ await handleStats(getContext(), options);
300
+ });
301
+ // ============================================================================
302
+ // FEEDBACK COMMANDS
303
+ // ============================================================================
304
+ const feedback = program
305
+ .command("feedback")
306
+ .description("Manage spec feedback from issues");
307
+ feedback
308
+ .command("add <issue-id> <spec-id>")
309
+ .description("Add feedback to a spec from an issue")
310
+ .option("-l, --line <number>", "Line number in spec")
311
+ .option("-t, --text <text>", "Text to search for anchor")
312
+ .option("--type <type>", "Feedback type (comment, suggestion, request)", "comment")
313
+ .option("-c, --content <text>", "Feedback content (required)")
314
+ .option("-a, --agent <name>", "Agent name")
315
+ .action(async (issueId, specId, options) => {
316
+ await handleFeedbackAdd(getContext(), issueId, specId, options);
317
+ });
318
+ feedback
319
+ .command("list")
320
+ .description("List all feedback")
321
+ .option("-i, --issue <id>", "Filter by issue ID")
322
+ .option("-s, --spec <id>", "Filter by spec ID")
323
+ .option("-t, --type <type>", "Filter by feedback type")
324
+ .option("--status <status>", "Filter by status (open, acknowledged, resolved, wont_fix)")
325
+ .option("--limit <num>", "Limit results", "50")
326
+ .action(async (options) => {
327
+ await handleFeedbackList(getContext(), options);
328
+ });
329
+ feedback
330
+ .command("show <id>")
331
+ .description("Show detailed feedback information")
332
+ .action(async (id) => {
333
+ await handleFeedbackShow(getContext(), id);
334
+ });
335
+ feedback
336
+ .command("dismiss <id>")
337
+ .description("Dismiss feedback")
338
+ .option("-c, --comment <text>", "Optional comment")
339
+ .action(async (id, options) => {
340
+ await handleFeedbackDismiss(getContext(), id, options);
341
+ });
342
+ feedback
343
+ .command("stale")
344
+ .description("List all stale feedback anchors")
345
+ .action(async () => {
346
+ await handleFeedbackStale(getContext());
347
+ });
348
+ feedback
349
+ .command("relocate <id>")
350
+ .description("Manually relocate a stale anchor")
351
+ .option("-l, --line <number>", "New line number (required)")
352
+ .action(async (id, options) => {
353
+ await handleFeedbackRelocate(getContext(), id, options);
354
+ });
355
+ // ============================================================================
356
+ // SYNC COMMANDS
357
+ // ============================================================================
358
+ program
359
+ .command("sync")
360
+ .description("Sync between markdown, JSONL, and database")
361
+ .option("--watch", "Watch for changes and auto-sync")
362
+ .option("--from-markdown", "Sync from markdown to database")
363
+ .option("--to-markdown", "Sync from database to markdown")
364
+ .action(async (options) => {
365
+ await handleSync(getContext(), options);
366
+ });
367
+ program
368
+ .command("export")
369
+ .description("Export database to JSONL")
370
+ .option("-o, --output <dir>", "Output directory", ".sudocode")
371
+ .action(async (options) => {
372
+ await handleExport(getContext(), options);
373
+ });
374
+ program
375
+ .command("import")
376
+ .description("Import from JSONL to database")
377
+ .option("-i, --input <dir>", "Input directory", ".sudocode")
378
+ .action(async (options) => {
379
+ await handleImport(getContext(), options);
380
+ });
381
+ // ============================================================================
382
+ // SERVER COMMANDS
383
+ // ============================================================================
384
+ program
385
+ .command("server")
386
+ .description("Start the sudocode local server")
387
+ .option("-p, --port <port>", "Port to run server on", "3000")
388
+ .option("-d, --detach", "Run server in background")
389
+ .action(async (options) => {
390
+ await handleServerStart(getContext(), options);
391
+ });
392
+ // ============================================================================
393
+ // UPDATE COMMANDS
394
+ // ============================================================================
395
+ program
396
+ .command("update")
397
+ .description("Update sudocode to the latest version")
398
+ .option("--check", "Check for updates without installing")
399
+ .action(async (options) => {
400
+ if (options.check) {
401
+ await handleUpdateCheck();
402
+ }
403
+ else {
404
+ await handleUpdate();
405
+ }
406
+ });
407
+ // Parse arguments
408
+ program.parse();
409
+ // Check for updates (non-blocking)
410
+ // Skip for update and server commands (server handles it explicitly)
411
+ const isUpdateCommand = process.argv.includes("update");
412
+ const isServerCommand = process.argv.includes("server");
413
+ if (!isUpdateCommand && !isServerCommand) {
414
+ getUpdateNotification()
415
+ .then((notification) => {
416
+ if (notification) {
417
+ console.log();
418
+ console.log(chalk.yellow(notification));
419
+ console.log();
420
+ }
421
+ })
422
+ .catch(() => {
423
+ // Silently ignore update check failures
424
+ });
425
+ }
426
+ //# sourceMappingURL=cli.js.map