trellis 2.1.9 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.md +65 -796
  2. package/dist/cli/index.d.ts +3 -1
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +2948 -182
  5. package/dist/client/index.js +4 -4
  6. package/dist/context/heat-map-manager.d.ts +100 -0
  7. package/dist/context/heat-map-manager.d.ts.map +1 -0
  8. package/dist/context/manager.d.ts +16 -0
  9. package/dist/context/manager.d.ts.map +1 -0
  10. package/dist/context/types.d.ts +20 -0
  11. package/dist/context/types.d.ts.map +1 -0
  12. package/dist/core/agents/harness.d.ts +10 -1
  13. package/dist/core/agents/harness.d.ts.map +1 -1
  14. package/dist/core/agents/types.d.ts +18 -2
  15. package/dist/core/agents/types.d.ts.map +1 -1
  16. package/dist/core/computation/expr-evaluator.d.ts +52 -0
  17. package/dist/core/computation/expr-evaluator.d.ts.map +1 -0
  18. package/dist/core/index.js +93 -5
  19. package/dist/core/kernel/logic-middleware.d.ts +19 -0
  20. package/dist/core/kernel/logic-middleware.d.ts.map +1 -0
  21. package/dist/core/kernel/schema-middleware.d.ts +15 -0
  22. package/dist/core/kernel/schema-middleware.d.ts.map +1 -0
  23. package/dist/core/kernel/security-middleware.d.ts +24 -0
  24. package/dist/core/kernel/security-middleware.d.ts.map +1 -0
  25. package/dist/core/kernel/sync-provider.d.ts +59 -0
  26. package/dist/core/kernel/sync-provider.d.ts.map +1 -0
  27. package/dist/core/kernel/trellis-kernel.d.ts +55 -0
  28. package/dist/core/kernel/trellis-kernel.d.ts.map +1 -1
  29. package/dist/core/ontology/builtins.d.ts.map +1 -1
  30. package/dist/core/ontology/core-ontology.d.ts +20 -0
  31. package/dist/core/ontology/core-ontology.d.ts.map +1 -0
  32. package/dist/core/ontology/index.d.ts +3 -1
  33. package/dist/core/ontology/index.d.ts.map +1 -1
  34. package/dist/core/ontology/types.d.ts +138 -34
  35. package/dist/core/ontology/types.d.ts.map +1 -1
  36. package/dist/core/persist/backend.d.ts +2 -0
  37. package/dist/core/persist/backend.d.ts.map +1 -1
  38. package/dist/core/persist/better-sqlite-backend.d.ts +33 -0
  39. package/dist/core/persist/better-sqlite-backend.d.ts.map +1 -0
  40. package/dist/core/persist/sqlite-backend.d.ts +2 -0
  41. package/dist/core/persist/sqlite-backend.d.ts.map +1 -1
  42. package/dist/core/store/eav-store.d.ts +4 -0
  43. package/dist/core/store/eav-store.d.ts.map +1 -1
  44. package/dist/db/index.js +10 -8
  45. package/dist/{deploy-99j5dc9c.js → deploy-999q207z.js} +2 -1
  46. package/dist/engine.d.ts +3 -1
  47. package/dist/engine.d.ts.map +1 -1
  48. package/dist/evals/types.d.ts +29 -0
  49. package/dist/evals/types.d.ts.map +1 -0
  50. package/dist/{import-fyg5sgq4.js → import-s2b8e0ft.js} +2 -2
  51. package/dist/{index-3ejh8k6v.js → index-0q7wbasy.js} +18 -4
  52. package/dist/{index-7t92ej34.js → index-0zk3fx2s.js} +467 -7
  53. package/dist/{index-xr7rx360.js → index-6n5dcebj.js} +33 -0
  54. package/dist/{index-4beszbgg.js → index-7e27kvvj.js} +1 -1
  55. package/dist/index-bmyt7k8n.js +90 -0
  56. package/dist/{index-k5kf7sd0.js → index-hmdbnd4n.js} +1 -1
  57. package/dist/{index-czecrvvn.js → index-q31hfjja.js} +858 -48
  58. package/dist/{index-8fjwnztt.js → index-skhn0agf.js} +1 -1
  59. package/dist/{index-04sq3h27.js → index-w7ng765c.js} +3 -1
  60. package/dist/{index-hgd30epa.js → index-wt8rz4gn.js} +4 -21
  61. package/dist/{index-5p6zgspx.js → index-y3d71wzd.js} +1 -1
  62. package/dist/index-y6a4kj0p.js +43 -0
  63. package/dist/{index-5bhe57y9.js → index-yhwjgfvj.js} +16 -0
  64. package/dist/index.d.ts +2 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +16 -6
  67. package/dist/llm/provider.d.ts +11 -0
  68. package/dist/llm/provider.d.ts.map +1 -0
  69. package/dist/llm/types.d.ts +74 -0
  70. package/dist/llm/types.d.ts.map +1 -0
  71. package/dist/mcp/index.d.ts +7 -1
  72. package/dist/mcp/index.d.ts.map +1 -1
  73. package/dist/orchestration/types.d.ts +22 -0
  74. package/dist/orchestration/types.d.ts.map +1 -0
  75. package/dist/plugins/agent-memory/graph-context-manager.d.ts +75 -0
  76. package/dist/plugins/agent-memory/graph-context-manager.d.ts.map +1 -0
  77. package/dist/plugins/agent-memory/index.d.ts +30 -0
  78. package/dist/plugins/agent-memory/index.d.ts.map +1 -0
  79. package/dist/plugins/agent-memory/ontology.d.ts +13 -0
  80. package/dist/plugins/agent-memory/ontology.d.ts.map +1 -0
  81. package/dist/plugins/agent-memory/plugin.d.ts +17 -0
  82. package/dist/plugins/agent-memory/plugin.d.ts.map +1 -0
  83. package/dist/plugins/brand/cache.d.ts +18 -0
  84. package/dist/plugins/brand/cache.d.ts.map +1 -0
  85. package/dist/plugins/brand/catalog-generator.d.ts +89 -0
  86. package/dist/plugins/brand/catalog-generator.d.ts.map +1 -0
  87. package/dist/plugins/brand/constraints.d.ts +55 -0
  88. package/dist/plugins/brand/constraints.d.ts.map +1 -0
  89. package/dist/plugins/brand/index.d.ts +44 -0
  90. package/dist/plugins/brand/index.d.ts.map +1 -0
  91. package/dist/plugins/brand/mcp-tools.d.ts +101 -0
  92. package/dist/plugins/brand/mcp-tools.d.ts.map +1 -0
  93. package/dist/plugins/brand/ontology.d.ts +13 -0
  94. package/dist/plugins/brand/ontology.d.ts.map +1 -0
  95. package/dist/plugins/brand/plugin.d.ts +21 -0
  96. package/dist/plugins/brand/plugin.d.ts.map +1 -0
  97. package/dist/plugins/brand/voice-tone.d.ts +24 -0
  98. package/dist/plugins/brand/voice-tone.d.ts.map +1 -0
  99. package/dist/plugins/idea-garden/api.d.ts +26 -0
  100. package/dist/plugins/idea-garden/api.d.ts.map +1 -0
  101. package/dist/plugins/idea-garden/index.d.ts +12 -0
  102. package/dist/plugins/idea-garden/index.d.ts.map +1 -0
  103. package/dist/plugins/idea-garden/plugin.d.ts +16 -0
  104. package/dist/plugins/idea-garden/plugin.d.ts.map +1 -0
  105. package/dist/plugins/idea-garden/types.d.ts +22 -0
  106. package/dist/plugins/idea-garden/types.d.ts.map +1 -0
  107. package/dist/plugins/plan-approval/index.d.ts +36 -0
  108. package/dist/plugins/plan-approval/index.d.ts.map +1 -0
  109. package/dist/plugins/plan-approval/ontology.d.ts +11 -0
  110. package/dist/plugins/plan-approval/ontology.d.ts.map +1 -0
  111. package/dist/plugins/plan-approval/plan-manager.d.ts +104 -0
  112. package/dist/plugins/plan-approval/plan-manager.d.ts.map +1 -0
  113. package/dist/plugins/plan-approval/plugin.d.ts +110 -0
  114. package/dist/plugins/plan-approval/plugin.d.ts.map +1 -0
  115. package/dist/plugins/proactive-watcher/index.d.ts +28 -0
  116. package/dist/plugins/proactive-watcher/index.d.ts.map +1 -0
  117. package/dist/plugins/proactive-watcher/ontology.d.ts +8 -0
  118. package/dist/plugins/proactive-watcher/ontology.d.ts.map +1 -0
  119. package/dist/plugins/proactive-watcher/plugin.d.ts +20 -0
  120. package/dist/plugins/proactive-watcher/plugin.d.ts.map +1 -0
  121. package/dist/plugins/proactive-watcher/watcher-manager.d.ts +36 -0
  122. package/dist/plugins/proactive-watcher/watcher-manager.d.ts.map +1 -0
  123. package/dist/plugins/sprite-tools/checkpoint-middleware.d.ts +43 -0
  124. package/dist/plugins/sprite-tools/checkpoint-middleware.d.ts.map +1 -0
  125. package/dist/plugins/sprite-tools/index.d.ts +40 -0
  126. package/dist/plugins/sprite-tools/index.d.ts.map +1 -0
  127. package/dist/plugins/sprite-tools/plugin.d.ts +69 -0
  128. package/dist/plugins/sprite-tools/plugin.d.ts.map +1 -0
  129. package/dist/react/index.js +4 -4
  130. package/dist/scaffold/index.d.ts +13 -0
  131. package/dist/scaffold/index.d.ts.map +1 -0
  132. package/dist/scaffold/infer.d.ts +42 -0
  133. package/dist/scaffold/infer.d.ts.map +1 -0
  134. package/dist/scaffold/profile.d.ts +51 -0
  135. package/dist/scaffold/profile.d.ts.map +1 -0
  136. package/dist/scaffold/seed.d.ts +27 -0
  137. package/dist/scaffold/seed.d.ts.map +1 -0
  138. package/dist/scaffold/write.d.ts +53 -0
  139. package/dist/scaffold/write.d.ts.map +1 -0
  140. package/dist/{sdk-sj8rp0m7.js → sdk-snn5gad3.js} +4 -4
  141. package/dist/server/deploy.d.ts.map +1 -1
  142. package/dist/server/index.d.ts +5 -3
  143. package/dist/server/index.d.ts.map +1 -1
  144. package/dist/server/index.js +37 -7
  145. package/dist/server/sprites.d.ts +26 -0
  146. package/dist/server/sprites.d.ts.map +1 -0
  147. package/dist/server/vm-config.d.ts +60 -0
  148. package/dist/server/vm-config.d.ts.map +1 -0
  149. package/dist/{server-3vkpnpbz.js → server-mrctdwzr.js} +2 -2
  150. package/dist/sprites-vc4qbrp1.js +16 -0
  151. package/dist/streaming/types.d.ts +43 -0
  152. package/dist/streaming/types.d.ts.map +1 -0
  153. package/dist/{tenancy-tjr7kk2v.js → tenancy-7d1g4ayp.js} +3 -3
  154. package/dist/ui/client.html +460 -664
  155. package/dist/ui/server.d.ts +6 -2
  156. package/dist/ui/server.d.ts.map +1 -1
  157. package/dist/vcs/decompose.d.ts.map +1 -1
  158. package/dist/vcs/index.js +2 -2
  159. package/dist/vcs/issue.d.ts.map +1 -1
  160. package/dist/vcs/types.d.ts +1 -0
  161. package/dist/vcs/types.d.ts.map +1 -1
  162. package/dist/vm-config-6xhsj6b3.js +22 -0
  163. package/package.json +14 -4
  164. /package/dist/{index-kbnht9p8.js → index-c9h37r6h.js} +0 -0
@@ -42,7 +42,7 @@ import {
42
42
  triageIssue,
43
43
  unblockIssue,
44
44
  updateIssue
45
- } from "./index-3ejh8k6v.js";
45
+ } from "./index-0q7wbasy.js";
46
46
  import {
47
47
  getDecision,
48
48
  getDecisionChain,
@@ -59,7 +59,7 @@ import {
59
59
  import {
60
60
  EAVStore,
61
61
  init_eav_store
62
- } from "./index-5bhe57y9.js";
62
+ } from "./index-yhwjgfvj.js";
63
63
  import {
64
64
  __esm
65
65
  } from "./index-a76rekgs.js";
@@ -342,6 +342,646 @@ var init_ingestion = __esm(() => {
342
342
  };
343
343
  });
344
344
 
345
+ // src/scaffold/infer.ts
346
+ import { existsSync, readdirSync, statSync, readFileSync } from "fs";
347
+ import { join as join2 } from "path";
348
+ function detectEcosystem(rootPath) {
349
+ const indicators = [];
350
+ let ecosystem = null;
351
+ let name = null;
352
+ let description = null;
353
+ let domain = null;
354
+ const pkgPath = join2(rootPath, "package.json");
355
+ if (existsSync(pkgPath)) {
356
+ indicators.push("package.json");
357
+ try {
358
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
359
+ name = pkg.name ?? null;
360
+ description = pkg.description ?? null;
361
+ ecosystem = "node";
362
+ const deps = {
363
+ ...pkg.dependencies,
364
+ ...pkg.devDependencies,
365
+ ...pkg.peerDependencies
366
+ };
367
+ const depNames = Object.keys(deps);
368
+ if (pkg.engines?.bun || depNames.includes("@types/bun")) {
369
+ ecosystem = "bun";
370
+ }
371
+ if (depNames.some((d) => d.includes("motion-canvas"))) {
372
+ domain = "animation-studio";
373
+ } else if (depNames.some((d) => ["react", "vue", "svelte", "next", "nuxt"].includes(d))) {
374
+ domain = "web-app";
375
+ } else if (depNames.some((d) => ["express", "fastify", "hono", "elysia"].includes(d))) {
376
+ domain = "api-server";
377
+ } else if (depNames.some((d) => d.includes("@tensorflow") || d.includes("langchain") || d.includes("openai"))) {
378
+ domain = "ai-ml";
379
+ }
380
+ } catch {}
381
+ }
382
+ if (existsSync(join2(rootPath, "pyproject.toml"))) {
383
+ indicators.push("pyproject.toml");
384
+ ecosystem = ecosystem ?? "python";
385
+ } else if (existsSync(join2(rootPath, "requirements.txt"))) {
386
+ indicators.push("requirements.txt");
387
+ ecosystem = ecosystem ?? "python";
388
+ }
389
+ const cargoPath = join2(rootPath, "Cargo.toml");
390
+ if (existsSync(cargoPath)) {
391
+ indicators.push("Cargo.toml");
392
+ ecosystem = ecosystem ?? "rust";
393
+ try {
394
+ const cargo = readFileSync(cargoPath, "utf-8");
395
+ const nameMatch = cargo.match(/^name\s*=\s*"(.+?)"/m);
396
+ if (nameMatch)
397
+ name = name ?? nameMatch[1] ?? null;
398
+ } catch {}
399
+ }
400
+ if (existsSync(join2(rootPath, "go.mod"))) {
401
+ indicators.push("go.mod");
402
+ ecosystem = ecosystem ?? "go";
403
+ }
404
+ if (existsSync(join2(rootPath, "Dockerfile")) || existsSync(join2(rootPath, "docker-compose.yml"))) {
405
+ indicators.push("Dockerfile");
406
+ domain = domain ?? "infrastructure";
407
+ }
408
+ let framework = null;
409
+ if (existsSync(pkgPath)) {
410
+ try {
411
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
412
+ const deps = {
413
+ ...pkg.dependencies,
414
+ ...pkg.devDependencies,
415
+ ...pkg.peerDependencies
416
+ };
417
+ const depNames = Object.keys(deps);
418
+ if (depNames.includes("next")) {
419
+ framework = "next";
420
+ } else if (depNames.includes("nuxt")) {
421
+ framework = "nuxt";
422
+ } else if (depNames.includes("svelte")) {
423
+ framework = "svelte";
424
+ } else if (depNames.includes("vue")) {
425
+ framework = "vue";
426
+ } else if (depNames.includes("remotion") || depNames.includes("@remotion/server")) {
427
+ framework = "remotion";
428
+ } else if (depNames.includes("expo") || depNames.includes("react-native")) {
429
+ framework = "expo";
430
+ } else if (depNames.some((d) => ["commander", "cac", "oclif", "yargs"].includes(d))) {
431
+ framework = "cli";
432
+ } else if (depNames.includes("react")) {
433
+ framework = "react";
434
+ }
435
+ } catch {}
436
+ }
437
+ return {
438
+ ecosystem: ecosystem ?? "unknown",
439
+ name,
440
+ description,
441
+ domain,
442
+ framework,
443
+ indicators
444
+ };
445
+ }
446
+ function extractReadmeDescription(rootPath) {
447
+ const candidates = ["README.md", "README.MD", "readme.md", "README.txt"];
448
+ for (const candidate of candidates) {
449
+ const readmePath = join2(rootPath, candidate);
450
+ if (!existsSync(readmePath))
451
+ continue;
452
+ try {
453
+ const content = readFileSync(readmePath, "utf-8");
454
+ const lines = content.split(`
455
+ `).slice(0, 60);
456
+ for (const line of lines) {
457
+ const trimmed = line.trim();
458
+ if (trimmed && !trimmed.startsWith("#") && !trimmed.startsWith("!") && trimmed.length > 20) {
459
+ const clean = trimmed.replace(/[*_`[\]]/g, "").replace(/\(https?:\/\/[^\)]+\)/g, "").trim();
460
+ if (clean.length > 10) {
461
+ return {
462
+ description: clean.slice(0, 200),
463
+ indicators: [candidate]
464
+ };
465
+ }
466
+ }
467
+ }
468
+ } catch {}
469
+ }
470
+ return { description: null, indicators: [] };
471
+ }
472
+ function shallowFileCount(rootPath, maxDepth = 3) {
473
+ let count = 0;
474
+ function walk(dir, depth) {
475
+ if (depth > maxDepth)
476
+ return;
477
+ let entries = [];
478
+ try {
479
+ entries = readdirSync(dir);
480
+ } catch {
481
+ return;
482
+ }
483
+ for (const entry of entries) {
484
+ if (entry.startsWith(".") || entry === "node_modules" || entry === ".trellis")
485
+ continue;
486
+ try {
487
+ const full = join2(dir, entry);
488
+ const stat2 = statSync(full);
489
+ if (stat2.isDirectory()) {
490
+ walk(full, depth + 1);
491
+ } else {
492
+ count++;
493
+ }
494
+ } catch {}
495
+ }
496
+ }
497
+ walk(rootPath, 0);
498
+ return count;
499
+ }
500
+ function computeConfidence(fileCount, indicators) {
501
+ if (fileCount <= 5)
502
+ return "high";
503
+ if (indicators.length >= 2)
504
+ return "high";
505
+ if (fileCount >= 1e4)
506
+ return "low";
507
+ if (indicators.length === 1)
508
+ return fileCount <= 500 ? "high" : "medium";
509
+ return "medium";
510
+ }
511
+ async function inferProjectContext(rootPath, opts) {
512
+ const fileCount = opts?.precomputedFileCount ?? shallowFileCount(rootPath);
513
+ const ecosystem = detectEcosystem(rootPath);
514
+ const readme = extractReadmeDescription(rootPath);
515
+ const allIndicators = [...ecosystem.indicators, ...readme.indicators];
516
+ const confidence = computeConfidence(fileCount, allIndicators);
517
+ return {
518
+ domain: ecosystem.domain,
519
+ description: readme.description ?? ecosystem.description,
520
+ ecosystem: ecosystem.ecosystem,
521
+ name: ecosystem.name,
522
+ framework: ecosystem.framework,
523
+ fileCount,
524
+ confidence,
525
+ indicators: allIndicators
526
+ };
527
+ }
528
+ var init_infer = () => {};
529
+
530
+ // src/scaffold/profile.ts
531
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
532
+ import { join as join3 } from "path";
533
+ import { homedir } from "os";
534
+ import { createInterface } from "readline";
535
+ function getProfileDir() {
536
+ return join3(homedir(), ".trellis");
537
+ }
538
+ function getProfilePath() {
539
+ return join3(getProfileDir(), "profile.json");
540
+ }
541
+ function loadProfile() {
542
+ const profilePath = getProfilePath();
543
+ if (!existsSync2(profilePath))
544
+ return null;
545
+ try {
546
+ const raw = readFileSync2(profilePath, "utf-8");
547
+ return JSON.parse(raw);
548
+ } catch {
549
+ return null;
550
+ }
551
+ }
552
+ function saveProfile(profile) {
553
+ const dir = getProfileDir();
554
+ if (!existsSync2(dir)) {
555
+ mkdirSync(dir, { recursive: true });
556
+ }
557
+ writeFileSync(getProfilePath(), JSON.stringify(profile, null, 2));
558
+ }
559
+ function hasProfile() {
560
+ return existsSync2(getProfilePath());
561
+ }
562
+ function ask(rl, question) {
563
+ return new Promise((resolve) => {
564
+ rl.question(question, (answer) => resolve(answer.trim()));
565
+ });
566
+ }
567
+ async function promptForProfile(hints) {
568
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
569
+ console.log();
570
+ console.log(" This takes about 60 seconds and only happens once.");
571
+ console.log(` Press Enter to skip any question.
572
+ `);
573
+ const defaultName = hints?.name ?? "";
574
+ const namePrompt = defaultName ? ` Your name [${defaultName}]: ` : " Your name: ";
575
+ const nameRaw = await ask(rl, namePrompt);
576
+ const name = nameRaw || defaultName;
577
+ const bio = await ask(rl, " In one sentence, what kind of work do you do? ");
578
+ const skillsRaw = await ask(rl, " Top 3\u20135 tools or skills (comma-separated): ");
579
+ const style = await ask(rl, " How would you describe your working style? ");
580
+ const verbosityRaw = await ask(rl, " Preferred response verbosity \u2014 concise / balanced / detailed [balanced]: ");
581
+ const toneRaw = await ask(rl, " Preferred AI tone \u2014 peer / mentor / formal [peer]: ");
582
+ rl.close();
583
+ const skills = skillsRaw ? skillsRaw.split(",").map((s) => s.trim()).filter(Boolean) : [];
584
+ const verbosity = ["concise", "balanced", "detailed"].includes(verbosityRaw) ? verbosityRaw : "balanced";
585
+ const tone = ["peer", "mentor", "formal"].includes(toneRaw) ? toneRaw : "peer";
586
+ const now = new Date().toISOString();
587
+ return {
588
+ name: name || "Unknown",
589
+ bio: bio || "",
590
+ skills,
591
+ style: style || "",
592
+ preferences: { verbosity, tone },
593
+ createdAt: now,
594
+ updatedAt: now
595
+ };
596
+ }
597
+ function updateProfile(updates) {
598
+ const existing = loadProfile();
599
+ const base = existing ?? {
600
+ name: "Unknown",
601
+ bio: "",
602
+ skills: [],
603
+ style: "",
604
+ preferences: { verbosity: "balanced", tone: "peer" },
605
+ createdAt: new Date().toISOString(),
606
+ updatedAt: new Date().toISOString()
607
+ };
608
+ const updated = {
609
+ ...base,
610
+ ...updates,
611
+ preferences: { ...base.preferences, ...updates.preferences ?? {} },
612
+ updatedAt: new Date().toISOString()
613
+ };
614
+ saveProfile(updated);
615
+ return updated;
616
+ }
617
+ var init_profile = () => {};
618
+
619
+ // src/scaffold/write.ts
620
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync3 } from "fs";
621
+ import { join as join4 } from "path";
622
+ function renderAgentsMd(profile, context) {
623
+ const userName = profile?.name ?? "the user";
624
+ const userBio = profile?.bio || "(No bio provided \u2014 run `trellis season` to set up your profile.)";
625
+ const userSkills = profile?.skills?.length ? profile.skills.join(", ") : "(not specified)";
626
+ const userStyle = profile?.style || "(not specified)";
627
+ const userVerbosity = profile?.preferences?.verbosity ?? "balanced";
628
+ const userTone = profile?.preferences?.tone ?? "peer";
629
+ const projectName = context.name ?? "(unnamed)";
630
+ const projectDomain = context.domain ?? "(not determined \u2014 run `trellis season` to specify)";
631
+ const projectDesc = context.description ?? "(no description found)";
632
+ const projectEco = context.ecosystem ?? "unknown";
633
+ const confidence = context.confidence;
634
+ return `# Trellis Agent Context
635
+
636
+ > This file was generated by \`trellis init\` and should be kept up to date.
637
+ > Inference confidence: **${confidence}**
638
+
639
+ ---
640
+
641
+ ## About the User
642
+
643
+ | Field | Value |
644
+ |-------|-------|
645
+ | **Name** | ${userName} |
646
+ | **Bio** | ${userBio} |
647
+ | **Skills** | ${userSkills} |
648
+ | **Style** | ${userStyle} |
649
+ | **Preferred verbosity** | ${userVerbosity} |
650
+ | **Preferred tone** | ${userTone} |
651
+
652
+ ---
653
+
654
+ ## About This Project
655
+
656
+ | Field | Value |
657
+ |-------|-------|
658
+ | **Name** | ${projectName} |
659
+ | **Domain** | ${projectDomain} |
660
+ | **Description** | ${projectDesc} |
661
+ | **Ecosystem** | ${projectEco} |
662
+ | **File count** | ~${context.fileCount} |
663
+
664
+ ---
665
+
666
+ ## Agent Instructions
667
+
668
+ You are operating in a Trellis-tracked repository. Follow these guidelines:
669
+
670
+ 1. **Read \`agent-context.json\`** in this directory for registered tools, ontologies, and domain settings.
671
+ 2. **Check \`skills/\`** for domain-specific operating instructions relevant to this project.
672
+ 3. **Check \`workflows/\`** for repeatable task procedures. Favor existing workflows before improvising.
673
+ 4. **Update this file** as the project evolves \u2014 new teammates, new goals, new tools.
674
+ 5. **Communicate through Trellis** \u2014 prefer writing to the graph kernel over mutating files directly when recording decisions or state.
675
+ 6. **Run \`trellis season\`** if context seems incomplete or out of date.
676
+
677
+ ---
678
+
679
+ ## Quick Reference
680
+
681
+ \`\`\`bash
682
+ trellis status # Current repo state
683
+ trellis log # Causal operation history
684
+ trellis milestone # Create narrative checkpoints
685
+ trellis ask "..." # Semantic search across the repo
686
+ trellis season # Re-run domain onboarding
687
+ \`\`\`
688
+ `;
689
+ }
690
+ function renderConfigJson(context) {
691
+ return {
692
+ domain: context.domain,
693
+ ecosystem: context.ecosystem,
694
+ tools: [],
695
+ ontologies: [],
696
+ generatedAt: new Date().toISOString(),
697
+ confidence: context.confidence
698
+ };
699
+ }
700
+ function renderSkillsReadme() {
701
+ return `# Skills
702
+
703
+ Place domain-specific operating instructions here as \`.md\` files.
704
+
705
+ Each skill file should follow the format:
706
+
707
+ \`\`\`markdown
708
+ ---
709
+ name: Skill Name
710
+ description: When to use this skill.
711
+ ---
712
+
713
+ # Instructions
714
+ ...
715
+ \`\`\`
716
+
717
+ The agent will discover and read skill files relevant to the current task.
718
+ `;
719
+ }
720
+ function renderWorkflowsReadme() {
721
+ return `# Workflows
722
+
723
+ Place repeatable task procedures here as \`.md\` files.
724
+
725
+ Each workflow file should follow the format:
726
+
727
+ \`\`\`markdown
728
+ ---
729
+ description: Short description of what this workflow does.
730
+ ---
731
+
732
+ ## Steps
733
+
734
+ 1. Step one
735
+ 2. Step two
736
+ // turbo
737
+ 3. Auto-runnable step
738
+ \`\`\`
739
+
740
+ Add \`// turbo\` above a step to allow the agent to auto-run it without confirmation.
741
+ Add \`// turbo-all\` anywhere in the file to auto-run every step.
742
+ `;
743
+ }
744
+ function writeAgentScaffold(rootPath, input) {
745
+ const agentsDir = join4(rootPath, ".trellis", "agents");
746
+ const skillsDir = join4(agentsDir, "skills");
747
+ const workflowsDir = join4(agentsDir, "workflows");
748
+ for (const dir of [agentsDir, skillsDir, workflowsDir]) {
749
+ if (!existsSync3(dir)) {
750
+ mkdirSync2(dir, { recursive: true });
751
+ }
752
+ }
753
+ writeFileSync2(join4(agentsDir, "AGENTS.md"), renderAgentsMd(input.profile, input.context), "utf-8");
754
+ writeFileSync2(join4(agentsDir, "agent-context.json"), JSON.stringify(renderConfigJson(input.context), null, 2), "utf-8");
755
+ const skillsReadmePath = join4(skillsDir, "README.md");
756
+ if (!existsSync3(skillsReadmePath)) {
757
+ writeFileSync2(skillsReadmePath, renderSkillsReadme(), "utf-8");
758
+ }
759
+ const workflowsReadmePath = join4(workflowsDir, "README.md");
760
+ if (!existsSync3(workflowsReadmePath)) {
761
+ writeFileSync2(workflowsReadmePath, renderWorkflowsReadme(), "utf-8");
762
+ }
763
+ }
764
+ function renderCursorRules(input) {
765
+ const projectName = input.context.name ?? "this project";
766
+ const domain = input.context.domain ?? "general";
767
+ const eco = input.context.ecosystem ?? "unknown";
768
+ const framework = input.framework && input.framework !== "none" ? input.framework : "vanilla";
769
+ const plugins = input.plugins.length > 0 ? input.plugins.map((p) => `- ${p}`).join(`
770
+ `) : "(none selected)";
771
+ return `# Cursor Rules for ${projectName}
772
+
773
+ > Generated by \`trellis init\`
774
+
775
+ ## Project Context
776
+ - **Domain**: ${domain}
777
+ - **Framework**: ${framework}
778
+ - **Ecosystem**: ${eco}
779
+ - **Confidence**: ${input.context.confidence}
780
+
781
+ ## Selected Features
782
+ ${plugins}
783
+
784
+ ## Agent Instructions
785
+ You are working in a Trellis-tracked repository. See \`.trellis/agents/AGENTS.md\` for full context.
786
+
787
+ ## Commands
788
+ - \`trellis status\` \u2014 Check repo state
789
+ - \`trellis seed\` \u2014 Refresh this context file
790
+ - \`trellis log\` \u2014 View causal history
791
+
792
+ ---
793
+ *Auto-generated by Trellis. Run \`trellis seed\` to refresh context.*
794
+ `;
795
+ }
796
+ function renderWindsurfRules(input) {
797
+ const projectName = input.context.name ?? "this project";
798
+ const domain = input.context.domain ?? "general";
799
+ const eco = input.context.ecosystem ?? "unknown";
800
+ const framework = input.framework && input.framework !== "none" ? input.framework : "vanilla";
801
+ const plugins = input.plugins.length > 0 ? input.plugins.map((p) => `- ${p}`).join(`
802
+ `) : "(none selected)";
803
+ return `# Windsurf Rules for ${projectName}
804
+
805
+ > Generated by \`trellis init\`
806
+
807
+ ## Project Context
808
+ - **Domain**: ${domain}
809
+ - **Framework**: ${framework}
810
+ - **Ecosystem**: ${eco}
811
+ - **Confidence**: ${input.context.confidence}
812
+
813
+ ## Selected Features
814
+ ${plugins}
815
+
816
+ ## Agent Instructions
817
+ You are working in a Trellis-tracked repository. See \`.trellis/agents/AGENTS.md\` for full context.
818
+
819
+ ## Commands
820
+ - \`trellis status\` \u2014 Check repo state
821
+ - \`trellis seed\` \u2014 Refresh this context file
822
+ - \`trellis log\` \u2014 View causal history
823
+
824
+ ---
825
+ *Auto-generated by Trellis. Run \`trellis seed\` to refresh context.*
826
+ `;
827
+ }
828
+ function renderClaudeMd(input) {
829
+ const projectName = input.context.name ?? "this project";
830
+ const domain = input.context.domain ?? "general";
831
+ const eco = input.context.ecosystem ?? "unknown";
832
+ const framework = input.framework && input.framework !== "none" ? input.framework : "vanilla";
833
+ const plugins = input.plugins.length > 0 ? input.plugins.map((p) => `- ${p}`).join(`
834
+ `) : "(none selected)";
835
+ return `# Claude Context for ${projectName}
836
+
837
+ > Generated by \`trellis init\`
838
+
839
+ ## Project Context
840
+ - **Domain**: ${domain}
841
+ - **Framework**: ${framework}
842
+ - **Ecosystem**: ${eco}
843
+ - **Confidence**: ${input.context.confidence}
844
+
845
+ ## Selected Features
846
+ ${plugins}
847
+
848
+ ## Agent Instructions
849
+ You are working in a Trellis-tracked repository. See \`.trellis/agents/AGENTS.md\` for full context.
850
+
851
+ ## Commands
852
+ - \`trellis status\` \u2014 Check repo state
853
+ - \`trellis seed\` \u2014 Refresh this context file
854
+ - \`trellis log\` \u2014 View causal history
855
+
856
+ ---
857
+ *Auto-generated by Trellis. Run \`trellis seed\` to refresh context.*
858
+ `;
859
+ }
860
+ function renderCopilotConfig(input) {
861
+ return {
862
+ version: "1.0",
863
+ generatedBy: "trellis init",
864
+ context: {
865
+ domain: input.context.domain,
866
+ framework: input.framework,
867
+ ecosystem: input.context.ecosystem,
868
+ projectName: input.context.name,
869
+ confidence: input.context.confidence
870
+ },
871
+ plugins: input.plugins
872
+ };
873
+ }
874
+ function renderCodexConfig(input) {
875
+ return {
876
+ version: "1.0",
877
+ generatedBy: "trellis init",
878
+ context: {
879
+ domain: input.context.domain,
880
+ framework: input.framework,
881
+ ecosystem: input.context.ecosystem,
882
+ projectName: input.context.name,
883
+ confidence: input.context.confidence
884
+ },
885
+ features: input.plugins
886
+ };
887
+ }
888
+ function renderGeminiConfig(input) {
889
+ return {
890
+ version: "1.0",
891
+ generatedBy: "trellis init",
892
+ context: {
893
+ domain: input.context.domain,
894
+ framework: input.framework,
895
+ ecosystem: input.context.ecosystem,
896
+ projectName: input.context.name,
897
+ confidence: input.context.confidence
898
+ },
899
+ features: input.plugins
900
+ };
901
+ }
902
+ function writeIdeScaffold(rootPath, input) {
903
+ const { ide, footprint, framework, plugins, context, profile } = input;
904
+ const fullInput = {
905
+ ide,
906
+ footprint,
907
+ framework,
908
+ plugins,
909
+ rootPath,
910
+ context,
911
+ profile
912
+ };
913
+ switch (ide) {
914
+ case "cursor": {
915
+ const cursorDir = join4(rootPath, ".cursor");
916
+ if (!existsSync3(cursorDir)) {
917
+ mkdirSync2(cursorDir, { recursive: true });
918
+ }
919
+ writeFileSync2(join4(cursorDir, "rules.md"), renderCursorRules(fullInput), "utf-8");
920
+ break;
921
+ }
922
+ case "windsurf": {
923
+ const windsurfDir = join4(rootPath, ".windsurf");
924
+ if (!existsSync3(windsurfDir)) {
925
+ mkdirSync2(windsurfDir, { recursive: true });
926
+ }
927
+ writeFileSync2(join4(windsurfDir, "rules.md"), renderWindsurfRules(fullInput), "utf-8");
928
+ break;
929
+ }
930
+ case "claude": {
931
+ const claudeDir = join4(rootPath, ".claude");
932
+ if (!existsSync3(claudeDir)) {
933
+ mkdirSync2(claudeDir, { recursive: true });
934
+ }
935
+ writeFileSync2(join4(claudeDir, "settings.md"), renderClaudeMd(fullInput), "utf-8");
936
+ break;
937
+ }
938
+ case "copilot": {
939
+ const copilotDir = join4(rootPath, ".github");
940
+ const copilotDirSub = join4(copilotDir, "copilot");
941
+ if (!existsSync3(copilotDirSub)) {
942
+ mkdirSync2(copilotDirSub, { recursive: true });
943
+ }
944
+ writeFileSync2(join4(copilotDirSub, "config.json"), JSON.stringify(renderCopilotConfig(fullInput), null, 2), "utf-8");
945
+ break;
946
+ }
947
+ case "codex": {
948
+ const codexDir = join4(rootPath, ".codex");
949
+ if (!existsSync3(codexDir)) {
950
+ mkdirSync2(codexDir, { recursive: true });
951
+ }
952
+ writeFileSync2(join4(codexDir, "config.json"), JSON.stringify(renderCodexConfig(fullInput), null, 2), "utf-8");
953
+ break;
954
+ }
955
+ case "gemini": {
956
+ const geminiDir = join4(rootPath, ".gemini");
957
+ if (!existsSync3(geminiDir)) {
958
+ mkdirSync2(geminiDir, { recursive: true });
959
+ }
960
+ writeFileSync2(join4(geminiDir, "config.json"), JSON.stringify(renderGeminiConfig(fullInput), null, 2), "utf-8");
961
+ break;
962
+ }
963
+ case "none":
964
+ break;
965
+ }
966
+ if (footprint === "full") {
967
+ const agentsDir = join4(rootPath, ".trellis", "agents");
968
+ if (existsSync3(agentsDir)) {
969
+ const current = readFileSync3(join4(agentsDir, "AGENTS.md"), "utf-8");
970
+ const updated = current.replace(/## Quick Reference[\s\S]*$/, `## Quick Reference
971
+
972
+ \`\`\`bash
973
+ trellis status # Current repo state
974
+ trellis log # Causal operation history
975
+ trellis seed # Refresh agent context (${ide})
976
+ trellis milestone # Create narrative checkpoints
977
+ \`\`\`
978
+ `);
979
+ writeFileSync2(join4(agentsDir, "AGENTS.md"), updated, "utf-8");
980
+ }
981
+ }
982
+ }
983
+ var init_write = () => {};
984
+
345
985
  // src/garden/cluster.ts
346
986
  function isFileOp(op) {
347
987
  return FILE_OP_KINDS.has(op.kind);
@@ -3498,14 +4138,14 @@ var init_semantic = __esm(() => {
3498
4138
 
3499
4139
  // src/engine.ts
3500
4140
  import {
3501
- existsSync,
3502
- mkdirSync,
3503
- readFileSync,
3504
- writeFileSync,
4141
+ existsSync as existsSync4,
4142
+ mkdirSync as mkdirSync3,
4143
+ readFileSync as readFileSync4,
4144
+ writeFileSync as writeFileSync3,
3505
4145
  copyFileSync
3506
4146
  } from "fs";
3507
4147
  import { readFile as readFile2 } from "fs/promises";
3508
- import { join as join2, dirname } from "path";
4148
+ import { join as join5, dirname } from "path";
3509
4149
 
3510
4150
  class JsonOpLog {
3511
4151
  ops = [];
@@ -3514,16 +4154,16 @@ class JsonOpLog {
3514
4154
  this.filePath = filePath;
3515
4155
  }
3516
4156
  load() {
3517
- if (existsSync(this.filePath)) {
3518
- const raw = readFileSync(this.filePath, "utf-8");
4157
+ if (existsSync4(this.filePath)) {
4158
+ const raw = readFileSync4(this.filePath, "utf-8");
3519
4159
  try {
3520
4160
  this.ops = JSON.parse(raw);
3521
4161
  } catch (err) {
3522
4162
  const backupPath = this.filePath + ".bak";
3523
- if (existsSync(backupPath)) {
3524
- const backupRaw = readFileSync(backupPath, "utf-8");
4163
+ if (existsSync4(backupPath)) {
4164
+ const backupRaw = readFileSync4(backupPath, "utf-8");
3525
4165
  this.ops = JSON.parse(backupRaw);
3526
- writeFileSync(this.filePath, backupRaw);
4166
+ writeFileSync3(this.filePath, backupRaw);
3527
4167
  } else {
3528
4168
  throw new Error(`Corrupted ops.json and no backup found. Run \`trellis repair\` to attempt recovery.`);
3529
4169
  }
@@ -3545,21 +4185,21 @@ class JsonOpLog {
3545
4185
  }
3546
4186
  flush() {
3547
4187
  const dir = dirname(this.filePath);
3548
- if (!existsSync(dir))
3549
- mkdirSync(dir, { recursive: true });
3550
- if (existsSync(this.filePath)) {
4188
+ if (!existsSync4(dir))
4189
+ mkdirSync3(dir, { recursive: true });
4190
+ if (existsSync4(this.filePath)) {
3551
4191
  const backupPath = this.filePath + ".bak";
3552
4192
  try {
3553
4193
  copyFileSync(this.filePath, backupPath);
3554
4194
  } catch {}
3555
4195
  }
3556
- writeFileSync(this.filePath, JSON.stringify(this.ops, null, 2));
4196
+ writeFileSync3(this.filePath, JSON.stringify(this.ops, null, 2));
3557
4197
  }
3558
4198
  static repair(filePath) {
3559
- if (!existsSync(filePath)) {
4199
+ if (!existsSync4(filePath)) {
3560
4200
  return { recovered: 0, lost: 0 };
3561
4201
  }
3562
- const raw = readFileSync(filePath, "utf-8");
4202
+ const raw = readFileSync4(filePath, "utf-8");
3563
4203
  try {
3564
4204
  const ops = JSON.parse(raw);
3565
4205
  return { recovered: ops.length, lost: 0 };
@@ -3567,43 +4207,43 @@ class JsonOpLog {
3567
4207
  const lastHash = raw.lastIndexOf('"hash": "trellis:op:');
3568
4208
  if (lastHash === -1) {
3569
4209
  const bakPath = filePath + ".bak";
3570
- if (existsSync(bakPath)) {
3571
- const bakRaw = readFileSync(bakPath, "utf-8");
4210
+ if (existsSync4(bakPath)) {
4211
+ const bakRaw = readFileSync4(bakPath, "utf-8");
3572
4212
  try {
3573
4213
  const ops = JSON.parse(bakRaw);
3574
- writeFileSync(filePath, bakRaw);
4214
+ writeFileSync3(filePath, bakRaw);
3575
4215
  return { recovered: ops.length, lost: 0 };
3576
4216
  } catch {}
3577
4217
  }
3578
- writeFileSync(filePath, "[]");
4218
+ writeFileSync3(filePath, "[]");
3579
4219
  return { recovered: 0, lost: -1 };
3580
4220
  }
3581
4221
  const endOfLine = raw.indexOf(`
3582
4222
  `, lastHash);
3583
4223
  const closingBrace = raw.indexOf(" }", endOfLine);
3584
4224
  if (closingBrace === -1) {
3585
- writeFileSync(filePath, "[]");
4225
+ writeFileSync3(filePath, "[]");
3586
4226
  return { recovered: 0, lost: -1 };
3587
4227
  }
3588
4228
  const fixed = raw.slice(0, closingBrace + 3) + `
3589
4229
  ]`;
3590
4230
  try {
3591
4231
  const ops = JSON.parse(fixed);
3592
- writeFileSync(filePath + ".corrupted", raw);
3593
- writeFileSync(filePath, fixed);
4232
+ writeFileSync3(filePath + ".corrupted", raw);
4233
+ writeFileSync3(filePath, fixed);
3594
4234
  return { recovered: ops.length, lost: 0 };
3595
4235
  } catch {
3596
- writeFileSync(filePath + ".corrupted", raw);
3597
- writeFileSync(filePath, "[]");
4236
+ writeFileSync3(filePath + ".corrupted", raw);
4237
+ writeFileSync3(filePath, "[]");
3598
4238
  return { recovered: 0, lost: -1 };
3599
4239
  }
3600
4240
  }
3601
4241
  }
3602
4242
  function parseIgnoreFile(filePath) {
3603
- if (!existsSync(filePath))
4243
+ if (!existsSync4(filePath))
3604
4244
  return [];
3605
4245
  try {
3606
- const content = readFileSync(filePath, "utf-8");
4246
+ const content = readFileSync4(filePath, "utf-8");
3607
4247
  return content.split(`
3608
4248
  `).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).map((line) => line.replace(/\/$/, ""));
3609
4249
  } catch {
@@ -3612,8 +4252,8 @@ function parseIgnoreFile(filePath) {
3612
4252
  }
3613
4253
  function readIgnorePatterns(rootPath) {
3614
4254
  return [
3615
- ...parseIgnoreFile(join2(rootPath, ".gitignore")),
3616
- ...parseIgnoreFile(join2(rootPath, ".trellisignore"))
4255
+ ...parseIgnoreFile(join5(rootPath, ".gitignore")),
4256
+ ...parseIgnoreFile(join5(rootPath, ".trellisignore"))
3617
4257
  ];
3618
4258
  }
3619
4259
 
@@ -3646,15 +4286,15 @@ class TrellisVcsEngine {
3646
4286
  };
3647
4287
  this.agentId = opts.agentId ?? `agent:${process.env.USER ?? "unknown"}`;
3648
4288
  this.store = new EAVStore;
3649
- this.opLog = new JsonOpLog(join2(this.config.rootPath, ".trellis", "ops.json"));
4289
+ this.opLog = new JsonOpLog(join5(this.config.rootPath, ".trellis", "ops.json"));
3650
4290
  }
3651
4291
  async initRepo(opts) {
3652
- const trellisDir = join2(this.config.rootPath, ".trellis");
3653
- if (!existsSync(trellisDir)) {
3654
- mkdirSync(trellisDir, { recursive: true });
4292
+ const trellisDir = join5(this.config.rootPath, ".trellis");
4293
+ if (!existsSync4(trellisDir)) {
4294
+ mkdirSync3(trellisDir, { recursive: true });
3655
4295
  }
3656
4296
  this._blobStore = new BlobStore(trellisDir);
3657
- const configPath = join2(trellisDir, "config.json");
4297
+ const configPath = join5(trellisDir, "config.json");
3658
4298
  const persistedConfig = {
3659
4299
  rootPath: this.config.rootPath,
3660
4300
  ignorePatterns: this.config.ignorePatterns,
@@ -3663,7 +4303,7 @@ class TrellisVcsEngine {
3663
4303
  agentId: this.agentId,
3664
4304
  createdAt: new Date().toISOString()
3665
4305
  };
3666
- writeFileSync(configPath, JSON.stringify(persistedConfig, null, 2));
4306
+ writeFileSync3(configPath, JSON.stringify(persistedConfig, null, 2));
3667
4307
  this.opLog.load();
3668
4308
  const branchOp = await createVcsOp("vcs:branchCreate", {
3669
4309
  agentId: this.agentId,
@@ -3702,7 +4342,7 @@ class TrellisVcsEngine {
3702
4342
  for (const event of events) {
3703
4343
  if (event.contentHash) {
3704
4344
  try {
3705
- const absPath = join2(this.config.rootPath, event.path);
4345
+ const absPath = join5(this.config.rootPath, event.path);
3706
4346
  const content = await readFile2(absPath);
3707
4347
  await this._blobStore.put(content);
3708
4348
  } catch {}
@@ -3729,21 +4369,32 @@ class TrellisVcsEngine {
3729
4369
  }
3730
4370
  }
3731
4371
  await this.flushAutoCheckpoint();
4372
+ opts?.onProgress?.({
4373
+ phase: "scaffolding",
4374
+ current: 0,
4375
+ total: 1,
4376
+ message: "Inferring project context\u2026"
4377
+ });
4378
+ const context = await inferProjectContext(this.config.rootPath, {
4379
+ precomputedFileCount: events.length
4380
+ });
4381
+ const profile = loadProfile();
4382
+ writeAgentScaffold(this.config.rootPath, { profile, context });
3732
4383
  opts?.onProgress?.({
3733
4384
  phase: "done",
3734
4385
  current: opsCreated,
3735
4386
  total: opsCreated,
3736
4387
  message: `Initialized repository with ${opsCreated} operations`
3737
4388
  });
3738
- return { opsCreated };
4389
+ return { opsCreated, context };
3739
4390
  }
3740
4391
  open() {
3741
4392
  this.opLog.load();
3742
- const trellisDir = join2(this.config.rootPath, ".trellis");
4393
+ const trellisDir = join5(this.config.rootPath, ".trellis");
3743
4394
  this._blobStore = new BlobStore(trellisDir);
3744
- const configPath = join2(this.config.rootPath, ".trellis", "config.json");
3745
- if (existsSync(configPath)) {
3746
- const raw = readFileSync(configPath, "utf-8");
4395
+ const configPath = join5(this.config.rootPath, ".trellis", "config.json");
4396
+ if (existsSync4(configPath)) {
4397
+ const raw = readFileSync4(configPath, "utf-8");
3747
4398
  const persisted = JSON.parse(raw);
3748
4399
  this.agentId = persisted.agentId;
3749
4400
  const filePatterns = readIgnorePatterns(this.config.rootPath);
@@ -3773,7 +4424,7 @@ class TrellisVcsEngine {
3773
4424
  onEvent: async (event) => {
3774
4425
  if ((event.type === "add" || event.type === "modify") && event.contentHash && this._blobStore) {
3775
4426
  try {
3776
- const absPath = join2(this.config.rootPath, event.path);
4427
+ const absPath = join5(this.config.rootPath, event.path);
3777
4428
  const content = await readFile2(absPath);
3778
4429
  await this._blobStore.put(content);
3779
4430
  } catch {}
@@ -3787,7 +4438,7 @@ class TrellisVcsEngine {
3787
4438
  if (!trackedPaths.has(event.path)) {
3788
4439
  if (event.contentHash && this._blobStore) {
3789
4440
  try {
3790
- const absPath = join2(this.config.rootPath, event.path);
4441
+ const absPath = join5(this.config.rootPath, event.path);
3791
4442
  const content = await readFile2(absPath);
3792
4443
  await this._blobStore.put(content);
3793
4444
  } catch {}
@@ -3854,10 +4505,10 @@ class TrellisVcsEngine {
3854
4505
  return this.config.rootPath;
3855
4506
  }
3856
4507
  static isRepo(rootPath) {
3857
- return existsSync(join2(rootPath, ".trellis", "config.json"));
4508
+ return existsSync4(join5(rootPath, ".trellis", "config.json"));
3858
4509
  }
3859
4510
  static repair(rootPath) {
3860
- const opsPath = join2(rootPath, ".trellis", "ops.json");
4511
+ const opsPath = join5(rootPath, ".trellis", "ops.json");
3861
4512
  return JsonOpLog.repair(opsPath);
3862
4513
  }
3863
4514
  async createBranch(name) {
@@ -4187,6 +4838,165 @@ var init_engine = __esm(() => {
4187
4838
  init_decisions();
4188
4839
  init_garden2();
4189
4840
  init_semantic();
4841
+ init_infer();
4842
+ init_profile();
4843
+ init_write();
4190
4844
  });
4191
4845
 
4192
- export { FileWatcher, init_fs_watcher, Ingestion, init_ingestion, TrellisVcsEngine, init_engine };
4846
+ // src/scaffold/seed.ts
4847
+ init_profile();
4848
+ init_infer();
4849
+ import { existsSync as existsSync5, writeFileSync as writeFileSync4 } from "fs";
4850
+ import { join as join6 } from "path";
4851
+ async function seedContext(opts) {
4852
+ const { rootPath, ide = "none", force = false } = opts;
4853
+ const filesUpdated = [];
4854
+ const timestamp = new Date().toISOString();
4855
+ const profile = loadProfile();
4856
+ const context = await inferProjectContext(rootPath);
4857
+ const agentsDir = join6(rootPath, ".trellis", "agents");
4858
+ if (existsSync5(agentsDir)) {
4859
+ const agentsMdPath = join6(agentsDir, "AGENTS.md");
4860
+ if (existsSync5(agentsMdPath) || force) {
4861
+ const content = renderSeedAgentsMd(profile, context, timestamp);
4862
+ writeFileSync4(agentsMdPath, content, "utf-8");
4863
+ filesUpdated.push(".trellis/agents/AGENTS.md");
4864
+ }
4865
+ const agentContextPath = join6(agentsDir, "agent-context.json");
4866
+ if (existsSync5(agentContextPath) || force) {
4867
+ const config = {
4868
+ domain: context.domain,
4869
+ ecosystem: context.ecosystem,
4870
+ tools: [],
4871
+ ontologies: [],
4872
+ generatedAt: timestamp,
4873
+ confidence: context.confidence,
4874
+ lastSeed: timestamp
4875
+ };
4876
+ writeFileSync4(agentContextPath, JSON.stringify(config, null, 2), "utf-8");
4877
+ filesUpdated.push(".trellis/agents/agent-context.json");
4878
+ }
4879
+ }
4880
+ switch (ide) {
4881
+ case "cursor": {
4882
+ const cursorRulesPath = join6(rootPath, ".cursor", "rules.md");
4883
+ if (existsSync5(cursorRulesPath) || force) {
4884
+ const content = renderSeedIdeRules(profile, context, "cursor", timestamp);
4885
+ writeFileSync4(cursorRulesPath, content, "utf-8");
4886
+ filesUpdated.push(".cursor/rules.md");
4887
+ }
4888
+ break;
4889
+ }
4890
+ case "windsurf": {
4891
+ const windsurfRulesPath = join6(rootPath, ".windsurf", "rules.md");
4892
+ if (existsSync5(windsurfRulesPath) || force) {
4893
+ const content = renderSeedIdeRules(profile, context, "windsurf", timestamp);
4894
+ writeFileSync4(windsurfRulesPath, content, "utf-8");
4895
+ filesUpdated.push(".windsurf/rules.md");
4896
+ }
4897
+ break;
4898
+ }
4899
+ case "claude": {
4900
+ const claudeSettingsPath = join6(rootPath, ".claude", "settings.md");
4901
+ if (existsSync5(claudeSettingsPath) || force) {
4902
+ const content = renderSeedIdeRules(profile, context, "claude", timestamp);
4903
+ writeFileSync4(claudeSettingsPath, content, "utf-8");
4904
+ filesUpdated.push(".claude/settings.md");
4905
+ }
4906
+ break;
4907
+ }
4908
+ case "none":
4909
+ break;
4910
+ }
4911
+ return {
4912
+ success: true,
4913
+ filesUpdated,
4914
+ timestamp
4915
+ };
4916
+ }
4917
+ function renderSeedAgentsMd(profile, context, timestamp) {
4918
+ const userName = profile?.name ?? "the user";
4919
+ const userBio = profile?.bio ?? "(not provided)";
4920
+ const userSkills = profile?.skills?.length ? profile.skills.join(", ") : "(not specified)";
4921
+ return `# Trellis Agent Context
4922
+
4923
+ > This file was seeded by \`trellis seed\` on ${timestamp}
4924
+ > Inference confidence: **${context.confidence}**
4925
+
4926
+ ---
4927
+
4928
+ ## About the User
4929
+
4930
+ | Field | Value |
4931
+ |-------|-------|
4932
+ | **Name** | ${userName} |
4933
+ | **Bio** | ${userBio} |
4934
+ | **Skills** | ${userSkills} |
4935
+
4936
+ ---
4937
+
4938
+ ## About This Project
4939
+
4940
+ | Field | Value |
4941
+ |-------|-------|
4942
+ | **Name** | ${context.name ?? "(unnamed)"} |
4943
+ | **Domain** | ${context.domain ?? "(not determined)"} |
4944
+ | **Description** | ${context.description ?? "(no description found)"} |
4945
+ | **Ecosystem** | ${context.ecosystem ?? "unknown"} |
4946
+ | **File count** | ~${context.fileCount} |
4947
+
4948
+ ---
4949
+
4950
+ ## Agent Instructions
4951
+
4952
+ You are operating in a Trellis-tracked repository. Follow these guidelines:
4953
+
4954
+ 1. **Read \`agent-context.json\`** in this directory for registered tools, ontologies, and domain settings.
4955
+ 2. **Check \`skills/\`** for domain-specific operating instructions relevant to this project.
4956
+ 3. **Check \`workflows/\`** for repeatable task procedures.
4957
+ 4. **Run \`trellis seed\`** to refresh this context file when the project evolves.
4958
+
4959
+ ---
4960
+
4961
+ ## Quick Reference
4962
+
4963
+ \`\`\`bash
4964
+ trellis status # Current repo state
4965
+ trellis log # Causal operation history
4966
+ trellis seed # Refresh this context
4967
+ trellis milestone # Create narrative checkpoints
4968
+ \`\`\`
4969
+ `;
4970
+ }
4971
+ function renderSeedIdeRules(profile, context, ide, timestamp) {
4972
+ const ideName = ide.charAt(0).toUpperCase() + ide.slice(1);
4973
+ const projectName = context.name ?? "this project";
4974
+ return `# ${ideName} Rules for ${projectName}
4975
+
4976
+ > Generated by \`trellis seed\` on ${timestamp}
4977
+
4978
+ ## Project Context
4979
+ - **Domain**: ${context.domain ?? "(not determined)"}
4980
+ - **Ecosystem**: ${context.ecosystem ?? "unknown"}
4981
+ - **File count**: ~${context.fileCount}
4982
+ - **Confidence**: ${context.confidence}
4983
+
4984
+ ## Agent Instructions
4985
+ You are working in a Trellis-tracked repository. See \`.trellis/agents/AGENTS.md\` for full context.
4986
+
4987
+ ## Commands
4988
+ - \`trellis status\` \u2014 Check repo state
4989
+ - \`trellis seed\` \u2014 Refresh this context file
4990
+ - \`trellis log\` \u2014 View causal history
4991
+
4992
+ ---
4993
+ *Auto-generated by Trellis. Run \`trellis seed\` to refresh context.*
4994
+ `;
4995
+ }
4996
+
4997
+ // src/scaffold/index.ts
4998
+ init_infer();
4999
+ init_profile();
5000
+ init_write();
5001
+
5002
+ export { FileWatcher, init_fs_watcher, Ingestion, init_ingestion, inferProjectContext, loadProfile, saveProfile, hasProfile, promptForProfile, updateProfile, writeAgentScaffold, writeIdeScaffold, TrellisVcsEngine, init_engine, seedContext };