@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.
- package/CHANGELOG.md +7 -0
- package/README.md +226 -17
- package/dist/cli/lineage-channel.js +25 -5
- package/dist/cli/lineage-channel.js.map +2 -2
- package/dist/cli/lineage-dev.js +163 -12
- package/dist/cli/lineage-dev.js.map +3 -3
- package/dist/cli/lineage-preview.js +163 -12
- package/dist/cli/lineage-preview.js.map +3 -3
- package/dist/cli/lineage.js +163 -12
- package/dist/cli/lineage.js.map +3 -3
- package/dist/cli/managed-service.js +19 -5
- package/dist/cli/managed-service.js.map +2 -2
- package/dist/runtime-build.json +4 -4
- package/dist/server.js +42 -8
- package/dist/server.js.map +2 -2
- package/dist/web/assets/agent-shared-state-DOfpTLiw.webp +0 -0
- package/dist/web/assets/agent-to-canvas-DtIu_cPq.mp4 +0 -0
- package/dist/web/assets/{app-DwTFac4u.css → app-B-fAyNsU.css} +1 -1
- package/dist/web/assets/app-DMogkUoS.js +16 -0
- package/dist/web/assets/attempt-history-D6wdic6n.webp +0 -0
- package/dist/web/assets/branching-tree-B8I5_S6D.png +0 -0
- package/dist/web/assets/canvas-cli-DHBacq7r.png +0 -0
- package/dist/web/assets/hero-agent-sync-CSyh0tHy.mp4 +0 -0
- package/dist/web/assets/hero-board-DG3ED4AW.webp +0 -0
- package/dist/web/assets/hero-lineage-growth-Bsl9tiq-.mp4 +0 -0
- package/dist/web/assets/hero-trace-connections-Bb52ABBc.mp4 +0 -0
- package/dist/web/assets/human-selection-BdDBDE-I.webp +0 -0
- package/dist/web/assets/human-to-agent-D1z92ZO9.mp4 +0 -0
- package/dist/web/assets/{jsx-runtime-_Rdg6et1.js → jsx-runtime-DAFSxiwi.js} +1 -1
- package/dist/web/assets/landing-Bn4qKbIO.css +1 -0
- package/dist/web/assets/landing-CoyGmxBo.js +1 -0
- package/dist/web/assets/reroll-history-DQcEH42R.mp4 +0 -0
- package/dist/web/index.html +3 -3
- package/dist/web/landing/index.html +3 -3
- package/fixtures/demo-project/lineage/swissifier-rich-demo.json +13 -13
- package/package.json +4 -3
- package/dist/web/assets/app-JYTx_Sd4.js +0 -16
- package/dist/web/assets/landing-D3Y679_B.css +0 -1
- package/dist/web/assets/landing-ii8AH_DG.js +0 -1
package/dist/cli/lineage.js
CHANGED
|
@@ -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 identity = 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,
|
|
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
|
-
|
|
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
|
|
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.
|
|
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:
|
|
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:
|
|
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
|
}
|