trellis 3.1.26 → 3.1.30

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/README.md CHANGED
@@ -33,6 +33,10 @@ npm install -g trellis
33
33
  mkdir my-project && cd my-project
34
34
  trellis init
35
35
 
36
+ # The init command now offers two paths:
37
+ # ⚡ Minimal Setup: One-shot setup with auto-detected defaults
38
+ # 🔧 Custom Guided Setup: Full control over framework, IDEs, and features
39
+
36
40
  # 3. Create content (tracked automatically)
37
41
  echo "# My Project" > README.md
38
42
 
@@ -40,10 +44,30 @@ echo "# My Project" > README.md
40
44
  trellis issue create -t "Bootstrap Visualization"
41
45
  trellis milestone create -m "Initial Release"
42
46
 
43
- # 5. Create coding session with trellis harness
47
+ # 5. Launch the local web client to explore your semantic graph
48
+ trellis web
49
+
50
+ # 6. Create coding session with trellis harness
44
51
  trellis code
45
52
  ```
46
53
 
54
+ After running `trellis init`, you'll see a progressive disclosure success screen:
55
+
56
+ **Next steps (VCS):**
57
+
58
+ - `trellis status` — Check repository status
59
+ - `trellis log` — View recent history
60
+ - `trellis branch` — List or create branches
61
+ - `trellis milestone` — Create narrative checkpoints
62
+ - `trellis garden` — Discover abandoned work
63
+ - `trellis issue` — Create and track issues
64
+
65
+ **Semantic Substrate (Live local services):**
66
+
67
+ - `trellis web` — Launch local web client / graph visualizer
68
+ - `trellis query` — Run EQL-S semantic queries against your code graph
69
+ - Agent Rules — Active for your IDE. Agents will auto-detect the graph.
70
+
47
71
  ![Trellis Demo](./trellis-opencode.gif)
48
72
 
49
73
  See the [CLI guide](https://trellis.computer/docs/cli) for complete documentation.
package/dist/cli/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
+ import {
4
+ seedContext
5
+ } from "../index-4gknc19b.js";
3
6
  import {
4
7
  TrellisVcsEngine,
5
8
  hasProfile,
@@ -8,11 +11,10 @@ import {
8
11
  loadProfile,
9
12
  promptForProfile,
10
13
  saveProfile,
11
- seedContext,
12
14
  updateProfile,
13
15
  writeAgentScaffold,
14
16
  writeIdeScaffold
15
- } from "../index-3qrxzwe4.js";
17
+ } from "../index-ncckgtrk.js";
16
18
  import {
17
19
  OntologyRegistry,
18
20
  builtinOntologies,
@@ -5707,7 +5709,7 @@ function base58btcEncode(buf) {
5707
5709
  return encoded || "1";
5708
5710
  }
5709
5711
  // src/cli/repo-path.ts
5710
- import { readFileSync as readFileSync3 } from "fs";
5712
+ import { readFileSync as readFileSync3, realpathSync } from "fs";
5711
5713
  import { dirname as dirname4, resolve } from "path";
5712
5714
  import { fileURLToPath } from "url";
5713
5715
  init_engine();
@@ -5721,12 +5723,19 @@ function cliVersion() {
5721
5723
  } catch {}
5722
5724
  return "0.0.0";
5723
5725
  }
5726
+ function canonicalRoot(dir) {
5727
+ try {
5728
+ return realpathSync(dir);
5729
+ } catch {
5730
+ return dir;
5731
+ }
5732
+ }
5724
5733
  function findRepoRoot(pathOpt) {
5725
5734
  const start = resolve(pathOpt ?? process.cwd());
5726
5735
  let dir = start;
5727
5736
  while (true) {
5728
5737
  if (TrellisVcsEngine.isRepo(dir))
5729
- return dir;
5738
+ return canonicalRoot(dir);
5730
5739
  const parent = dirname4(dir);
5731
5740
  if (parent === dir)
5732
5741
  return;
@@ -5757,7 +5766,11 @@ program2.name("trellis").description("TrellisVCS \u2014 graph-native, code-first
5757
5766
  async function runInit(rootPath, opts = {}) {
5758
5767
  const isInteractive = opts.interactive !== false && process.stdout.isTTY && !process.argv.includes("--no-interactive");
5759
5768
  if (TrellisVcsEngine.isRepo(rootPath)) {
5760
- return;
5769
+ return {
5770
+ selectedIdes: opts.ides || [],
5771
+ footprint: opts.footprint || "standard",
5772
+ framework: opts.framework || "none"
5773
+ };
5761
5774
  }
5762
5775
  if (!hasProfile()) {
5763
5776
  const identity = hasIdentity(rootPath) ? loadIdentity(join6(rootPath, ".trellis")) : null;
@@ -5962,6 +5975,7 @@ async function runInit(rootPath, opts = {}) {
5962
5975
  });
5963
5976
  }
5964
5977
  }
5978
+ return { selectedIdes, footprint, framework };
5965
5979
  }
5966
5980
  program2.command("init").description("Initialize a new TrellisVCS repository in the current directory").option("-p, --path <path>", "Path to initialize", ".").option("--ides <ides...>", "IDEs to scaffold for (cursor, windsurf, claude, copilot, codex, gemini)").option("--framework <framework>", "Project framework (react, vue, svelte, next, nuxt, remotion, expo, bun, node, cli, library, animation, games, none)", "none").option("--footprint <footprint>", "Workspace footprint (minimal, standard, full)", "standard").option("--no-interactive", "Skip interactive prompts").action(async (opts) => {
5967
5981
  const rootPath = resolve2(opts.path);
@@ -5969,7 +5983,7 @@ program2.command("init").description("Initialize a new TrellisVCS repository in
5969
5983
  console.log(source_default.yellow("Already a Trellis workspace."));
5970
5984
  return;
5971
5985
  }
5972
- await runInit(rootPath, {
5986
+ const configResult = await runInit(rootPath, {
5973
5987
  interactive: process.stdout.isTTY && !process.argv.includes("--no-interactive"),
5974
5988
  ides: opts.ides,
5975
5989
  framework: opts.framework,
@@ -5991,7 +6005,7 @@ program2.command("init").description("Initialize a new TrellisVCS repository in
5991
6005
  console.log(` ${source_default.dim("Ecosystem:")} ${preInfer.ecosystem}`);
5992
6006
  }
5993
6007
  console.log();
5994
- console.log(source_default.bold("Next steps:"));
6008
+ console.log(source_default.bold("Next steps (VCS):"));
5995
6009
  console.log();
5996
6010
  console.log(` ${source_default.cyan("trellis status")} Check repository status`);
5997
6011
  console.log(` ${source_default.cyan("trellis log")} View recent history`);
@@ -6003,6 +6017,14 @@ program2.command("init").description("Initialize a new TrellisVCS repository in
6003
6017
  console.log(` ${source_default.cyan("trellis season")} Enrich project context for agents`);
6004
6018
  }
6005
6019
  console.log();
6020
+ console.log(source_default.bold("Semantic Substrate (Live local services):"));
6021
+ console.log();
6022
+ console.log(` ${source_default.cyan("trellis web")} Launch local web client / graph visualizer`);
6023
+ console.log(` ${source_default.cyan("trellis query")} Run EQL-S semantic queries against your code graph`);
6024
+ if (configResult.selectedIdes.length > 0) {
6025
+ console.log(` ${source_default.cyan("Agent Rules")} Active for ${source_default.bold(configResult.selectedIdes.join(", "))}. Agents will auto-detect the graph.`);
6026
+ }
6027
+ console.log();
6006
6028
  console.log(source_default.dim("The causal stream is now active. Every file change will be tracked."));
6007
6029
  });
6008
6030
  program2.command("seed").description("Refresh agent context files with current project state").option("-p, --path <path>", "Repository path", ".").option("--ide <ide>", "IDE to update (cursor, windsurf, claude, copilot)", "none").option("-f, --force", "Force rewrite even if files do not exist", false).action(async (opts) => {
@@ -6064,27 +6086,58 @@ program2.command("status").description("Show current repository status").option(
6064
6086
  }
6065
6087
  }
6066
6088
  });
6067
- program2.command("log").description("Show operation history").option("-p, --path <path>", "Repository path", ".").option("-n, --limit <n>", "Number of ops to show", "20").option("-f, --file <file>", "Filter by file path").action(async (opts) => {
6089
+ program2.command("log").description("Show operation history").option("-p, --path <path>", "Repository path", ".").option("-n, --limit <n>", "Number of ops to show", "20").option("-f, --file <file>", "Filter by file path").option("--remote <remote>", "Filter by remote workspace").option("--all", "Include operations from all remotes").action(async (opts) => {
6068
6090
  const rootPath = resolveRepoRoot(opts.path);
6069
6091
  const engine = new TrellisVcsEngine({ rootPath });
6070
6092
  engine.open();
6071
- const ops = engine.log({
6093
+ let ops = engine.log({
6072
6094
  limit: parseInt(opts.limit, 10),
6073
6095
  filePath: opts.file
6074
6096
  });
6097
+ if (opts.remote || opts.all) {
6098
+ const { RemoteManager } = await import("../remote-manager-n71bmcy1.js");
6099
+ const remoteManager = new RemoteManager(join6(rootPath, ".trellis"));
6100
+ if (opts.all) {
6101
+ const remotes = remoteManager.listRemotes();
6102
+ const remoteOps = ops.filter((op) => op.facts?.some((fact) => fact.e === "op" && fact.a === "remote" && remotes.some((remote) => fact.v === remote.name)));
6103
+ if (opts.remote) {
6104
+ ops = remoteOps.filter((op) => op.facts?.some((fact) => fact.e === "op" && fact.a === "remote" && fact.v === opts.remote));
6105
+ } else {
6106
+ ops = remoteOps;
6107
+ }
6108
+ } else if (opts.remote) {
6109
+ ops = ops.filter((op) => op.facts?.some((fact) => fact.e === "op" && fact.a === "remote" && fact.v === opts.remote));
6110
+ }
6111
+ }
6075
6112
  if (ops.length === 0) {
6076
6113
  console.log(source_default.dim("No operations found."));
6077
6114
  return;
6078
6115
  }
6116
+ const groupedOps = opts.all || opts.remote ? ops.reduce((groups, op) => {
6117
+ const remoteFact = op.facts?.find((fact) => fact.e === "op" && fact.a === "remote");
6118
+ const remote = remoteFact ? remoteFact.v : "local";
6119
+ if (!groups[remote])
6120
+ groups[remote] = [];
6121
+ groups[remote].push(op);
6122
+ return groups;
6123
+ }, {}) : { local: ops };
6079
6124
  console.log(source_default.bold(`Causal Stream \u2014 ${ops.length} ops`));
6080
6125
  console.log();
6081
- for (const op of ops.reverse()) {
6082
- const kind = formatOpKind(op.kind);
6083
- const hash = source_default.dim(op.hash.slice(0, 28) + "\u2026");
6084
- const time = formatRelativeTime(op.timestamp);
6085
- const file = op.vcs?.filePath ? source_default.white(op.vcs.filePath) : "";
6086
- const rename = op.vcs?.oldFilePath ? source_default.dim(` (from ${op.vcs.oldFilePath})`) : "";
6087
- console.log(` ${hash} ${kind} ${file}${rename} ${source_default.dim(time)}`);
6126
+ for (const [remote, remoteOps] of Object.entries(groupedOps)) {
6127
+ if (opts.all || opts.remote) {
6128
+ console.log(source_default.cyan(`${remote === "local" ? "Local" : remote}:`));
6129
+ }
6130
+ for (const op of remoteOps.reverse()) {
6131
+ const kind = formatOpKind(op.kind);
6132
+ const hash = source_default.dim(op.hash.slice(0, 28) + "\u2026");
6133
+ const time = formatRelativeTime(op.timestamp);
6134
+ const file = op.vcs?.filePath ? source_default.white(op.vcs.filePath) : "";
6135
+ const rename = op.vcs?.oldFilePath ? source_default.dim(` (from ${op.vcs.oldFilePath})`) : "";
6136
+ console.log(` ${hash} ${kind} ${file}${rename} ${source_default.dim(time)}`);
6137
+ }
6138
+ if (opts.all || opts.remote) {
6139
+ console.log();
6140
+ }
6088
6141
  }
6089
6142
  });
6090
6143
  program2.command("files").description("List all tracked files").option("-p, --path <path>", "Repository path", ".").action(async (opts) => {
@@ -6715,29 +6768,59 @@ issueCmd.command("create").description("Create a new issue").requiredOption("-t,
6715
6768
  console.log(` ${source_default.dim("Criteria:")} ${criteria.length} acceptance criteria`);
6716
6769
  }
6717
6770
  });
6718
- issueCmd.command("list").description("List issues").option("--status <status>", "Filter by status: backlog, queue, in_progress, paused, closed").option("--label <label>", "Filter by label").option("--assignee <agentId>", "Filter by assignee").option("--parent <id>", "Filter by parent issue").option("-p, --path <path>", "Repository path", ".").action((opts) => {
6771
+ issueCmd.command("list").description("List issues").option("--status <status>", "Filter by status: backlog, queue, in_progress, paused, closed").option("--label <label>", "Filter by label").option("--assignee <agentId>", "Filter by assignee").option("--parent <id>", "Filter by parent issue").option("--remote <remote>", "Filter by remote workspace").option("--all", "Include issues from all remotes").option("-p, --path <path>", "Repository path", ".").action(async (opts) => {
6719
6772
  const rootPath = resolveRepoRoot(opts.path);
6720
6773
  const engine = new TrellisVcsEngine({ rootPath });
6721
6774
  engine.open();
6722
- const issues = engine.listIssues({
6775
+ let issues = engine.listIssues({
6723
6776
  status: opts.status,
6724
6777
  label: opts.label,
6725
6778
  assignee: opts.assignee,
6726
6779
  parentId: opts.parent
6727
6780
  });
6781
+ if (opts.remote || opts.all) {
6782
+ const { RemoteManager } = await import("../remote-manager-n71bmcy1.js");
6783
+ const remoteManager = new RemoteManager(join6(rootPath, ".trellis"));
6784
+ if (opts.all) {
6785
+ const remotes = remoteManager.listRemotes();
6786
+ const remoteIssues = issues.filter((issue) => remotes.some((remote) => issue.id.startsWith(`${remote.name}:`)));
6787
+ if (opts.remote) {
6788
+ issues = remoteIssues.filter((issue) => issue.id.startsWith(`${opts.remote}:`));
6789
+ } else {
6790
+ issues = remoteIssues;
6791
+ }
6792
+ } else if (opts.remote) {
6793
+ issues = issues.filter((issue) => issue.id.startsWith(`${opts.remote}:`));
6794
+ }
6795
+ }
6728
6796
  if (issues.length === 0) {
6729
6797
  console.log(source_default.dim("No issues found."));
6730
6798
  return;
6731
6799
  }
6800
+ const groupedIssues = opts.all || opts.remote ? issues.reduce((groups, issue) => {
6801
+ const colonIndex = issue.id.indexOf(":");
6802
+ const remote = colonIndex > 0 ? issue.id.substring(0, colonIndex) : "local";
6803
+ if (!groups[remote])
6804
+ groups[remote] = [];
6805
+ groups[remote].push(issue);
6806
+ return groups;
6807
+ }, {}) : { local: issues };
6732
6808
  console.log(source_default.bold(`Issues (${issues.length})
6733
6809
  `));
6734
- for (const issue of issues) {
6735
- const labels = issue.labels.length > 0 ? source_default.dim(` [${issue.labels.join(",")}]`) : "";
6736
- const assignee = issue.assignee ? source_default.dim(` \u2192 ${issue.assignee}`) : "";
6737
- const parent = issue.parentId ? source_default.dim(` \u2190 ${issue.parentId}`) : "";
6738
- const blocked = issue.isBlocked ? source_default.yellow(" \uD83D\uDD12 blocked") : "";
6739
- const criteria = issue.criteria.length > 0 ? source_default.dim(` (${issue.criteria.filter((c) => c.status === "passed").length}/${issue.criteria.length} AC)`) : "";
6740
- console.log(` ${formatPriority(issue.priority)} ${source_default.bold(issue.id)} ${formatIssueStatus(issue.status)} ${issue.title ?? ""}${labels}${assignee}${parent}${blocked}${criteria}`);
6810
+ for (const [remote, remoteIssues] of Object.entries(groupedIssues)) {
6811
+ if (opts.all || opts.remote) {
6812
+ console.log(source_default.cyan(`
6813
+ ${remote === "local" ? "Local" : remote}:`));
6814
+ }
6815
+ for (const issue of remoteIssues) {
6816
+ const labels = issue.labels.length > 0 ? source_default.dim(` [${issue.labels.join(",")}]`) : "";
6817
+ const assignee = issue.assignee ? source_default.dim(` \u2192 ${issue.assignee}`) : "";
6818
+ const parent = issue.parentId ? source_default.dim(` \u2190 ${issue.parentId}`) : "";
6819
+ const blocked = issue.isBlocked ? source_default.yellow(" \uD83D\uDD12 blocked") : "";
6820
+ const criteria = issue.criteria.length > 0 ? source_default.dim(` (${issue.criteria.filter((c) => c.status === "passed").length}/${issue.criteria.length} AC)`) : "";
6821
+ const displayId = opts.all || opts.remote ? issue.id : issue.id;
6822
+ console.log(` ${formatPriority(issue.priority)} ${source_default.bold(displayId)} ${formatIssueStatus(issue.status)} ${issue.title ?? ""}${labels}${assignee}${parent}${blocked}${criteria}`);
6823
+ }
6741
6824
  }
6742
6825
  });
6743
6826
  issueCmd.command("show").description("Show issue details").argument("<id>", "Issue ID (e.g. TRL-1)").option("-p, --path <path>", "Repository path", ".").action((id, opts) => {
@@ -8851,6 +8934,91 @@ cmsCmd.command("register-library <pkg>").description("Register a Svelte 5 compon
8851
8934
  process.exit(1);
8852
8935
  }
8853
8936
  });
8937
+ program2.command("remote").description("Manage remote workspace subscriptions").argument("[action]", '"add", "remove", or "list" (default: list)').argument("[name]", "Remote name (for add/remove)").argument("[path]", "Remote path (for add)").option("-p, --path <path>", "Repository path", ".").action(async (action, name, path, opts) => {
8938
+ const rootPath = resolveRepoRoot(opts.path);
8939
+ const { RemoteManager } = await import("../remote-manager-n71bmcy1.js");
8940
+ const remoteManager = new RemoteManager(join6(rootPath, ".trellis"));
8941
+ try {
8942
+ if (!action || action === "list") {
8943
+ const remotes = remoteManager.listRemotes();
8944
+ if (remotes.length === 0) {
8945
+ console.log(source_default.dim("No remotes configured."));
8946
+ return;
8947
+ }
8948
+ console.log(source_default.bold(`Remotes (${remotes.length})
8949
+ `));
8950
+ for (const remote of remotes) {
8951
+ const lastPulled = remote.pulledAt ? source_default.dim(` (pulled ${new Date(remote.pulledAt).toLocaleDateString()})`) : source_default.dim(" (never pulled)");
8952
+ console.log(` ${source_default.cyan(remote.name)}: ${remote.path}${lastPulled}`);
8953
+ }
8954
+ return;
8955
+ }
8956
+ if (action === "add") {
8957
+ if (!name) {
8958
+ console.error(source_default.red("Error: Remote name required for add"));
8959
+ process.exit(1);
8960
+ }
8961
+ if (!path) {
8962
+ console.error(source_default.red("Error: Remote path required for add"));
8963
+ process.exit(1);
8964
+ }
8965
+ remoteManager.addRemote(name, path);
8966
+ console.log(source_default.green(`\u2713 Added remote '${name}' -> ${path}`));
8967
+ return;
8968
+ }
8969
+ if (action === "remove") {
8970
+ if (!name) {
8971
+ console.error(source_default.red("Error: Remote name required for remove"));
8972
+ process.exit(1);
8973
+ }
8974
+ remoteManager.removeRemote(name);
8975
+ console.log(source_default.green(`\u2713 Removed remote '${name}'`));
8976
+ return;
8977
+ }
8978
+ console.error(source_default.red(`Unknown action: ${action}`));
8979
+ process.exit(1);
8980
+ } catch (error) {
8981
+ console.error(source_default.red(`Error: ${error}`));
8982
+ process.exit(1);
8983
+ }
8984
+ });
8985
+ program2.command("pull").description("Pull operations from remote workspaces").option("-p, --path <path>", "Repository path", ".").option("--remote <remote>", "Pull from specific remote only").action(async (opts) => {
8986
+ const rootPath = resolveRepoRoot(opts.path);
8987
+ const { RemoteManager } = await import("../remote-manager-n71bmcy1.js");
8988
+ const remoteManager = new RemoteManager(join6(rootPath, ".trellis"));
8989
+ const engine = new TrellisVcsEngine({ rootPath });
8990
+ engine.open();
8991
+ try {
8992
+ if (opts.remote) {
8993
+ const result = await remoteManager.pullRemote(opts.remote, engine);
8994
+ console.log(source_default.bold(`Pull from ${opts.remote}
8995
+ `));
8996
+ console.log(` ${source_default.dim("New ops:")} ${result.newOps}`);
8997
+ if (result.errors.length > 0) {
8998
+ console.log(` ${source_default.dim("Errors:")} ${result.errors.join(", ")}`);
8999
+ }
9000
+ console.log(` ${source_default.dim("Duration:")} ${result.durationMs}ms`);
9001
+ } else {
9002
+ const result = await remoteManager.pullAll(engine);
9003
+ console.log(source_default.bold(`Pull from all remotes
9004
+ `));
9005
+ console.log(` ${source_default.dim("Total new ops:")} ${result.totalNewOps}`);
9006
+ console.log(` ${source_default.dim("Duration:")} ${result.totalDurationMs}ms`);
9007
+ for (const remoteResult of result.results) {
9008
+ const status = remoteResult.errors.length > 0 ? source_default.red("\u2717") : source_default.green("\u2713");
9009
+ console.log(` ${status} ${remoteResult.remote}: ${remoteResult.newOps} new ops`);
9010
+ if (remoteResult.errors.length > 0) {
9011
+ for (const error of remoteResult.errors) {
9012
+ console.log(` ${source_default.dim(error)}`);
9013
+ }
9014
+ }
9015
+ }
9016
+ }
9017
+ } catch (error) {
9018
+ console.error(source_default.red(`Pull failed: ${error}`));
9019
+ process.exit(1);
9020
+ }
9021
+ });
8854
9022
  program2.command("skills").description("Install Trellis agent skills using the skills CLI (npx skills)").argument("[args...]", "Additional arguments to pass to the skills CLI").allowUnknownOption().action(async () => {
8855
9023
  const skillsIndex = process.argv.indexOf("skills");
8856
9024
  const extraArgs = skillsIndex !== -1 ? process.argv.slice(skillsIndex + 1) : [];
@@ -1 +1 @@
1
- {"version":3,"file":"repo-path.d.ts","sourceRoot":"","sources":["../../src/cli/repo-path.ts"],"names":[],"mappings":"AAQA,kEAAkE;AAClE,wBAAgB,UAAU,IAAI,MAAM,CASnC;AAED,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASjE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAalE"}
1
+ {"version":3,"file":"repo-path.d.ts","sourceRoot":"","sources":["../../src/cli/repo-path.ts"],"names":[],"mappings":"AAQA,kEAAkE;AAClE,wBAAgB,UAAU,IAAI,MAAM,CASnC;AAUD,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASjE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAalE"}
package/dist/db/index.js CHANGED
@@ -1,5 +1,9 @@
1
1
  // @bun
2
2
  import"../index-c9h37r6h.js";
3
+ import {
4
+ importFile,
5
+ importRecords
6
+ } from "../index-skhn0agf.js";
3
7
  import {
4
8
  deploy
5
9
  } from "../index-wt8rz4gn.js";
@@ -23,10 +27,6 @@ import {
23
27
  startServer,
24
28
  verifyJwt
25
29
  } from "../index-53f3b8p8.js";
26
- import {
27
- importFile,
28
- importRecords
29
- } from "../index-skhn0agf.js";
30
30
  import"../index-n9f2qyh5.js";
31
31
  import"../index-k5b0xskw.js";
32
32
  import {
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Trellis Federation — Remote Manager
3
+ *
4
+ * Handles remote workspace configuration and pull operations.
5
+ * Implements read-only mirroring with watermark-based incremental sync.
6
+ */
7
+ import { TrellisVcsEngine } from '../engine.js';
8
+ import type { RemoteConfig, RemotesConfig, PullResult, PullAllResult } from './types.js';
9
+ export declare class RemoteManager {
10
+ private trellisPath;
11
+ private remotesPath;
12
+ constructor(trellisPath: string);
13
+ /** Load remotes configuration */
14
+ loadRemotes(): RemotesConfig;
15
+ /** Save remotes configuration */
16
+ saveRemotes(config: RemotesConfig): void;
17
+ /** Add a new remote */
18
+ addRemote(name: string, path: string): void;
19
+ /** Remove a remote */
20
+ removeRemote(name: string): void;
21
+ /** List all remotes */
22
+ listRemotes(): RemoteConfig[];
23
+ /** Pull new ops from a specific remote */
24
+ pullRemote(remoteName: string, localEngine: TrellisVcsEngine): Promise<PullResult>;
25
+ /** Pull from all configured remotes */
26
+ pullAll(localEngine: TrellisVcsEngine): Promise<PullAllResult>;
27
+ /** Prefix entity IDs in operations with remote name */
28
+ private prefixOpEntities;
29
+ }
30
+ //# sourceMappingURL=remote-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-manager.d.ts","sourceRoot":"","sources":["../../src/federation/remote-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,qBAAa,aAAa;IACxB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,EAAE,MAAM;IAK/B,iCAAiC;IACjC,WAAW,IAAI,aAAa;IAY5B,iCAAiC;IACjC,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAYxC,uBAAuB;IACvB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAsB3C,sBAAsB;IACtB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAWhC,uBAAuB;IACvB,WAAW,IAAI,YAAY,EAAE;IAK7B,0CAA0C;IACpC,UAAU,CACd,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,gBAAgB,GAC5B,OAAO,CAAC,UAAU,CAAC;IAgFtB,uCAAuC;IACjC,OAAO,CAAC,WAAW,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,CAAC;IAuCpE,uDAAuD;IACvD,OAAO,CAAC,gBAAgB;CAgFzB"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Trellis Federation — Type Definitions
3
+ *
4
+ * Simple remote pull model for federated graphs across workspaces.
5
+ * Read-only mirroring with watermark-based incremental sync.
6
+ */
7
+ export interface RemoteConfig {
8
+ /** Remote workspace name */
9
+ name: string;
10
+ /** Path to remote .trellis directory */
11
+ path: string;
12
+ /** Last pulled op ID (watermark for incremental sync) */
13
+ lastOpId?: string;
14
+ /** Timestamp of last pull */
15
+ pulledAt?: string;
16
+ }
17
+ export interface RemotesConfig {
18
+ /** All configured remotes */
19
+ remotes: Record<string, RemoteConfig>;
20
+ }
21
+ export interface PullResult {
22
+ /** Remote name */
23
+ remote: string;
24
+ /** Number of new ops pulled */
25
+ newOps: number;
26
+ /** Latest op ID after pull */
27
+ latestOpId: string;
28
+ /** Pull duration in milliseconds */
29
+ durationMs: number;
30
+ /** Errors encountered */
31
+ errors: string[];
32
+ }
33
+ export interface PullAllResult {
34
+ /** Results per remote */
35
+ results: PullResult[];
36
+ /** Total new ops across all remotes */
37
+ totalNewOps: number;
38
+ /** Total duration */
39
+ totalDurationMs: number;
40
+ }
41
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/federation/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,UAAU;IACzB,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,eAAe,EAAE,MAAM,CAAC;CACzB"}
@@ -0,0 +1,166 @@
1
+ // @bun
2
+ import {
3
+ inferProjectContext,
4
+ init_infer,
5
+ init_profile,
6
+ init_write,
7
+ loadProfile
8
+ } from "./index-ncckgtrk.js";
9
+
10
+ // src/scaffold/seed.ts
11
+ init_profile();
12
+ init_infer();
13
+ import { existsSync, writeFileSync } from "fs";
14
+ import { join } from "path";
15
+ async function seedContext(opts) {
16
+ const { rootPath, ide = "none", force = false } = opts;
17
+ const filesUpdated = [];
18
+ const timestamp = new Date().toISOString();
19
+ const profile = loadProfile();
20
+ const context = await inferProjectContext(rootPath);
21
+ const agentsDir = join(rootPath, ".trellis", "agents");
22
+ if (existsSync(agentsDir)) {
23
+ const agentsMdPath = join(agentsDir, "AGENTS.md");
24
+ if (existsSync(agentsMdPath) || force) {
25
+ const content = renderSeedAgentsMd(profile, context, timestamp);
26
+ writeFileSync(agentsMdPath, content, "utf-8");
27
+ filesUpdated.push(".trellis/agents/AGENTS.md");
28
+ }
29
+ const agentContextPath = join(agentsDir, "agent-context.json");
30
+ if (existsSync(agentContextPath) || force) {
31
+ const config = {
32
+ domain: context.domain,
33
+ ecosystem: context.ecosystem,
34
+ tools: [],
35
+ ontologies: [],
36
+ generatedAt: timestamp,
37
+ confidence: context.confidence,
38
+ lastSeed: timestamp
39
+ };
40
+ writeFileSync(agentContextPath, JSON.stringify(config, null, 2), "utf-8");
41
+ filesUpdated.push(".trellis/agents/agent-context.json");
42
+ }
43
+ }
44
+ switch (ide) {
45
+ case "cursor": {
46
+ const cursorRulesPath = join(rootPath, ".cursor", "rules.md");
47
+ if (existsSync(cursorRulesPath) || force) {
48
+ const content = renderSeedIdeRules(profile, context, "cursor", timestamp);
49
+ writeFileSync(cursorRulesPath, content, "utf-8");
50
+ filesUpdated.push(".cursor/rules.md");
51
+ }
52
+ break;
53
+ }
54
+ case "windsurf": {
55
+ const windsurfRulesPath = join(rootPath, ".windsurf", "rules.md");
56
+ if (existsSync(windsurfRulesPath) || force) {
57
+ const content = renderSeedIdeRules(profile, context, "windsurf", timestamp);
58
+ writeFileSync(windsurfRulesPath, content, "utf-8");
59
+ filesUpdated.push(".windsurf/rules.md");
60
+ }
61
+ break;
62
+ }
63
+ case "claude": {
64
+ const claudeSettingsPath = join(rootPath, ".claude", "settings.md");
65
+ if (existsSync(claudeSettingsPath) || force) {
66
+ const content = renderSeedIdeRules(profile, context, "claude", timestamp);
67
+ writeFileSync(claudeSettingsPath, content, "utf-8");
68
+ filesUpdated.push(".claude/settings.md");
69
+ }
70
+ break;
71
+ }
72
+ case "none":
73
+ break;
74
+ }
75
+ return {
76
+ success: true,
77
+ filesUpdated,
78
+ timestamp
79
+ };
80
+ }
81
+ function renderSeedAgentsMd(profile, context, timestamp) {
82
+ const userName = profile?.name ?? "the user";
83
+ const userBio = profile?.bio ?? "(not provided)";
84
+ const userSkills = profile?.skills?.length ? profile.skills.join(", ") : "(not specified)";
85
+ return `# Trellis Agent Context
86
+
87
+ > This file was seeded by \`trellis seed\` on ${timestamp}
88
+ > Inference confidence: **${context.confidence}**
89
+
90
+ ---
91
+
92
+ ## About the User
93
+
94
+ | Field | Value |
95
+ |-------|-------|
96
+ | **Name** | ${userName} |
97
+ | **Bio** | ${userBio} |
98
+ | **Skills** | ${userSkills} |
99
+
100
+ ---
101
+
102
+ ## About This Project
103
+
104
+ | Field | Value |
105
+ |-------|-------|
106
+ | **Name** | ${context.name ?? "(unnamed)"} |
107
+ | **Domain** | ${context.domain ?? "(not determined)"} |
108
+ | **Description** | ${context.description ?? "(no description found)"} |
109
+ | **Ecosystem** | ${context.ecosystem ?? "unknown"} |
110
+ | **File count** | ~${context.fileCount} |
111
+
112
+ ---
113
+
114
+ ## Agent Instructions
115
+
116
+ You are operating in a Trellis-tracked repository. Follow these guidelines:
117
+
118
+ 1. **Read \`agent-context.json\`** in this directory for registered tools, ontologies, and domain settings.
119
+ 2. **Check \`skills/\`** for domain-specific operating instructions relevant to this project.
120
+ 3. **Check \`workflows/\`** for repeatable task procedures.
121
+ 4. **Run \`trellis seed\`** to refresh this context file when the project evolves.
122
+
123
+ ---
124
+
125
+ ## Quick Reference
126
+
127
+ \`\`\`bash
128
+ trellis status # Current repo state
129
+ trellis log # Causal operation history
130
+ trellis seed # Refresh this context
131
+ trellis milestone # Create narrative checkpoints
132
+ \`\`\`
133
+ `;
134
+ }
135
+ function renderSeedIdeRules(profile, context, ide, timestamp) {
136
+ const ideName = ide.charAt(0).toUpperCase() + ide.slice(1);
137
+ const projectName = context.name ?? "this project";
138
+ return `# ${ideName} Rules for ${projectName}
139
+
140
+ > Generated by \`trellis seed\` on ${timestamp}
141
+
142
+ ## Project Context
143
+ - **Domain**: ${context.domain ?? "(not determined)"}
144
+ - **Ecosystem**: ${context.ecosystem ?? "unknown"}
145
+ - **File count**: ~${context.fileCount}
146
+ - **Confidence**: ${context.confidence}
147
+
148
+ ## Agent Instructions
149
+ You are working in a Trellis-tracked repository. See \`.trellis/agents/AGENTS.md\` for full context.
150
+
151
+ ## Commands
152
+ - \`trellis status\` \u2014 Check repo state
153
+ - \`trellis seed\` \u2014 Refresh this context file
154
+ - \`trellis log\` \u2014 View causal history
155
+
156
+ ---
157
+ *Auto-generated by Trellis. Run \`trellis seed\` to refresh context.*
158
+ `;
159
+ }
160
+
161
+ // src/scaffold/index.ts
162
+ init_infer();
163
+ init_profile();
164
+ init_write();
165
+
166
+ export { seedContext };