mirai-graph 1.1.1 → 1.3.0

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.
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env node
2
+
3
+ "use strict";
4
+
5
+ const assert = require("assert");
6
+ const fs = require("fs");
7
+ const os = require("os");
8
+ const path = require("path");
9
+ const { spawnSync } = require("child_process");
10
+ const technology = require("../project-technology");
11
+
12
+ function writeJson(file, value) {
13
+ fs.mkdirSync(path.dirname(file), { recursive: true });
14
+ fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
15
+ }
16
+
17
+ function git(repo, ...args) {
18
+ const run = spawnSync("git", args, { cwd: repo, encoding: "utf8" });
19
+ if (run.status !== 0) throw new Error(run.stderr || `git ${args.join(" ")} failed`);
20
+ return run.stdout.trim();
21
+ }
22
+
23
+ function manifest(id) {
24
+ return {
25
+ $schema: "https://mirai-graph.dev/schemas/graph-manifest.schema.json",
26
+ format: "mirai-graph", schema_version: "2.0.0", id, aliases: [], title: id,
27
+ scope: "repository", kind: "repository_graph", owner: "fixture-owner",
28
+ profiles: ["project_management", "implementation_control"],
29
+ graph: {
30
+ root: "graph", source_of_truth: ["graph/specs"], objects: ["graph/specs/objects.json"],
31
+ relations: ["graph/specs/relations.json"], schemas: [], generated: ["graph/generated"], raw_sources: ["README.md"],
32
+ },
33
+ imports: [],
34
+ extensions: { "mirai.project_technology": technology.extensionContract() },
35
+ };
36
+ }
37
+
38
+ function createRepo(root, name, withGit = true) {
39
+ const repo = path.join(root, name); fs.mkdirSync(repo, { recursive: true });
40
+ writeJson(path.join(repo, "graph.json"), manifest(name));
41
+ writeJson(path.join(repo, "graph/specs/objects.json"), [{
42
+ id: "goal.fixture.delivery", kind: "goal", title: "Deliver fixture", summary: "Complete a safe fixture task",
43
+ readiness: "accepted", profile: "project_management", source_refs: ["README.md"],
44
+ }]);
45
+ writeJson(path.join(repo, "graph/specs/relations.json"), []);
46
+ fs.writeFileSync(path.join(repo, "README.md"), "# Fixture\nPortable safe context.\n");
47
+ if (withGit) {
48
+ git(repo, "init", "-q"); git(repo, "config", "user.name", "Mirai Fixture"); git(repo, "config", "user.email", "fixture@example.invalid");
49
+ git(repo, "add", "."); git(repo, "commit", "-qm", "initial graph");
50
+ }
51
+ return repo;
52
+ }
53
+
54
+ function evidence(task, options = {}) {
55
+ return {
56
+ task_digest: technology.sha256(task, true),
57
+ outcome: options.outcome || `Verified result for ${task}`,
58
+ requirement_refs: options.requirement_refs || ["requirement.fixture.portability"],
59
+ evidence_refs: ["repo://fixture/checks/continuity"],
60
+ checks: [{ id: "check.fixture.continuity", verdict: "pass", evidence_ref: "repo://fixture/checks/continuity" }],
61
+ changed_surfaces: ["src/fixture.js"],
62
+ case_signature: options.case_signature || "case.fixture.portable-work",
63
+ method_candidate: options.method_candidate || null,
64
+ decisions: options.decisions || [],
65
+ source_revision: options.source_revision || null,
66
+ };
67
+ }
68
+
69
+ const checks = [];
70
+ function check(id, condition, details = null) {
71
+ checks.push({ id, passed: Boolean(condition), details });
72
+ assert.ok(condition, `${id}: ${JSON.stringify(details)}`);
73
+ }
74
+
75
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "mirai-continuity-"));
76
+ const stateRoot = path.join(root, "host-state");
77
+ try {
78
+ const repo = createRepo(root, "git-project");
79
+ const before = git(repo, "status", "--porcelain=v1");
80
+ const taskStart = technology.execute("sync", repo, { apply: true, boundary: "task_start", stateRoot });
81
+ check("task_start_is_read_only", taskStart.status === "success" && taskStart.changed === false && git(repo, "status", "--porcelain=v1") === before, taskStart);
82
+ const preview = technology.execute("sync", repo, { apply: false, boundary: "task_complete", continuityEvidence: evidence("preview"), stateRoot });
83
+ check("preview_is_zero_write", preview.status === "preview" && git(repo, "status", "--porcelain=v1") === before, preview);
84
+ const missingReceiptVerify = technology.verify(repo, { stateRoot });
85
+ check("configured_continuity_without_receipt_blocks_verify", missingReceiptVerify.status === "blocked" && missingReceiptVerify.blockers.includes("continuity_missing"), missingReceiptVerify);
86
+
87
+ const first = technology.execute("sync", repo, { apply: true, boundary: "stage_complete", continuityEvidence: evidence("first", { method_candidate: "Use the verified bounded fixture path." }), stateRoot });
88
+ check("verified_result_is_saved", first.status === "success" && first.changed && first.continuity.saved_refs.length === 2, first);
89
+ check("portable_authority_is_graph_specs", fs.existsSync(path.join(repo, "graph/specs/project-continuity.json")) && first.continuity.authority === "graph/specs");
90
+ check("host_state_is_outside_project", !fs.existsSync(path.join(repo, ".mirai-graph/project-technology/receipts")) && fs.existsSync(stateRoot));
91
+ check("human_projection_is_generated", fs.readFileSync(path.join(repo, "graph/docs/project-context.md"), "utf8").includes("not a source of truth"));
92
+ const objectsAfterFirst = JSON.parse(fs.readFileSync(path.join(repo, "graph/specs/project-continuity.json"), "utf8")).objects;
93
+ check("first_method_is_proposal", objectsAfterFirst.some((item) => item.kind === "lesson" && item.readiness === "proposal"));
94
+ check("architecture_decision_is_not_accepted", technology.execute("sync", repo, {
95
+ apply: true, boundary: "task_complete", stateRoot,
96
+ continuityEvidence: evidence("decision", { decisions: [{ summary: "Replace the project architecture", changes_architecture: true }] }),
97
+ }).status === "success");
98
+ const decisionObjects = JSON.parse(fs.readFileSync(path.join(repo, "graph/specs/project-continuity.json"), "utf8")).objects;
99
+ check("architecture_change_remains_proposal", decisionObjects.some((item) => item.kind === "decision" && item.summary === "Replace the project architecture" && item.readiness === "proposal"));
100
+
101
+ const second = technology.execute("sync", repo, { apply: true, boundary: "task_complete", continuityEvidence: evidence("second", { method_candidate: "Use the verified bounded fixture path." }), stateRoot });
102
+ check("second_independent_case_is_saved", second.status === "success", second);
103
+ const objectsAfterSecond = JSON.parse(fs.readFileSync(path.join(repo, "graph/specs/project-continuity.json"), "utf8")).objects;
104
+ check("method_promotes_after_two_independent_cases", objectsAfterSecond.some((item) => item.kind === "lesson" && item.readiness === "accepted" && item.supporting_case_ids.length >= 2));
105
+
106
+ const beforeRepeat = fs.readFileSync(path.join(repo, "graph/specs/project-continuity.json"));
107
+ const repeated = technology.execute("sync", repo, { apply: true, boundary: "task_complete", continuityEvidence: evidence("second", { method_candidate: "Use the verified bounded fixture path." }), stateRoot });
108
+ check("repeat_is_byte_identical", repeated.status === "success" && repeated.changed === false && fs.readFileSync(path.join(repo, "graph/specs/project-continuity.json")).equals(beforeRepeat), repeated);
109
+ check("fresh_continuity_verifies_without_target_for_light_work", technology.verify(repo, { stateRoot }).status === "success");
110
+ check("fresh_receipt_allows_significant_work", technology.continuity.verify(repo, JSON.parse(fs.readFileSync(path.join(repo, "graph.json"), "utf8")), { stateRoot }).status === "success");
111
+
112
+ const staleDigest = technology.continuity.graphDigest(repo);
113
+ fs.appendFileSync(path.join(repo, "graph/specs/objects.json"), " ");
114
+ check("stale_continuity_blocks_significant_work", technology.continuity.verify(repo, JSON.parse(fs.readFileSync(path.join(repo, "graph.json"), "utf8")), { stateRoot }).blockers.includes("continuity_stale"));
115
+ const baseObjects = JSON.parse(fs.readFileSync(path.join(repo, "graph/specs/objects.json"), "utf8"));
116
+ baseObjects[0].summary = "Changed concurrently";
117
+ fs.writeFileSync(path.join(repo, "graph/specs/objects.json"), JSON.stringify(baseObjects, null, 2) + "\n");
118
+ const cas = technology.execute("sync", repo, { apply: true, boundary: "task_complete", continuityEvidence: evidence("cas"), expectedGraphDigest: staleDigest, stateRoot });
119
+ check("compare_and_swap_conflict_is_safe", cas.status === "blocked" && cas.blockers.includes("continuity_compare_and_swap_conflict"), cas);
120
+ baseObjects[0].summary = "Complete a safe fixture task";
121
+ fs.writeFileSync(path.join(repo, "graph/specs/objects.json"), JSON.stringify(baseObjects, null, 2) + "\n");
122
+
123
+ const secret = technology.execute("sync", repo, { apply: true, boundary: "task_complete", continuityEvidence: evidence("secret", { outcome: "token=not-a-real-secret-value-123456" }), stateRoot });
124
+ check("secret_is_rejected", secret.status === "blocked" && secret.blockers.includes("continuity_sensitive_or_host_data_forbidden"), secret);
125
+ const privatePath = technology.execute("sync", repo, { apply: true, boundary: "task_complete", continuityEvidence: { ...evidence("private"), changed_surfaces: ["source/memory/private.md"] }, stateRoot });
126
+ check("private_projection_is_rejected", privatePath.status === "blocked" && privatePath.blockers.includes("continuity_sensitive_or_host_data_forbidden"), privatePath);
127
+ const failedCheck = technology.execute("sync", repo, { apply: true, boundary: "task_complete", continuityEvidence: { ...evidence("fail"), checks: [{ id: "check.fixture", verdict: "fail", evidence_ref: "repo://fixture/fail" }] }, stateRoot });
128
+ check("unverified_result_is_rejected", failedCheck.status === "blocked" && failedCheck.blockers.includes("continuity_result_not_verified"), failedCheck);
129
+
130
+ git(repo, "add", "graph.json", "graph/specs", "graph/docs"); git(repo, "commit", "-qm", "portable continuity records");
131
+ const discovered = technology.context(repo, { phase: "discover", task: "use the verified portable work case" });
132
+ check("new_task_discovers_past_case", discovered.status === "success" && discovered.traversal_receipt.candidates.some((item) => item.id.startsWith("regression_case.continuity.")), discovered.blockers);
133
+ const beforeReadOnly = git(repo, "status", "--porcelain=v1");
134
+ technology.status(repo); technology.context(repo, { phase: "discover", task: "read only project context" });
135
+ check("read_only_operations_write_nothing", git(repo, "status", "--porcelain=v1") === beforeReadOnly);
136
+
137
+ const folder = createRepo(root, "shared-folder", false);
138
+ const folderFirst = technology.execute("sync", folder, { apply: true, boundary: "task_complete", continuityEvidence: evidence("folder"), stateRoot });
139
+ check("non_git_folder_supports_continuity", folderFirst.status === "success" && folderFirst.changed, folderFirst);
140
+ const folderRepeat = technology.execute("sync", folder, { apply: true, boundary: "task_complete", continuityEvidence: evidence("folder"), stateRoot });
141
+ check("non_git_repeat_is_idempotent", folderRepeat.status === "success" && folderRepeat.changed === false, folderRepeat);
142
+ const sharedLease = path.join(folder, "graph/.project-technology-continuity.lock");
143
+ fs.writeFileSync(sharedLease, "occupied\n");
144
+ const leaseConflict = technology.execute("sync", folder, { apply: true, boundary: "task_complete", continuityEvidence: evidence("parallel"), stateRoot: path.join(root, "third-installation-state") });
145
+ check("shared_folder_lease_blocks_parallel_writer", leaseConflict.status === "blocked" && leaseConflict.blockers.includes("continuity_lease_conflict"), leaseConflict);
146
+ fs.unlinkSync(sharedLease);
147
+ const folderDiscovery = technology.context(folder, { phase: "discover", task: "portable fixture case" });
148
+ check("non_git_context_is_available", folderDiscovery.status === "success", folderDiscovery.blockers);
149
+ check("same_content_has_stable_digest", technology.continuity.graphDigest(folder) === technology.continuity.graphDigest(folder));
150
+
151
+ const otherStateRoot = path.join(root, "other-installation-state");
152
+ const firstInstallContext = technology.context(repo, { phase: "discover", task: "use verified portable work" });
153
+ const secondInstallContext = technology.context(repo, { phase: "discover", task: "use verified portable work", stateRoot: otherStateRoot });
154
+ check("two_installations_get_same_context", firstInstallContext.traversal_receipt.traversal_digest === secondInstallContext.traversal_receipt.traversal_digest);
155
+ check("portable_specs_contain_no_host_paths", !/(?:\/Users\/|\/home\/|[A-Za-z]:\\Users\\)/.test(fs.readFileSync(path.join(repo, "graph/specs/project-continuity.json"), "utf8")));
156
+ check("continuity_policy_keeps_contract_version", JSON.parse(fs.readFileSync(path.join(repo, "graph.json"), "utf8")).extensions["mirai.project_technology"].contract_version === "1.0.0");
157
+
158
+ const bootstrapRepo = path.join(root, "existing-code-new-graph");
159
+ fs.mkdirSync(bootstrapRepo, { recursive: true });
160
+ fs.writeFileSync(path.join(bootstrapRepo, "README.md"), "# Existing code\n");
161
+ git(bootstrapRepo, "init", "-q"); git(bootstrapRepo, "config", "user.name", "Mirai Fixture"); git(bootstrapRepo, "config", "user.email", "fixture@example.invalid");
162
+ git(bootstrapRepo, "add", "README.md"); git(bootstrapRepo, "commit", "-qm", "existing code");
163
+ writeJson(path.join(bootstrapRepo, "graph.json"), manifest("bootstrap-project"));
164
+ writeJson(path.join(bootstrapRepo, "graph/specs/objects.json"), [{ id: "goal.bootstrap", kind: "goal", title: "Bootstrap", summary: "Use content-bound bootstrap context", readiness: "accepted", profile: "project_management" }]);
165
+ writeJson(path.join(bootstrapRepo, "graph/specs/relations.json"), []);
166
+ const bootstrapContext = technology.context(bootstrapRepo, { phase: "discover", task: "bootstrap context" });
167
+ check("new_git_graph_is_content_bound_before_first_commit", bootstrapContext.status === "success" && String(bootstrapContext.traversal_receipt.graph.revision).startsWith("content:"), bootstrapContext.blockers);
168
+
169
+ process.stdout.write(`${JSON.stringify({ status: "success", checks_passed: checks.length, checks_failed: 0, checks }, null, 2)}\n`);
170
+ } catch (error) {
171
+ process.stdout.write(`${JSON.stringify({ status: "fail", checks_passed: checks.filter((item) => item.passed).length, checks_failed: 1, checks, error: error.message }, null, 2)}\n`);
172
+ process.exitCode = 1;
173
+ }
@@ -72,6 +72,18 @@ function executionContract() {
72
72
  };
73
73
  }
74
74
 
75
+ function continuityEvidence(repositoryId) {
76
+ return {
77
+ task_digest: technology.sha256(`task:${repositoryId}`, true),
78
+ outcome: `Exact target binding verified for ${repositoryId}`,
79
+ requirement_refs: ["requirement.fixture.runtime"],
80
+ evidence_refs: ["repo://fixture/evidence/project-technology"],
81
+ checks: [{ id: "check.fixture.binding", verdict: "pass", evidence_ref: "repo://fixture/evidence/project-technology" }],
82
+ changed_surfaces: ["graph/specs/project-continuity.json"],
83
+ case_signature: "case.fixture.target-binding",
84
+ };
85
+ }
86
+
75
87
  function initRepo(root, name, scope = "repository", profiles) {
76
88
  const repo = path.join(root, name); fs.mkdirSync(repo, { recursive: true });
77
89
  git(repo, "init", "-q"); git(repo, "config", "user.name", "Mirai Fixture");
@@ -104,6 +116,7 @@ function check(id, condition, details = null) {
104
116
  }
105
117
 
106
118
  const root = fs.mkdtempSync(path.join(os.tmpdir(), "mirai-project-technology-test-"));
119
+ process.env.MIRAI_GRAPH_STATE_ROOT = path.join(root, "host-state");
107
120
  try {
108
121
  const provider = initRepo(root, "fixture-provider", "repository");
109
122
  const consumer = initRepo(root, "fixture-consumer", "repository");
@@ -112,6 +125,11 @@ try {
112
125
  const federation = initRepo(root, "fixture-federation", "federation", ["project_management", "implementation_control"]);
113
126
  const providerRevision = addTarget(provider);
114
127
 
128
+ const legacyRuntimeRepo = initRepo(root, "legacy-runtime-repository");
129
+ writeJson(path.join(legacyRuntimeRepo, ".mirai-graph/project-technology/inventory.json"), { schema_version: "1.0.0", repository_id: "legacy-runtime-repository", inventory_digest: `sha256:${"0".repeat(64)}`, files: [] });
130
+ const legacyRuntimeEnabled = technology.execute("enable", legacyRuntimeRepo, { apply: true });
131
+ check("project_local_runtime_moves_to_host_state", legacyRuntimeEnabled.status === "success" && legacyRuntimeEnabled.migration_ref.startsWith("host-local://") && fs.existsSync(path.join(legacyRuntimeRepo, ".mirai-graph/project-technology/inventory.json")), legacyRuntimeEnabled);
132
+
115
133
  const before = fs.readFileSync(path.join(consumer, "graph.json"));
116
134
  const preview = technology.execute("enable", consumer, { apply: false });
117
135
  check("preview_is_zero_write", preview.status === "preview" && fs.readFileSync(path.join(consumer, "graph.json")).equals(before));
@@ -147,12 +165,18 @@ try {
147
165
  apply: true, source: exportPath, targetId: TARGET_ID,
148
166
  semanticDigest: SEMANTIC_DIGEST, providerRevision,
149
167
  });
150
- check("consumer_binding_ready", connected.status === "success" && technology.verify(consumer, { significantWork: true }).status === "success", connected.blockers);
168
+ const consumerContinuity = technology.execute("sync", consumer, {
169
+ apply: true, boundary: "task_complete", continuityEvidence: continuityEvidence("fixture-consumer"),
170
+ });
171
+ check("consumer_binding_ready", connected.status === "success" && consumerContinuity.status === "success" && technology.verify(consumer, { significantWork: true }).status === "success", { connect: connected.blockers, continuity: consumerContinuity.blockers });
151
172
  const connectedTwo = technology.execute("connect", consumerTwo, {
152
173
  apply: true, source: exportPath, targetId: TARGET_ID,
153
174
  semanticDigest: SEMANTIC_DIGEST, providerRevision,
154
175
  });
155
- check("second_consumer_binding_ready", connectedTwo.status === "success" && technology.verify(consumerTwo, { significantWork: true }).status === "success", connectedTwo.blockers);
176
+ const consumerTwoContinuity = technology.execute("sync", consumerTwo, {
177
+ apply: true, boundary: "task_complete", continuityEvidence: continuityEvidence("fixture-consumer-two"),
178
+ });
179
+ check("second_consumer_binding_ready", connectedTwo.status === "success" && consumerTwoContinuity.status === "success" && technology.verify(consumerTwo, { significantWork: true }).status === "success", { connect: connectedTwo.blockers, continuity: consumerTwoContinuity.blockers });
156
180
  const repeated = technology.execute("connect", consumer, {
157
181
  apply: true, source: exportPath, targetId: TARGET_ID,
158
182
  semanticDigest: SEMANTIC_DIGEST, providerRevision,