prjct-cli 3.60.0 → 3.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +67 -33
- package/dist/bin/prjct-core.mjs +2 -2
- package/dist/bin/prjct-hooks.mjs +1 -1
- package/dist/daemon/entry.mjs +1 -1
- package/dist/mcp/server.mjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -106,13 +106,17 @@ After install, **next session in any prjct-cli project**:
|
|
|
106
106
|
- **Lookup-first protocol**: Claude queries prjct (`prjct search`, `prjct context memory`, MCP `prjct_*`) BEFORE re-exploring source. Cuts ~10K tokens of exploration per session.
|
|
107
107
|
- **Auto-capture**: Stop hook scans the assistant transcript and persists durable insights (decisions/learnings/gotchas) tagged for dedup. The next session finds them via recall.
|
|
108
108
|
- **Pattern detection**: Stop hook detects hot files (>3 changes in 7 days), recurring bugs (gotchas with the same topic), tech-debt growth (TODO/FIXME count rising). All persisted as learnings, surfaced next session.
|
|
109
|
-
- **
|
|
109
|
+
- **6 quality workflows** activated by natural language ("review this branch", "qa the UI", "security check", "investigate this bug"):
|
|
110
110
|
- `review` — Production Bug Hunt + Completeness Gate (3 modes)
|
|
111
111
|
- `qa` — Real Browser, Atomic Fixes, Regression Tests
|
|
112
112
|
- `security` — OWASP Top 10 + STRIDE, 8/10 confidence gate, concrete exploit per finding
|
|
113
113
|
- `investigate` — Iron Law (no fix without investigation), max 3 failed hypotheses
|
|
114
|
-
- `ship` (
|
|
114
|
+
- `ship` (hardened) — Coverage Gate + Auto-Document
|
|
115
|
+
- `audit` — one-shot orchestrator: review + security + investigate combined
|
|
115
116
|
- **Delivery-geometry advisory** (`prjct review-risk`): reads the committed changeset vs the merge-base and suggests a size tier (trivial/normal/large) + whether to ship direct, as one PR, or split — with the touched top-level dirs as natural split lines. Purely advisory: never gates, never mutates git.
|
|
117
|
+
- **Session ceremonies**: `prjct prime` restores the full work state at session start; `prjct land` closes it — hand-off persisted to SQLite plus memory consolidation via `prjct dream` when its gates open.
|
|
118
|
+
- **Multi-agent work graph**: dependency edges, ready frontier, race-free `prjct claim`, topological `prjct phases` — fan several agents out on one cycle without collisions. `prjct crew` runs the leader / implementers / reviewer flow.
|
|
119
|
+
- **Code symbol graph**: `prjct code symbols|trace|impact|architecture|dead` — structural code intel built by `prjct sync` and injected by hooks alongside Grep results.
|
|
116
120
|
|
|
117
121
|
## How it works
|
|
118
122
|
|
|
@@ -286,10 +290,17 @@ Cursor and Windsurf use their installed prjct router files; otherwise run `prjct
|
|
|
286
290
|
| `prjct sync` | Re-index files, git co-change, imports; refresh project analysis. |
|
|
287
291
|
| `prjct agents doctor` | Show the auditable compatibility matrix for local and project agent runtimes. |
|
|
288
292
|
| `prjct review-risk` | Advisory change-size + delivery-geometry signal for the branch (read-only; never gates, never splits). |
|
|
293
|
+
| `prjct prime` / `prjct land` | Open / close a session: restore full work state · persist hand-off + trigger memory consolidation. |
|
|
294
|
+
| `prjct dream` | Consolidate memory: orient / gather / consolidate / prune. |
|
|
295
|
+
| `prjct ready` / `claim` / `depend` / `phases` | Multi-agent work graph: ready frontier, race-free claim, dependency edges, topological phases. |
|
|
296
|
+
| `prjct crew` | Multi-subagent crew flow: leader / implementers / reviewer. |
|
|
297
|
+
| `prjct code <sub>` | Symbol-graph queries: `symbols`, `trace`, `impact`, `architecture`, `dead`. |
|
|
298
|
+
| `prjct tdd` / `sdd` / `lean` | Quality gates: test-first, spec-driven development, anti-over-engineering. |
|
|
299
|
+
| `prjct memory export` / `import` | Git-shareable memory bundles for teams without cloud sync. |
|
|
289
300
|
|
|
290
301
|
Compatibility aliases from v2 still execute for existing scripts: `task`,
|
|
291
302
|
`status`, `tag`, `capture`, `spec`, `audit-spec`, `value`, `memory-doctor`,
|
|
292
|
-
`report`, `handoff`, `guardrails`,
|
|
303
|
+
`report`, `handoff`, `guardrails`, and `analyze`. They are no longer
|
|
293
304
|
the product surface.
|
|
294
305
|
|
|
295
306
|
## Personas & Packs
|
|
@@ -308,46 +319,54 @@ the product surface.
|
|
|
308
319
|
}
|
|
309
320
|
```
|
|
310
321
|
|
|
311
|
-
|
|
322
|
+
Seven built-in packs (TypeScript manifests in `core/packs/manifests.ts`, not bash pipelines):
|
|
312
323
|
|
|
313
324
|
| Pack | Persona | Memory types enabled | Workflow slots |
|
|
314
325
|
|---|---|---|---|
|
|
315
326
|
| `code` | DEV | `fact`, `decision`, `learning`, `gotcha`, `pattern`, `anti-pattern`, `shipped` | `ship`, `review` |
|
|
327
|
+
| `code-strict` | DEV | same as `code`, with SDD+TDD strict + delivery-geometry / land / conflict gates | `ship`, `review` |
|
|
316
328
|
| `daily` | — | `inbox`, `todo`, `idea` | `morning`, `clarify`, `review` |
|
|
317
|
-
| `pm` | PM | `
|
|
318
|
-
| `founder` | Founder | `goal`, `okr`, `person`, `stakeholder`, `decision` | `
|
|
319
|
-
| `
|
|
329
|
+
| `pm` | PM | `insight`, `question`, `stakeholder`, `decision`, `source` | `spec`, `triage`, `interview` |
|
|
330
|
+
| `founder` | Founder | `goal`, `okr`, `person`, `stakeholder`, `decision`, `shipped` | `investor-update`, `1on1`, `strategy` |
|
|
331
|
+
| `lean` | — | `over-engineering`, `lean-debt` | `review`, `audit`, `debt` |
|
|
332
|
+
| `research` | Research | `source`, `claim`, `question`, `insight` | `lit-review`, `analyze` |
|
|
320
333
|
|
|
321
334
|
Slots ship **empty** — the human or the agent fills them on demand.
|
|
322
335
|
|
|
323
336
|
## Claude Hooks Adapter (opt-in)
|
|
324
337
|
|
|
325
|
-
`prjct install` refreshes the universal project surface (`AGENTS.md`) when run inside a prjct project, writes the Claude Code hooks adapter to `~/.claude/settings.json`, and repairs detected Codex config in `~/.codex/config.toml` (prjct MCP + TUI `status_line`).
|
|
338
|
+
`prjct install` refreshes the universal project surface (`AGENTS.md`) when run inside a prjct project, writes the Claude Code hooks adapter to `~/.claude/settings.json`, and repairs detected Codex config in `~/.codex/config.toml` (prjct MCP + TUI `status_line`). Most of the 13 hook subcommands inject `additionalContext`; two guard: the credential guard denies tool calls that would leak secrets, and the package guard denies unknown installs under strict packs. Other agents use the support level shown by `prjct agents doctor`.
|
|
326
339
|
|
|
327
|
-
| Event |
|
|
340
|
+
| Event | Does |
|
|
328
341
|
|---|---|
|
|
329
342
|
| `SessionStart` | Persona; on cold start (startup/clear/compact) also the knowledge digest — top traps + decisions in force, so a freshly-updated model starts grounded |
|
|
330
343
|
| `UserPromptSubmit` | Active project state (task, branch, inbox) |
|
|
344
|
+
| `PreToolUse` (any tool) | Credential guard — **denies** the call when tool arguments contain secret material, so credentials never leave the machine |
|
|
345
|
+
| `PreToolUse` (Bash package installs) | Package legitimacy — flags packages not already in `package.json` before the install runs (strict packs deny) |
|
|
331
346
|
| `PreToolUse` (Bash git commit) | Anti-patterns tagged with touched files |
|
|
332
347
|
| `PreToolUse` (Edit/Write) | The file's preventive memory (gotchas/anti-patterns) right before you edit it — pushes what `prjct guard` makes pull |
|
|
348
|
+
| `PreToolUse` (Grep/Glob) | Injects indexed symbol-graph hits alongside search results (never gates) |
|
|
333
349
|
| `PostToolUse` (Edit/Write) | Silently annotates `files_touched` on active task |
|
|
334
350
|
| `Stop` | Async prompt: "learn anything reusable?"; scans the transcript for durable captures |
|
|
335
351
|
| `SubagentStart` | Persona for fresh-brain subagents (cache-stable, digest-free) |
|
|
352
|
+
| `SubagentStop` | Desktop notification when a subagent finishes (`config.notify`, default on) |
|
|
353
|
+
| `Notification` | Desktop notification when the agent is waiting for input or permission |
|
|
336
354
|
| `CwdChanged` | Re-contextualizes on project switch |
|
|
337
355
|
|
|
338
356
|
Remove with `prjct claude uninstall` (hooks only) or `prjct uninstall` (everything).
|
|
339
357
|
|
|
340
358
|
## MCP Server
|
|
341
359
|
|
|
342
|
-
prjct-cli exposes an MCP server with
|
|
360
|
+
prjct-cli exposes an MCP server with 6 tool groups (every tool is prefixed `prjct_`):
|
|
343
361
|
|
|
344
362
|
| Group | Tools |
|
|
345
363
|
|---|---|
|
|
346
|
-
| **memory** |
|
|
347
|
-
| **project** |
|
|
348
|
-
| **files** |
|
|
349
|
-
| **workflow** |
|
|
350
|
-
| **code-intel** |
|
|
364
|
+
| **memory** | `mem_save`, `mem_list`, `mem_similar`, `mem_forget`, `guard`, `record_decision` / `record_gotcha` / `record_learning` / `record_fact`, `capture_inbox` |
|
|
365
|
+
| **project** | `session_resume`, `task_status`, `task_start`, `task_set_status`, `analysis`, `cost_add`, `developer`, `signals`, `skills`, `context_tiers`, `safe_artifacts` |
|
|
366
|
+
| **files** | `relevant_files`, `signatures`, `history` |
|
|
367
|
+
| **workflow** | `workflow_rules`, `workflow_list`, `workflow_status` |
|
|
368
|
+
| **code-intel** | `impact_analysis`, `search_symbols`, `trace_path`, `architecture`, `cochange`, `dead_code`, `import_graph`, `related_context` |
|
|
369
|
+
| **spec** | 9 `spec_*` tools — create, get, list, update, and the rest of the SDD lifecycle |
|
|
351
370
|
|
|
352
371
|
The broker model: if you already have `linear`, `jira`, `posthog`, `gmail` MCPs wired, prjct-cli **does not duplicate them** — it tells your agent they're available for the current persona and caches your insights locally.
|
|
353
372
|
|
|
@@ -375,9 +394,9 @@ Every command supports `--md` to emit LLM-optimized markdown for agent consumpti
|
|
|
375
394
|
|
|
376
395
|
## Memory
|
|
377
396
|
|
|
378
|
-
|
|
397
|
+
20 built-in types + user-defined lowercase identifiers:
|
|
379
398
|
|
|
380
|
-
`fact`, `decision`, `learning`, `gotcha`, `pattern`, `anti-pattern`, `shipped`, `inbox`, `todo`, `idea`, `insight`, `question`, `source`, `person` — plus anything you invent (`recipe`, `workout`, `interview`, …).
|
|
399
|
+
`fact`, `decision`, `learning`, `gotcha`, `pattern`, `anti-pattern`, `shipped`, `identity`, `voice`, `glossary`, `framework`, `context`, `inbox`, `todo`, `idea`, `insight`, `question`, `source`, `person`, `spec` — plus anything you invent (`recipe`, `workout`, `interview`, …). Packs add more on top (e.g. `goal`, `okr` from `founder`).
|
|
381
400
|
|
|
382
401
|
```bash
|
|
383
402
|
prjct remember decision "we chose SQLite because the app is local"
|
|
@@ -434,15 +453,16 @@ Without a key the built-in local embedder is used. Vector dimensionality is dete
|
|
|
434
453
|
|
|
435
454
|
## Code Intelligence
|
|
436
455
|
|
|
437
|
-
`prjct sync` builds
|
|
456
|
+
`prjct sync` builds four indexes:
|
|
438
457
|
|
|
439
458
|
| Index | Purpose |
|
|
440
459
|
|---|---|
|
|
441
460
|
| BM25 | Full-text search over names, symbols, comments |
|
|
461
|
+
| Symbol graph | Structural code symbols + call sites — powers `prjct code symbols/trace/impact/architecture/dead` and the Grep/Glob hook augment |
|
|
442
462
|
| Import graph | Forward + reverse dependency edges |
|
|
443
463
|
| Git co-change | Files that change together |
|
|
444
464
|
|
|
445
|
-
A combined ranker fuses the
|
|
465
|
+
A combined ranker fuses the signals (`core/domain/file-ranker.ts`) and powers `prjct context files`, plus the code-intel MCP tools (`prjct_related_context`, `prjct_impact_analysis`, `prjct_search_symbols`, `prjct_trace_path`, …).
|
|
446
466
|
|
|
447
467
|
## Issue Tracker Integration
|
|
448
468
|
|
|
@@ -469,28 +489,42 @@ Bring your own MCP — prjct-cli doesn't duplicate trackers.
|
|
|
469
489
|
```
|
|
470
490
|
prjct-cli/
|
|
471
491
|
bin/prjct.cjs Portable package-manager launcher
|
|
472
|
-
|
|
492
|
+
bin/prjct.ts Source entry — daemon + hook fast paths, self-heal
|
|
493
|
+
dist/bin/prjct.mjs Built JS shim (daemon-first)
|
|
473
494
|
core/
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
495
|
+
agentic/ Agent template loader
|
|
496
|
+
cli/ Bin-command helpers
|
|
497
|
+
commands/ Command registry (command-data.ts) + all verb handlers
|
|
498
|
+
config/ Static command-context config
|
|
499
|
+
constants/ Algorithm / timing / token constants
|
|
500
|
+
daemon/ Background daemon (client, dispatch, protocol)
|
|
501
|
+
domain/ BM25, symbol graph, import-graph, git-cochange, file-ranker
|
|
502
|
+
eval/ Retrieval evals + ledger
|
|
503
|
+
events/ Sync event bus
|
|
504
|
+
hooks/ 13 hook subcommands (Claude Code adapter)
|
|
505
|
+
infrastructure/ path-manager, ai-provider, command-installer, agent-detector
|
|
506
|
+
mcp/ MCP server (6 tool groups)
|
|
507
|
+
memory/ Memory model, recall, formatting
|
|
508
|
+
packs/ Pack manifests (TS) + pack-manager
|
|
481
509
|
schemas/ Zod — runtime validation
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
510
|
+
services/ sync-service, skill-generator, embeddings, retention
|
|
511
|
+
session/ Git session helpers
|
|
512
|
+
storage/ SQLite (one DB per project) — source of truth
|
|
513
|
+
sync/ Cloud sync client + auth + entity handlers
|
|
514
|
+
tools/ Context tools (signatures, history, relevant files)
|
|
515
|
+
types/ Shared TypeScript types
|
|
516
|
+
utils/ Output, branding, cache helpers
|
|
517
|
+
workflow-engine/ Rule state-machine + when-evaluator
|
|
518
|
+
workflows/ Onboarding wizard
|
|
485
519
|
templates/
|
|
486
|
-
|
|
487
|
-
packs/ JSON pack manifests
|
|
520
|
+
codex/ crew/ cursor/ windsurf/ antigravity/ Per-agent surfaces
|
|
488
521
|
global/ Per-editor router templates
|
|
522
|
+
skills/ Skill templates
|
|
489
523
|
```
|
|
490
524
|
|
|
491
525
|
## Requirements
|
|
492
526
|
|
|
493
|
-
- Node.js 22.
|
|
527
|
+
- Node.js 22.5+ (ships `node:sqlite`) or Bun 1.0+
|
|
494
528
|
- One of: Claude Code, Gemini CLI, Cursor IDE, Windsurf, OpenAI Codex, Antigravity
|
|
495
529
|
|
|
496
530
|
## Common questions
|
package/dist/bin/prjct-core.mjs
CHANGED
|
@@ -17,7 +17,7 @@ ${e}`,action:"appended"};let o=t.substring(0,t.indexOf(n)),i=t.substring(t.index
|
|
|
17
17
|
`)}
|
|
18
18
|
`}var rG,i_,sG,oG,Cn,a_,c_,u_,d_,m_,f_,fy=y(()=>{"use strict";Cr();po();rG=cy.join("/"),i_="Generated with [p/](https://www.prjct.app/)",sG="<!-- prjct:start - DO NOT REMOVE THIS MARKER -->",oG="<!-- prjct:end - DO NOT REMOVE THIS MARKER -->",Cn={rag:"prjct is a RAG-backed project memory harness; do not preload project history.",entrypoint:'`prjct work "<intent>" --md` is the single entrypoint \u2014 recognize intent and run the verb yourself.',pull:"Pull only what surfaces: `prjct search` / `context memory` / `guard` / MCP \u2014 not something to load wholesale.",remember:'Save synthesized memory in English: `prjct remember <decision|learning|gotcha|context> "<text>"`.',kb:`KB (\`${rG}\`): \`remember <facet>\` / \`context memory <facet>\` \u2014 on demand, never injected here.`,ship:"Ship only after user OKs: `prjct ship --md`.",loop:"Loop: land; H2+ intent; tip\u2192user SoT; close.",identity:"L0 portable; id=cwd."};c(ep,"buildCompactSkill");a_=ep,c_=ep;c(l_,"buildGlobalConfig");u_=c(()=>l_("Gemini"),"buildGeminiConfig"),d_=c(()=>l_("Antigravity"),"buildAntigravityConfig");c(p_,"buildIdePointer");m_=c(()=>p_(`description: "prjct \u2014 pull project memory + workflow on demand"
|
|
19
19
|
alwaysApply: true`),"buildCursorRule"),f_=c(()=>p_(`trigger: always_on
|
|
20
|
-
description: "prjct \u2014 pull project memory + workflow on demand"`),"buildWindsurfRule")});var Fi={};C(Fi,{PACKAGE_ROOT:()=>Ln,VERSION:()=>xe,getPackageRoot:()=>hy,getVersion:()=>fo,resetPackageRoot:()=>yy});import gy from"node:fs";import tp from"node:path";function hy(){if(Li)return Li;let t=__dirname;for(let e=0;e<5;e++){let n=tp.join(t,"package.json");if(gy.existsSync(n))try{if(JSON.parse(gy.readFileSync(n,"utf-8")).name==="prjct-cli")return Li=t,t}catch{}t=tp.dirname(t)}return Li=tp.join(__dirname,"..","..",".."),Li}function fo(){if(mo)return mo;let t="3.
|
|
20
|
+
description: "prjct \u2014 pull project memory + workflow on demand"`),"buildWindsurfRule")});var Fi={};C(Fi,{PACKAGE_ROOT:()=>Ln,VERSION:()=>xe,getPackageRoot:()=>hy,getVersion:()=>fo,resetPackageRoot:()=>yy});import gy from"node:fs";import tp from"node:path";function hy(){if(Li)return Li;let t=__dirname;for(let e=0;e<5;e++){let n=tp.join(t,"package.json");if(gy.existsSync(n))try{if(JSON.parse(gy.readFileSync(n,"utf-8")).name==="prjct-cli")return Li=t,t}catch{}t=tp.dirname(t)}return Li=tp.join(__dirname,"..","..",".."),Li}function fo(){if(mo)return mo;let t="3.61.0";if(t&&/^\d+\.\d+\.\d+/.test(t))return mo=t,mo;try{let e=tp.join(hy(),"package.json");return mo=JSON.parse(gy.readFileSync(e,"utf-8")).version,mo}catch(e){return process.env.PRJCT_DEBUG==="1"&&console.error("Failed to read version from package.json:",S(e)),"0.0.0"}}function yy(t){Li=t,mo=null}var mo,Li,xe,Ln,pt=y(()=>{"use strict";V();mo=null,Li=null;c(hy,"getPackageRoot");c(fo,"getVersion");c(yy,"resetPackageRoot");xe=fo(),Ln=hy()});var op={};C(op,{default:()=>fG,getTemplateContent:()=>Ct,listTemplates:()=>sp,resetBundle:()=>dG});import ky from"node:fs";import iG from"node:fs/promises";import rp from"node:path";function by(){if(wy)return np;wy=!0;let t=rp.join(Ln,"dist","templates.json");try{let e=ky.readFileSync(t,"utf-8");return np=JSON.parse(e),np}catch{return null}}function cG(t){let e=go.indexOf(t);e>-1&&go.splice(e,1),go.push(t)}function lG(){for(;Hi.size>=aG&&go.length>0;){let t=go.shift();t&&Hi.delete(t)}}function g_(t){let e=/^---\n([\s\S]+?)\n---\n([\s\S]*)$/,n=t.match(e);if(!n)return{frontmatter:{},content:t.trim()};let[,r,s]=n,o={};return r.split(`
|
|
21
21
|
`).forEach(i=>{let[a,...l]=i.split(":");if(a&&l.length>0){let u=l.join(":").trim();u.startsWith("[")&&u.endsWith("]")?o[a.trim()]=u.slice(1,-1).split(",").map(d=>d.trim()):o[a.trim()]=u.replace(/^["']|["']$/g,"")}}),{frontmatter:o,content:s.trim()}}async function h_(t){if(Hi.has(t))return cG(t),Hi.get(t);let e,n=by();if(n){let s=`commands/${t}.md`;e=n[s]}if(!e){let s=rp.join(Ln,"templates","commands",`${t}.md`);try{e=await iG.readFile(s,"utf-8")}catch{throw Kd.notFound(t)}}let r=g_(e);return lG(),Hi.set(t,r),go.push(t),r}async function uG(t){return(await h_(t)).frontmatter["allowed-tools"]||[]}function y_(){Hi.clear(),go.length=0}function dG(){np=null,wy=!1,y_()}function Ct(t){let e=by();if(e?.[t])return e[t];let n=pG(t);if(n)return n;let r=rp.join(Ln,"templates",t);try{return ky.readFileSync(r,"utf-8")}catch{return null}}function pG(t){switch(t){case"codex/SKILL.md":return a_();case"antigravity/SKILL.md":return c_();case"global/GEMINI.md":return u_();case"global/ANTIGRAVITY.md":return d_();case"global/CURSOR.mdc":return m_();case"global/WINDSURF.md":return f_();default:return null}}function sp(t){let e=by();if(e)return Object.keys(e).filter(r=>r.startsWith(t));let n=rp.join(Ln,"templates",t);try{return ky.readdirSync(n).map(s=>`${t}${s}`)}catch{return[]}}var aG,Hi,go,np,wy,mG,fG,ir=y(()=>{"use strict";ts();fy();pt();aG=50,Hi=new Map,go=[],np=null,wy=!1;c(by,"loadBundle");c(cG,"updateLruOrder");c(lG,"evictLru");c(g_,"parseFrontmatter");c(h_,"load");c(uG,"getAllowedTools");c(y_,"clearCache");c(dG,"resetBundle");c(Ct,"getTemplateContent");c(pG,"getGeneratedTemplateContent");c(sp,"listTemplates");mG={load:h_,parseFrontmatter:g_,getAllowedTools:uG,clearCache:y_,getTemplateContent:Ct,listTemplates:sp},fG=mG});var ip=y(()=>{"use strict"});var k_={};C(k_,{resolveUserHome:()=>Rr,resolveUserPath:()=>Re});import gG from"node:os";import w_ from"node:path";function Rr(){let t=process.env.HOME?.trim()||process.env.USERPROFILE?.trim();return t?w_.resolve(t):gG.homedir()}function Re(...t){return w_.join(Rr(),...t)}var Fn=y(()=>{"use strict";c(Rr,"resolveUserHome");c(Re,"resolveUserPath")});var b_,ap,v_,cp=y(()=>{"use strict";b_=new Set(["node_modules",".git","dist","build","out",".next",".nuxt","coverage",".cache",".turbo",".vercel",".parcel-cache","__pycache__",".pytest_cache","target","vendor",".venv","venv","eggs","*.egg-info",".prjct",".worktrees"]),ap=["",".ts",".tsx",".js",".jsx","/index.ts","/index.js"],v_=/(?:import|from)\s+['"]([^'"]+)['"]/g});import T_ from"node:fs/promises";async function x_(t,e){let n;try{n=await T_.readFile(t,"utf-8")}catch(o){if(ne(o))return null;throw o}let r;try{r=JSON.parse(n)}catch{return await E_(t,n),S_(t,"Malformed JSON"),null}let s=e.safeParse(r);return s.success?r:(await E_(t,n),S_(t,hG(s.error)),null)}async function E_(t,e){let n=`${t}.backup`;try{await T_.writeFile(n,e,{encoding:"utf-8",flag:"wx"})}catch{}}function S_(t,e){console.error(`[prjct] Warning: Corrupted storage file: ${t}`),console.error(`[prjct] Reason: ${e}`),console.error("[prjct] A .backup file has been created. Returning defaults.")}function hG(t){return t.issues.slice(0,3).map(e=>`${e.path.join(".")}: ${e.message}`).join("; ")}var C_=y(()=>{"use strict";V();c(x_,"safeRead");c(E_,"createBackup");c(S_,"logCorruption");c(hG,"formatZodError")});var Un={};C(Un,{batchProcess:()=>Hn,dirExists:()=>wt,ensureDir:()=>on,fileExists:()=>A,listFiles:()=>rs,readFile:()=>_n,readJson:()=>Ke,walkDir:()=>Rn,writeFile:()=>ns,writeFileAtomic:()=>ho,writeJson:()=>Le});import sn from"node:fs/promises";import Oc from"node:path";async function vy(t,e,n){try{return await n()}catch(r){throw py(r)||dy(r)?new Error(Mi(r,t,e)):r}}async function Rn(t,e={}){let n=[],r=e.maxFiles??1/0,s=e.dotfileAllowlist?new Set(e.dotfileAllowlist):null;async function o(i){if(n.length>=r)return;let a=await sn.readdir(i,{withFileTypes:!0}).catch(()=>[]);for(let l of a){if(n.length>=r)break;let u=String(l.name);if(b_.has(u)||e.skipDotfiles&&u.startsWith(".")&&(!s||!s.has(u)))continue;let d=Oc.join(i,u);l.isDirectory()?await o(d):l.isFile()&&n.push(Oc.relative(t,d))}}return c(o,"walk"),await o(t),n}async function Hn(t,e,n){let r=[];for(let s=0;s<t.length;s+=e){let o=await Promise.all(t.slice(s,s+e).map(n));for(let i of o)i!==null&&r.push(i)}return r}async function Ke(t,e=null,n){if(n)return await x_(t,n)??e;try{let r=await sn.readFile(t,"utf-8");return JSON.parse(r)}catch(r){if(ne(r))return e;throw r}}async function Le(t,e,n=2){await vy(t,"config",async()=>{let r=Oc.dirname(t);await sn.mkdir(r,{recursive:!0});let s=`${JSON.stringify(e,null,n)}
|
|
22
22
|
`;await sn.writeFile(t,s,"utf-8")})}async function _n(t,e=""){try{return await sn.readFile(t,"utf-8")}catch(n){if(ne(n))return e;throw n}}async function ns(t,e){await vy(t,"file",async()=>{let n=Oc.dirname(t);await sn.mkdir(n,{recursive:!0}),await sn.writeFile(t,e,"utf-8")})}async function ho(t,e){await vy(t,"file",async()=>{let n=Oc.dirname(t);await sn.mkdir(n,{recursive:!0});let r=`${t}.tmp`;await sn.writeFile(r,e,"utf-8"),await sn.rename(r,t)})}async function A(t){try{return await sn.access(t),!0}catch(e){if(ne(e))return!1;throw e}}async function wt(t){try{return(await sn.stat(t)).isDirectory()}catch(e){if(ne(e))return!1;throw e}}async function on(t){await sn.mkdir(t,{recursive:!0})}async function rs(t,e={}){try{let r=await sn.readdir(t,{withFileTypes:!0});return e.filesOnly&&(r=r.filter(s=>s.isFile())),e.dirsOnly&&(r=r.filter(s=>s.isDirectory())),e.extension&&(r=r.filter(s=>s.name.endsWith(e.extension))),r.map(s=>s.name)}catch(n){if(ne(n))return[];throw n}}var se=y(()=>{"use strict";cp();C_();V();c(vy,"withWriteErrorContext");c(Rn,"walkDir");c(Hn,"batchProcess");c(Ke,"readJson");c(Le,"writeJson");c(_n,"readFile");c(ns,"writeFile");c(ho,"writeFileAtomic");c(A,"fileExists");c(wt,"dirExists");c(on,"ensureDir");c(rs,"listFiles")});var Ey,R_=y(()=>{"use strict";Ey="mcp-remote@0.1.38"});import yG from"node:fs";import wG from"node:fs/promises";import __ from"node:os";import ss from"node:path";function kG(){let t=bG();if(t)return{command:t,args:["mcp-server"],description:Sy};try{let e=ss.dirname(Sn.resolve("prjct-cli/package.json"));return{command:ss.join(e,"bin","prjct"),args:["mcp-server"],description:Sy}}catch{return{command:"npx",args:["-y","prjct-cli","mcp-server"],description:Sy}}}function bG(){let t=process.argv[1],e=[t?ss.resolve(ss.dirname(t),"prjct"):"",t?ss.resolve(ss.dirname(t),"..","bin","prjct"):"",ss.resolve(process.cwd(),"bin","prjct")].filter(Boolean);for(let n of e)if(yG.existsSync(n))return n;return null}function Ui(){return process.env.PRJCT_TEST_MODE==="1"?ss.join(__.tmpdir(),"prjct-context7-test","mcp.json"):ss.join(__.homedir(),".claude","mcp.json")}async function A_(t=Ui()){try{let e=await wG.readFile(t,"utf-8");return JSON.parse(e)}catch(e){let n=S(e).toLowerCase();if(n.includes("no such file")||n.includes("enoent"))return{};throw new Error(`Failed to read MCP config at ${t}: ${S(e)}`)}}async function vG(t,e=Ui()){await Le(e,t)}async function Mc(t,e,n=Ui()){let r=await A_(n),s={...r.mcpServers||{}},o=s[t];s[t]=e,r.mcpServers=s;let i=JSON.stringify(o)!==JSON.stringify(e);return await vG(r,n),{path:n,changed:i}}async function I_(t,e=Ui()){return!!(await A_(e)).mcpServers?.[t]}var Sy,Wn,Wi=y(()=>{"use strict";V();se();R_();Sy="prjct: agentic harness with project memory, workflow gates, intent briefs, and performance context. Use prjct_task_start as the MCP entrypoint for a work cycle; prjct retrieves focused context, persists evidence stations, and keeps humans in the loop for risky gates. Agents resume from prjct_task_status/workflow output, create or link reviewed intent/spec briefs when required, and persist synthesized learning instead of raw transcript fragments.";c(kG,"getPrjctMcpConfig");c(bG,"resolveLocalPrjctBin");Wn={context7:{command:"npx",args:["-y","@upstash/context7-mcp@latest"],description:"Library documentation lookup"},prjct:kG(),linear:{command:"npx",args:["-y",Ey,"https://mcp.linear.app/mcp"],description:"Linear MCP server (OAuth)"},jira:{command:"npx",args:["-y",Ey,"https://mcp.atlassian.com/v1/mcp"],description:"Atlassian MCP server for Jira (OAuth)"}};c(Ui,"getClaudeMcpConfigPath");c(A_,"readMcpConfig");c(vG,"writeMcpConfig");c(Mc,"upsertMcpServer");c(I_,"hasMcpServer")});var U_={};C(U_,{buildCodexStatusLineToml:()=>H_,buildContext7McpTomlBlock:()=>L_,buildPrjctMcpTomlBlock:()=>M_,codexHasContext7Server:()=>xy,ensureCodexContext7Server:()=>Fc,ensureCodexMcpServer:()=>Lc,getCodexConfigTomlPath:()=>ar});import yo from"node:fs/promises";import Ty from"node:path";function ar(){return process.env.PRJCT_TEST_MODE==="1"?Ty.join(Re(".prjct-tests"),"codex","config.toml"):Re(".codex","config.toml")}function lp(t){return`"${t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}function O_(t,e,n,r){let s=(e.args??[]).map(lp).join(", ");return[n,`[mcp_servers.${t}]`,`command = ${lp(e.command)}`,`args = [${s}]`,r,""].join(`
|
|
23
23
|
`)}function M_(t=Wn.prjct){return O_("prjct",t,P_,j_)}function L_(t=Wn.context7){return O_("context7",t,$_,N_)}function F_(t,e,n,r,s){let o=t.indexOf(n),i=t.indexOf(r);if(o!==-1&&i!==-1&&i>o){let a=t.slice(0,o),l=t.slice(i+r.length);return l.startsWith(`
|
|
@@ -3009,7 +3009,7 @@ ${Pi.dim("Providers:")}`}var cne,DR=y(()=>{"use strict";cne={ready:Pi.green("\u2
|
|
|
3009
3009
|
${s.dim("Run 'prjct start' to configure global/runtime adapters")}
|
|
3010
3010
|
${s.dim("Run 'prjct init' or 'prjct sync' to refresh AGENTS.md and project-level rules")}
|
|
3011
3011
|
${s.cyan("https://prjct.app")}
|
|
3012
|
-
`)}else return!1;return!0}var EB=y(()=>{"use strict";c(lne,"runBinCommand")});var SB=NB((GWe,une)=>{une.exports={name:"prjct-cli",version:"3.
|
|
3012
|
+
`)}else return!1;return!0}var EB=y(()=>{"use strict";c(lne,"runBinCommand")});var SB=NB((GWe,une)=>{une.exports={name:"prjct-cli",version:"3.61.0",description:"The agentic harness for AI coding agents \u2014 work cycles, bounded RAG context, persistent memory, guardrails, and performance evals.",main:"dist/bin/prjct.mjs",bin:{prjct:"bin/prjct.cjs"},publishConfig:{access:"public",registry:"https://registry.npmjs.org"},scripts:{build:"node scripts/build.js","build:node":"node scripts/build.js",release:"node scripts/release.js","release:patch":"node scripts/release.js patch","release:minor":"node scripts/release.js minor","release:major":"node scripts/release.js major",prepare:"lefthook install","update-commands":`bun -e "const installer = require('./core/infrastructure/command-installer'); installer.syncCommands().then(r => console.log('Commands updated:', r)).catch(e => console.error('Error:', e.message))"`,"install-global":"./scripts/install.sh",update:"./scripts/update.sh",test:"bun test","test:unit":"bun test --path-ignore-patterns='**/e2e/**'","test:fast":"bun test --path-ignore-patterns='**/e2e/**' --dots","test:watch":"bun test --watch","test:coverage":"bun test --coverage",typecheck:"tsc --noEmit -p core/tsconfig.json","typecheck:watch":"tsc --noEmit -p core/tsconfig.json --watch",validate:"bun scripts/validate-commands.js",lint:"biome lint .","lint:fix":"biome lint --write .",knip:"knip","lint:meta":"bun core/cli/lint-meta-commentary.ts",format:"biome format --write .","format:check":"biome format .",check:"biome check .","check:fix":"biome check --write .","test:e2e":"bun test core/__tests__/e2e/","bench:ab":"bun scripts/bench-ab.ts","bench:weak-model":"bun scripts/bench-weak-model.ts","demo:weak-vs-frontier":"bun scripts/demo-weak-vs-frontier.ts","harness:score":"bun bin/prjct.ts harness score --md","gate:dominance":"bun test core/__tests__/services/weak-model-bench.test.ts core/__tests__/services/weak-frontier-demo.test.ts core/__tests__/services/harness-score.test.ts core/__tests__/services/dynasty-outcomes.test.ts core/__tests__/services/content-bound-stamp.test.ts core/__tests__/services/sot-bind.test.ts core/__tests__/services/trap-surface-slo.test.ts core/__tests__/services/impact-ready.test.ts core/__tests__/services/delivery-geometry.test.ts core/__tests__/services/cycle-budget-card.test.ts core/__tests__/services/land-rho.test.ts core/__tests__/services/one-breath-install.test.ts core/__tests__/services/doctor-heal.test.ts && bun run bench:weak-model && bun run demo:weak-vs-frontier"},keywords:["claude-code","gemini-cli","ai-agents","context-layer","developer-tools","ai-assistant","productivity","mcp","llm","coding-agents"],author:{name:"Juan Jos\xE9 L\xF3pez Lira",email:"jlopezlira@gmail.com",url:"https://prjct.app"},contributors:[{name:"prjct.app contributors"}],license:"MIT",licenses:[{type:"MIT",url:"https://opensource.org/licenses/MIT"}],dependencies:{"@clack/prompts":"1.0.0","@modelcontextprotocol/sdk":"1.29.0",chalk:"4.1.2",chokidar:"5.0.0","jsonc-parser":"3.3.1",zod:"3.25.76"},overrides:{"path-to-regexp":"8.4.0","brace-expansion":"5.0.5","fast-uri":">=3.1.2",hono:"4.12.27","ip-address":">=10.1.1",qs:"6.15.2"},devDependencies:{"@biomejs/biome":"2.3.13","@types/bun":"latest","@types/chokidar":"2.1.7","@types/node":"^22",esbuild:"0.28.1",knip:"6.3.1",lefthook:"2.1.0",typescript:"5.9.3"},repository:{type:"git",url:"git+https://github.com/prjct-app/cli.git"},bugs:{url:"https://github.com/prjct-app/cli/issues"},homepage:"https://cli.prjct.app",packageManager:"bun@1.2.23",engines:{bun:">=1.0.0",node:">=22.5.0"},files:["assets/","bin/prjct","bin/prjct.cjs","dist/","templates/","scripts/install.sh","LICENSE","NOTICE","README.md","CHANGELOG.md"],prepublishOnly:"node scripts/build.js"}});var hne={};import TB from"node:os";import Zh from"node:path";import ji from"chalk";async function dne(){let[t,...e]=process.argv.slice(2);if(["-v","--version","version"].includes(t)){let r=await Promise.resolve().then(()=>DB(SB()));await fne(r.version),process.exit(0)}if(["-h","--help",void 0].includes(t)&&(gne(),process.exit(0)),t&&td(t)&&!At.getByName(t)){let r=ed[t];r&&(h.failWithHint({message:`'prjct ${t}' was removed in v2. ${r.note}`,hint:`Use: ${r.replacement}`}),process.exit(1))}if(t&&!At.getByName(t)&&!(e.length===0&&Pd(t)!==null)){let s=[t,...e.filter(i=>!i.startsWith("-"))].join(" "),o=e.filter(i=>i.startsWith("-"));t="capture",e=[s,...o]}let n=e.includes("--md");n||h.start();try{let r=At.getByName(t);if(!r){let m=Pd(t),f=m?`Did you mean 'prjct ${m}'? Run 'prjct --help' for all commands`:"Run 'prjct --help' to see available commands";h.failWithHint(Uc("UNKNOWN_COMMAND",{message:`Unknown command: ${t}`,hint:f})),n||h.end(),process.exit(1)}if(r.deprecated){let m=r.replacedBy?`Use 'prjct ${r.replacedBy}' instead`:"Run 'prjct --help' to see available commands";h.failWithHint({message:`Command '${t}' is deprecated`,hint:m}),n||h.end(),process.exit(1)}r.implemented||(h.failWithHint({message:`Command '${t}' is not yet implemented`,hint:"Run 'prjct --help' to see available commands",docs:"https://github.com/prjct-app/cli"}),n||h.end(),process.exit(1));let{parsedArgs:s,options:o}=mne(r,e),i=!process.stdin.isTTY||o.md===!0||o.json===!0;r.requiresLlm&&!i&&(h.failWithHint({message:`'prjct ${t}' requires an AI agent to process its output`,hint:`Use 'p. ${t}' inside Claude/Cursor, or add --md flag`}),n||h.end(),process.exit(1));let a=pne(r,s);a&&(h.failWithHint(a),n||h.end(),process.exit(1));let l=null,u=Date.now();try{l=await R.getProjectId(process.cwd()),l&&(await pi.expireIfStale(l),await pi.touch(l))}catch{}let d=new Ci,p;if(t==="analyze")p=await d.analyze(o);else if(t==="setup")p=await d.setup(o);else if(t==="update"||t==="upgrade")p=await d.update(o);else{let m=s.join(" ")||null,f=o.md===!0,g=At.getByName(t);if(g?.optionSchema)p=await At.executeWithOptions(t,m,process.cwd(),Xh(o,g.optionSchema));else{let k={spec:c(b=>jd(d,(b??"").trim().split(/\s+/).filter(Boolean),o,process.cwd()),"spec"),intent:c(b=>jd(d,(b??"").trim().split(/\s+/).filter(Boolean),o,process.cwd()),"intent"),"audit-spec":c(b=>b?d.specAudit(b,process.cwd(),{md:f,lenses:o.lenses?String(o.lenses):void 0}):Promise.resolve({success:!1,error:"audit-spec requires a spec id"}),"audit-spec"),init:c(b=>d.init({idea:b,yes:o.yes===!0,pack:o.pack?String(o.pack):void 0,persona:o.persona?String(o.persona):void 0}),"init"),sync:c(()=>d.sync(process.cwd(),{preview:o.preview===!0||o["dry-run"]===!0,yes:o.yes===!0,json:o.json===!0,md:f,package:o.package?String(o.package):void 0,full:o.full===!0}),"sync"),"analysis-save-llm":c(b=>b?d.saveLlmAnalysis(b,process.cwd(),{md:f}):Promise.resolve({success:!1,error:"analysis-save-llm requires analysis text, JSON, or a file path"}),"analysis-save-llm"),start:c(()=>d.start(),"start"),login:c(()=>d.login({md:f}),"login"),logout:c(()=>d.logout(),"logout"),auth:c(b=>d.auth(b,{md:f}),"auth")}[t];if(k)p=await k(m);else throw new Error(`Command '${t}' has no handler`)}}if(l){let m=Date.now()-u;try{await pi.trackCommand(l,t,m)}catch{}try{await nd.recordTiming(l,"command_duration",m,{command:t});let f=globalThis.__perfStartNs;if(f){let g=Number(process.hrtime.bigint()-f)/1e6;await nd.recordTiming(l,"startup_time",g)}await nd.recordMemory(l,{command:t})}catch{}}p?.message?console.log(p.message):p?.error&&console.error(p.error),n||h.end(),process.exit(p?.success?0:1)}catch(r){console.error("Error:",S(r)),process.env.DEBUG&&console.error(my(r)),n||h.end(),process.exit(1)}}function pne(t,e){if(!t.params)return null;let r=t.params.replace(/\[[^\]]*\]/g,"").match(/<[^>]+>/g);if(!r||r.length===0)return null;if(e.length<r.length){let s=r.map(i=>i.slice(1,-1)).join(", "),o=t.usage.terminal||`prjct ${t.name} ${t.params}`;return Uc("MISSING_PARAM",{message:`Missing required parameter: ${s}`,hint:`Usage: ${o}`})}return null}function mne(t,e){let n=[],r={};for(let s=0;s<e.length;s++){let o=e[s];if(o.startsWith("--")){let i=o.slice(2);s+1<e.length&&!e[s+1].startsWith("--")?r[i]=e[++s]:r[i]=!0}else n.push(o)}return{parsedArgs:n,options:r}}async function fne(t){let e=await bo(),n=Zh.join(TB.homedir(),".claude","commands","p.md"),r=Zh.join(TB.homedir(),".gemini","commands","p.toml"),[s,o,i,a]=await Promise.all([A(n),A(r),A(Zh.join(process.cwd(),".cursor","commands","sync.md")),A(Zh.join(process.cwd(),".cursor"))]),l=await Xc();console.log(NR(t)),console.log(Cc("Claude Code",e.claude.installed?s?"ready":"installed":"missing",e.claude.version?ji.dim(` (v${e.claude.version})`):"")),console.log(Cc("Gemini CLI",e.gemini.installed?o?"ready":"installed":"missing",e.gemini.version?ji.dim(` (v${e.gemini.version})`):"")),console.log(Cc("Antigravity",l.installed?l.skillInstalled?"ready":"detected":"missing",l.installed&&!l.skillInstalled?` ${ji.dim("(run prjct start)")}`:"")),console.log(Cc("Cursor IDE",i?"ready":a?"detected":"missing",i?` ${ji.dim("(use prjct router)")}`:a?` ${ji.dim("(run prjct init)")}`:"","\u25CB no .cursor/ folder")),console.log(`
|
|
3013
3013
|
${ji.dim("Run 'prjct start' for Claude/Gemini, 'prjct init' for Cursor")}
|
|
3014
3014
|
${ji.cyan("https://prjct.app")}
|
|
3015
3015
|
`)}function gne(){console.log(`
|
package/dist/bin/prjct-hooks.mjs
CHANGED
|
@@ -1228,7 +1228,7 @@ CREATE TABLE velocity_sprints (
|
|
|
1228
1228
|
name TEXT NOT NULL,
|
|
1229
1229
|
applied_at TEXT NOT NULL
|
|
1230
1230
|
)
|
|
1231
|
-
`);let r=new Set(e.prepare("SELECT version FROM _migrations").all().map(i=>i.version)),s=Wo.filter(i=>!r.has(i.version));if(s.length!==0){if(n&&r.size>0)try{let i=`${n}.pre-migrate.bak`;ci.existsSync(i)&&ci.rmSync(i,{force:!0}),e.prepare("VACUUM INTO ?").run(i)}catch(i){console.warn(`prjct: pre-migration backup failed (continuing): ${i?.message??i}`)}for(let i of s)du(e,()=>{i.up(e),e.prepare("INSERT INTO _migrations (version, name, applied_at) VALUES (?, ?, ?)").run(i.version,i.name,new Date().toISOString())})}}getMigrations(e){return this.getDb(e).prepare("SELECT * FROM _migrations ORDER BY version").all()}getSchemaVersion(e){return this.getDb(e).prepare("SELECT MAX(version) as version FROM _migrations").get()?.version??0}},E=new Bo,y=E});function Uh(t){let e=t.toLowerCase();return e.includes("github")?"github":e.includes("gitlab")?"gitlab":e.includes("bitbucket")?"bitbucket":"other"}function pu(t){let e=t.trim();if(!e)return{};let n=e.match(/^[^/@]+@([^:/]+):(.+?)(?:\.git)?\/?$/);if(n)return{provider:Uh(n[1]),repoSlug:n[2]};try{let r=new URL(e),s=r.pathname.replace(/^\/+/,"").replace(/\.git$/,"").replace(/\/+$/,"");return!r.host||!s?{}:{provider:Uh(r.host),repoSlug:s}}catch{return{}}}async function YI(t){try{let{stdout:e}=await U("git",["remote","get-url","origin"],{cwd:t});return e.trim()||void 0}catch{return}}async function zI(t){try{let{stdout:e}=await U("git",["symbolic-ref","--short","refs/remotes/origin/HEAD"],{cwd:t});return e.trim().replace(/^origin\//,"")||void 0}catch{return}}function tr(t){return typeof t=="string"&&t.length>0?t:void 0}function Wh(t){return typeof t=="number"&&Number.isFinite(t)?t:void 0}function QI(t){return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}async function Bh(t){let e=E.getDoc(t,"project")||{},n=tr(e.repoPath),{provider:r,repoSlug:s}=n?pu(await YI(n)||""):{},i=n?await zI(n):void 0,o=Array.isArray(e.techStack)?e.techStack.filter(c=>typeof c=="string"):void 0;return QI({provider:r,repoSlug:s,currentBranch:tr(e.currentBranch),defaultBranch:i,stack:tr(e.stack),techStack:o&&o.length>0?o:void 0,version:tr(e.version),commitCount:Wh(e.commitCount),fileCount:Wh(e.fileCount),lastCommit:tr(e.lastSyncCommit),hasUncommitted:typeof e.hasUncommittedChanges=="boolean"?e.hasUncommittedChanges:void 0,cliVersion:tr(e.cliVersion),syncedAt:tr(e.lastSync)})}var mu=f(()=>{"use strict";L();ne();a(Uh,"providerForHost");a(pu,"parseRemote");a(YI,"gitRemoteUrl");a(zI,"gitDefaultBranch");a(tr,"str");a(Wh,"num");a(QI,"compact");a(Bh,"buildProjectMeta")});import{execFile as ZI}from"node:child_process";import eN from"node:crypto";import{promisify as tN}from"node:util";function sN(t,e=rN){let n=Buffer.from(e.replace(/-/g,""),"hex"),s=eN.createHash("sha1").update(n).update(t,"utf8").digest().subarray(0,16);s[6]=s[6]&15|80,s[8]=s[8]&63|128;let i=s.toString("hex");return`${i.slice(0,8)}-${i.slice(8,12)}-${i.slice(12,16)}-${i.slice(16,20)}-${i.slice(20,32)}`}async function iN(t){let e;try{let{stdout:s}=await nN("git",["remote","get-url","origin"],{cwd:t});e=s.trim()||void 0}catch{return null}if(!e)return null;let{provider:n,repoSlug:r}=pu(e);return!n||!r?null:`${n}:${r}`.toLowerCase()}async function Gh(t){let e=await iN(t);return e?sN(e):null}var nN,rN,Xh=f(()=>{"use strict";mu();nN=tN(ZI),rN="6f9b2c1a-3d4e-5f60-8a7b-1c2d3e4f5a6b";a(sN,"uuidv5");a(iN,"repoKey");a(Gh,"deriveProjectId")});var hu={};C(hu,{PACKAGE_ROOT:()=>ln,VERSION:()=>Be,getPackageRoot:()=>fu,getVersion:()=>Xo,resetPackageRoot:()=>oN});import gu from"node:fs";import Go from"node:path";function fu(){if(Yr)return Yr;let t=__dirname;for(let e=0;e<5;e++){let n=Go.join(t,"package.json");if(gu.existsSync(n))try{if(JSON.parse(gu.readFileSync(n,"utf-8")).name==="prjct-cli")return Yr=t,t}catch{}t=Go.dirname(t)}return Yr=Go.join(__dirname,"..","..",".."),Yr}function Xo(){if(nr)return nr;let t="3.
|
|
1231
|
+
`);let r=new Set(e.prepare("SELECT version FROM _migrations").all().map(i=>i.version)),s=Wo.filter(i=>!r.has(i.version));if(s.length!==0){if(n&&r.size>0)try{let i=`${n}.pre-migrate.bak`;ci.existsSync(i)&&ci.rmSync(i,{force:!0}),e.prepare("VACUUM INTO ?").run(i)}catch(i){console.warn(`prjct: pre-migration backup failed (continuing): ${i?.message??i}`)}for(let i of s)du(e,()=>{i.up(e),e.prepare("INSERT INTO _migrations (version, name, applied_at) VALUES (?, ?, ?)").run(i.version,i.name,new Date().toISOString())})}}getMigrations(e){return this.getDb(e).prepare("SELECT * FROM _migrations ORDER BY version").all()}getSchemaVersion(e){return this.getDb(e).prepare("SELECT MAX(version) as version FROM _migrations").get()?.version??0}},E=new Bo,y=E});function Uh(t){let e=t.toLowerCase();return e.includes("github")?"github":e.includes("gitlab")?"gitlab":e.includes("bitbucket")?"bitbucket":"other"}function pu(t){let e=t.trim();if(!e)return{};let n=e.match(/^[^/@]+@([^:/]+):(.+?)(?:\.git)?\/?$/);if(n)return{provider:Uh(n[1]),repoSlug:n[2]};try{let r=new URL(e),s=r.pathname.replace(/^\/+/,"").replace(/\.git$/,"").replace(/\/+$/,"");return!r.host||!s?{}:{provider:Uh(r.host),repoSlug:s}}catch{return{}}}async function YI(t){try{let{stdout:e}=await U("git",["remote","get-url","origin"],{cwd:t});return e.trim()||void 0}catch{return}}async function zI(t){try{let{stdout:e}=await U("git",["symbolic-ref","--short","refs/remotes/origin/HEAD"],{cwd:t});return e.trim().replace(/^origin\//,"")||void 0}catch{return}}function tr(t){return typeof t=="string"&&t.length>0?t:void 0}function Wh(t){return typeof t=="number"&&Number.isFinite(t)?t:void 0}function QI(t){return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}async function Bh(t){let e=E.getDoc(t,"project")||{},n=tr(e.repoPath),{provider:r,repoSlug:s}=n?pu(await YI(n)||""):{},i=n?await zI(n):void 0,o=Array.isArray(e.techStack)?e.techStack.filter(c=>typeof c=="string"):void 0;return QI({provider:r,repoSlug:s,currentBranch:tr(e.currentBranch),defaultBranch:i,stack:tr(e.stack),techStack:o&&o.length>0?o:void 0,version:tr(e.version),commitCount:Wh(e.commitCount),fileCount:Wh(e.fileCount),lastCommit:tr(e.lastSyncCommit),hasUncommitted:typeof e.hasUncommittedChanges=="boolean"?e.hasUncommittedChanges:void 0,cliVersion:tr(e.cliVersion),syncedAt:tr(e.lastSync)})}var mu=f(()=>{"use strict";L();ne();a(Uh,"providerForHost");a(pu,"parseRemote");a(YI,"gitRemoteUrl");a(zI,"gitDefaultBranch");a(tr,"str");a(Wh,"num");a(QI,"compact");a(Bh,"buildProjectMeta")});import{execFile as ZI}from"node:child_process";import eN from"node:crypto";import{promisify as tN}from"node:util";function sN(t,e=rN){let n=Buffer.from(e.replace(/-/g,""),"hex"),s=eN.createHash("sha1").update(n).update(t,"utf8").digest().subarray(0,16);s[6]=s[6]&15|80,s[8]=s[8]&63|128;let i=s.toString("hex");return`${i.slice(0,8)}-${i.slice(8,12)}-${i.slice(12,16)}-${i.slice(16,20)}-${i.slice(20,32)}`}async function iN(t){let e;try{let{stdout:s}=await nN("git",["remote","get-url","origin"],{cwd:t});e=s.trim()||void 0}catch{return null}if(!e)return null;let{provider:n,repoSlug:r}=pu(e);return!n||!r?null:`${n}:${r}`.toLowerCase()}async function Gh(t){let e=await iN(t);return e?sN(e):null}var nN,rN,Xh=f(()=>{"use strict";mu();nN=tN(ZI),rN="6f9b2c1a-3d4e-5f60-8a7b-1c2d3e4f5a6b";a(sN,"uuidv5");a(iN,"repoKey");a(Gh,"deriveProjectId")});var hu={};C(hu,{PACKAGE_ROOT:()=>ln,VERSION:()=>Be,getPackageRoot:()=>fu,getVersion:()=>Xo,resetPackageRoot:()=>oN});import gu from"node:fs";import Go from"node:path";function fu(){if(Yr)return Yr;let t=__dirname;for(let e=0;e<5;e++){let n=Go.join(t,"package.json");if(gu.existsSync(n))try{if(JSON.parse(gu.readFileSync(n,"utf-8")).name==="prjct-cli")return Yr=t,t}catch{}t=Go.dirname(t)}return Yr=Go.join(__dirname,"..","..",".."),Yr}function Xo(){if(nr)return nr;let t="3.61.0";if(t&&/^\d+\.\d+\.\d+/.test(t))return nr=t,nr;try{let e=Go.join(fu(),"package.json");return nr=JSON.parse(gu.readFileSync(e,"utf-8")).version,nr}catch(e){return process.env.PRJCT_DEBUG==="1"&&console.error("Failed to read version from package.json:",R(e)),"0.0.0"}}function oN(t){Yr=t,nr=null}var nr,Yr,Be,ln,Dt=f(()=>{"use strict";te();nr=null,Yr=null;a(fu,"getPackageRoot");a(Xo,"getVersion");a(oN,"resetPackageRoot");Be=Xo(),ln=fu()});async function qo(t){try{let{stdout:e}=await H(t,{timeout:5e3});return{success:!0,output:e.trim()}}catch{return{success:!1,output:""}}}async function aN(){let t=await qo("gh api user --jq .login");return t.success&&t.output||(t=await qo("git config --global github.user"),t.success&&t.output)?t.output:null}async function cN(){let t=await qo("git config user.name");return t.success&&t.output?t.output:null}async function lN(){let t=await qo("git config user.email");return t.success&&t.output?t.output:null}async function zr(){let[t,e,n]=await Promise.all([aN(),cN(),lN()]);return{github:t,email:n,name:e||t||"Unknown"}}var Vo=f(()=>{"use strict";ne();a(qo,"execCommand");a(aN,"detectGitHubUsername");a(cN,"detectGitName");a(lN,"detectGitEmail");a(zr,"detect")});var Jo={};C(Jo,{worktreeService:()=>uN});import Eu from"node:fs/promises";import qt from"node:path";var qh,ku,uN,Ko=f(()=>{"use strict";ne();Y();qh=".worktrees",ku=class{static{a(this,"WorktreeService")}async create(e,n,r={}){let s=await this.getMainWorktree(e),i=qt.join(s,qh,n),o=r.branch||`feat/${n}`;await Eu.mkdir(qt.join(s,qh),{recursive:!0});let c=r.baseBranch?` ${r.baseBranch}`:"";await H(`git worktree add "${i}" -b "${o}"${c}`,{cwd:s});let{stdout:l}=await H("git rev-parse HEAD",{cwd:i});return{path:i,branch:o,commit:l.trim(),isMain:!1,slug:n}}async remove(e,n=!1){let r=await this.getMainWorktree(e),s;if(n)try{let{stdout:i}=await H("git rev-parse --abbrev-ref HEAD",{cwd:e});s=i.trim()}catch{}if(await H(`git worktree remove "${e}" --force`,{cwd:r}),n&&s&&s!=="main"&&s!=="master")try{await H(`git branch -D "${s}"`,{cwd:r})}catch{}}async list(e){let n=await this.getMainWorktree(e),{stdout:r}=await H("git worktree list --porcelain",{cwd:n});return this.parsePorcelainOutput(r,n)}async detect(e){try{let{stdout:n}=await H("git rev-parse --git-common-dir",{cwd:e}),{stdout:r}=await H("git rev-parse --git-dir",{cwd:e}),s=qt.resolve(e,n.trim()),i=qt.resolve(e,r.trim());if(s!==i){let{stdout:o}=await H("git rev-parse --abbrev-ref HEAD",{cwd:e}),{stdout:c}=await H("git rev-parse HEAD",{cwd:e}),{stdout:l}=await H("git rev-parse --show-toplevel",{cwd:e}),u=l.trim(),d=qt.basename(u);return{path:u,branch:o.trim(),commit:c.trim(),isMain:!1,slug:d}}return null}catch{return null}}async getMainWorktree(e){try{let{stdout:r}=await H("git worktree list --porcelain",{cwd:e}),s=r.split(`
|
|
1232
1232
|
`)[0];if(s?.startsWith("worktree "))return s.replace("worktree ","").trim()}catch{}let{stdout:n}=await H("git rev-parse --show-toplevel",{cwd:e});return n.trim()}async setup(e,n){let r=qt.join(n,".env");await D(r)&&await Eu.copyFile(r,qt.join(e,".env"));let s=qt.join(n,".prjct"),i=qt.join(e,".prjct");await D(s)&&!await D(i)&&await Eu.symlink(s,i,"dir")}async teardown(e){}async clean(e){let n=await this.list(e),r=[],s=await this.getMainWorktree(e);await H("git worktree prune",{cwd:s});for(let i of n)i.isMain||await D(i.path)||r.push(i.slug);return r}parsePorcelainOutput(e,n){let r=[],s=e.trim().split(`
|
|
1233
1233
|
|
|
1234
1234
|
`);for(let i of s){if(!i.trim())continue;let o=i.trim().split(`
|
package/dist/daemon/entry.mjs
CHANGED
|
@@ -1253,7 +1253,7 @@ CREATE TABLE velocity_sprints (
|
|
|
1253
1253
|
LIMIT ?`,s,t.kind,r).map(Ba):b.query(n,`SELECT * FROM code_symbols
|
|
1254
1254
|
WHERE name LIKE ? COLLATE NOCASE OR qname LIKE ? COLLATE NOCASE
|
|
1255
1255
|
ORDER BY exported DESC, name
|
|
1256
|
-
LIMIT ?`,s,s,r).map(Ba)}catch{return[]}}function Fg(n,e,t=20){let r=e.split(/[^A-Za-z0-9_]+/).flatMap(o=>o.replace(/([a-z])([A-Z])/g,"$1 $2").split(/\s+/)).map(o=>o.trim()).filter(o=>o.length>2);if(r.length===0||!Xe(n))return[];let s=new Map;for(let o of r){let i=Tn(n,o,{limit:40});for(let c of i){let l=c.name.toLowerCase()===o.toLowerCase()?1:.55,u=c.exported?1.15:1,d=c.kind==="function"||c.kind==="class"||c.kind==="route"?1.1:1,p=l*u*d,m=s.get(c.file)??{score:0,names:new Set};m.score+=p,m.names.add(c.name),s.set(c.file,m)}}return Array.from(s.entries()).map(([o,i])=>({path:o,score:i.score,matchedNames:[...i.names]})).sort((o,i)=>i.score-o.score).slice(0,t)}function Bs(n,e){try{return b.query(n,"SELECT * FROM code_symbols WHERE file = ? ORDER BY start_line",e).map(Ba)}catch{return[]}}function Hg(n,e="CALLS"){let t=new Map,r=new Map;try{let s=b.query(n,"SELECT src, dst FROM code_symbol_edges WHERE edge_type = ?",e);for(let o of s)t.has(o.src)||t.set(o.src,[]),t.get(o.src).push(o.dst),r.has(o.dst)||r.set(o.dst,[]),r.get(o.dst).push(o.src)}catch{}return{forward:t,reverse:r}}function Px(n,e){try{let t=b.get(n,"SELECT * FROM code_symbols WHERE id = ?",e);return t?Ba(t):null}catch{return null}}function Ga(n,e,t={}){let r=t.direction??"both",s=Math.min(Math.max(t.depth??3,1),5),o=Tn(n,e,{limit:10}).filter(f=>f.name.toLowerCase()===e.toLowerCase()),i=o.length>0?o:Tn(n,e,{limit:5});if(i.length===0)return null;let{forward:c,reverse:l}=Hg(n,"CALLS"),u=[],d=[],p=a((f,g,w,k)=>{let S=new Set(f),x=f.map(T=>({id:T,depth:0}));for(let T=0;T<x.length;T++){let{id:$,depth:A}=x[T];if(!(A>=k))for(let N of g.get($)??[]){if(S.has(N))continue;if(S.add(N),N.startsWith("file:")){let ee=N.slice(5),je=Bs(n,ee),re=je.find(Q=>Q.exported&&(Q.kind==="function"||Q.kind==="class"))??je.find(Q=>Q.kind==="function"||Q.kind==="class")??je[0];re&&!S.has(re.id)&&(S.add(re.id),w.push({symbol:re,depth:A+1,via:"CALLS"}),x.push({id:re.id,depth:A+1})),x.push({id:N,depth:A+1});continue}let U=Px(n,N);U&&(w.push({symbol:U,depth:A+1,via:"CALLS"}),x.push({id:N,depth:A+1}))}}},"bfs"),m=i.map(f=>f.id);return(r==="inbound"||r==="both")&&p(m,l,u,s),(r==="outbound"||r==="both")&&p(m,c,d,s),{root:i,inbound:u,outbound:d}}function qa(n,e){let t=Bs(n,e);if(t.length===0)return 0;let{reverse:r}=Hg(n,"CALLS"),s=new Set;for(let o of t)for(let i of r.get(o.id)??[])s.add(i);return s.size}function Ug(n,e,t=2){let r=new Set(e),{reverse:s}=Hg(n,"CALLS"),o=new Set;for(let u of e)for(let d of Bs(n,u))o.add(d.id);let i=new Set,c=new Set(o),l=[...o];for(let u=0;u<t;u++){let d=[];for(let p of l)for(let m of s.get(p)??[])if(!c.has(m))if(c.add(m),d.push(m),m.startsWith("file:")){let f=m.slice(5);r.has(f)||i.add(f)}else{let f=Px(n,m);f&&!r.has(f.file)&&i.add(f.file)}l=d}return[...i]}var Mg,ZU,e1,t1,xn=y(()=>{"use strict";wu();H();de();Mg="symbol-graph",ZU=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".go",".rs",".java"]),e1=new Set(["if","for","while","switch","catch","function","class","return","typeof","new","throw","await","void","super","this","import","require","console","Math","JSON","Object","Array","Promise","Map","Set","Date","Error","Buffer","process","describe","it","test","expect","beforeEach","afterEach","beforeAll","afterAll"]),t1=new Set(["if","for","while","switch","catch","return","await","typeof","new","throw","else","case","from","import","export","class","function","const","let","var","get","set","constructor","async","static","public","private","protected","readonly","abstract","extends","implements","interface","type","enum","default","as","of","in","do","try","finally","yield","with"]);a(Jt,"lineOf");a(n1,"symbolId");a(vx,"qnameOf");a(Ou,"isSourceFile");a(ii,"stripNoise");a(Tx,"emptyExtract");a(xx,"finalizeCalls");a(r1,"extractTsJs");a(s1,"extractPython");a(o1,"extractGo");a(i1,"extractRust");a(a1,"extractJava");a(Rx,"extractFile");a(c1,"loadTsPathMap");a(l1,"applyTsPath");a(u1,"resolveSpecifierToFile");a(d1,"resolveImportsForExtract");a(Sx,"matchFileToMod");a(Cx,"enclosingSymbol");a(_x,"resolveCallTargets");a(Ax,"buildFromExtracts");a(Ix,"extractProject");a(p1,"persistGraph");a(m1,"patchGraph");a(Ws,"indexSymbols");a(Lg,"updateSymbols");a(Xe,"hasSymbolIndex");a(un,"loadMeta");a(Ba,"rowToSymbol");a(rr,"listAllSymbols");a(Tn,"searchSymbols");a(Fg,"scoreFilesFromQuery");a(Bs,"symbolsInFile");a(Hg,"loadEdges");a(Px,"symbolById");a(Ga,"tracePath");a(qa,"fileFanIn");a(Ug,"filesCallingInto")});function Du(n){if(n.length===0)return[];let e=n[0]?.score||1;return n.map(t=>({path:t.path,score:t.score/e}))}var Xa,Nx=y(()=>{"use strict";ri();si();_r();xn();a(Du,"normalize");Xa=[{name:"bm25",kind:"query",defaultWeight:.45,hasIndex:a(n=>fx(n),"hasIndex"),scoreFromQuery:a((n,e,t)=>Du(Pu(n,e,t)),"scoreFromQuery")},{name:"symbols",kind:"query",defaultWeight:.2,hasIndex:a(n=>Xe(n),"hasIndex"),scoreFromQuery:a((n,e,t)=>Du(Fg(n,e,t)),"scoreFromQuery")},{name:"imports",kind:"seed",defaultWeight:.2,hasIndex:a(n=>Tt(n)!==null,"hasIndex"),scoreFromSeeds:a((n,e,t)=>{let r=Tt(n);return r?Du(oi(e,r,t.importDepth)):[]},"scoreFromSeeds")},{name:"cochange",kind:"seed",defaultWeight:.15,hasIndex:a(n=>vn(n)!==null,"hasIndex"),scoreFromSeeds:a((n,e)=>{let t=vn(n);return t?Du(Fs(e,t)):[]},"scoreFromSeeds")}]});function $x(n,e,t={}){let r={...f1,...t},s={bm25:r.bm25Weight,symbols:r.symbolsWeight,imports:r.importWeight,cochange:r.cochangeWeight},o=Xa.filter(m=>m.kind==="query"),i=Xa.filter(m=>m.kind==="seed"),c=new Map,l=new Map;for(let m of o){let f=m.scoreFromQuery(n,e,r.topN*3);if(f.length!==0){c.set(m.name,new Map(f.map(g=>[g.path,g.score])));for(let g of f.slice(0,jx))l.set(g.path,Math.max(l.get(g.path)??0,g.score))}}if(c.size===0)return[];let u=[...l.entries()].sort((m,f)=>f[1]-m[1]).slice(0,jx).map(([m])=>m);for(let m of i){let f=m.scoreFromSeeds(n,u,{importDepth:r.importDepth});f.length!==0&&c.set(m.name,new Map(f.map(g=>[g.path,g.score])))}let d=new Set;for(let m of c.values())for(let f of m.keys())d.add(f);let p=[];for(let m of d){let f=0;for(let[g,w]of c){let k=w.get(m)??0,S=s[g]??Xa.find(x=>x.name===g)?.defaultWeight??0;f+=k*S}p.push({path:m,finalScore:f,signals:{bm25:c.get("bm25")?.get(m)??0,imports:c.get("imports")?.get(m)??0,cochange:c.get("cochange")?.get(m)??0,symbols:c.get("symbols")?.get(m)??0}})}return p.sort((m,f)=>f.finalScore-m.finalScore),p.slice(0,r.topN)}function Ox(n){let e={};for(let t of Xa)e[t.name]=t.hasIndex(n);return{bm25:e.bm25??!1,imports:e.imports??!1,cochange:e.cochange??!1,symbols:e.symbols??!1}}var f1,jx,Dx=y(()=>{"use strict";Nx();f1={bm25Weight:.45,importWeight:.2,cochangeWeight:.15,symbolsWeight:.2,topN:15,importDepth:2},jx=10;a($x,"rankFiles");a(Ox,"hasIndexes")});function g1(n){return n instanceof ai}function lt(n){return g1(n)||n instanceof Error?n.message:typeof n=="string"?n:"Unknown error"}var ai,Mu,Lu,Ja,Ar=y(()=>{"use strict";ai=class extends Error{static{a(this,"PrjctError")}code;isOperational;constructor(e,t="PRJCT_ERROR"){super(e),this.name="PrjctError",this.code=t,this.isOperational=!0,Error.captureStackTrace?.(this,this.constructor)}},Mu=class n extends ai{static{a(this,"ProjectError")}constructor(e,t="PROJECT_ERROR"){super(e,t),this.name="ProjectError"}static notInitialized(){return new n("Project not initialized. Run p. init first.","PROJECT_NOT_INIT")}static notFound(e){return new n(`Project not found: ${e}`,"PROJECT_NOT_FOUND")}static invalidId(e){return new n(`Invalid project ID: ${e}`,"PROJECT_INVALID_ID")}},Lu=class n extends ai{static{a(this,"TemplateError")}constructor(e,t="TEMPLATE_ERROR"){super(e,t),this.name="TemplateError"}static notFound(e){return new n(`Template not found: ${e}.md`,"TEMPLATE_NOT_FOUND")}static parseFailed(e){return new n(`Failed to parse template: ${e}`,"TEMPLATE_PARSE_ERROR")}},Ja=class n extends ai{static{a(this,"AgentError")}constructor(e,t="AGENT_ERROR"){super(e,t),this.name="AgentError"}static notSupported(e){return new n(`Unsupported agent type: ${e}`,"AGENT_NOT_SUPPORTED")}static initFailed(e){return new n(`Agent initialization failed: ${e}`,"AGENT_INIT_FAILED")}};a(g1,"isPrjctError");a(lt,"getErrorMessage")});function Mx(n){let e=n.toLowerCase();return e.includes("github")?"github":e.includes("gitlab")?"gitlab":e.includes("bitbucket")?"bitbucket":"other"}function Bg(n){let e=n.trim();if(!e)return{};let t=e.match(/^[^/@]+@([^:/]+):(.+?)(?:\.git)?\/?$/);if(t)return{provider:Mx(t[1]),repoSlug:t[2]};try{let r=new URL(e),s=r.pathname.replace(/^\/+/,"").replace(/\.git$/,"").replace(/\/+$/,"");return!r.host||!s?{}:{provider:Mx(r.host),repoSlug:s}}catch{return{}}}async function h1(n){try{let{stdout:e}=await G("git",["remote","get-url","origin"],{cwd:n});return e.trim()||void 0}catch{return}}async function y1(n){try{let{stdout:e}=await G("git",["symbolic-ref","--short","refs/remotes/origin/HEAD"],{cwd:n});return e.trim().replace(/^origin\//,"")||void 0}catch{return}}function Gs(n){return typeof n=="string"&&n.length>0?n:void 0}function Lx(n){return typeof n=="number"&&Number.isFinite(n)?n:void 0}function w1(n){return Object.fromEntries(Object.entries(n).filter(([,e])=>e!==void 0))}async function Fu(n){let e=E.getDoc(n,"project")||{},t=Gs(e.repoPath),{provider:r,repoSlug:s}=t?Bg(await h1(t)||""):{},o=t?await y1(t):void 0,i=Array.isArray(e.techStack)?e.techStack.filter(c=>typeof c=="string"):void 0;return w1({provider:r,repoSlug:s,currentBranch:Gs(e.currentBranch),defaultBranch:o,stack:Gs(e.stack),techStack:i&&i.length>0?i:void 0,version:Gs(e.version),commitCount:Lx(e.commitCount),fileCount:Lx(e.fileCount),lastCommit:Gs(e.lastSyncCommit),hasUncommitted:typeof e.hasUncommittedChanges=="boolean"?e.hasUncommittedChanges:void 0,cliVersion:Gs(e.cliVersion),syncedAt:Gs(e.lastSync)})}var Hu=y(()=>{"use strict";H();fe();a(Mx,"providerForHost");a(Bg,"parseRemote");a(h1,"gitRemoteUrl");a(y1,"gitDefaultBranch");a(Gs,"str");a(Lx,"num");a(w1,"compact");a(Fu,"buildProjectMeta")});import{execFile as k1}from"node:child_process";import b1 from"node:crypto";import{promisify as E1}from"node:util";function T1(n,e=v1){let t=Buffer.from(e.replace(/-/g,""),"hex"),s=b1.createHash("sha1").update(t).update(n,"utf8").digest().subarray(0,16);s[6]=s[6]&15|80,s[8]=s[8]&63|128;let o=s.toString("hex");return`${o.slice(0,8)}-${o.slice(8,12)}-${o.slice(12,16)}-${o.slice(16,20)}-${o.slice(20,32)}`}async function x1(n){let e;try{let{stdout:s}=await S1("git",["remote","get-url","origin"],{cwd:n});e=s.trim()||void 0}catch{return null}if(!e)return null;let{provider:t,repoSlug:r}=Bg(e);return!t||!r?null:`${t}:${r}`.toLowerCase()}async function Fx(n){let e=await x1(n);return e?T1(e):null}var S1,v1,Hx=y(()=>{"use strict";Hu();S1=E1(k1),v1="6f9b2c1a-3d4e-5f60-8a7b-1c2d3e4f5a6b";a(T1,"uuidv5");a(x1,"repoKey");a(Fx,"deriveProjectId")});var Jg={};C(Jg,{PACKAGE_ROOT:()=>Ir,VERSION:()=>ut,getPackageRoot:()=>qg,getVersion:()=>Xs,resetPackageRoot:()=>Xg});import Gg from"node:fs";import Uu from"node:path";function qg(){if(ci)return ci;let n=__dirname;for(let e=0;e<5;e++){let t=Uu.join(n,"package.json");if(Gg.existsSync(t))try{if(JSON.parse(Gg.readFileSync(t,"utf-8")).name==="prjct-cli")return ci=n,n}catch{}n=Uu.dirname(n)}return ci=Uu.join(__dirname,"..","..",".."),ci}function Xs(){if(qs)return qs;let n="3.60.0";if(n&&/^\d+\.\d+\.\d+/.test(n))return qs=n,qs;try{let e=Uu.join(qg(),"package.json");return qs=JSON.parse(Gg.readFileSync(e,"utf-8")).version,qs}catch(e){return process.env.PRJCT_DEBUG==="1"&&console.error("Failed to read version from package.json:",v(e)),"0.0.0"}}function Xg(n){ci=n,qs=null}var qs,ci,ut,Ir,Wt=y(()=>{"use strict";V();qs=null,ci=null;a(qg,"getPackageRoot");a(Xs,"getVersion");a(Xg,"resetPackageRoot");ut=Xs(),Ir=qg()});async function Wu(n){try{let{stdout:e}=await z(n,{timeout:5e3});return{success:!0,output:e.trim()}}catch{return{success:!1,output:""}}}async function R1(){let n=await Wu("gh api user --jq .login");return n.success&&n.output||(n=await Wu("git config --global github.user"),n.success&&n.output)?n.output:null}async function C1(){let n=await Wu("git config user.name");return n.success&&n.output?n.output:null}async function _1(){let n=await Wu("git config user.email");return n.success&&n.output?n.output:null}async function li(){let[n,e,t]=await Promise.all([R1(),C1(),_1()]);return{github:n,email:t,name:e||n||"Unknown"}}var Bu=y(()=>{"use strict";fe();a(Wu,"execCommand");a(R1,"detectGitHubUsername");a(C1,"detectGitName");a(_1,"detectGitEmail");a(li,"detect")});var Gu={};C(Gu,{worktreeService:()=>A1});import Kg from"node:fs/promises";import sr from"node:path";var Ux,zg,A1,qu=y(()=>{"use strict";fe();de();Ux=".worktrees",zg=class{static{a(this,"WorktreeService")}async create(e,t,r={}){let s=await this.getMainWorktree(e),o=sr.join(s,Ux,t),i=r.branch||`feat/${t}`;await Kg.mkdir(sr.join(s,Ux),{recursive:!0});let c=r.baseBranch?` ${r.baseBranch}`:"";await z(`git worktree add "${o}" -b "${i}"${c}`,{cwd:s});let{stdout:l}=await z("git rev-parse HEAD",{cwd:o});return{path:o,branch:i,commit:l.trim(),isMain:!1,slug:t}}async remove(e,t=!1){let r=await this.getMainWorktree(e),s;if(t)try{let{stdout:o}=await z("git rev-parse --abbrev-ref HEAD",{cwd:e});s=o.trim()}catch{}if(await z(`git worktree remove "${e}" --force`,{cwd:r}),t&&s&&s!=="main"&&s!=="master")try{await z(`git branch -D "${s}"`,{cwd:r})}catch{}}async list(e){let t=await this.getMainWorktree(e),{stdout:r}=await z("git worktree list --porcelain",{cwd:t});return this.parsePorcelainOutput(r,t)}async detect(e){try{let{stdout:t}=await z("git rev-parse --git-common-dir",{cwd:e}),{stdout:r}=await z("git rev-parse --git-dir",{cwd:e}),s=sr.resolve(e,t.trim()),o=sr.resolve(e,r.trim());if(s!==o){let{stdout:i}=await z("git rev-parse --abbrev-ref HEAD",{cwd:e}),{stdout:c}=await z("git rev-parse HEAD",{cwd:e}),{stdout:l}=await z("git rev-parse --show-toplevel",{cwd:e}),u=l.trim(),d=sr.basename(u);return{path:u,branch:i.trim(),commit:c.trim(),isMain:!1,slug:d}}return null}catch{return null}}async getMainWorktree(e){try{let{stdout:r}=await z("git worktree list --porcelain",{cwd:e}),s=r.split(`
|
|
1256
|
+
LIMIT ?`,s,s,r).map(Ba)}catch{return[]}}function Fg(n,e,t=20){let r=e.split(/[^A-Za-z0-9_]+/).flatMap(o=>o.replace(/([a-z])([A-Z])/g,"$1 $2").split(/\s+/)).map(o=>o.trim()).filter(o=>o.length>2);if(r.length===0||!Xe(n))return[];let s=new Map;for(let o of r){let i=Tn(n,o,{limit:40});for(let c of i){let l=c.name.toLowerCase()===o.toLowerCase()?1:.55,u=c.exported?1.15:1,d=c.kind==="function"||c.kind==="class"||c.kind==="route"?1.1:1,p=l*u*d,m=s.get(c.file)??{score:0,names:new Set};m.score+=p,m.names.add(c.name),s.set(c.file,m)}}return Array.from(s.entries()).map(([o,i])=>({path:o,score:i.score,matchedNames:[...i.names]})).sort((o,i)=>i.score-o.score).slice(0,t)}function Bs(n,e){try{return b.query(n,"SELECT * FROM code_symbols WHERE file = ? ORDER BY start_line",e).map(Ba)}catch{return[]}}function Hg(n,e="CALLS"){let t=new Map,r=new Map;try{let s=b.query(n,"SELECT src, dst FROM code_symbol_edges WHERE edge_type = ?",e);for(let o of s)t.has(o.src)||t.set(o.src,[]),t.get(o.src).push(o.dst),r.has(o.dst)||r.set(o.dst,[]),r.get(o.dst).push(o.src)}catch{}return{forward:t,reverse:r}}function Px(n,e){try{let t=b.get(n,"SELECT * FROM code_symbols WHERE id = ?",e);return t?Ba(t):null}catch{return null}}function Ga(n,e,t={}){let r=t.direction??"both",s=Math.min(Math.max(t.depth??3,1),5),o=Tn(n,e,{limit:10}).filter(f=>f.name.toLowerCase()===e.toLowerCase()),i=o.length>0?o:Tn(n,e,{limit:5});if(i.length===0)return null;let{forward:c,reverse:l}=Hg(n,"CALLS"),u=[],d=[],p=a((f,g,w,k)=>{let S=new Set(f),x=f.map(T=>({id:T,depth:0}));for(let T=0;T<x.length;T++){let{id:$,depth:A}=x[T];if(!(A>=k))for(let N of g.get($)??[]){if(S.has(N))continue;if(S.add(N),N.startsWith("file:")){let ee=N.slice(5),je=Bs(n,ee),re=je.find(Q=>Q.exported&&(Q.kind==="function"||Q.kind==="class"))??je.find(Q=>Q.kind==="function"||Q.kind==="class")??je[0];re&&!S.has(re.id)&&(S.add(re.id),w.push({symbol:re,depth:A+1,via:"CALLS"}),x.push({id:re.id,depth:A+1})),x.push({id:N,depth:A+1});continue}let U=Px(n,N);U&&(w.push({symbol:U,depth:A+1,via:"CALLS"}),x.push({id:N,depth:A+1}))}}},"bfs"),m=i.map(f=>f.id);return(r==="inbound"||r==="both")&&p(m,l,u,s),(r==="outbound"||r==="both")&&p(m,c,d,s),{root:i,inbound:u,outbound:d}}function qa(n,e){let t=Bs(n,e);if(t.length===0)return 0;let{reverse:r}=Hg(n,"CALLS"),s=new Set;for(let o of t)for(let i of r.get(o.id)??[])s.add(i);return s.size}function Ug(n,e,t=2){let r=new Set(e),{reverse:s}=Hg(n,"CALLS"),o=new Set;for(let u of e)for(let d of Bs(n,u))o.add(d.id);let i=new Set,c=new Set(o),l=[...o];for(let u=0;u<t;u++){let d=[];for(let p of l)for(let m of s.get(p)??[])if(!c.has(m))if(c.add(m),d.push(m),m.startsWith("file:")){let f=m.slice(5);r.has(f)||i.add(f)}else{let f=Px(n,m);f&&!r.has(f.file)&&i.add(f.file)}l=d}return[...i]}var Mg,ZU,e1,t1,xn=y(()=>{"use strict";wu();H();de();Mg="symbol-graph",ZU=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".go",".rs",".java"]),e1=new Set(["if","for","while","switch","catch","function","class","return","typeof","new","throw","await","void","super","this","import","require","console","Math","JSON","Object","Array","Promise","Map","Set","Date","Error","Buffer","process","describe","it","test","expect","beforeEach","afterEach","beforeAll","afterAll"]),t1=new Set(["if","for","while","switch","catch","return","await","typeof","new","throw","else","case","from","import","export","class","function","const","let","var","get","set","constructor","async","static","public","private","protected","readonly","abstract","extends","implements","interface","type","enum","default","as","of","in","do","try","finally","yield","with"]);a(Jt,"lineOf");a(n1,"symbolId");a(vx,"qnameOf");a(Ou,"isSourceFile");a(ii,"stripNoise");a(Tx,"emptyExtract");a(xx,"finalizeCalls");a(r1,"extractTsJs");a(s1,"extractPython");a(o1,"extractGo");a(i1,"extractRust");a(a1,"extractJava");a(Rx,"extractFile");a(c1,"loadTsPathMap");a(l1,"applyTsPath");a(u1,"resolveSpecifierToFile");a(d1,"resolveImportsForExtract");a(Sx,"matchFileToMod");a(Cx,"enclosingSymbol");a(_x,"resolveCallTargets");a(Ax,"buildFromExtracts");a(Ix,"extractProject");a(p1,"persistGraph");a(m1,"patchGraph");a(Ws,"indexSymbols");a(Lg,"updateSymbols");a(Xe,"hasSymbolIndex");a(un,"loadMeta");a(Ba,"rowToSymbol");a(rr,"listAllSymbols");a(Tn,"searchSymbols");a(Fg,"scoreFilesFromQuery");a(Bs,"symbolsInFile");a(Hg,"loadEdges");a(Px,"symbolById");a(Ga,"tracePath");a(qa,"fileFanIn");a(Ug,"filesCallingInto")});function Du(n){if(n.length===0)return[];let e=n[0]?.score||1;return n.map(t=>({path:t.path,score:t.score/e}))}var Xa,Nx=y(()=>{"use strict";ri();si();_r();xn();a(Du,"normalize");Xa=[{name:"bm25",kind:"query",defaultWeight:.45,hasIndex:a(n=>fx(n),"hasIndex"),scoreFromQuery:a((n,e,t)=>Du(Pu(n,e,t)),"scoreFromQuery")},{name:"symbols",kind:"query",defaultWeight:.2,hasIndex:a(n=>Xe(n),"hasIndex"),scoreFromQuery:a((n,e,t)=>Du(Fg(n,e,t)),"scoreFromQuery")},{name:"imports",kind:"seed",defaultWeight:.2,hasIndex:a(n=>Tt(n)!==null,"hasIndex"),scoreFromSeeds:a((n,e,t)=>{let r=Tt(n);return r?Du(oi(e,r,t.importDepth)):[]},"scoreFromSeeds")},{name:"cochange",kind:"seed",defaultWeight:.15,hasIndex:a(n=>vn(n)!==null,"hasIndex"),scoreFromSeeds:a((n,e)=>{let t=vn(n);return t?Du(Fs(e,t)):[]},"scoreFromSeeds")}]});function $x(n,e,t={}){let r={...f1,...t},s={bm25:r.bm25Weight,symbols:r.symbolsWeight,imports:r.importWeight,cochange:r.cochangeWeight},o=Xa.filter(m=>m.kind==="query"),i=Xa.filter(m=>m.kind==="seed"),c=new Map,l=new Map;for(let m of o){let f=m.scoreFromQuery(n,e,r.topN*3);if(f.length!==0){c.set(m.name,new Map(f.map(g=>[g.path,g.score])));for(let g of f.slice(0,jx))l.set(g.path,Math.max(l.get(g.path)??0,g.score))}}if(c.size===0)return[];let u=[...l.entries()].sort((m,f)=>f[1]-m[1]).slice(0,jx).map(([m])=>m);for(let m of i){let f=m.scoreFromSeeds(n,u,{importDepth:r.importDepth});f.length!==0&&c.set(m.name,new Map(f.map(g=>[g.path,g.score])))}let d=new Set;for(let m of c.values())for(let f of m.keys())d.add(f);let p=[];for(let m of d){let f=0;for(let[g,w]of c){let k=w.get(m)??0,S=s[g]??Xa.find(x=>x.name===g)?.defaultWeight??0;f+=k*S}p.push({path:m,finalScore:f,signals:{bm25:c.get("bm25")?.get(m)??0,imports:c.get("imports")?.get(m)??0,cochange:c.get("cochange")?.get(m)??0,symbols:c.get("symbols")?.get(m)??0}})}return p.sort((m,f)=>f.finalScore-m.finalScore),p.slice(0,r.topN)}function Ox(n){let e={};for(let t of Xa)e[t.name]=t.hasIndex(n);return{bm25:e.bm25??!1,imports:e.imports??!1,cochange:e.cochange??!1,symbols:e.symbols??!1}}var f1,jx,Dx=y(()=>{"use strict";Nx();f1={bm25Weight:.45,importWeight:.2,cochangeWeight:.15,symbolsWeight:.2,topN:15,importDepth:2},jx=10;a($x,"rankFiles");a(Ox,"hasIndexes")});function g1(n){return n instanceof ai}function lt(n){return g1(n)||n instanceof Error?n.message:typeof n=="string"?n:"Unknown error"}var ai,Mu,Lu,Ja,Ar=y(()=>{"use strict";ai=class extends Error{static{a(this,"PrjctError")}code;isOperational;constructor(e,t="PRJCT_ERROR"){super(e),this.name="PrjctError",this.code=t,this.isOperational=!0,Error.captureStackTrace?.(this,this.constructor)}},Mu=class n extends ai{static{a(this,"ProjectError")}constructor(e,t="PROJECT_ERROR"){super(e,t),this.name="ProjectError"}static notInitialized(){return new n("Project not initialized. Run p. init first.","PROJECT_NOT_INIT")}static notFound(e){return new n(`Project not found: ${e}`,"PROJECT_NOT_FOUND")}static invalidId(e){return new n(`Invalid project ID: ${e}`,"PROJECT_INVALID_ID")}},Lu=class n extends ai{static{a(this,"TemplateError")}constructor(e,t="TEMPLATE_ERROR"){super(e,t),this.name="TemplateError"}static notFound(e){return new n(`Template not found: ${e}.md`,"TEMPLATE_NOT_FOUND")}static parseFailed(e){return new n(`Failed to parse template: ${e}`,"TEMPLATE_PARSE_ERROR")}},Ja=class n extends ai{static{a(this,"AgentError")}constructor(e,t="AGENT_ERROR"){super(e,t),this.name="AgentError"}static notSupported(e){return new n(`Unsupported agent type: ${e}`,"AGENT_NOT_SUPPORTED")}static initFailed(e){return new n(`Agent initialization failed: ${e}`,"AGENT_INIT_FAILED")}};a(g1,"isPrjctError");a(lt,"getErrorMessage")});function Mx(n){let e=n.toLowerCase();return e.includes("github")?"github":e.includes("gitlab")?"gitlab":e.includes("bitbucket")?"bitbucket":"other"}function Bg(n){let e=n.trim();if(!e)return{};let t=e.match(/^[^/@]+@([^:/]+):(.+?)(?:\.git)?\/?$/);if(t)return{provider:Mx(t[1]),repoSlug:t[2]};try{let r=new URL(e),s=r.pathname.replace(/^\/+/,"").replace(/\.git$/,"").replace(/\/+$/,"");return!r.host||!s?{}:{provider:Mx(r.host),repoSlug:s}}catch{return{}}}async function h1(n){try{let{stdout:e}=await G("git",["remote","get-url","origin"],{cwd:n});return e.trim()||void 0}catch{return}}async function y1(n){try{let{stdout:e}=await G("git",["symbolic-ref","--short","refs/remotes/origin/HEAD"],{cwd:n});return e.trim().replace(/^origin\//,"")||void 0}catch{return}}function Gs(n){return typeof n=="string"&&n.length>0?n:void 0}function Lx(n){return typeof n=="number"&&Number.isFinite(n)?n:void 0}function w1(n){return Object.fromEntries(Object.entries(n).filter(([,e])=>e!==void 0))}async function Fu(n){let e=E.getDoc(n,"project")||{},t=Gs(e.repoPath),{provider:r,repoSlug:s}=t?Bg(await h1(t)||""):{},o=t?await y1(t):void 0,i=Array.isArray(e.techStack)?e.techStack.filter(c=>typeof c=="string"):void 0;return w1({provider:r,repoSlug:s,currentBranch:Gs(e.currentBranch),defaultBranch:o,stack:Gs(e.stack),techStack:i&&i.length>0?i:void 0,version:Gs(e.version),commitCount:Lx(e.commitCount),fileCount:Lx(e.fileCount),lastCommit:Gs(e.lastSyncCommit),hasUncommitted:typeof e.hasUncommittedChanges=="boolean"?e.hasUncommittedChanges:void 0,cliVersion:Gs(e.cliVersion),syncedAt:Gs(e.lastSync)})}var Hu=y(()=>{"use strict";H();fe();a(Mx,"providerForHost");a(Bg,"parseRemote");a(h1,"gitRemoteUrl");a(y1,"gitDefaultBranch");a(Gs,"str");a(Lx,"num");a(w1,"compact");a(Fu,"buildProjectMeta")});import{execFile as k1}from"node:child_process";import b1 from"node:crypto";import{promisify as E1}from"node:util";function T1(n,e=v1){let t=Buffer.from(e.replace(/-/g,""),"hex"),s=b1.createHash("sha1").update(t).update(n,"utf8").digest().subarray(0,16);s[6]=s[6]&15|80,s[8]=s[8]&63|128;let o=s.toString("hex");return`${o.slice(0,8)}-${o.slice(8,12)}-${o.slice(12,16)}-${o.slice(16,20)}-${o.slice(20,32)}`}async function x1(n){let e;try{let{stdout:s}=await S1("git",["remote","get-url","origin"],{cwd:n});e=s.trim()||void 0}catch{return null}if(!e)return null;let{provider:t,repoSlug:r}=Bg(e);return!t||!r?null:`${t}:${r}`.toLowerCase()}async function Fx(n){let e=await x1(n);return e?T1(e):null}var S1,v1,Hx=y(()=>{"use strict";Hu();S1=E1(k1),v1="6f9b2c1a-3d4e-5f60-8a7b-1c2d3e4f5a6b";a(T1,"uuidv5");a(x1,"repoKey");a(Fx,"deriveProjectId")});var Jg={};C(Jg,{PACKAGE_ROOT:()=>Ir,VERSION:()=>ut,getPackageRoot:()=>qg,getVersion:()=>Xs,resetPackageRoot:()=>Xg});import Gg from"node:fs";import Uu from"node:path";function qg(){if(ci)return ci;let n=__dirname;for(let e=0;e<5;e++){let t=Uu.join(n,"package.json");if(Gg.existsSync(t))try{if(JSON.parse(Gg.readFileSync(t,"utf-8")).name==="prjct-cli")return ci=n,n}catch{}n=Uu.dirname(n)}return ci=Uu.join(__dirname,"..","..",".."),ci}function Xs(){if(qs)return qs;let n="3.61.0";if(n&&/^\d+\.\d+\.\d+/.test(n))return qs=n,qs;try{let e=Uu.join(qg(),"package.json");return qs=JSON.parse(Gg.readFileSync(e,"utf-8")).version,qs}catch(e){return process.env.PRJCT_DEBUG==="1"&&console.error("Failed to read version from package.json:",v(e)),"0.0.0"}}function Xg(n){ci=n,qs=null}var qs,ci,ut,Ir,Wt=y(()=>{"use strict";V();qs=null,ci=null;a(qg,"getPackageRoot");a(Xs,"getVersion");a(Xg,"resetPackageRoot");ut=Xs(),Ir=qg()});async function Wu(n){try{let{stdout:e}=await z(n,{timeout:5e3});return{success:!0,output:e.trim()}}catch{return{success:!1,output:""}}}async function R1(){let n=await Wu("gh api user --jq .login");return n.success&&n.output||(n=await Wu("git config --global github.user"),n.success&&n.output)?n.output:null}async function C1(){let n=await Wu("git config user.name");return n.success&&n.output?n.output:null}async function _1(){let n=await Wu("git config user.email");return n.success&&n.output?n.output:null}async function li(){let[n,e,t]=await Promise.all([R1(),C1(),_1()]);return{github:n,email:t,name:e||n||"Unknown"}}var Bu=y(()=>{"use strict";fe();a(Wu,"execCommand");a(R1,"detectGitHubUsername");a(C1,"detectGitName");a(_1,"detectGitEmail");a(li,"detect")});var Gu={};C(Gu,{worktreeService:()=>A1});import Kg from"node:fs/promises";import sr from"node:path";var Ux,zg,A1,qu=y(()=>{"use strict";fe();de();Ux=".worktrees",zg=class{static{a(this,"WorktreeService")}async create(e,t,r={}){let s=await this.getMainWorktree(e),o=sr.join(s,Ux,t),i=r.branch||`feat/${t}`;await Kg.mkdir(sr.join(s,Ux),{recursive:!0});let c=r.baseBranch?` ${r.baseBranch}`:"";await z(`git worktree add "${o}" -b "${i}"${c}`,{cwd:s});let{stdout:l}=await z("git rev-parse HEAD",{cwd:o});return{path:o,branch:i,commit:l.trim(),isMain:!1,slug:t}}async remove(e,t=!1){let r=await this.getMainWorktree(e),s;if(t)try{let{stdout:o}=await z("git rev-parse --abbrev-ref HEAD",{cwd:e});s=o.trim()}catch{}if(await z(`git worktree remove "${e}" --force`,{cwd:r}),t&&s&&s!=="main"&&s!=="master")try{await z(`git branch -D "${s}"`,{cwd:r})}catch{}}async list(e){let t=await this.getMainWorktree(e),{stdout:r}=await z("git worktree list --porcelain",{cwd:t});return this.parsePorcelainOutput(r,t)}async detect(e){try{let{stdout:t}=await z("git rev-parse --git-common-dir",{cwd:e}),{stdout:r}=await z("git rev-parse --git-dir",{cwd:e}),s=sr.resolve(e,t.trim()),o=sr.resolve(e,r.trim());if(s!==o){let{stdout:i}=await z("git rev-parse --abbrev-ref HEAD",{cwd:e}),{stdout:c}=await z("git rev-parse HEAD",{cwd:e}),{stdout:l}=await z("git rev-parse --show-toplevel",{cwd:e}),u=l.trim(),d=sr.basename(u);return{path:u,branch:i.trim(),commit:c.trim(),isMain:!1,slug:d}}return null}catch{return null}}async getMainWorktree(e){try{let{stdout:r}=await z("git worktree list --porcelain",{cwd:e}),s=r.split(`
|
|
1257
1257
|
`)[0];if(s?.startsWith("worktree "))return s.replace("worktree ","").trim()}catch{}let{stdout:t}=await z("git rev-parse --show-toplevel",{cwd:e});return t.trim()}async setup(e,t){let r=sr.join(t,".env");await L(r)&&await Kg.copyFile(r,sr.join(e,".env"));let s=sr.join(t,".prjct"),o=sr.join(e,".prjct");await L(s)&&!await L(o)&&await Kg.symlink(s,o,"dir")}async teardown(e){}async clean(e){let t=await this.list(e),r=[],s=await this.getMainWorktree(e);await z("git worktree prune",{cwd:s});for(let o of t)o.isMain||await L(o.path)||r.push(o.slug);return r}parsePorcelainOutput(e,t){let r=[],s=e.trim().split(`
|
|
1258
1258
|
|
|
1259
1259
|
`);for(let o of s){if(!o.trim())continue;let i=o.trim().split(`
|
package/dist/mcp/server.mjs
CHANGED
|
@@ -1260,7 +1260,7 @@ CREATE TABLE velocity_sprints (
|
|
|
1260
1260
|
_No changes detected (clean tree / no base range)._
|
|
1261
1261
|
`;let e=["## Detect changes","",`- **Source**: ${t.source}`,`- **Changed**: ${t.changedFiles.length} file(s)`,`- **Blast radius**: ${t.affectedFiles.length} file(s) (imports + call-graph)`,`- **Risk**: critical ${t.summary.critical} \xB7 high ${t.summary.high} \xB7 medium ${t.summary.medium} \xB7 low ${t.summary.low}`,"","### Per-file risk",""];for(let n of t.changes){let r=n.touchedSymbols.length>0?` \xB7 symbols: ${n.touchedSymbols.slice(0,6).join(", ")}`:"";e.push(`- **${n.risk.toUpperCase()}** \`${n.file}\`${r}`,` - ${n.reasons.join("; ")}`)}if(t.affectedFiles.length>t.changedFiles.length){e.push("","### Affected beyond diff","");let n=t.affectedFiles.filter(r=>!t.changedFiles.includes(r)).slice(0,25);for(let r of n)e.push(`- \`${r}\``);t.affectedFiles.length-t.changedFiles.length>25&&e.push(`- _\u2026+${t.affectedFiles.length-t.changedFiles.length-25} more_`)}return e.push("","_Advisory. Expand with `prjct code trace <symbol>` or MCP `prjct_trace_path`._"),e.join(`
|
|
1262
1262
|
`)}function XR(t){if(t.changedFiles.length===0)return"detect-changes: no changes detected";let e=[`Detect changes (${t.source}): ${t.changedFiles.length} changed \u2192 blast ${t.affectedFiles.length}`,`Risk: critical=${t.summary.critical} high=${t.summary.high} medium=${t.summary.medium} low=${t.summary.low}`];for(let n of t.changes.slice(0,30)){let r=n.touchedSymbols.length?` [${n.touchedSymbols.slice(0,4).join(",")}]`:"";e.push(` [${n.risk.toUpperCase()}] ${n.file}${r} \u2014 ${n.reasons[0]??""}`)}return e.join(`
|
|
1263
|
-
`)}function qR(t){return t.changedFiles.length===0?null:t.summary.critical>0?`\u26A0\uFE0F Structural risk CRITICAL (${t.summary.critical} file(s), blast ${t.affectedFiles.length}). Review: \`prjct code impact --md\`.`:t.summary.high>0?`\u26A0\uFE0F Structural risk HIGH (${t.summary.high} file(s), blast ${t.affectedFiles.length}). Consider \`prjct code impact --md\`.`:null}var WR,BR,xl=h(()=>{"use strict";Zt();en();le();a(ft,"safeGit");a($R,"listWorkingTreeFiles");a(FR,"listCommittedFiles");a(HR,"resolveDiffBase");a(Qf,"parseChangedLinesFromUnifiedDiff");a(UR,"loadHunkLines");a(Zf,"symbolsTouchedByHunks");WR=/(?:^|\/)(?:auth|security|crypto|billing|payment|migrate|schema|migrations?)(?:\/|$)/i,BR=/(?:^|\/)(?:storage|database|db|sync|daemon|mcp|hooks?|session)(?:\/|$)/i;a(GR,"classifyRisk");a(vl,"detectChanges");a(_l,"formatDetectChangesMd");a(XR,"formatDetectChangesText");a(qR,"shipStructuralRiskCue")});function VR(t){return t instanceof Js}function Se(t){return VR(t)||t instanceof Error?t.message:typeof t=="string"?t:"Unknown error"}var Js,Io,Ks,tn=h(()=>{"use strict";Js=class extends Error{static{a(this,"PrjctError")}code;isOperational;constructor(e,n="PRJCT_ERROR"){super(e),this.name="PrjctError",this.code=n,this.isOperational=!0,Error.captureStackTrace?.(this,this.constructor)}},Io=class t extends Js{static{a(this,"ProjectError")}constructor(e,n="PROJECT_ERROR"){super(e,n),this.name="ProjectError"}static notInitialized(){return new t("Project not initialized. Run p. init first.","PROJECT_NOT_INIT")}static notFound(e){return new t(`Project not found: ${e}`,"PROJECT_NOT_FOUND")}static invalidId(e){return new t(`Invalid project ID: ${e}`,"PROJECT_INVALID_ID")}},Ks=class t extends Js{static{a(this,"AgentError")}constructor(e,n="AGENT_ERROR"){super(e,n),this.name="AgentError"}static notSupported(e){return new t(`Unsupported agent type: ${e}`,"AGENT_NOT_SUPPORTED")}static initFailed(e){return new t(`Agent initialization failed: ${e}`,"AGENT_INIT_FAILED")}};a(VR,"isPrjctError");a(Se,"getErrorMessage")});function th(t){let e=t.toLowerCase();return e.includes("github")?"github":e.includes("gitlab")?"gitlab":e.includes("bitbucket")?"bitbucket":"other"}function Rl(t){let e=t.trim();if(!e)return{};let n=e.match(/^[^/@]+@([^:/]+):(.+?)(?:\.git)?\/?$/);if(n)return{provider:th(n[1]),repoSlug:n[2]};try{let r=new URL(e),s=r.pathname.replace(/^\/+/,"").replace(/\.git$/,"").replace(/\/+$/,"");return!r.host||!s?{}:{provider:th(r.host),repoSlug:s}}catch{return{}}}async function JR(t){try{let{stdout:e}=await U("git",["remote","get-url","origin"],{cwd:t});return e.trim()||void 0}catch{return}}async function KR(t){try{let{stdout:e}=await U("git",["symbolic-ref","--short","refs/remotes/origin/HEAD"],{cwd:t});return e.trim().replace(/^origin\//,"")||void 0}catch{return}}function Yn(t){return typeof t=="string"&&t.length>0?t:void 0}function nh(t){return typeof t=="number"&&Number.isFinite(t)?t:void 0}function YR(t){return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}async function rh(t){let e=k.getDoc(t,"project")||{},n=Yn(e.repoPath),{provider:r,repoSlug:s}=n?Rl(await JR(n)||""):{},i=n?await KR(n):void 0,o=Array.isArray(e.techStack)?e.techStack.filter(c=>typeof c=="string"):void 0;return YR({provider:r,repoSlug:s,currentBranch:Yn(e.currentBranch),defaultBranch:i,stack:Yn(e.stack),techStack:o&&o.length>0?o:void 0,version:Yn(e.version),commitCount:nh(e.commitCount),fileCount:nh(e.fileCount),lastCommit:Yn(e.lastSyncCommit),hasUncommitted:typeof e.hasUncommittedChanges=="boolean"?e.hasUncommittedChanges:void 0,cliVersion:Yn(e.cliVersion),syncedAt:Yn(e.lastSync)})}var Cl=h(()=>{"use strict";O();le();a(th,"providerForHost");a(Rl,"parseRemote");a(JR,"gitRemoteUrl");a(KR,"gitDefaultBranch");a(Yn,"str");a(nh,"num");a(YR,"compact");a(rh,"buildProjectMeta")});import{execFile as zR}from"node:child_process";import QR from"node:crypto";import{promisify as ZR}from"node:util";function nC(t,e=tC){let n=Buffer.from(e.replace(/-/g,""),"hex"),s=QR.createHash("sha1").update(n).update(t,"utf8").digest().subarray(0,16);s[6]=s[6]&15|80,s[8]=s[8]&63|128;let i=s.toString("hex");return`${i.slice(0,8)}-${i.slice(8,12)}-${i.slice(12,16)}-${i.slice(16,20)}-${i.slice(20,32)}`}async function rC(t){let e;try{let{stdout:s}=await eC("git",["remote","get-url","origin"],{cwd:t});e=s.trim()||void 0}catch{return null}if(!e)return null;let{provider:n,repoSlug:r}=Rl(e);return!n||!r?null:`${n}:${r}`.toLowerCase()}async function sh(t){let e=await rC(t);return e?nC(e):null}var eC,tC,ih=h(()=>{"use strict";Cl();eC=ZR(zR),tC="6f9b2c1a-3d4e-5f60-8a7b-1c2d3e4f5a6b";a(nC,"uuidv5");a(rC,"repoKey");a(sh,"deriveProjectId")});var Il={};L(Il,{PACKAGE_ROOT:()=>An,VERSION:()=>Cn,getPackageRoot:()=>Nl,getVersion:()=>Do,resetPackageRoot:()=>sC});import Al from"node:fs";import Po from"node:path";function Nl(){if(jr)return jr;let t=__dirname;for(let e=0;e<5;e++){let n=Po.join(t,"package.json");if(Al.existsSync(n))try{if(JSON.parse(Al.readFileSync(n,"utf-8")).name==="prjct-cli")return jr=t,t}catch{}t=Po.dirname(t)}return jr=Po.join(__dirname,"..","..",".."),jr}function Do(){if(zn)return zn;let t="3.
|
|
1263
|
+
`)}function qR(t){return t.changedFiles.length===0?null:t.summary.critical>0?`\u26A0\uFE0F Structural risk CRITICAL (${t.summary.critical} file(s), blast ${t.affectedFiles.length}). Review: \`prjct code impact --md\`.`:t.summary.high>0?`\u26A0\uFE0F Structural risk HIGH (${t.summary.high} file(s), blast ${t.affectedFiles.length}). Consider \`prjct code impact --md\`.`:null}var WR,BR,xl=h(()=>{"use strict";Zt();en();le();a(ft,"safeGit");a($R,"listWorkingTreeFiles");a(FR,"listCommittedFiles");a(HR,"resolveDiffBase");a(Qf,"parseChangedLinesFromUnifiedDiff");a(UR,"loadHunkLines");a(Zf,"symbolsTouchedByHunks");WR=/(?:^|\/)(?:auth|security|crypto|billing|payment|migrate|schema|migrations?)(?:\/|$)/i,BR=/(?:^|\/)(?:storage|database|db|sync|daemon|mcp|hooks?|session)(?:\/|$)/i;a(GR,"classifyRisk");a(vl,"detectChanges");a(_l,"formatDetectChangesMd");a(XR,"formatDetectChangesText");a(qR,"shipStructuralRiskCue")});function VR(t){return t instanceof Js}function Se(t){return VR(t)||t instanceof Error?t.message:typeof t=="string"?t:"Unknown error"}var Js,Io,Ks,tn=h(()=>{"use strict";Js=class extends Error{static{a(this,"PrjctError")}code;isOperational;constructor(e,n="PRJCT_ERROR"){super(e),this.name="PrjctError",this.code=n,this.isOperational=!0,Error.captureStackTrace?.(this,this.constructor)}},Io=class t extends Js{static{a(this,"ProjectError")}constructor(e,n="PROJECT_ERROR"){super(e,n),this.name="ProjectError"}static notInitialized(){return new t("Project not initialized. Run p. init first.","PROJECT_NOT_INIT")}static notFound(e){return new t(`Project not found: ${e}`,"PROJECT_NOT_FOUND")}static invalidId(e){return new t(`Invalid project ID: ${e}`,"PROJECT_INVALID_ID")}},Ks=class t extends Js{static{a(this,"AgentError")}constructor(e,n="AGENT_ERROR"){super(e,n),this.name="AgentError"}static notSupported(e){return new t(`Unsupported agent type: ${e}`,"AGENT_NOT_SUPPORTED")}static initFailed(e){return new t(`Agent initialization failed: ${e}`,"AGENT_INIT_FAILED")}};a(VR,"isPrjctError");a(Se,"getErrorMessage")});function th(t){let e=t.toLowerCase();return e.includes("github")?"github":e.includes("gitlab")?"gitlab":e.includes("bitbucket")?"bitbucket":"other"}function Rl(t){let e=t.trim();if(!e)return{};let n=e.match(/^[^/@]+@([^:/]+):(.+?)(?:\.git)?\/?$/);if(n)return{provider:th(n[1]),repoSlug:n[2]};try{let r=new URL(e),s=r.pathname.replace(/^\/+/,"").replace(/\.git$/,"").replace(/\/+$/,"");return!r.host||!s?{}:{provider:th(r.host),repoSlug:s}}catch{return{}}}async function JR(t){try{let{stdout:e}=await U("git",["remote","get-url","origin"],{cwd:t});return e.trim()||void 0}catch{return}}async function KR(t){try{let{stdout:e}=await U("git",["symbolic-ref","--short","refs/remotes/origin/HEAD"],{cwd:t});return e.trim().replace(/^origin\//,"")||void 0}catch{return}}function Yn(t){return typeof t=="string"&&t.length>0?t:void 0}function nh(t){return typeof t=="number"&&Number.isFinite(t)?t:void 0}function YR(t){return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}async function rh(t){let e=k.getDoc(t,"project")||{},n=Yn(e.repoPath),{provider:r,repoSlug:s}=n?Rl(await JR(n)||""):{},i=n?await KR(n):void 0,o=Array.isArray(e.techStack)?e.techStack.filter(c=>typeof c=="string"):void 0;return YR({provider:r,repoSlug:s,currentBranch:Yn(e.currentBranch),defaultBranch:i,stack:Yn(e.stack),techStack:o&&o.length>0?o:void 0,version:Yn(e.version),commitCount:nh(e.commitCount),fileCount:nh(e.fileCount),lastCommit:Yn(e.lastSyncCommit),hasUncommitted:typeof e.hasUncommittedChanges=="boolean"?e.hasUncommittedChanges:void 0,cliVersion:Yn(e.cliVersion),syncedAt:Yn(e.lastSync)})}var Cl=h(()=>{"use strict";O();le();a(th,"providerForHost");a(Rl,"parseRemote");a(JR,"gitRemoteUrl");a(KR,"gitDefaultBranch");a(Yn,"str");a(nh,"num");a(YR,"compact");a(rh,"buildProjectMeta")});import{execFile as zR}from"node:child_process";import QR from"node:crypto";import{promisify as ZR}from"node:util";function nC(t,e=tC){let n=Buffer.from(e.replace(/-/g,""),"hex"),s=QR.createHash("sha1").update(n).update(t,"utf8").digest().subarray(0,16);s[6]=s[6]&15|80,s[8]=s[8]&63|128;let i=s.toString("hex");return`${i.slice(0,8)}-${i.slice(8,12)}-${i.slice(12,16)}-${i.slice(16,20)}-${i.slice(20,32)}`}async function rC(t){let e;try{let{stdout:s}=await eC("git",["remote","get-url","origin"],{cwd:t});e=s.trim()||void 0}catch{return null}if(!e)return null;let{provider:n,repoSlug:r}=Rl(e);return!n||!r?null:`${n}:${r}`.toLowerCase()}async function sh(t){let e=await rC(t);return e?nC(e):null}var eC,tC,ih=h(()=>{"use strict";Cl();eC=ZR(zR),tC="6f9b2c1a-3d4e-5f60-8a7b-1c2d3e4f5a6b";a(nC,"uuidv5");a(rC,"repoKey");a(sh,"deriveProjectId")});var Il={};L(Il,{PACKAGE_ROOT:()=>An,VERSION:()=>Cn,getPackageRoot:()=>Nl,getVersion:()=>Do,resetPackageRoot:()=>sC});import Al from"node:fs";import Po from"node:path";function Nl(){if(jr)return jr;let t=__dirname;for(let e=0;e<5;e++){let n=Po.join(t,"package.json");if(Al.existsSync(n))try{if(JSON.parse(Al.readFileSync(n,"utf-8")).name==="prjct-cli")return jr=t,t}catch{}t=Po.dirname(t)}return jr=Po.join(__dirname,"..","..",".."),jr}function Do(){if(zn)return zn;let t="3.61.0";if(t&&/^\d+\.\d+\.\d+/.test(t))return zn=t,zn;try{let e=Po.join(Nl(),"package.json");return zn=JSON.parse(Al.readFileSync(e,"utf-8")).version,zn}catch(e){return process.env.PRJCT_DEBUG==="1"&&console.error("Failed to read version from package.json:",x(e)),"0.0.0"}}function sC(t){jr=t,zn=null}var zn,jr,Cn,An,nn=h(()=>{"use strict";ie();zn=null,jr=null;a(Nl,"getPackageRoot");a(Do,"getVersion");a(sC,"resetPackageRoot");Cn=Do(),An=Nl()});async function Lo(t){try{let{stdout:e}=await H(t,{timeout:5e3});return{success:!0,output:e.trim()}}catch{return{success:!1,output:""}}}async function iC(){let t=await Lo("gh api user --jq .login");return t.success&&t.output||(t=await Lo("git config --global github.user"),t.success&&t.output)?t.output:null}async function oC(){let t=await Lo("git config user.name");return t.success&&t.output?t.output:null}async function aC(){let t=await Lo("git config user.email");return t.success&&t.output?t.output:null}async function Mr(){let[t,e,n]=await Promise.all([iC(),oC(),aC()]);return{github:t,email:n,name:e||t||"Unknown"}}var Oo=h(()=>{"use strict";le();a(Lo,"execCommand");a(iC,"detectGitHubUsername");a(oC,"detectGitName");a(aC,"detectGitEmail");a(Mr,"detect")});var jo={};L(jo,{worktreeService:()=>cC});import Dl from"node:fs/promises";import jt from"node:path";var oh,Ll,cC,Mo=h(()=>{"use strict";le();se();oh=".worktrees",Ll=class{static{a(this,"WorktreeService")}async create(e,n,r={}){let s=await this.getMainWorktree(e),i=jt.join(s,oh,n),o=r.branch||`feat/${n}`;await Dl.mkdir(jt.join(s,oh),{recursive:!0});let c=r.baseBranch?` ${r.baseBranch}`:"";await H(`git worktree add "${i}" -b "${o}"${c}`,{cwd:s});let{stdout:l}=await H("git rev-parse HEAD",{cwd:i});return{path:i,branch:o,commit:l.trim(),isMain:!1,slug:n}}async remove(e,n=!1){let r=await this.getMainWorktree(e),s;if(n)try{let{stdout:i}=await H("git rev-parse --abbrev-ref HEAD",{cwd:e});s=i.trim()}catch{}if(await H(`git worktree remove "${e}" --force`,{cwd:r}),n&&s&&s!=="main"&&s!=="master")try{await H(`git branch -D "${s}"`,{cwd:r})}catch{}}async list(e){let n=await this.getMainWorktree(e),{stdout:r}=await H("git worktree list --porcelain",{cwd:n});return this.parsePorcelainOutput(r,n)}async detect(e){try{let{stdout:n}=await H("git rev-parse --git-common-dir",{cwd:e}),{stdout:r}=await H("git rev-parse --git-dir",{cwd:e}),s=jt.resolve(e,n.trim()),i=jt.resolve(e,r.trim());if(s!==i){let{stdout:o}=await H("git rev-parse --abbrev-ref HEAD",{cwd:e}),{stdout:c}=await H("git rev-parse HEAD",{cwd:e}),{stdout:l}=await H("git rev-parse --show-toplevel",{cwd:e}),u=l.trim(),d=jt.basename(u);return{path:u,branch:o.trim(),commit:c.trim(),isMain:!1,slug:d}}return null}catch{return null}}async getMainWorktree(e){try{let{stdout:r}=await H("git worktree list --porcelain",{cwd:e}),s=r.split(`
|
|
1264
1264
|
`)[0];if(s?.startsWith("worktree "))return s.replace("worktree ","").trim()}catch{}let{stdout:n}=await H("git rev-parse --show-toplevel",{cwd:e});return n.trim()}async setup(e,n){let r=jt.join(n,".env");await N(r)&&await Dl.copyFile(r,jt.join(e,".env"));let s=jt.join(n,".prjct"),i=jt.join(e,".prjct");await N(s)&&!await N(i)&&await Dl.symlink(s,i,"dir")}async teardown(e){}async clean(e){let n=await this.list(e),r=[],s=await this.getMainWorktree(e);await H("git worktree prune",{cwd:s});for(let i of n)i.isMain||await N(i.path)||r.push(i.slug);return r}parsePorcelainOutput(e,n){let r=[],s=e.trim().split(`
|
|
1265
1265
|
|
|
1266
1266
|
`);for(let i of s){if(!i.trim())continue;let o=i.trim().split(`
|
package/package.json
CHANGED