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.
- package/README.md +65 -796
- package/dist/cli/index.d.ts +3 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2948 -182
- package/dist/client/index.js +4 -4
- package/dist/context/heat-map-manager.d.ts +100 -0
- package/dist/context/heat-map-manager.d.ts.map +1 -0
- package/dist/context/manager.d.ts +16 -0
- package/dist/context/manager.d.ts.map +1 -0
- package/dist/context/types.d.ts +20 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/core/agents/harness.d.ts +10 -1
- package/dist/core/agents/harness.d.ts.map +1 -1
- package/dist/core/agents/types.d.ts +18 -2
- package/dist/core/agents/types.d.ts.map +1 -1
- package/dist/core/computation/expr-evaluator.d.ts +52 -0
- package/dist/core/computation/expr-evaluator.d.ts.map +1 -0
- package/dist/core/index.js +93 -5
- package/dist/core/kernel/logic-middleware.d.ts +19 -0
- package/dist/core/kernel/logic-middleware.d.ts.map +1 -0
- package/dist/core/kernel/schema-middleware.d.ts +15 -0
- package/dist/core/kernel/schema-middleware.d.ts.map +1 -0
- package/dist/core/kernel/security-middleware.d.ts +24 -0
- package/dist/core/kernel/security-middleware.d.ts.map +1 -0
- package/dist/core/kernel/sync-provider.d.ts +59 -0
- package/dist/core/kernel/sync-provider.d.ts.map +1 -0
- package/dist/core/kernel/trellis-kernel.d.ts +55 -0
- package/dist/core/kernel/trellis-kernel.d.ts.map +1 -1
- package/dist/core/ontology/builtins.d.ts.map +1 -1
- package/dist/core/ontology/core-ontology.d.ts +20 -0
- package/dist/core/ontology/core-ontology.d.ts.map +1 -0
- package/dist/core/ontology/index.d.ts +3 -1
- package/dist/core/ontology/index.d.ts.map +1 -1
- package/dist/core/ontology/types.d.ts +138 -34
- package/dist/core/ontology/types.d.ts.map +1 -1
- package/dist/core/persist/backend.d.ts +2 -0
- package/dist/core/persist/backend.d.ts.map +1 -1
- package/dist/core/persist/better-sqlite-backend.d.ts +33 -0
- package/dist/core/persist/better-sqlite-backend.d.ts.map +1 -0
- package/dist/core/persist/sqlite-backend.d.ts +2 -0
- package/dist/core/persist/sqlite-backend.d.ts.map +1 -1
- package/dist/core/store/eav-store.d.ts +4 -0
- package/dist/core/store/eav-store.d.ts.map +1 -1
- package/dist/db/index.js +10 -8
- package/dist/{deploy-99j5dc9c.js → deploy-999q207z.js} +2 -1
- package/dist/engine.d.ts +3 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/evals/types.d.ts +29 -0
- package/dist/evals/types.d.ts.map +1 -0
- package/dist/{import-fyg5sgq4.js → import-s2b8e0ft.js} +2 -2
- package/dist/{index-3ejh8k6v.js → index-0q7wbasy.js} +18 -4
- package/dist/{index-7t92ej34.js → index-0zk3fx2s.js} +467 -7
- package/dist/{index-xr7rx360.js → index-6n5dcebj.js} +33 -0
- package/dist/{index-4beszbgg.js → index-7e27kvvj.js} +1 -1
- package/dist/index-bmyt7k8n.js +90 -0
- package/dist/{index-k5kf7sd0.js → index-hmdbnd4n.js} +1 -1
- package/dist/{index-czecrvvn.js → index-q31hfjja.js} +858 -48
- package/dist/{index-8fjwnztt.js → index-skhn0agf.js} +1 -1
- package/dist/{index-04sq3h27.js → index-w7ng765c.js} +3 -1
- package/dist/{index-hgd30epa.js → index-wt8rz4gn.js} +4 -21
- package/dist/{index-5p6zgspx.js → index-y3d71wzd.js} +1 -1
- package/dist/index-y6a4kj0p.js +43 -0
- package/dist/{index-5bhe57y9.js → index-yhwjgfvj.js} +16 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -6
- package/dist/llm/provider.d.ts +11 -0
- package/dist/llm/provider.d.ts.map +1 -0
- package/dist/llm/types.d.ts +74 -0
- package/dist/llm/types.d.ts.map +1 -0
- package/dist/mcp/index.d.ts +7 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/orchestration/types.d.ts +22 -0
- package/dist/orchestration/types.d.ts.map +1 -0
- package/dist/plugins/agent-memory/graph-context-manager.d.ts +75 -0
- package/dist/plugins/agent-memory/graph-context-manager.d.ts.map +1 -0
- package/dist/plugins/agent-memory/index.d.ts +30 -0
- package/dist/plugins/agent-memory/index.d.ts.map +1 -0
- package/dist/plugins/agent-memory/ontology.d.ts +13 -0
- package/dist/plugins/agent-memory/ontology.d.ts.map +1 -0
- package/dist/plugins/agent-memory/plugin.d.ts +17 -0
- package/dist/plugins/agent-memory/plugin.d.ts.map +1 -0
- package/dist/plugins/brand/cache.d.ts +18 -0
- package/dist/plugins/brand/cache.d.ts.map +1 -0
- package/dist/plugins/brand/catalog-generator.d.ts +89 -0
- package/dist/plugins/brand/catalog-generator.d.ts.map +1 -0
- package/dist/plugins/brand/constraints.d.ts +55 -0
- package/dist/plugins/brand/constraints.d.ts.map +1 -0
- package/dist/plugins/brand/index.d.ts +44 -0
- package/dist/plugins/brand/index.d.ts.map +1 -0
- package/dist/plugins/brand/mcp-tools.d.ts +101 -0
- package/dist/plugins/brand/mcp-tools.d.ts.map +1 -0
- package/dist/plugins/brand/ontology.d.ts +13 -0
- package/dist/plugins/brand/ontology.d.ts.map +1 -0
- package/dist/plugins/brand/plugin.d.ts +21 -0
- package/dist/plugins/brand/plugin.d.ts.map +1 -0
- package/dist/plugins/brand/voice-tone.d.ts +24 -0
- package/dist/plugins/brand/voice-tone.d.ts.map +1 -0
- package/dist/plugins/idea-garden/api.d.ts +26 -0
- package/dist/plugins/idea-garden/api.d.ts.map +1 -0
- package/dist/plugins/idea-garden/index.d.ts +12 -0
- package/dist/plugins/idea-garden/index.d.ts.map +1 -0
- package/dist/plugins/idea-garden/plugin.d.ts +16 -0
- package/dist/plugins/idea-garden/plugin.d.ts.map +1 -0
- package/dist/plugins/idea-garden/types.d.ts +22 -0
- package/dist/plugins/idea-garden/types.d.ts.map +1 -0
- package/dist/plugins/plan-approval/index.d.ts +36 -0
- package/dist/plugins/plan-approval/index.d.ts.map +1 -0
- package/dist/plugins/plan-approval/ontology.d.ts +11 -0
- package/dist/plugins/plan-approval/ontology.d.ts.map +1 -0
- package/dist/plugins/plan-approval/plan-manager.d.ts +104 -0
- package/dist/plugins/plan-approval/plan-manager.d.ts.map +1 -0
- package/dist/plugins/plan-approval/plugin.d.ts +110 -0
- package/dist/plugins/plan-approval/plugin.d.ts.map +1 -0
- package/dist/plugins/proactive-watcher/index.d.ts +28 -0
- package/dist/plugins/proactive-watcher/index.d.ts.map +1 -0
- package/dist/plugins/proactive-watcher/ontology.d.ts +8 -0
- package/dist/plugins/proactive-watcher/ontology.d.ts.map +1 -0
- package/dist/plugins/proactive-watcher/plugin.d.ts +20 -0
- package/dist/plugins/proactive-watcher/plugin.d.ts.map +1 -0
- package/dist/plugins/proactive-watcher/watcher-manager.d.ts +36 -0
- package/dist/plugins/proactive-watcher/watcher-manager.d.ts.map +1 -0
- package/dist/plugins/sprite-tools/checkpoint-middleware.d.ts +43 -0
- package/dist/plugins/sprite-tools/checkpoint-middleware.d.ts.map +1 -0
- package/dist/plugins/sprite-tools/index.d.ts +40 -0
- package/dist/plugins/sprite-tools/index.d.ts.map +1 -0
- package/dist/plugins/sprite-tools/plugin.d.ts +69 -0
- package/dist/plugins/sprite-tools/plugin.d.ts.map +1 -0
- package/dist/react/index.js +4 -4
- package/dist/scaffold/index.d.ts +13 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/infer.d.ts +42 -0
- package/dist/scaffold/infer.d.ts.map +1 -0
- package/dist/scaffold/profile.d.ts +51 -0
- package/dist/scaffold/profile.d.ts.map +1 -0
- package/dist/scaffold/seed.d.ts +27 -0
- package/dist/scaffold/seed.d.ts.map +1 -0
- package/dist/scaffold/write.d.ts +53 -0
- package/dist/scaffold/write.d.ts.map +1 -0
- package/dist/{sdk-sj8rp0m7.js → sdk-snn5gad3.js} +4 -4
- package/dist/server/deploy.d.ts.map +1 -1
- package/dist/server/index.d.ts +5 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +37 -7
- package/dist/server/sprites.d.ts +26 -0
- package/dist/server/sprites.d.ts.map +1 -0
- package/dist/server/vm-config.d.ts +60 -0
- package/dist/server/vm-config.d.ts.map +1 -0
- package/dist/{server-3vkpnpbz.js → server-mrctdwzr.js} +2 -2
- package/dist/sprites-vc4qbrp1.js +16 -0
- package/dist/streaming/types.d.ts +43 -0
- package/dist/streaming/types.d.ts.map +1 -0
- package/dist/{tenancy-tjr7kk2v.js → tenancy-7d1g4ayp.js} +3 -3
- package/dist/ui/client.html +460 -664
- package/dist/ui/server.d.ts +6 -2
- package/dist/ui/server.d.ts.map +1 -1
- package/dist/vcs/decompose.d.ts.map +1 -1
- package/dist/vcs/index.js +2 -2
- package/dist/vcs/issue.d.ts.map +1 -1
- package/dist/vcs/types.d.ts +1 -0
- package/dist/vcs/types.d.ts.map +1 -1
- package/dist/vm-config-6xhsj6b3.js +22 -0
- package/package.json +14 -4
- /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-
|
|
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-
|
|
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
|
|
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 (
|
|
3518
|
-
const raw =
|
|
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 (
|
|
3524
|
-
const backupRaw =
|
|
4163
|
+
if (existsSync4(backupPath)) {
|
|
4164
|
+
const backupRaw = readFileSync4(backupPath, "utf-8");
|
|
3525
4165
|
this.ops = JSON.parse(backupRaw);
|
|
3526
|
-
|
|
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 (!
|
|
3549
|
-
|
|
3550
|
-
if (
|
|
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
|
-
|
|
4196
|
+
writeFileSync3(this.filePath, JSON.stringify(this.ops, null, 2));
|
|
3557
4197
|
}
|
|
3558
4198
|
static repair(filePath) {
|
|
3559
|
-
if (!
|
|
4199
|
+
if (!existsSync4(filePath)) {
|
|
3560
4200
|
return { recovered: 0, lost: 0 };
|
|
3561
4201
|
}
|
|
3562
|
-
const raw =
|
|
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 (
|
|
3571
|
-
const bakRaw =
|
|
4210
|
+
if (existsSync4(bakPath)) {
|
|
4211
|
+
const bakRaw = readFileSync4(bakPath, "utf-8");
|
|
3572
4212
|
try {
|
|
3573
4213
|
const ops = JSON.parse(bakRaw);
|
|
3574
|
-
|
|
4214
|
+
writeFileSync3(filePath, bakRaw);
|
|
3575
4215
|
return { recovered: ops.length, lost: 0 };
|
|
3576
4216
|
} catch {}
|
|
3577
4217
|
}
|
|
3578
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3593
|
-
|
|
4232
|
+
writeFileSync3(filePath + ".corrupted", raw);
|
|
4233
|
+
writeFileSync3(filePath, fixed);
|
|
3594
4234
|
return { recovered: ops.length, lost: 0 };
|
|
3595
4235
|
} catch {
|
|
3596
|
-
|
|
3597
|
-
|
|
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 (!
|
|
4243
|
+
if (!existsSync4(filePath))
|
|
3604
4244
|
return [];
|
|
3605
4245
|
try {
|
|
3606
|
-
const content =
|
|
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(
|
|
3616
|
-
...parseIgnoreFile(
|
|
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(
|
|
4289
|
+
this.opLog = new JsonOpLog(join5(this.config.rootPath, ".trellis", "ops.json"));
|
|
3650
4290
|
}
|
|
3651
4291
|
async initRepo(opts) {
|
|
3652
|
-
const trellisDir =
|
|
3653
|
-
if (!
|
|
3654
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
4393
|
+
const trellisDir = join5(this.config.rootPath, ".trellis");
|
|
3743
4394
|
this._blobStore = new BlobStore(trellisDir);
|
|
3744
|
-
const configPath =
|
|
3745
|
-
if (
|
|
3746
|
-
const raw =
|
|
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 =
|
|
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 =
|
|
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
|
|
4508
|
+
return existsSync4(join5(rootPath, ".trellis", "config.json"));
|
|
3858
4509
|
}
|
|
3859
4510
|
static repair(rootPath) {
|
|
3860
|
-
const opsPath =
|
|
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
|
-
|
|
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 };
|