@mean-weasel/lineage 0.1.16 → 0.1.17

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 (39) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +226 -17
  3. package/dist/cli/lineage-channel.js +25 -5
  4. package/dist/cli/lineage-channel.js.map +2 -2
  5. package/dist/cli/lineage-dev.js +163 -12
  6. package/dist/cli/lineage-dev.js.map +3 -3
  7. package/dist/cli/lineage-preview.js +163 -12
  8. package/dist/cli/lineage-preview.js.map +3 -3
  9. package/dist/cli/lineage.js +163 -12
  10. package/dist/cli/lineage.js.map +3 -3
  11. package/dist/cli/managed-service.js +19 -5
  12. package/dist/cli/managed-service.js.map +2 -2
  13. package/dist/runtime-build.json +4 -4
  14. package/dist/server.js +42 -8
  15. package/dist/server.js.map +2 -2
  16. package/dist/web/assets/agent-shared-state-DOfpTLiw.webp +0 -0
  17. package/dist/web/assets/agent-to-canvas-DtIu_cPq.mp4 +0 -0
  18. package/dist/web/assets/{app-DwTFac4u.css → app-B-fAyNsU.css} +1 -1
  19. package/dist/web/assets/app-DMogkUoS.js +16 -0
  20. package/dist/web/assets/attempt-history-D6wdic6n.webp +0 -0
  21. package/dist/web/assets/branching-tree-B8I5_S6D.png +0 -0
  22. package/dist/web/assets/canvas-cli-DHBacq7r.png +0 -0
  23. package/dist/web/assets/hero-agent-sync-CSyh0tHy.mp4 +0 -0
  24. package/dist/web/assets/hero-board-DG3ED4AW.webp +0 -0
  25. package/dist/web/assets/hero-lineage-growth-Bsl9tiq-.mp4 +0 -0
  26. package/dist/web/assets/hero-trace-connections-Bb52ABBc.mp4 +0 -0
  27. package/dist/web/assets/human-selection-BdDBDE-I.webp +0 -0
  28. package/dist/web/assets/human-to-agent-D1z92ZO9.mp4 +0 -0
  29. package/dist/web/assets/{jsx-runtime-_Rdg6et1.js → jsx-runtime-DAFSxiwi.js} +1 -1
  30. package/dist/web/assets/landing-Bn4qKbIO.css +1 -0
  31. package/dist/web/assets/landing-CoyGmxBo.js +1 -0
  32. package/dist/web/assets/reroll-history-DQcEH42R.mp4 +0 -0
  33. package/dist/web/index.html +3 -3
  34. package/dist/web/landing/index.html +3 -3
  35. package/fixtures/demo-project/lineage/swissifier-rich-demo.json +13 -13
  36. package/package.json +4 -3
  37. package/dist/web/assets/app-JYTx_Sd4.js +0 -16
  38. package/dist/web/assets/landing-D3Y679_B.css +0 -1
  39. package/dist/web/assets/landing-ii8AH_DG.js +0 -1
@@ -645,6 +645,7 @@ import { dirname as dirname3, isAbsolute, join as join4, relative as relative2,
645
645
 
646
646
  // src/shared/lineageProfileTypes.ts
647
647
  var lineageProfileSchemaVersion = "lineage.profile.v1";
648
+ var lineageProfileInitSchemaVersion = "lineage.profile_init.v1";
648
649
  var lineageProfileDoctorSchemaVersion = "lineage.profile_doctor.v1";
649
650
  var lineageProfileCloneReceiptSchemaVersion = "lineage.profile_clone_receipt.v1";
650
651
  var lineageProfileAssetsCloneReceiptSchemaVersion = "lineage.profile_assets_clone_receipt.v1";
@@ -793,6 +794,120 @@ function lineageProfileFingerprint(profile) {
793
794
  service_origin: profile.service_origin
794
795
  })).digest("hex");
795
796
  }
797
+ function initializeLineageProfile(profileId, serviceOrigin, runtime, confirmWrite, withWriterLease) {
798
+ if (!confirmWrite) throw new Error("Profile init requires --confirm-write");
799
+ if (!profileIdPattern.test(profileId)) throw new Error(`Invalid profile ID: ${profileId}`);
800
+ if (!runtime.code?.verified) throw new Error("Profile init requires a verified runtime code identity");
801
+ if (runtime.code.origin !== "checkout" && runtime.code.origin !== "package") {
802
+ throw new Error(`Profile init requires checkout or package code, not ${runtime.code.origin}`);
803
+ }
804
+ if (!runtime.code.fingerprint || !/^[a-f0-9]{64}$/i.test(runtime.code.fingerprint)) {
805
+ throw new Error("Profile init requires a valid executing code fingerprint");
806
+ }
807
+ const validatedServiceOrigin = validateServiceOrigin(serviceOrigin);
808
+ const root = lineageProfileRoot();
809
+ mkdirSync3(root, { recursive: true, mode: 448 });
810
+ const profileDirectory = join4(root, profileId);
811
+ try {
812
+ mkdirSync3(profileDirectory, { mode: 448 });
813
+ } catch (error) {
814
+ if (error && typeof error === "object" && "code" in error && error.code === "EEXIST") {
815
+ const doctor = doctorLineageProfile(profileId, runtime);
816
+ if (doctor.ok) {
817
+ throw new Error(`Profile ${profileId} already exists and passes doctor. No files were changed. Reuse it with \`start --profile ${profileId}\`; verify it first with \`profile doctor --profile ${profileId} --json\`.`, { cause: error });
818
+ }
819
+ const failures = doctor.checks.filter((check) => check.status === "fail").map((check) => `${check.id}: ${check.message}`).join("; ");
820
+ throw new Error(`Profile ${profileId} already exists but did not pass doctor. No files were changed. Run \`profile doctor --profile ${profileId} --json\`, then inspect ${profileDirectory} manually before retrying. ${failures}`, { cause: error });
821
+ }
822
+ throw error;
823
+ }
824
+ const manifestPath = join4(profileDirectory, "profile.json");
825
+ const databasePath = join4(profileDirectory, "lineage.sqlite");
826
+ const assetRoot = join4(profileDirectory, "media");
827
+ const environment = channelEnvironment(runtime.channel);
828
+ const manifest = {
829
+ asset_root: assetRoot,
830
+ database_path: databasePath,
831
+ environment,
832
+ expected_runtime: {
833
+ channel: runtime.channel,
834
+ code_fingerprint: runtime.code.fingerprint.toLowerCase(),
835
+ code_origin: runtime.code.origin
836
+ },
837
+ profile_id: profileId,
838
+ schema_version: lineageProfileSchemaVersion,
839
+ service_origin: validatedServiceOrigin
840
+ };
841
+ const profile = {
842
+ ...manifest,
843
+ manifest_path: manifestPath,
844
+ profile_fingerprint: lineageProfileFingerprint(manifest)
845
+ };
846
+ try {
847
+ assertProfileChannel(profile, runtime.channel);
848
+ assertProfileRuntimePin(profile, runtime);
849
+ const identity2 = withWriterLease(profile, () => {
850
+ mkdirSync3(assetRoot, { mode: 448 });
851
+ const databaseFd = openSync(databasePath, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_RDWR, 384);
852
+ closeSync(databaseFd);
853
+ const { DatabaseSync } = require2("node:sqlite");
854
+ const database = new DatabaseSync(databasePath);
855
+ let boundIdentity;
856
+ try {
857
+ boundIdentity = bindOpenDatabase(database, profile, false);
858
+ } finally {
859
+ database.close();
860
+ }
861
+ const manifestPayload = {
862
+ asset_root: "./media",
863
+ database_path: "./lineage.sqlite",
864
+ environment: profile.environment,
865
+ expected_runtime: profile.expected_runtime,
866
+ profile_id: profile.profile_id,
867
+ schema_version: profile.schema_version,
868
+ service_origin: profile.service_origin
869
+ };
870
+ writeFileSync2(manifestPath, `${JSON.stringify(manifestPayload, null, 2)}
871
+ `, { encoding: "utf8", flag: "wx", mode: 384 });
872
+ const manifestFd = openSync(manifestPath, "r");
873
+ try {
874
+ fsyncSync(manifestFd);
875
+ } finally {
876
+ closeSync(manifestFd);
877
+ }
878
+ const directoryFd = openSync(profileDirectory, "r");
879
+ try {
880
+ fsyncSync(directoryFd);
881
+ } finally {
882
+ closeSync(directoryFd);
883
+ }
884
+ const published = resolveLineageProfile(profileId);
885
+ if (published.profile_fingerprint !== profile.profile_fingerprint) {
886
+ throw new Error("Initialized profile fingerprint does not match its published manifest");
887
+ }
888
+ return boundIdentity;
889
+ });
890
+ return {
891
+ asset_root: profile.asset_root,
892
+ database_path: profile.database_path,
893
+ environment: profile.environment,
894
+ identity: identity2,
895
+ manifest_path: profile.manifest_path,
896
+ profile_fingerprint: profile.profile_fingerprint,
897
+ profile_id: profile.profile_id,
898
+ runtime: {
899
+ channel: runtime.channel,
900
+ code_fingerprint: runtime.code.fingerprint,
901
+ code_origin: runtime.code.origin
902
+ },
903
+ schema_version: lineageProfileInitSchemaVersion,
904
+ service_origin: profile.service_origin
905
+ };
906
+ } catch (error) {
907
+ rmSync(profileDirectory, { force: true, recursive: true });
908
+ throw error;
909
+ }
910
+ }
796
911
  function sha256(value) {
797
912
  return createHash2("sha256").update(value).digest("hex");
798
913
  }
@@ -1524,7 +1639,7 @@ function acquireProfileWriterLease(profile, channel, role = "service") {
1524
1639
  }
1525
1640
  function assertProfileWriterLeaseHeld() {
1526
1641
  if (!process.env.LINEAGE_PROFILE) {
1527
- throw new Error("Persistent writes require a selected named Lineage profile and its writer lease; legacy-unbound access is read-only");
1642
+ throw new Error("Persistent writes require a selected named Lineage profile and its writer lease; legacy-unbound access is read-only. Create a fresh profile with `profile init --profile <id> --confirm-write`, then pass that profile to the command");
1528
1643
  }
1529
1644
  const profileId = process.env.LINEAGE_PROFILE_ID;
1530
1645
  const profileFingerprint = process.env.LINEAGE_PROFILE_FINGERPRINT;
@@ -5785,6 +5900,9 @@ function getLineageRuntimeInfo(options = {}) {
5785
5900
  const code = options.code || getLineageCodeIdentity(channel);
5786
5901
  const databaseInfo = { exists: existsSync10(dbPath), path: dbPath };
5787
5902
  const schema = { migration_keys: [] };
5903
+ const serviceInstanceId = process.env.LINEAGE_SERVICE_INSTANCE_ID;
5904
+ const launcherPid = process.env.LINEAGE_LAUNCHER_PID ? Number(process.env.LINEAGE_LAUNCHER_PID) : void 0;
5905
+ const isServiceProcess = Boolean(serviceInstanceId && Number.isInteger(launcherPid) && launcherPid > 0);
5788
5906
  if (databaseInfo.exists) {
5789
5907
  try {
5790
5908
  const stat = statSync6(dbPath);
@@ -5822,14 +5940,22 @@ function getLineageRuntimeInfo(options = {}) {
5822
5940
  git_sha: code.git_sha,
5823
5941
  node_env: process.env.NODE_ENV,
5824
5942
  package_name: info.name,
5825
- profile: runtimeProfileIdentity(channel),
5826
- schema,
5827
- service: {
5828
- instance_id: process.env.LINEAGE_SERVICE_INSTANCE_ID,
5829
- launcher_pid: process.env.LINEAGE_LAUNCHER_PID ? Number(process.env.LINEAGE_LAUNCHER_PID) : void 0,
5943
+ process: {
5830
5944
  pid: process.pid,
5945
+ role: isServiceProcess ? "service" : "command",
5831
5946
  started_at: processStartedAt
5832
5947
  },
5948
+ profile: runtimeProfileIdentity(channel),
5949
+ schema,
5950
+ ...isServiceProcess ? {
5951
+ service: {
5952
+ instance_id: serviceInstanceId,
5953
+ launcher_pid: launcherPid,
5954
+ mode: process.env.LINEAGE_SERVICE_MODE === "managed" ? "managed" : "foreground",
5955
+ pid: process.pid,
5956
+ started_at: processStartedAt
5957
+ }
5958
+ } : {},
5833
5959
  version: info.version
5834
5960
  };
5835
5961
  }
@@ -5983,6 +6109,9 @@ function parentFilesOption(value) {
5983
6109
  return mappings;
5984
6110
  }
5985
6111
  function resolveStartOptions(config, args) {
6112
+ if (!profileSelector(args)) {
6113
+ throw new Error("Start requires --profile or LINEAGE_PROFILE. Create one with `profile init --profile <id> --confirm-write`, then start again with that profile");
6114
+ }
5986
6115
  const profile = prepareCliProfile(config, args);
5987
6116
  const serviceUrl = profile ? new URL(profile.service_origin) : void 0;
5988
6117
  const rawPort = readOption(args, "--port") || process.env.PORT || serviceUrl?.port || String(config.defaultPort);
@@ -6062,7 +6191,8 @@ function formatLineageHelp(config) {
6062
6191
  return `${config.binName} ${packageVersion()}
6063
6192
 
6064
6193
  Usage:
6065
- ${config.binName} start [--profile <id-or-manifest>] [--port <port>] [--host <host>] [--db <path>] [--asset-root <path>] [--open] [--json]
6194
+ ${config.binName} start --profile <id-or-manifest> [--open] [--json]
6195
+ ${config.binName} profile init --profile <new-profile-id> [--service-origin <http-origin>] --confirm-write [--json]
6066
6196
  ${config.binName} profile doctor --profile <id-or-manifest> [--json]
6067
6197
  ${config.binName} profile bind --profile <id-or-manifest> --confirm-write [--json]
6068
6198
  ${config.binName} profile clone --source-db <snapshot-source> --target-profile <id-or-manifest> --confirm-write [--json]
@@ -6503,6 +6633,25 @@ function runLineageDbCommand(config, command, args) {
6503
6633
  function runLineageProfileCommand(config, command, args) {
6504
6634
  const runtime = getLineageRuntimeInfo({ channel: config.channel });
6505
6635
  const runtimeIdentity = { channel: config.channel, code: runtime.code, gitSha: runtime.git_sha, version: runtime.version };
6636
+ if (command === "init") {
6637
+ if (hasOption(args, "--db")) throw new Error("Profile init cannot be combined with --db");
6638
+ if (hasOption(args, "--asset-root")) throw new Error("Profile init cannot be combined with --asset-root");
6639
+ if (!args.includes("--confirm-write")) throw new Error("Profile init requires --confirm-write");
6640
+ const profileId = readOption(args, "--profile");
6641
+ if (!profileId) throw new Error("lineage profile init requires --profile");
6642
+ if (process.env.LINEAGE_PROFILE && process.env.LINEAGE_PROFILE !== profileId) {
6643
+ throw new Error("Profile init requires an explicit --profile that does not conflict with LINEAGE_PROFILE");
6644
+ }
6645
+ const serviceOrigin = readOption(args, "--service-origin") || `http://${config.defaultHost}:${config.defaultPort}`;
6646
+ return initializeLineageProfile(profileId, serviceOrigin, runtimeIdentity, true, (profile, initialize) => {
6647
+ const writerLease = acquireProfileWriterLease(profile, config.channel, "cli");
6648
+ try {
6649
+ return initialize();
6650
+ } finally {
6651
+ writerLease.release();
6652
+ }
6653
+ });
6654
+ }
6506
6655
  if (command === "clone") {
6507
6656
  const source = readOption(args, "--source-db");
6508
6657
  const target = readOption(args, "--target-profile");
@@ -6561,7 +6710,10 @@ function printProfileResult(result, json) {
6561
6710
  console.log(JSON.stringify(result, null, 2));
6562
6711
  return;
6563
6712
  }
6564
- if (result.schema_version === "lineage.profile_doctor.v1") {
6713
+ if (result.schema_version === "lineage.profile_init.v1") {
6714
+ console.log(`Initialized ${result.profile_id} at ${result.manifest_path}`);
6715
+ console.log(`Service: ${result.service_origin}`);
6716
+ } else if (result.schema_version === "lineage.profile_doctor.v1") {
6565
6717
  console.log(`Profile doctor: ${result.ok ? "ok" : "failed"}`);
6566
6718
  for (const check of result.checks) console.log(`${check.status.toUpperCase()} ${check.id}: ${check.message}`);
6567
6719
  } else if (result.schema_version === "lineage.profile_bind.v1") {
@@ -6792,7 +6944,6 @@ function start(config, args) {
6792
6944
  } else {
6793
6945
  console.log(`${config.displayName} starting at ${url}`);
6794
6946
  if (options.profile) console.log(`Profile: ${options.profile.profile_id} (${options.profile.environment})`);
6795
- else console.warn("Warning: legacy-unbound runtime; database and asset paths are not protected by a named profile.");
6796
6947
  console.log(`SQLite: ${options.dbPath}`);
6797
6948
  console.log(`Assets: ${options.assetRoot}`);
6798
6949
  }
@@ -6805,7 +6956,7 @@ function start(config, args) {
6805
6956
  LINEAGE_ASSET_ROOT: options.assetRoot,
6806
6957
  LINEAGE_CHANNEL: config.channel,
6807
6958
  LINEAGE_DB: options.dbPath,
6808
- LINEAGE_PROFILE: options.profile ? process.env.LINEAGE_PROFILE : void 0,
6959
+ LINEAGE_PROFILE: process.env.LINEAGE_PROFILE,
6809
6960
  LINEAGE_PROFILE_ENVIRONMENT: options.profile?.environment,
6810
6961
  LINEAGE_PROFILE_FINGERPRINT: options.profile?.profile_fingerprint,
6811
6962
  LINEAGE_PROFILE_ID: options.profile?.profile_id,
@@ -6813,7 +6964,7 @@ function start(config, args) {
6813
6964
  LINEAGE_PROFILE_SERVICE_ORIGIN: options.profile?.service_origin,
6814
6965
  LINEAGE_LAUNCHER_PID: String(process.pid),
6815
6966
  LINEAGE_SERVICE_INSTANCE_ID: serviceInstanceId,
6816
- LINEAGE_DB_ACCESS: options.profile ? void 0 : "read-only",
6967
+ LINEAGE_DB_ACCESS: void 0,
6817
6968
  NODE_ENV: "production",
6818
6969
  PORT: String(options.port)
6819
6970
  },
@@ -6933,7 +7084,7 @@ async function runLineageCli(config, args = process.argv.slice(2)) {
6933
7084
  process.env.LINEAGE_DB_ACCESS = "read-only";
6934
7085
  }
6935
7086
  } else if (requiresWriter) {
6936
- throw new Error("Persistent writes require --profile; legacy-unbound access is read-only");
7087
+ throw new Error("Persistent writes require --profile; legacy-unbound access is read-only. Create a fresh profile with `profile init --profile <id> --confirm-write`, then pass that profile to the command");
6937
7088
  } else {
6938
7089
  process.env.LINEAGE_DB_ACCESS = "read-only";
6939
7090
  }